--======================================================================================= -- TITLE : Trigger generator -- DESCRIPTION : Generates triggers from events, calibration pulses or external inputs -- FILE : trigger_generator.vhd -- COMPANY : Micro-Cameras & Space Exploration SA --======================================================================================= -- CREATION -- DATE AUTHOR PROJECT REVISION -- 14/03/2011 JGi 110314a --======================================================================================= -- MODIFICATION HISTORY -- DATE AUTHOR PROJECT REVISION COMMENTS -- 14/03/2011 JGi 110314a Description -- 13/04/2011 JGi 110413a Update trigger enable management -- 15/04/2011 JGi 110415a Update LP1 "N-out-of-40" logic detection -- in order to allow user to reset it by -- disabling LP1 pulse as trigger source if the -- N is never reached and system is locked --======================================================================================= -- Library Definition library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library ftm_definitions; use ftm_definitions.ftm_array_types.all; use ftm_definitions.ftm_constants.all; -- Entity Definition entity trigger_generator is port( --clock clk_250MHz : in std_logic; --config inputs start_run : in std_logic; stop_run : in std_logic; general_settings : in std_logic_vector(7 downto 0); maj_coinc_n_phys : in std_logic_vector(5 downto 0); maj_coinc_n_calib : in std_logic_vector(5 downto 0); trigger_delay : in std_logic_vector(9 downto 0); TIM_delay : in std_logic_vector(9 downto 0); dead_time : in std_logic_vector(15 downto 0); --trigger inputs ext_trig_1 : in std_logic; ext_trig_2 : in std_logic; ext_veto : in std_logic; FAD_busy_0 : in std_logic; FAD_busy_1 : in std_logic; FAD_busy_2 : in std_logic; FAD_busy_3 : in std_logic; phys_events : in std_logic_vector(5 downto 0); calib_events : in std_logic_vector(5 downto 0); LP1_pulse : in std_logic; LP2_pulse : in std_logic; PED_pulse : in std_logic; --outputs trigger_ID_done : out std_logic; trigger_ID : out std_logic_vector(55 downto 0); trigger_active : out std_logic; trigger_signal : out std_logic; TIM_signal : out std_logic); end trigger_generator; -- Architecture Definition architecture RTL of trigger_generator is component deadtime_generator is port( clk_250MHz : in std_logic; deadtime : in std_logic_vector(15 downto 0); start : in std_logic; waiting : out std_logic); end component; signal i_deadtime : std_logic; component delayed_pulse is generic( pulse_width : integer range 0 to 15); port( clk_250MHz : in std_logic; delay : in std_logic_vector(9 downto 0); input : in std_logic; output : out std_logic); end component; signal i_trigger_signal : std_logic; signal i_TIM_signal : std_logic; component trigger_ID_count is port( clk_250MHz : in std_logic; start_run : in std_logic; stop_run : in std_logic; maj_coinc_n_phys : in std_logic_vector(5 downto 0); maj_coinc_n_calib : in std_logic_vector(5 downto 0); trigger : in std_logic_vector(8 downto 0); phys_trigger : in std_logic; calib_trigger : in std_logic; internal_trigger : in std_logic_vector(1 downto 0); external_trigger : in std_logic_vector(1 downto 0); trigger_ID_done : out std_logic; trigger_ID : out std_logic_vector(55 downto 0)); end component; type t_reg is record -- Internal register declaration start_run : std_logic; LP1_delay : std_logic_vector(2 downto 0); LP2_delay : std_logic_vector(2 downto 0); PED_delay : std_logic_vector(2 downto 0); ext_trig_1 : std_logic_vector(2 downto 0); ext_trig_2 : std_logic_vector(2 downto 0); ext_veto : std_logic_vector(1 downto 0); FAD_busy_0 : std_logic_vector(1 downto 0); FAD_busy_1 : std_logic_vector(1 downto 0); FAD_busy_2 : std_logic_vector(1 downto 0); FAD_busy_3 : std_logic_vector(1 downto 0); general_settings : std_logic_vector(7 downto 0); maj_coinc_n_phys : std_logic_vector(5 downto 0); maj_coinc_n_calib : std_logic_vector(5 downto 0); enable_trigger : std_logic; phys_compare : std_logic_vector(1 downto 0); phys_trigger : std_logic; ext_trigger : std_logic_vector(1 downto 0); calib_compare : std_logic_vector(1 downto 0); calib_trigger : std_logic; wait_for_calib : std_logic; internal_trigger : std_logic_vector(1 downto 0); trigger : std_logic_vector(12 downto 0); trigger_active : std_logic; -- Ouput register declaration end record; signal i_next_reg : t_reg := (start_run => '0', LP1_delay => (others => '0'), LP2_delay => (others => '0'), PED_delay => (others => '0'), ext_trig_1 => (others => '0'), ext_trig_2 => (others => '0'), ext_veto => (others => '0'), FAD_busy_0 => (others => '0'), FAD_busy_1 => (others => '0'), FAD_busy_2 => (others => '0'), FAD_busy_3 => (others => '0'), general_settings => (others => '0'), maj_coinc_n_phys => (others => '1'), maj_coinc_n_calib => (others => '1'), enable_trigger => '0', phys_compare => (others => '0'), phys_trigger => '0', ext_trigger => (others => '0'), calib_compare => (others => '0'), calib_trigger => '0', wait_for_calib => '0', internal_trigger => (others => '0'), trigger => (others => '0'), trigger_active => '1'); signal i_reg : t_reg := (start_run => '0', LP1_delay => (others => '0'), LP2_delay => (others => '0'), PED_delay => (others => '0'), ext_trig_1 => (others => '0'), ext_trig_2 => (others => '0'), ext_veto => (others => '0'), FAD_busy_0 => (others => '0'), FAD_busy_1 => (others => '0'), FAD_busy_2 => (others => '0'), FAD_busy_3 => (others => '0'), general_settings => (others => '0'), maj_coinc_n_phys => (others => '1'), maj_coinc_n_calib => (others => '1'), enable_trigger => '0', phys_compare => (others => '0'), phys_trigger => '0', ext_trigger => (others => '0'), calib_compare => (others => '0'), calib_trigger => '0', wait_for_calib => '0', internal_trigger => (others => '0'), trigger => (others => '0'), trigger_active => '1'); begin -- Component instantiation inst_deadtime: deadtime_generator port map( clk_250MHz => clk_250MHz, deadtime => dead_time, start => i_reg.trigger(0), waiting => i_deadtime); inst_phys_trig: delayed_pulse generic map( pulse_width => TRIG_SIGNAL_PULSE_WIDTH) port map( clk_250MHz => clk_250MHz, delay => trigger_delay, input => i_reg.trigger(1), output => i_trigger_signal); trigger_signal <= i_trigger_signal and i_reg.start_run; inst_phys_TIM: delayed_pulse generic map( pulse_width => TIM_SIGNAL_PULSE_WIDTH) port map( clk_250MHz => clk_250MHz, delay => TIM_delay, input => i_reg.trigger(2), output => i_TIM_signal); TIM_signal <= i_TIM_signal and i_reg.start_run; inst_trig_ID: trigger_ID_count port map( clk_250MHz => clk_250MHz, start_run => start_run, stop_run => stop_run, maj_coinc_n_phys => maj_coinc_n_phys, maj_coinc_n_calib => maj_coinc_n_calib, trigger => i_reg.trigger(12 downto 4), phys_trigger => i_reg.phys_trigger, calib_trigger => i_reg.calib_trigger, internal_trigger => i_reg.internal_trigger, external_trigger => i_reg.ext_trigger, trigger_ID_done => trigger_ID_done, trigger_ID => trigger_ID); -- Combinatorial logic process(start_run, general_settings, maj_coinc_n_phys, maj_coinc_n_calib, ext_trig_1, ext_trig_2, ext_veto, FAD_busy_0, FAD_busy_1, FAD_busy_2, FAD_busy_3, phys_events, calib_events, LP1_pulse, LP2_pulse, PED_pulse, i_deadtime, i_reg) variable v_reg : t_reg := (start_run => '0', LP1_delay => (others => '0'), LP2_delay => (others => '0'), PED_delay => (others => '0'), ext_trig_1 => (others => '0'), ext_trig_2 => (others => '0'), ext_veto => (others => '0'), FAD_busy_0 => (others => '0'), FAD_busy_1 => (others => '0'), FAD_busy_2 => (others => '0'), FAD_busy_3 => (others => '0'), general_settings => (others => '0'), maj_coinc_n_phys => (others => '1'), maj_coinc_n_calib => (others => '1'), enable_trigger => '0', phys_compare => (others => '0'), phys_trigger => '0', ext_trigger => (others => '0'), calib_compare => (others => '0'), calib_trigger => '0', wait_for_calib => '0', internal_trigger => (others => '0'), trigger => (others => '0'), trigger_active => '1'); begin v_reg := i_reg; --=================================================================================== --=================================================================================== -- External inputs double-sync --=================================================================================== v_reg.ext_trig_1(0) := ext_trig_1; v_reg.ext_trig_1(1) := i_reg.ext_trig_1(0); v_reg.ext_trig_1(2) := i_reg.ext_trig_1(1); v_reg.ext_trig_2(0) := ext_trig_2; v_reg.ext_trig_2(1) := i_reg.ext_trig_2(0); v_reg.ext_trig_2(2) := i_reg.ext_trig_2(1); v_reg.ext_veto(0) := ext_veto; v_reg.ext_veto(1) := i_reg.ext_veto(0); v_reg.FAD_busy_0(0) := FAD_busy_0; v_reg.FAD_busy_0(1) := i_reg.FAD_busy_0(0); v_reg.FAD_busy_1(0) := FAD_busy_1; v_reg.FAD_busy_1(1) := i_reg.FAD_busy_1(0); v_reg.FAD_busy_2(0) := FAD_busy_2; v_reg.FAD_busy_2(1) := i_reg.FAD_busy_2(0); v_reg.FAD_busy_3(0) := FAD_busy_3; v_reg.FAD_busy_3(1) := i_reg.FAD_busy_3(0); --=================================================================================== --=================================================================================== -- Re-sync of calibration and pedestal triggers to the 250MHz clock --=================================================================================== v_reg.LP1_delay(0) := LP1_pulse; v_reg.LP1_delay(1) := i_reg.LP1_delay(0); v_reg.LP1_delay(2) := i_reg.LP1_delay(1); v_reg.LP2_delay(0) := LP2_pulse; v_reg.LP2_delay(1) := i_reg.LP2_delay(0); v_reg.LP2_delay(2) := i_reg.LP2_delay(1); v_reg.PED_delay(0) := PED_pulse; v_reg.PED_delay(1) := i_reg.PED_delay(0); v_reg.PED_delay(2) := i_reg.PED_delay(1); --=================================================================================== --=================================================================================== -- Settings registration --=================================================================================== v_reg.general_settings := general_settings; v_reg.maj_coinc_n_phys := maj_coinc_n_phys; v_reg.maj_coinc_n_calib := maj_coinc_n_calib; --=================================================================================== --=================================================================================== -- Master enable management --=================================================================================== v_reg.start_run := start_run; --=================================================================================== --=================================================================================== -- Trigger generation --=================================================================================== -- Enable trigger generation only if veto is not active, FAD are not busy and -- deadtime is not enabled if i_reg.trigger(3) = '1' or i_deadtime = '1' or (i_reg.ext_veto(1) = '1' and i_reg.general_settings(1) = '1') or i_reg.FAD_busy_0(1) = '1' or i_reg.FAD_busy_1(1) = '1' or i_reg.FAD_busy_2(1) = '1' or i_reg.FAD_busy_3(1) = '1' then v_reg.enable_trigger := '0'; else v_reg.enable_trigger := '1'; end if; -- Compare number of detected physics event to the physics threshold if phys_events >= i_reg.maj_coinc_n_phys then v_reg.phys_compare(0) := '1'; else v_reg.phys_compare(0) := '0'; end if; v_reg.phys_compare(1) := i_reg.phys_compare(0); -- Activate physics trigger when enabled by settings and physics threhsold is reached if i_reg.general_settings(7) = '1' and i_reg.wait_for_calib = '0' and i_reg.phys_compare(0) = '1' and i_reg.phys_compare(1) = '0' and i_reg.enable_trigger = '1' then v_reg.phys_trigger := '1'; else v_reg.phys_trigger := '0'; end if; -- Lock trigger generator when a pulse on LP1 is detected and wait for FTU events -- counter reach the calibration threshold if i_reg.LP1_delay(1) = '1' and i_reg.LP1_delay(2) = '0' and general_settings(4) = '1' then v_reg.wait_for_calib := '1'; -- If trigger is processed or disabled by user, reset detection logic to avoid -- remaining in locked state elsif i_reg.enable_trigger = '0' or general_settings(4) = '0' then v_reg.wait_for_calib := '0'; end if; -- Compare number of detected physics event to the calibration threshold if calib_events >= i_reg.maj_coinc_n_calib then v_reg.calib_compare(0) := '1'; else v_reg.calib_compare(0) := '0'; end if; v_reg.calib_compare(1) := i_reg.calib_compare(0); -- Activate calibration trigger when enabled by settings and -- calibration threhsold is reached if i_reg.general_settings(4) = '1' and i_reg.wait_for_calib = '1' and i_reg.calib_compare(0) = '1' and i_reg.calib_compare(1) = '0' and i_reg.enable_trigger = '1' then v_reg.calib_trigger := '1'; else v_reg.calib_trigger := '0'; end if; -- Activate trigger number 1 from external NIM inputs if i_reg.ext_trig_1(1) = '1' and i_reg.ext_trig_1(2) = '0' and i_reg.general_settings(2) = '1' and i_reg.wait_for_calib = '0' and i_reg.enable_trigger = '1' then v_reg.ext_trigger(0) := '1'; else v_reg.ext_trigger(0) := '0'; end if; -- Activate trigger number 2 from external NIM inputs if i_reg.ext_trig_2(1) = '1' and i_reg.ext_trig_2(2) = '0' and i_reg.general_settings(3) = '1' and i_reg.wait_for_calib = '0' and i_reg.enable_trigger = '1' then v_reg.ext_trigger(1) := '1'; else v_reg.ext_trigger(1) := '0'; end if; -- Activate calibration trigger from LP2 pulse if i_reg.LP2_delay(1) = '1' and i_reg.LP2_delay(2) = '0' and i_reg.general_settings(5) = '1' and i_reg.wait_for_calib = '0' and i_reg.enable_trigger = '1' then v_reg.internal_trigger(0) := '1'; else v_reg.internal_trigger(0) := '0'; end if; -- Activate calibration trigger from Pedestal signal if i_reg.PED_delay(1) = '1' and i_reg.PED_delay(2) = '0' and i_reg.general_settings(6) = '1' and i_reg.wait_for_calib = '0' and i_reg.enable_trigger = '1' then v_reg.internal_trigger(1) := '1'; else v_reg.internal_trigger(1) := '0'; end if; -- Generate master trigger for deadtime, trigger and TIM signals, -- triggers counting and ID generation -- It is replicated to limit fanout and improve speed v_reg.trigger(0) := i_reg.phys_trigger or i_reg.calib_trigger or i_reg.ext_trigger(0) or i_reg.ext_trigger(1) or i_reg.internal_trigger(0) or i_reg.internal_trigger(1); v_reg.trigger(1) := v_reg.trigger(0); v_reg.trigger(2) := v_reg.trigger(0); v_reg.trigger(3) := v_reg.trigger(0); v_reg.trigger(4) := v_reg.trigger(0); v_reg.trigger(5) := v_reg.trigger(0); v_reg.trigger(6) := v_reg.trigger(0); v_reg.trigger(7) := v_reg.trigger(0); v_reg.trigger(8) := v_reg.trigger(0); v_reg.trigger(9) := v_reg.trigger(0); v_reg.trigger(10) := v_reg.trigger(0); v_reg.trigger(11) := v_reg.trigger(0); v_reg.trigger(12) := v_reg.trigger(0); -- Manage trigger active signal -- Set low when a trigger is processed or FAD are busy or veto is active v_reg.trigger_active := i_reg.enable_trigger and not(i_reg.wait_for_calib); --=================================================================================== --=================================================================================== -- Drive register input i_next_reg <= v_reg; --=================================================================================== -- Output assignation trigger_active <= i_reg.trigger_active; --=================================================================================== end process; -- Sequential logic process(clk_250MHz) begin if rising_edge(clk_250MHz) then i_reg <= i_next_reg; end if; end process; end RTL;