Commit a590a053 authored by David Cussans's avatar David Cussans

Adding bottom 3 bits of 40MHz time stamp to fine-grain timestamp

parent a59dc76e
......@@ -61,6 +61,7 @@ use work.ipbus_reg_types.all;
ENTITY eventFormatter IS
GENERIC(
g_EVENT_DATA_WIDTH : positive := 64;
g_COARSE_TIMESTAMP_WIDTH : positive := 48; -- ! Number of bits in 40MHz timestamp
g_IPBUS_WIDTH : positive := 32;
g_COUNTER_TRIG_WIDTH : positive := 32;
g_COUNTER_WIDTH : positive := 12;
......@@ -92,6 +93,7 @@ ENTITY eventFormatter IS
ipbus_o : OUT ipb_rbus;
data_strobe_o : OUT std_logic; --! goes high when data ready to load into event buffer
event_data_o : OUT std_logic_vector (g_EVENT_DATA_WIDTH-1 DOWNTO 0);
coarse_timestamp_o : OUT std_logic_vector (g_COUNTER_TRIG_WIDTH-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
reset_timestamp_i : IN std_logic; --! Taking high causes timestamp to be reset. Combined with internal timestmap reset and written to reset_timestamp_o
reset_timestamp_o : OUT std_logic --! Goes high for one clock cycle of clk_4x_logic when timestamp reset
);
......@@ -134,8 +136,7 @@ ARCHITECTURE rtl OF eventFormatter IS
signal s_data_o : std_logic_vector(g_EVENT_DATA_WIDTH-1 DOWNTO 0); -- Multiplexed data from FIFOs
constant c_COARSE_TIMESTAMP_WIDTH : positive := 48; -- ! Number of bits in 40MHz timestamp
signal s_coarse_timestamp : std_logic_vector(c_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
signal s_coarse_timestamp : std_logic_vector(g_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
signal s_coarse_timestamp_ipbus : ipb_reg_v(1 downto 0) := ( others => (others => '0')); --! 40MHz timestamp on IPB clock domain.
-- signal s_event_number : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- increment after each post-veto trigger.
......@@ -327,8 +328,8 @@ BEGIN
s_word0_p1 <= s_evttype & s_var & s_coarse_timestamp;
s_word1 <= "000" & trigger_times_d1(0) & "000" & trigger_times_d1(1) &
"000" & trigger_times_d1(2) & "000" & trigger_times_d1(3) &
s_word1 <= trigger_times_d1(0) & trigger_times_d1(1) &
trigger_times_d1(2) & trigger_times_d1(3) &
trigger_cnt_i;
......@@ -375,7 +376,8 @@ BEGIN
enable_i => logic_strobe_i,
result_o => s_coarse_timestamp);
coarse_timestamp_o <= s_coarse_timestamp;
-- Generate data in format decided at DESY. Put out two strobes for the
-- two 64 bit words.
-- get trigger inputs to also generate a global time-stamp ??
......
......@@ -13,11 +13,13 @@ LIBRARY ieee;
USE ieee.std_logic_1164.all;
PACKAGE fmcTLU IS
constant c_NUM_TIME_BITS : natural := 5;
constant c_NUM_TIME_BITS : natural := 8;
constant c_NUM_TRIG_INPUTS : natural := 4;
constant c_EVENT_DATA_WIDTH : natural := 32;
constant c_DATA_WIDTH : natural := 32;
constant c_COARSE_TIMESTAMP_WIDTH : natural := 48;
constant c_TRIGIN_NUM_COARSE_TS_BITS : natural := 3;
subtype t_triggerTime is std_logic_vector(c_NUM_TIME_BITS-1 downto 0);
--type t_triggerTimeArray is array(natural range <>) of t_triggerTime;
type t_triggerTimeArray is array(natural range <>) of std_logic_vector(c_NUM_TIME_BITS-1 downto 0) ;
......
......@@ -82,7 +82,8 @@ use unisim.vcomponents.all;
ENTITY triggerInputs_newTLU IS
GENERIC(
g_NUM_INPUTS : natural := 1;--1
g_NUM_INPUTS : natural := 1;--1
g_NUM_COARSE_TS_BITS : natural := 3; --! Number of coarse ( clk_1x_logic normally 40MHz ) timestamp bits to add to MSB of trigger times.
g_IPBUS_WIDTH : positive := 32
);
PORT(
......@@ -94,6 +95,7 @@ ENTITY triggerInputs_newTLU IS
threshold_discr_p_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
threshold_discr_n_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
reset_i : IN std_logic;
coarse_timestamp_i : in std_logic_vector (g_NUM_COARSE_TS_BITS-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
trigger_times_o : OUT t_triggerTimeArray (g_NUM_INPUTS-1 DOWNTO 0); --! trigger arrival time ( w.r.t. logic_strobe)
trigger_o : OUT std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! Goes high on leading edge of trigger, in sync with clk_4x_logic_i
--trigger_debug_o : OUT std_logic_vector ( ((2*g_NUM_INPUTS)-1) DOWNTO 0); --! Copy of input trigger level. High bits CFD, Low threshold
......@@ -199,7 +201,11 @@ BEGIN
--BEGIN FOR LOOP
-- Instantiate one for each trigger input of the TLU
trigger_input_loop: for triggerInput in 0 to (g_NUM_INPUTS-1) generate
signal s_edge_rising_time_short : std_logic_vector( (c_NUM_TIME_BITS-c_TRIGIN_NUM_COARSE_TS_BITS)-1 downto 0);
signal s_edge_falling_time_short : std_logic_vector( (c_NUM_TIME_BITS-c_TRIGIN_NUM_COARSE_TS_BITS)-1 downto 0);
begin
-- Differential buffer. Receives differential trigger input and produces a buffered differential signal.
IBUFDS_DIFF_OUT_inst : IBUFDS_DIFF_OUT
generic map (
......@@ -238,25 +244,13 @@ BEGIN
clk_4x_logic_i => clk_4x_logic,
strobe_4x_logic_i => strobe_4x_logic_i,
deserialized_data_i => s_deserialized_threshold_data_l(triggerInput),
first_rising_edge_time_o => s_edge_rising_times(triggerInput),
last_falling_edge_time_o => s_edge_falling_times(triggerInput),
first_rising_edge_time_o => s_edge_rising_time_short,
last_falling_edge_time_o => s_edge_falling_time_short,
rising_edge_o => s_edge_rising(triggerInput),
falling_edge_o => s_edge_falling(triggerInput),
multiple_edges_o => open
);
-- The leading edge may be a high-->low or a low-->high transition (
-- depending on polarity of input signal. ). For now assume that leading
-- edge is low-->high and connect trigger times and trigger output accordingly.
-- In the future have this selectable.
edge_rising_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
edge_falling_times_o(triggerInput) <= s_edge_falling_times(triggerInput);
edge_rising_o(triggerInput) <= s_edge_rising(triggerInput);
edge_falling_o(triggerInput) <= s_edge_falling(triggerInput);
trigger_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
trigger_o(triggerInput) <= s_edge_rising(triggerInput);
p_register_delayed_bits : process ( clk_4x_logic )
begin
if rising_edge(clk_4x_logic) then
......@@ -269,7 +263,37 @@ BEGIN
--s_status_to_ipbus(0)(24+triggerInput) <= s_CFD_previous_late_bit(triggerInput);
end if ;
end process;
s_edge_rising_times(triggerInput) <= coarse_timestamp_i & s_edge_rising_time_short;
s_edge_falling_times(triggerInput) <= coarse_timestamp_i & s_edge_falling_time_short;
-- purpose: registers output of arrivalTimeLUT and performs optional edge
proc_registerLUT_output : process (clk_4x_logic) is
begin -- process proc_registerLUT_output
if rising_edge(clk_4x_logic) then
-- The leading edge may be a high-->low or a low-->high transition (
-- depending on polarity of input signal. ). For now assume that leading
-- edge is low-->high and connect trigger times and trigger output accordingly.
-- In the future have this selectable.
edge_rising_o(triggerInput) <= s_edge_rising(triggerInput);
if (s_edge_rising(triggerInput) = '1') then
trigger_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
edge_rising_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
end if;
edge_falling_o(triggerInput) <= s_edge_falling(triggerInput);
if (s_edge_falling(triggerInput) = '1') then
edge_falling_times_o(triggerInput) <= s_edge_falling_times(triggerInput);
end if;
trigger_o(triggerInput) <= s_edge_rising(triggerInput);
end if;
end process proc_registerLUT_output;
--! Instantiate counter for output triggers.
--! Input I is connected to address I+1
cmp_inputTriggerCounter : entity work.counterWithReset
......
......@@ -20,6 +20,7 @@ architecture bench of triggerInputs_newTLU_tb is
component triggerInputs_newTLU
generic(
g_NUM_INPUTS : natural := g_NUM_INPUTS;
g_NUM_COARSE_TS_BITS : natural := 3; --! Number of coarse ( clk_1x_logic normally 40MHz ) timestamp bits to add to MSB of trigger times.
g_IPBUS_WIDTH : positive := g_IPBUS_WIDTH
);
port(
......@@ -29,6 +30,7 @@ architecture bench of triggerInputs_newTLU_tb is
threshold_discr_p_i : in std_logic_vector (g_NUM_INPUTS-1 downto 0);
threshold_discr_n_i : in std_logic_vector (g_NUM_INPUTS-1 downto 0);
reset_i : in std_logic;
coarse_timestamp_i : in std_logic_vector (g_NUM_COARSE_TS_BITS-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
trigger_times_o : out t_triggerTimeArray (g_NUM_INPUTS-1 downto 0);
trigger_o : out std_logic_vector (g_NUM_INPUTS-1 downto 0);
edge_rising_times_o : out t_triggerTimeArray (g_NUM_INPUTS-1 downto 0);
......@@ -64,6 +66,7 @@ architecture bench of triggerInputs_newTLU_tb is
signal clk_8x_logic_i : std_logic;
signal clk_logic : std_logic;
signal strobe_8x_logic_i : std_logic;
signal s_coarse_timestamp : std_logic_vector(c_TRIGIN_NUM_COARSE_TS_BITS-1 downto 0) := ( others => '0' ); -- counts on each strobe_4x_logic pulse
-- constant C_NUM_STROBE_TAPS : positive := 2; --! Adjust to shift strobes relative to 40MHz clock edge
-- signal s_clk40_delayed_160 : std_logic_vector(C_NUM_STROBE_TAPS downto 0); --! Shift register used to generate clock_4x strobe. Adjust length for correct alignment with incoming clock
-- signal s_clk40_delayed_320 : std_logic_vector((2*C_NUM_STROBE_TAPS)+1 downto 0); --! Shift register used to generate clock_8x strobe. Adjust length for correct alignment with incoming clock
......@@ -97,6 +100,7 @@ begin
threshold_discr_p_i => threshold_discr_p_i,
threshold_discr_n_i => threshold_discr_n_i,
reset_i => s_logic_reset,
coarse_timestamp_i => s_coarse_timestamp,
trigger_times_o => trigger_times_o,
trigger_o => trigger_o,
edge_rising_times_o => edge_rising_times_o,
......@@ -156,8 +160,9 @@ begin
triggerNumber_o => open,
timeStamp_o => open
);
threshold_discr_p_i <= s_pulses;
threshold_discr_n_i <= not s_pulses;
threshold_discr_p_i <= s_pulses;
threshold_discr_n_i <= not s_pulses;
clockGenerator : entity work.logic_clocks
port map (
......@@ -204,5 +209,20 @@ threshold_discr_n_i <= not s_pulses;
wait;
end process;
tsCounter : process
variable v_tsctr : unsigned ( c_TRIGIN_NUM_COARSE_TS_BITS-1 downto 0) := (others => '0') ;
begin
while not stop_the_clock loop
wait until rising_edge(clk_4x_logic);
if reset_i = '1' then
v_tsctr := ( others => '0');
elsif strobe_4x_logic_i ='1' then
v_tsctr := v_tsctr + 1;
end if;
s_coarse_timestamp <= std_logic_vector(v_tsctr);
end loop;
end process;
end;
......@@ -16,76 +16,81 @@ use work.BFMTypes.all;
use std.TEXTIO.all;
entity variablePulseTransactor is
generic(
g_BUSWIDTH : integer := 32); -- width for triggernumber and timestamp
port(
clk_i : in std_logic;
trans_i : in t_pulseTransaction;
returnedData_o : out t_pulseTransactionReturn;
signal_o : out std_logic_vector(c_NPULSE_CHANNELS - 1 downto 0); --! Signal pulses low-high-low
triggerNumber_o : out std_logic_vector(g_BUSWIDTH - 1 downto 0);
timeStamp_o : out std_logic_vector(g_BUSWIDTH - 1 downto 0)
);
generic(
g_BUSWIDTH : integer := 32); -- width for triggernumber and timestamp
port(
clk_i : in std_logic;
trans_i : in t_pulseTransaction;
returnedData_o : out t_pulseTransactionReturn;
signal_o : out std_logic_vector(c_NPULSE_CHANNELS - 1 downto 0); --! Signal pulses low-high-low
triggerNumber_o : out std_logic_vector(g_BUSWIDTH - 1 downto 0);
timeStamp_o : out std_logic_vector(g_BUSWIDTH - 1 downto 0)
);
end variablePulseTransactor;
architecture rtl of variablePulseTransactor is
signal s_timeStamp : unsigned(g_BUSWIDTH - 1 downto 0) := (others => '0');
constant c_timeGranularity : time := 1 ps;
signal s_pulseNum : integer := 0;
signal s_timeStamp : unsigned(g_BUSWIDTH - 1 downto 0) := (others => '0');
constant c_timeGranularity : time := 1 ps;
signal s_pulseNum : integer := 0;
begin -- rtl
begin -- rtl
p_pulseGen : process is
variable v_pulseDelay : time := 0 ps;
variable v_pulseWidth : time := 0 ps;
variable v_lastEdge : time := 0 ps;
begin
report "variablePulseBFM: waiting for transaction" severity note;
p_pulseGen : process is
variable v_pulseDelay : time := 0 ps;
variable v_pulseWidth : time := 0 ps;
variable v_lastEdge : time := 0 ps;
signal_o <= (others => '0');
begin
report "variablePulseBFM: waiting for transaction" severity note;
wait on trans_i'transaction;
report "variablePulseBFM: Got transaction" severity note;
signal_o <= (others => '0');
wait until rising_edge(clk_i);
wait on trans_i'transaction;
report "variablePulseBFM: Got transaction" severity note;
for chan in 0 to signal_o'length - 1 loop
v_pulseDelay := trans_i(chan).r_delay * TIMEUNIT;
v_pulseWidth := trans_i(chan).r_width * TIMEUNIT;
wait until rising_edge(clk_i);
if (v_pulseDelay + v_pulseWidth ) > v_lastEdge then
v_lastEdge := (v_pulseDelay + v_pulseWidth );
end if;
report "Queing pulse . chan , delay , width " & integer'image(chan) & " " & time'image(v_pulseDelay) & " " & time'image(v_pulseWidth);
signal_o(chan) <= '1' after v_pulseDelay, '0' after (v_pulseDelay + v_pulseWidth);
for chan in 0 to signal_o'length - 1 loop
v_pulseDelay := trans_i(chan).r_delay * TIMEUNIT;
v_pulseWidth := trans_i(chan).r_width * TIMEUNIT;
end loop;
if (v_pulseDelay + v_pulseWidth) > v_lastEdge then
v_lastEdge := (v_pulseDelay + v_pulseWidth);
end if;
wait for v_lastEdge;
-- Update trigger number
s_pulseNum <= s_pulseNum + 1;
triggerNumber_o <= std_logic_vector(to_unsigned(s_pulseNum, g_BUSWIDTH));
if trans_i(chan).r_delay > 0 then
report "Queing pulse . chan , delay , width " & integer'image(chan) & " " & time'image(v_pulseDelay) & " " & time'image(v_pulseWidth);
signal_o(chan) <= '1' after v_pulseDelay, '0' after (v_pulseDelay + v_pulseWidth);
else
report "NO Pulse queued chr chan " & integer'image(chan);
end if;
-- output current time-stamp
timeStamp_o <= std_logic_vector(s_timeStamp);
returnedData_o <= s_pulseNum;
end loop;
end process p_pulseGen;
wait for v_lastEdge;
-- purpose: keeps a timestamp in terms of clock cycles
-- type : sequential
-- inputs : clk_i, s_timeStamp
-- outputs: s_timeStamp
p_timeStamp : process(clk_i)
begin -- process p_timeStamp
if rising_edge(clk_i) then
s_timeStamp <= s_timeStamp + 1;
end if;
end process p_timeStamp;
-- Update trigger number
s_pulseNum <= s_pulseNum + 1;
triggerNumber_o <= std_logic_vector(to_unsigned(s_pulseNum, g_BUSWIDTH));
-- output current time-stamp
timeStamp_o <= std_logic_vector(s_timeStamp);
returnedData_o <= s_pulseNum;
end process p_pulseGen;
-- purpose: keeps a timestamp in terms of clock cycles
-- type : sequential
-- inputs : clk_i, s_timeStamp
-- outputs: s_timeStamp
p_timeStamp : process(clk_i)
begin -- process p_timeStamp
if rising_edge(clk_i) then
s_timeStamp <= s_timeStamp + 1;
end if;
end process p_timeStamp;
end rtl;
......@@ -51,7 +51,7 @@ use work.ipbus.ALL;
entity top is
generic(
constant FW_VERSION : unsigned(31 downto 0):= X"1e000024"; -- Firmware revision. Remember to change this as needed.
constant FW_VERSION : unsigned(31 downto 0):= X"1e000025"; -- Firmware revision. Remember to change this as needed.
g_NUM_DUTS : positive := 4; -- <- was 3
g_NUM_TRIG_INPUTS :positive := 6;-- <- was 4
g_NUM_EDGE_INPUTS :positive := 6;-- <-- was 4
......@@ -171,6 +171,7 @@ architecture rtl of top is
SIGNAL triggers : std_logic_vector(g_NUM_TRIG_INPUTS-1 DOWNTO 0); --! Rising edge of trigger inputs
SIGNAL s_veto : std_logic; --! goes high when one or more DUT are busy
signal s_shutter_veto : std_logic; --! Goes high when triggers should be vetoed by shutter
signal s_coarse_timestamp : std_logic_vector(c_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
signal ctrl, stat: ipb_reg_v(0 downto 0);
--My signals
--SIGNAL busy_toggle_o : std_logic_vector(g_NUM_DUTS-1 downto 0);
......@@ -257,6 +258,7 @@ architecture rtl of top is
COMPONENT eventFormatter
GENERIC (
g_EVENT_DATA_WIDTH : positive := 64;
g_COARSE_TIMESTAMP_WIDTH : positive := 48; -- ! Number of bits in 40MHz timestamp
g_IPBUS_WIDTH : positive := 32;
g_COUNTER_TRIG_WIDTH : positive := 32;
g_COUNTER_WIDTH : positive := 12;
......@@ -288,6 +290,7 @@ architecture rtl of top is
ipbus_o : OUT ipb_rbus ;
data_strobe_o : OUT std_logic ; --! goes high when data ready TO load into event buffer
event_data_o : OUT std_logic_vector (g_EVENT_DATA_WIDTH-1 DOWNTO 0);
coarse_timestamp_o : out std_logic_vector (g_COUNTER_TRIG_WIDTH-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
reset_timestamp_i : IN std_logic ; --! Taking high causes timestamp TO be reset. Combined with internal timestmap reset and written to reset_timestamp_o
reset_timestamp_o : OUT std_logic --! Goes high for one clock cycle of clk_4x_logic when timestamp reset
);
......@@ -320,7 +323,8 @@ architecture rtl of top is
----------------------------------------------
COMPONENT triggerInputs_newTLU
GENERIC (
g_NUM_INPUTS : natural := 1;
g_NUM_INPUTS : natural := 1;
g_NUM_COARSE_TS_BITS : natural := 3; --! Number of coarse ( clk_1x_logic normally 40MHz ) timestamp bits to add to MSB of trigger times.
g_IPBUS_WIDTH : positive := 32
);
PORT (
......@@ -332,6 +336,7 @@ architecture rtl of top is
threshold_discr_p_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
threshold_discr_n_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
reset_i : IN std_logic ;
coarse_timestamp_i : in std_logic_vector (g_NUM_COARSE_TS_BITS-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
trigger_times_o : OUT t_triggerTimeArray (g_NUM_INPUTS-1 DOWNTO 0); --! trigger arrival time ( w.r.t. logic_strobe)
trigger_o : OUT std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! Goes high on leading edge of trigger, in sync with clk_4x_logic_i
--trigger_debug_o : OUT std_logic_vector ( ((2*g_NUM_INPUTS)-1) DOWNTO 0); --! Copy of input trigger level. High bits CFD, Low threshold
......@@ -566,6 +571,7 @@ begin
threshold_discr_p_i => threshold_discr_p_i,
threshold_discr_n_i => threshold_discr_n_i,
reset_i => logic_reset,
coarse_timestamp_i => s_coarse_timestamp(c_TRIGIN_NUM_COARSE_TS_BITS-1 downto 0),
trigger_times_o => trigger_times,
trigger_o => triggers,
--trigger_debug_o => OPEN,
......@@ -616,6 +622,7 @@ begin
ipbus_o => ipbrr(N_SLV_EVENT_FORMATTER),
data_strobe_o => data_strobe,
event_data_o => event_data,
coarse_timestamp_o => s_coarse_timestamp,
reset_timestamp_i => s_T0,
reset_timestamp_o => OPEN
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment