Commit a0a81ebc authored by Alvaro Dosil's avatar Alvaro Dosil

Add TPx3 and Synchronous handshakes, and fix TDC alignment

parent c981c4f7
This diff is collapsed.
......@@ -11,16 +11,10 @@
--
--! @brief Produces shutters \n
--! IPBus address map:\n
--! 0x00000000 RO - Number of shutters issued since last reset.\n
--! 0x00000001 RO - Number of possible shutters since last reset (i.e. pre-veto triggers)\n
--! 0x00000010 RW - Interval between internal triggers in ticks of logic_strobe_i\n
--! 0x00000011 RW - shutter mask ( 1 bit per input )\n
--! 0x00000100 RW - bit-0 - internal shutter veto. Set to halt vetos.\n
--! 0x00000101 RO - state of external veto
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--! @author Alvaro Dosil , alvaro.dosil@usc.es
--
--! @date 16:06:19 11/09/12
--! @date 16:06:19 11/06/14
--
--! @version v0.1
--
......@@ -58,12 +52,11 @@ ENTITY TPx3Logic IS
);
PORT(
clk_i : IN std_logic; -- ! Rising edge active
T0syncAut_i : IN std_logic;
T0syncFlag_i : IN std_logic;
Start_T0sync_i : IN std_logic;
T0syncLen_i : IN std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0);
ShDTLen_i : IN std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0);
logic_reset_i : IN std_logic; -- active high. Synchronous with clk_4x_logic
Busy_i : IN std_logic;
Veto_i : IN std_logic;
Shutter_o : OUT std_logic;
T0sync_o : OUT std_logic
);
......@@ -76,19 +69,15 @@ END ENTITY TPx3Logic ;
--
ARCHITECTURE rtl OF TPx3Logic IS
type state_values is (st0, st1, st2, st3, st4, st5);
type state_values is (st0, st1);
signal pres_state, next_state: state_values;
signal s_Enable : std_logic := '0';
signal s_Shutter, s_T0sync : std_logic := '0';
--signal T0syncTime, ShDTime : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0); -- Result from counters
signal T0syncFlag, T0syncAut : std_logic := '1'; --T0 sync flag and T0sync authomatic/manual mode
signal s_Enable, s_Veto : std_logic := '0';
signal s_Shutter, s_Shutter_old, s_T0sync : std_logic := '0';
signal s_Start_T0sync, s_Start_T0sync_d1, s_Start_T0sync_d2, s_Start_T0sync_d3 : std_logic;
signal Rst_T0sync, T0syncT : std_logic; --Load signal and flag for the T0sync
signal Rst_ShDT, ShDT : std_logic; --Load signal and flag for the interval between T0sync and Shutter
signal s_RunNumber : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- ! counters for runs
BEGIN
-----------------------------------------------------------------------------
......@@ -107,112 +96,74 @@ BEGIN
Count => open,
Q => T0syncT
);
--Start up dead time counter
c_STDT: entity work.CounterDown
generic map(
MAX_WIDTH => g_IPBUS_WIDTH
)
port map(
Clk => clk_i,
Reset => '0',
Load => Rst_ShDT,
InitVal => std_logic_vector(unsigned(ShDTLen_i)-1),
Count => open,
Q => ShDT
);
-- --T0sync counter
-- c_T0sync: entity work.counterWithReset
-- GENERIC MAP(
-- g_OUTPUT_REGISTERS => 1 --! Number of output registers. Minumum =1. Aids timing closure.
-- )
-- PORT MAP(
-- clock_i => clk_i, --! rising edge active clock
-- reset_i => Rst_T0sync, --! Active high. syncronous with rising clk
-- enable_i => '1', --! counts when enable=1
-- result_o => T0syncTime --! Unsigned integer output
-- );
-- T0syncT <= '1' when T0syncTime>=std_logic_vector(unsigned(T0syncLen_i)-1) else
-- '0';
-- --Start up dead time counter
-- c_STDT: entity work.counterWithReset
-- GENERIC MAP(
-- g_OUTPUT_REGISTERS => 1 --! Number of output registers. Minumum =1. Aids timing closure.
-- )
-- PORT MAP(
-- clock_i => clk_i, --! rising edge active clock
-- reset_i => Rst_ShDT, --! Active high. syncronous with rising clk
-- enable_i => '1', --! counts when enable=1
-- result_o => ShDTime --! Unsigned integer output
-- );
-- ShDT <= '1' when ShDTime=std_logic_vector(unsigned(ShDTLen_i)-1) else
-- '0';
-----------------------------------------------------------------------------
-- FSM register
-----------------------------------------------------------------------------
statereg: process(clk_i, s_Enable)
statereg: process(clk_i)
begin
if s_Enable = '0' then
pres_state <= st0; --Move to the "initial" state
elsif rising_edge(clk_i) then
if rising_edge(clk_i) then
pres_state <= next_state; --Move to the next state
end if;
end process statereg;
-----------------------------------------------------------------------------
-- FSM combinational block
-----------------------------------------------------------------------------
fsm: process(pres_state, s_Enable, T0syncT, shDT)
begin
next_state<=pres_state;
fsm: process(pres_state, s_Start_T0sync, T0syncT)
begin
next_state<=pres_state;
--To avoid latches we write the default values
s_Shutter<='0';
s_T0sync <='0';
Rst_T0sync <= '1';
Rst_ShDT <='1';
Rst_T0sync <= '1';
case pres_state is
when st0=>
if s_Enable = '1' then
next_state<=st1; --Next state is "Whait for T0sync flag"
end if;
when st1=>
if (T0syncAut_i = '1') or (T0syncFlag_i = '1' and T0syncAut_i = '0') then
next_state <= st2; --Next state is "Whait for end of T0sync signal"
if s_Start_T0sync = '1' then
next_state <= st1; --Next state is "Whait for end of T0sync signal"
end if;
when st2 =>
when st1 =>
Rst_T0sync <='0';
s_T0sync <='1';
if (T0syncT = '1') and ShDTLen_i=X"00000000" then
next_state<=st4; --Next state is "Whait for end of start up Dead Time"
elsif (T0syncT = '1') and ShDTLen_i/=X"00000000" then
next_state<=st3; --Next state is "Shutter open"
if T0syncT = '1' then
next_state<=st0; --Next state is "Whait for end of T0-sync counter"
end if;
when st3 =>
Rst_ShDT <='0';
if ShDT = '1' then
next_state<=st4; --Next state is "Shutter open"
end if;
when st4 =>
s_Shutter <= '1';
when others=>
next_state<=st0; --Next state is "Idle"
next_state<=st0; --Next state is "Whait for T0sync start"
end case;
end process fsm;
s_Enable <= not Busy_i;
Shutter_o <= s_Shutter;
T0sync_o <= s_T0sync;
-----------------------------------------------------------------------------
-- Busy signals
-----------------------------------------------------------------------------
s_Enable <= not Busy_i;
Shutter_o <= s_Enable and not s_Veto;
T0sync_o <= s_T0sync;
-----------------------------------------------------------------------------
-- Count runs and synchronization
-----------------------------------------------------------------------------
p_run_counter: process (clk_i )
begin -- process p_run_counter
if rising_edge(clk_i) then
s_Start_T0sync_d1 <= Start_T0sync_i;
s_Start_T0sync_d2 <= s_Start_T0sync_d1;
s_Start_T0sync_d3 <= s_Start_T0sync_d2;
s_Start_T0sync <= s_Start_T0sync_d2 and ( not s_Start_T0sync_d3);
s_Shutter_old <= s_Shutter;
if logic_reset_i = '1' then
s_RunNumber <= (others => '0');
elsif s_Shutter='1' and s_Shutter_old='0' then
s_RunNumber <= s_RunNumber + 1;
end if;
end if;
end process p_run_counter;
END ARCHITECTURE rtl;
......@@ -157,7 +157,7 @@ BEGIN
-- type : combinational
-- inputs : clk_4x_logic_i
-- outputs: arrival_time_o , rising_edge_o , falling_edge_o
examine_lut: process (clk_4x_logic_i , deserialized_data_i)
examine_lut: process (clk_4x_logic_i) -- , deserialized_data_i)
-- variable v_LUT_entry : std_logic_vector(g_NUM_FINE_BITS+2-1 downto 0); --! Entry in LUT pointed to by deserialized data
begin -- process examine_lut
......@@ -169,7 +169,7 @@ BEGIN
last_falling_edge_time_o <= s_coarse_bits & s_LUT_ENTRY(g_NUM_FINE_BITS-1 downto 0);
rising_edge_o <= s_LUT_ENTRY(c_RISING_EDGE_BIT);
falling_edge_o <= s_LUT_ENTRY(c_FALLING_EDGE_BIT);
multiple_edges_o <= s_LUT_ENTRY(c_MULTI_EDGE_BIT);
multiple_edges_o <= s_LUT_ENTRY(c_MULTI_EDGE_BIT);
end if;
end process examine_lut;
......
......@@ -57,7 +57,6 @@ ENTITY dualSERDES_1to4 IS
data_o : OUT std_logic_vector (7 DOWNTO 0); --! Deserialized data. Interleaved between prompt and delayed serdes.
--! data_o(0) is the oldest data
status_o : OUT std_logic_vector(1 downto 0) --! outputs from IODELAY "busy" 0=prompt,1=delayed
);
-- Declarations
......@@ -98,9 +97,9 @@ BEGIN
DATA_RATE => "SDR", -- "SDR" or "DDR"
DELAY_SRC => "IDATAIN", -- "IO", "ODATAIN" or "IDATAIN"
SERDES_MODE => "NONE", -- <NONE>, MASTER, SLAVE
IDELAY_TYPE => "VARIABLE_FROM_HALF_MAX",
IDELAY_VALUE => 0, -- Amount of taps for fixed input delay (0-255)
SIM_TAPDELAY_VALUE=> 75 -- Per tap delay used for simulation in ps
IDELAY_TYPE => "FIXED", --"VARIABLE_FROM_HALF_MAX",
IDELAY_VALUE => 116,--116, -- Amount of taps for fixed input delay (0-255)
SIM_TAPDELAY_VALUE=> 10 -- Per tap delay used for simulation in ps
)
port map (
-- BUSY => s_busy_idelay_m, -- 1-bit output: Busy output after CAL
......@@ -130,11 +129,11 @@ BEGIN
DATA_RATE => "SDR", -- "SDR" or "DDR"
DELAY_SRC => "IDATAIN", -- "IO", "ODATAIN" or "IDATAIN"
SERDES_MODE => "NONE", -- <NONE>, MASTER, SLAVE
IDELAY_TYPE => "VARIABLE_FROM_ZERO",
IDELAY_VALUE => 0, -- Amount of taps for fixed input delay (0-255) 10->0.75nS, 11->0.825nS
IDELAY_TYPE => "FIXED", --"VARIABLE_FROM_ZERO",
IDELAY_VALUE => 150,--130, -- Amount of taps for fixed input delay (0-255)
IDELAY2_VALUE => 0, -- Delay value when IDELAY_MODE="PCI" (0-255)
ODELAY_VALUE => 0, -- Amount of taps fixed output delay (0-255)
SIM_TAPDELAY_VALUE => 75 -- Per tap delay used for simulation in ps
SIM_TAPDELAY_VALUE => 10 -- Per tap delay used for simulation in ps
)
port map (
-- BUSY => s_busy_idelay_s, -- 1-bit output: Busy output after CAL
......@@ -168,10 +167,10 @@ BEGIN
)
port map (
-- Q1 - Q4: 1-bit (each) output Registered outputs to FPGA logic
Q1 => s_Data_o(0), -- oldest data
Q2 => s_Data_o(2),
Q3 => s_Data_o(4),
Q4 => s_Data_o(6), -- most recent data
Q1 => s_Data_o(1), -- Oldest data
Q2 => s_Data_o(3),
Q3 => s_Data_o(5),
Q4 => s_Data_o(7), -- most recent data
--SHIFTOUT => SHIFTOUTsig, -- 1-bit output Cascade output signal for master/slave I/O
VALID => open, -- 1-bit output Output status of the phase detector
BITSLIP => '0', -- 1-bit input Bitslip enable input
......@@ -194,11 +193,11 @@ BEGIN
SERDES_MODE => "NONE" -- "NONE", "MASTER" or "SLAVE"
)
port map (
-- Q1 - Q4: 1-bit (each) output Registered outputs to FPGA logic
Q1 => s_Data_o(1), -- Oldest data
Q2 => s_Data_o(3),
Q3 => s_Data_o(5),
Q4 => s_Data_o(7), -- most recent data
-- Q1 - Q4: 1-bit (each) output Registered outputs to FPGA logic
Q1 => s_Data_o(0), -- oldest data
Q2 => s_Data_o(2),
Q3 => s_Data_o(4),
Q4 => s_Data_o(6), -- most recent data
--SHIFTOUT => SHIFTOUTsig, -- 1-bit output Cascade output signal for master/slave I/O
VALID => open, -- 1-bit output Output status of the phase detector
BITSLIP => '0', -- 1-bit input Bitslip enable input
......
......@@ -144,7 +144,7 @@ ARCHITECTURE rtl OF eventFormatter IS
--signal s_data_o_mask : unsigned(3+g_NUM_EDGE_INPUTS-1 downto 0) := (g_NUM_TRIG_INPUTS+g_NUM_EDGE_INPUTS-1 =>'1',others=>'0'); -- Output data mask
constant c_COARSE_TIMESTAMP_WIDTH : positive := 48; -- ! Number of bits in 40MHz timestamp
signal s_coarse_timestamp : unsigned(c_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
signal s_coarse_timestamp, s_coarse_timestamp_d1, s_coarse_timestamp_d2, s_coarse_timestamp_d3 : unsigned(c_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
-- signal s_event_number : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- increment after each post-veto trigger.
signal s_word0 , s_word1, s_word2 : std_logic_vector(g_EVENT_DATA_WIDTH-1 downto 0) := (others => '0'); -- clocked to data output on logic_strobe , s_logic_strobe_d1 , etc.
......@@ -240,6 +240,9 @@ BEGIN
spill_i_d1 <= spill_i and s_enable_spill;
spill_i_d2 <= spill_i_d1;
s_coarse_timestamp_d1 <= s_coarse_timestamp;
s_coarse_timestamp_d2 <= s_coarse_timestamp_d1;
s_coarse_timestamp_d3 <= s_coarse_timestamp_d2;
end if;
end process p_reg;
......@@ -257,12 +260,13 @@ BEGIN
"0001";
s_var(0) <= trigger_inputs_fired_d1 & std_logic_vector(to_unsigned(0,s_var(0)'length-g_NUM_TRIG_INPUTS));
s_word0 <= s_evttype(0) & s_var(0) & std_logic_vector(s_coarse_timestamp);
s_word0 <= s_evttype(0) & s_var(0) & std_logic_vector(s_coarse_timestamp_d2);
s_word1 <= "000" & trigger_times_d1(0) & "000" & trigger_times_d1(1) &
"000" & trigger_times_d1(2) & "000" & trigger_times_d1(3) &
trigger_cnt_i;
-- Different number of trigger inputs require packing into s_word2 in
-- different ways.
-- Do this in a generate since g_NUM_TRIG_INPUTS is static and
......@@ -272,45 +276,6 @@ BEGIN
gen_word2: for v_trigInput in 4 to g_NUM_TRIG_INPUTS-1 generate
s_word2( (((11-v_trigInput)*8)+c_NUM_TIME_BITS-1) downto ((11-v_trigInput)*8) ) <= trigger_times_i(v_trigInput);
end generate;
-- N.B. This is VHDL-2008 syntax.
-- Would be easier to do this with a for ... generate loop, but I
-- didn't think of this in time....
-- gen_word2: case g_NUM_TRIG_INPUTS generate
-- when 5 =>
-- s_word2 <= "000" & trigger_times_i(4) & X"00000000000000";
-- when 6 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- X"000000000000";
-- when 7 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & X"0000000000";
-- when 8 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- X"00000000";
-- when 9 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & X"000000" ;
-- when 10 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
-- X"0000" ;
-- when 11 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
-- "000" & trigger_times_i(10)& X"00" ;
-- when 12 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
-- "000" & trigger_times_i(10)& "000" & trigger_times_i(11) ;
-- when others =>
-- s_word2 <= (others=>'0');
-- end generate;
--! Could also output data on trigger_i , but let's use the delayed signals. \n
......@@ -351,7 +316,7 @@ BEGIN
-------------------------------------------------------------------------------
gen_FIFO_i : for i in 1 to 3+g_NUM_EDGE_INPUTS-1 generate
s_FIFO_i(i) <= s_evttype(i) & s_var(i) & std_logic_vector(s_coarse_timestamp);
s_FIFO_i(i) <= s_evttype(i) & s_var(i) & std_logic_vector(s_coarse_timestamp_d2);
end generate gen_FIFO_i;
gen_FIFOs : for i in 0 to 3+g_NUM_EDGE_INPUTS-1 generate
......@@ -392,34 +357,7 @@ BEGIN
end loop;
end process;
-- s_FIFO_rd <= "0001" when s_FIFO_empty(0) = '0' else
-- "0010" when s_FIFO_empty(1) = '0' else
-- "0100" when s_FIFO_empty(2) = '0' else
-- "1000" when s_FIFO_empty(3) = '0' else
-- (others=>'0');
-- p_data_o: process (s_FIFO_rd_d)
-- begin -- process p_generate_strobes
-- s_data_o <= (others=>'0');
-- l_data_o: for i in 0 to 3+g_NUM_EDGE_INPUTS-1 loop
-- if s_FIFO_rd_d(i) = '1' then
-- s_data_o <= s_FIFO_o(i);
-- exit l_data_o;
-- end if;
-- end loop;
-- end process;
-- Decide which FIFO to take into account as function of the read status in the last clock cicle
-- p_FIFO_rd_d: process(s_FIFO_rd_d)
-- begin
-- s_data_o <= (others=>'0');
-- l_FIFO_rd_d: for i in 0 to 3+g_NUM_EDGE_INPUTS-1 loop
-- if s_FIFO_rd_d(i) = '1' then
-- s_data_o <= s_FIFO_o(i);
-- exit l_FIFO_rd_d;
-- end if;
-- end loop;
-- end process;
s_data_o <= s_FIFO_o(0) when s_FIFO_rd_d(0) = '1' else -- Write it in a more elegant style
s_FIFO_o(1) when s_FIFO_rd_d(1) = '1' else
s_FIFO_o(2) when s_FIFO_rd_d(2) = '1' else
......
......@@ -30,7 +30,7 @@
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
--! @todo <next thing to do> \n
--! @todo \n
--! <another thing to do> \n
--
--------------------------------------------------------------------------------
......@@ -49,14 +49,13 @@ ENTITY handshakes IS
g_IPBUS_WIDTH : positive := 32
);
PORT(
clk_4x_logic_i : IN std_logic;
DUT_clk_i : IN std_logic;
clk_i : IN std_logic;
Trigger_i : IN std_logic;
ipbus_clk_i : IN std_logic;
ipbus_i : IN ipb_wbus;
ipbus_reset_i : IN std_logic;
ipbus_o : OUT ipb_rbus;
logic_reset_i : IN std_logic; -- reset buffers when high. Synch withclk_4x_logic
logic_reset_i : IN std_logic;
Busy_i : IN std_logic;
Trigger_o : OUT std_logic;
rst_or_clk_o : OUT std_logic -- CONT in schematics
......@@ -70,17 +69,28 @@ END ENTITY handshakes ;
ARCHITECTURE rtl OF handshakes IS
signal s_handshakeEnabled : std_logic_vector(g_IPBUS_WIDTH-1 downto 0);
signal s_Trigger_o, s_Trigger, s_Shutter, s_T0sync, s_T0sync_o : std_logic;
signal TPx3_T0syncAut, TPx3_T0syncFlag : std_logic;
signal s_Shutter, s_T0sync : std_logic;
signal s_Trigger, s_TrigAux : std_logic := '0';
signal s_Busy, s_Busy_d1, s_Busy_d2, s_Busy_d3 : std_logic;
signal TPx3_T0syncTime, TPx3_ShDTime : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0); -- Result from counters
signal TPx3_T0syncLen : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := x"00000004"; --Load signal and flag for the start up dead time
signal TPx3_ShDTLen : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := x"00000010"; --Load signal and flag for the start up dead time
signal TPx3_T0syncLen : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := x"00000004"; --! T0-sync length
signal TPx3_Start_T0sync : std_logic; --! Flag to start the T0-sync signal
signal s_Veto : std_logic := '0';
signal s_WU : std_logic := '0';
signal s_NMaxPulses : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := (others=>'0');
signal s_SuDTime : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := (others=>'0');
signal s_PulseLen : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := x"00000001";
signal s_IpDTime : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := x"00000001";
signal s_RearmTime : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := x"10000000";
signal s_PulseDelay : std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0) := (others=>'0');
signal s_MaxPulses : std_logic;
signal s_pulse : std_logic;
constant c_N_CTRL : positive := 5;
constant c_N_STAT : positive := 6;
signal s_status_to_ipbus, s_sync_status_to_ipbus : ipb_reg_v(c_N_STAT-1 downto 0);
signal s_control_from_ipbus,s_sync_control_from_ipbus : ipb_reg_v(c_N_CTRL-1 downto 0);
constant c_N_CTRL : positive := 13;
constant c_N_STAT : positive := 13;
signal s_status_to_ipbus, s_sync_status_to_ipbus : ipb_reg_v(c_N_STAT-1 downto 0);
signal s_control_from_ipbus,s_sync_control_from_ipbus : ipb_reg_v(c_N_CTRL-1 downto 0);
BEGIN
......@@ -107,7 +117,7 @@ BEGIN
generic map (
g_NUM_REGISTERS => c_N_STAT )
port map (
clk_input_i => clk_4x_logic_i,
clk_input_i => clk_i,
data_i => s_status_to_ipbus,
data_o => s_sync_status_to_ipbus,
clk_output_i => ipbus_clk_i);
......@@ -120,70 +130,115 @@ BEGIN
clk_input_i => ipbus_clk_i,
data_i => s_control_from_ipbus,
data_o => s_sync_control_from_ipbus,
clk_output_i => clk_4x_logic_i);
clk_output_i => clk_i);
-----------------------------------------------------------------------------
-- Logic not ready to use
-----------------------------------------------------------------------------
--Map the control registers
s_handshakeEnabled <= s_sync_control_from_ipbus(0);
TPx3_T0syncAut <= s_sync_control_from_ipbus(1)(0);
TPx3_T0syncFlag <= s_sync_control_from_ipbus(1)(1);
TPx3_T0syncLen <= x"00000001" when s_sync_control_from_ipbus(2)<x"000000002" else
s_sync_control_from_ipbus(2);
TPx3_ShDTLen <= s_sync_control_from_ipbus(3);
s_status_to_ipbus(0) <= s_handshakeEnabled;
-- No handshake registers
s_NMaxPulses <= s_sync_control_from_ipbus(5);
s_SuDTime <= s_sync_control_from_ipbus(6);
s_PulseLen <= s_sync_control_from_ipbus(7);
s_IpDTime <= s_sync_control_from_ipbus(8);
s_RearmTime <= s_sync_control_from_ipbus(9);
s_PulseDelay <= s_sync_control_from_ipbus(10);
s_Veto <= s_sync_control_from_ipbus(11)(0);
s_WU <= s_sync_control_from_ipbus(11)(1);
s_status_to_ipbus(5) <= s_NMaxPulses;
s_status_to_ipbus(6) <= s_SuDTime;
s_status_to_ipbus(7) <= s_PulseLen;
s_status_to_ipbus(8) <= s_IpDTime;
s_status_to_ipbus(9) <= s_RearmTime;
s_status_to_ipbus(10) <= s_PulseDelay;
s_status_to_ipbus(11) <= x"0000000"& "00" & s_WU & s_Veto;
s_status_to_ipbus(12) <= x"0000000"& "000" & s_MaxPulses;
-- Map the status registers
s_status_to_ipbus(0) <= s_handshakeEnabled;
-- TPx3 registers
TPx3_Start_T0sync <= s_sync_control_from_ipbus(1)(0);
TPx3_T0syncLen <= x"00000001" when s_sync_control_from_ipbus(2)<x"000000002" else
s_sync_control_from_ipbus(2);
s_status_to_ipbus(1) <= x"0000000" & "00" & TPx3_T0syncFlag & TPx3_T0syncAut;
s_status_to_ipbus(2) <= TPx3_T0syncLen;
s_status_to_ipbus(3) <= TPx3_ShDTLen;
s_status_to_ipbus(1) <= x"0000000" & "000" & TPx3_Start_T0sync;
s_status_to_ipbus(2) <= TPx3_T0syncLen;
-----------------------------------------------------------------------------
-- Synchronization - Rewrite!!!
-----------------------------------------------------------------------------
p_trigger : process(Trigger_i, s_Trigger)
begin
if Trigger_i = '1' then
s_TrigAux <= '1';
elsif s_Trigger = '1' then
s_TrigAux <= '0';
end if;
end process p_trigger;
p_sync: process (clk_i )
begin -- process p_run_counter
if rising_edge(clk_i) then
s_Trigger <= s_TrigAux;
s_Busy_d1 <= Busy_i;
s_Busy_d2 <= s_Busy_d1;
s_Busy_d3 <= s_Busy_d2;
s_Busy <= s_Busy_d2;
end if;
end process p_sync;
-----------------------------------------------------------------------------
-- I/O
-----------------------------------------------------------------------------
Trigger_o <= s_Trigger_o;
s_Trigger <= Trigger_i when s_handshakeEnabled = x"00000000" else
Trigger_i when s_handshakeEnabled = x"00000001" and Busy_i='0' else
s_Shutter when s_handshakeEnabled = x"00000002" else
Trigger_o <= s_Trigger when s_handshakeEnabled = x"00000000" and s_Busy = '0' else
s_pulse when s_handshakeEnabled = x"00000001" else -- No handshake
s_Shutter when s_handshakeEnabled = x"00000002" else -- TPx3 handshake
'0';
rst_or_clk_o <= s_T0sync_o when s_handshakeEnabled = x"00000002" else
rst_or_clk_o <= s_T0sync when s_handshakeEnabled = x"00000002" else
'0';
-- Single Handshake (GPP)
-- No Handshake (GPP)
No_handshake: entity work.GPP
GENERIC MAP(
g_IPBUS_WIDTH => g_IPBUS_WIDTH)
PORT MAP(
clk_i => clk_i,
Enable_i => not (s_Busy or s_Veto),
Reset_i => logic_reset_i,
RstPulsCnt_i => '0',
Trigger_i => s_Trigger,
NMaxPulses_i => s_NMaxPulses,
SuDTime_i => s_SuDTime,
PulsLen_i => s_PulseLen,
IpDTime_i => s_IpDTime,
RearmTime_i => s_RearmTime,
Force_PullDown_i => s_Busy or s_Veto,
WU_i => s_WU,
PulseDelay_i => s_PulseDelay,
event_number_o => open,
MaxPulses_o => open, --s_MaxPulses,
Pulse_o => s_pulse,
Pulse_d_o => open);
-- TPx3 Handshake
TPx3_logic: entity work.TPx3Logic
PORT MAP(
clk_i => clk_4x_logic_i,
T0syncAut_i => TPx3_T0syncAut,
T0syncFlag_i => TPx3_T0syncFlag,
clk_i => clk_i,
Start_T0sync_i => TPx3_Start_T0sync,
T0syncLen_i => TPx3_T0syncLen,
ShDTLen_i => TPx3_ShDTLen,
logic_reset_i => logic_reset_i,
Busy_i => Busy_i,
Busy_i => s_Busy,
Veto_i => s_Veto,
Shutter_o => s_Shutter,
T0sync_o => s_T0sync
);
-----------------------------------------------------------------------------
-- Synchronizing signals
-----------------------------------------------------------------------------
SyncDUTTrig : entity work.pulseClockDomainCrossing
port map(
clk_input_i => clk_4x_logic_i, --! clock for input
pulse_i => s_Trigger, --! input pulse. Active high
clk_output_i => DUT_clk_i, --! clock for output
pulse_o => s_Trigger_o); --! Single cycle pulse synchronized to clock_output_i
SyncDUTT0sync : entity work.pulseClockDomainCrossing
port map(
clk_input_i => clk_4x_logic_i, --! clock for input
pulse_i => s_T0sync, --! input pulse. Active high
clk_output_i => DUT_clk_i, --! clock for output
pulse_o => s_T0sync_o); --! Single cycle pulse synchronized to clock_output_i
END ARCHITECTURE rtl;
......@@ -133,8 +133,11 @@ ARCHITECTURE rtl OF logic_clocks IS
signal s_clock_status_ipb : std_logic_vector( ipbus_o.ipb_rdata'range ); --! Hold status of clocks
BEGIN
-----------------------------------------------------------------------------
-- Simulation!!!
-----------------------------------------------------------------------------
--s_clk_is_xtal <= '1';
-----------------------------------------------------------------------------
-- IPBus write
-----------------------------------------------------------------------------
......@@ -286,13 +289,13 @@ BEGIN
DIVCLK_DIVIDE => 1,
CLKFBOUT_MULT => 16,
CLKFBOUT_PHASE => 0.000,
CLKOUT0_DIVIDE => 2, -- 1-->2 move from 640 to 320
CLKOUT0_DIVIDE => 1, -- 1-->2 move from 640 to 320
CLKOUT0_PHASE => 0.000,
CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT1_DIVIDE => 8, -- 4-->8 move from 160 to 80
CLKOUT1_DIVIDE => 4, -- 4-->8 move from 160 to 80
CLKOUT1_PHASE => 0.000,
CLKOUT1_DUTY_CYCLE => 0.500,
CLKOUT2_DIVIDE => 32, -- 16--> 32 move from 40 to 20
CLKOUT2_DIVIDE => 16, -- 16--> 32 move from 40 to 20
CLKOUT2_PHASE => 0.000,
CLKOUT2_DUTY_CYCLE => 0.500,
CLKIN_PERIOD => 25.000,
......@@ -343,7 +346,7 @@ BEGIN
-- Can't use a clock signal as a combinatorial signal. Hence the baroque
-- method of generating a strobe. Add a mechanism to restart if the '1' gets
-- lost ....
generate_4x_strobe: process (s_clk160 , s_clk40_out)
generate_4x_strobe: process (s_clk160)-- , s_clk40_out)
begin -- process generate_4x_strobe
if rising_edge(s_clk160) then
if s_logic_reset = '1' then
......
......@@ -84,6 +84,7 @@ use work.ipbus_reg_types.all;
USE work.fmcTLU.all;
library unisim ;
use unisim.vcomponents.all;
......@@ -94,14 +95,15 @@ ENTITY triggerInputs IS
);
PORT(
cfd_discr_p_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0);--! Inputs from constant-fraction discriminators
cfd_discr_n_i : IN std_logic_vector (g_NUM_INPUTS-1 downto 0);--! Input from CFD
cfd_discr_n_i : IN std_logic_vector (g_NUM_INPUTS-1 downto 0);--! Input from CFD
clk_4x_logic : IN std_logic; --! Rising edge active. By default = 4*40MHz = 160MHz
strobe_4x_logic_i : IN std_logic; --! Pulses high once every 4 cycles of clk_4x_logic
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
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
threshold_discr_n_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
reset_i : IN std_logic;
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
edge_rising_times_o : OUT t_triggerTimeArray (g_NUM_INPUTS-1 DOWNTO 0); --! edge arrival time ( w.r.t. logic_strobe)
edge_falling_times_o : OUT t_triggerTimeArray (g_NUM_INPUTS-1 DOWNTO 0); --! edge arrival time ( w.r.t. logic_strobe)
edge_rising_o : OUT std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! High when rising edge. Syncronous with clk_4x_logic_i
......@@ -126,7 +128,7 @@ ARCHITECTURE rtl OF triggerInputs IS
signal s_threshold_discr_input , s_cfd_discr_input : std_logic_vector(g_NUM_INPUTS-1 downto 0); --! inputs from comparator
type t_deserialized_trigger_data_array is array ( natural range <> ) of std_logic_vector(7 downto 0); --
signal s_deserialized_threshold_data , s_deserialized_cfd_data : t_deserialized_trigger_data_array(g_NUM_INPUTS-1 downto 0);
signal s_deserialized_threshold_data, s_deserialized_threshold_data_d , s_deserialized_cfd_data, s_deserialized_cfd_data_d : t_deserialized_trigger_data_array(g_NUM_INPUTS-1 downto 0);
type t_deserialized_trigger_data_array_l is array ( natural range <> ) of std_logic_vector(8 downto 0); --
signal s_deserialized_threshold_data_l , s_deserialized_cfd_data_l : t_deserialized_trigger_data_array_l(g_NUM_INPUTS-1 downto 0);
......@@ -154,7 +156,6 @@ ARCHITECTURE rtl OF triggerInputs IS
signal s_counter_reset, s_calibrate_idelay: std_logic := '0';
BEGIN
-----------------------------------------------------------------------------
-- IPBus interface
-----------------------------------------------------------------------------
......@@ -196,9 +197,9 @@ BEGIN
-- Map the control registers...
-- Register that controls IODELAY and ISERDES reset is at address 0
s_rst_iserdes <= s_sync_control_from_ipbus(0)(0);
s_rst_iserdes <= reset_i or s_sync_control_from_ipbus(0)(0);
s_counter_reset <= s_sync_control_from_ipbus(0)(1);
s_calibrate_idelay <= s_sync_control_from_ipbus(0)(2);
--s_calibrate_idelay <= s_sync_control_from_ipbus(0)(2);
s_status_to_ipbus(0)(0) <= s_rst_iserdes;
s_status_to_ipbus(0)(1) <= s_counter_reset;
s_status_to_ipbus(0)(2) <= s_calibrate_idelay;
......@@ -226,8 +227,8 @@ BEGIN
thresholdDeserializer: entity work.dualSERDES_1to4
port map (
reset_i => s_rst_iserdes,
calibrate_i => s_calibrate_idelay,
reset_i => s_rst_iserdes,
calibrate_i => s_calibrate_idelay,
data_i => s_threshold_discr_input(triggerInput),
fastClk_i => clk_16x_logic_i,
fabricClk_i => clk_4x_logic,
......@@ -235,8 +236,9 @@ BEGIN
data_o => s_deserialized_threshold_data(triggerInput),
status_o => s_status_to_ipbus(0)(5+(2*triggerInput) downto 4+(2*triggerInput))
);
s_deserialized_threshold_data_l(triggerInput) <= s_deserialized_threshold_data(triggerInput) & s_threshold_previous_late_bit(triggerInput);
s_deserialized_threshold_data_l(triggerInput) <= s_deserialized_threshold_data(triggerInput)(3 downto 0) & s_deserialized_threshold_data_d(triggerInput)(7 downto 3);
--s_deserialized_threshold_data_l(triggerInput) <= s_deserialized_threshold_data(triggerInput) & s_threshold_previous_late_bit(triggerInput);
thresholdLUT : entity work.arrivalTimeLUT
port map (
clk_4x_logic_i => clk_4x_logic,
......@@ -301,7 +303,8 @@ BEGIN
p_register_delayed_bits : process ( clk_4x_logic )
begin
if rising_edge(clk_4x_logic) then
s_threshold_previous_late_bit(triggerInput) <= s_deserialized_threshold_data(triggerInput)(7);
--s_threshold_previous_late_bit(triggerInput) <= s_deserialized_threshold_data(triggerInput)(7);
s_deserialized_threshold_data_d(triggerInput) <= s_deserialized_threshold_data(triggerInput);
s_CFD_previous_late_bit(triggerInput) <= s_deserialized_CFD_data(triggerInput)(7);
-- Monitor output of serdes - just look at one per serdes
......@@ -326,11 +329,12 @@ BEGIN
end generate trigger_input_loop;
trigger_debug_o( (g_NUM_INPUTS-1) downto 0) <= s_threshold_discr_input;
--trigger_debug_o( ((2*g_NUM_INPUTS)-1) downto g_NUM_INPUTS) <= s_CFD_discr_input;
--trigger_debug_o( ((2*g_NUM_INPUTS)-1) downto g_NUM_INPUTS) <= s_edge_rising;
--! Monitor output of deserializer
-- trigger_debug_o( ((2*g_NUM_INPUTS)-1) downto g_NUM_INPUTS) <= s_status_to_ipbus(0)(23 downto 20);
--trigger_debug_o( (g_NUM_INPUTS-1) downto 0) <= s_edge_rising;
trigger_debug_o( (g_NUM_INPUTS-1) downto 0) <= s_threshold_discr_input;
trigger_debug_o( ((2*g_NUM_INPUTS)-1) downto g_NUM_INPUTS) <= s_edge_rising;
END ARCHITECTURE rtl;
......
......@@ -81,13 +81,13 @@ END ENTITY triggerLogic ;
ARCHITECTURE rtl OF triggerLogic IS
--! vector that stores trigger output for each combination of trigger inputs.
signal s_trigger_pattern , s_trigger_pattern_ipb : std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := (others=>'1');
signal s_trigger_pattern , s_trigger_pattern_ipb : std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := x"00000001";--(others=>'1');
signal s_external_trigger , s_internal_veto , s_internal_veto_ipb : std_logic := '0';
signal s_internal_trigger_interval: std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- setting s_internal_trigger_interval to zero means no internal triggers
signal s_pre_veto_trigger_counter , s_post_veto_trigger_counter : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- ! counters for triggers before and after veto
signal s_pre_veto_trigger_counter_ipb , s_post_veto_trigger_counter_ipb : std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- ! counters for triggers before and after veto, on ipbus clock domain
signal s_internal_trigger : std_logic := '0'; -- ! Strobes high for one clock cycle at intervals of s_internal_trigger_interval cycles
signal s_internal_trigger, s_internal_trigger_d : std_logic := '0'; -- ! Strobes high for one clock cycle at intervals of s_internal_trigger_interval cycles
-- signal s_internal_trigger_timer : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- counter for internal trigger generation
signal s_internal_trigger_timer , s_internal_trigger_timer_d : std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- counter for internal trigger generation and counter delay
signal s_internal_trigger_active , s_internal_trigger_active_d, s_internal_trigger_active_ipb : std_logic := '0'; -- ! Goes high when internal trigger is running.
......@@ -104,7 +104,6 @@ ARCHITECTURE rtl OF triggerLogic IS
signal s_external_veto_word : std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := (others => '0');
BEGIN
-----------------------------------------------------------------------------
-- IPBus interface
-----------------------------------------------------------------------------
......@@ -197,7 +196,8 @@ BEGIN
s_internal_trigger <= '1' when (s_internal_trigger_timer = ( x"00000000" )) and (s_internal_trigger_timer_d = ( x"00000001" ))
else '0';
-- Use a coregen counter to allow timing constraints to be met.
c_internal_triggers: entity work.internalTriggerGenerator
PORT MAP (
......
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