------------------------------------------------------------------------------- -- Attilio Tarantola -- Create Date: 18/11/2007 -- Description: When I receive a trigger this entity distribute it to all bus/buses, wait -- for the token back. -- -- 29/02/2008 I add the calibration states. When a calibration trigger is -- retrived, it sends the cal trigger to all buses, the CAL parameters are loaded -- and data is collected. The input A_RDO_IN is the AND between all buses -- This entity generates the token back for TRB. -- INIT_ALL_BUSES_OUT <= "1" normal trigger -- INIT_ALL_BUSES_OUT <= "B" begrun trigger -- INIT_ALL_BUSES_OUT <= "C" calibration trigger -- INIT_ALL_BUSES_OUT <= "0" idle -- -- 01/12/2008 I start adapting to the OEPB ------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; entity trigger_distributor is port( CLK : in std_logic; RESET : in std_logic; INTERNAL_RESET_IN : in std_logic; A_RDO_IN : in std_logic; TRIGGER_IN : in std_logic; TRIGGER_TYPE_IN : in std_logic; INIT_ALL_BUSES_OUT : out std_logic_vector(3 downto 0); ROC1_WRITTEN_IN : in std_logic; TOKEN_TO_TRB_OUT : out std_logic; CAL_TRIGGER_REGISTER_IN : in std_logic_vector(15 downto 0); DEBUG_REGISTER_OUT : out std_logic_vector(31 downto 0); LED_CNT_1_OUT : out std_logic; LED_CNT_2_OUT : out std_logic; LED_ERROR_OUT : out std_logic; LED_GOOD_OUT : out std_logic); end trigger_distributor; architecture behavioral of trigger_distributor is constant WAIT_AFTER_ROC1_IS_LOADED : std_logic_vector(12 downto 0) := "0011111010000"; type state_type is (idle_state, normal_trigger_state, begrun_trigger_state, wait_roc1_written, wait_token_back_state, roc1_written_state, send_token_state, --calibration state calibration_state, wait_cal1_written); ~ signal current_state, next_state : state_type; signal reset_calibration_counter : std_logic; signal reg_init_all_buses, next_init_all_buses : std_logic_vector(3 downto 0); signal reg_token_to_trb, next_token_to_trb : std_logic; signal counter_number_of_trigger : std_logic_vector(11 downto 0); signal up_number_of_trigger : std_logic; signal register_trigger_condition : std_logic_vector(15 downto 0); signal internal_calibration_trigger : std_logic; signal reg_trigger_type_in, reg_trigger_in : std_logic; signal reg_debug_register, next_debug_register : std_logic_vector(3 downto 0); signal debug_normal_trigger_number, debug_calibration_trigger_number : std_logic_vector(7 downto 0); signal debug_token_back_number : std_logic_vector(7 downto 0); signal pulse_a_rdo_in : std_logic; signal pulse_begin_run_trigger : std_logic; signal not_reset : std_logic; signal counter_wait_after_roc1 : std_logic_vector(12 downto 0); ------------------------------------------------------------------------------- -- I use this exeption for naming signal(they should be lower case in general). In this case -- capital letters with "reg" or "next" at the beginning. ------------------------------------------------------------------------------- signal reg_LED_CNT_1_OUT, reg_LED_CNT_2_OUT : std_logic; signal reg_LED_ERROR_OUT, reg_LED_GOOD_OUT : std_logic; signal next_LED_CNT_1_OUT, next_LED_CNT_2_OUT : std_logic; signal next_LED_ERROR_OUT, next_LED_GOOD_OUT : std_logic; component edge_to_pulse port ( CLOCK : in std_logic; ENABLE_CLK_IN : in std_logic; SIGNAL_IN : in std_logic; PILSE_OUT : out std_logic); end component; begin -- behavioral ------------------------------------------------------------------------------- -- it creates a pulse of 10ns from the input signal. -- A_RDO_IN is the token back. ------------------------------------------------------------------------------- A_RDO_PULSE : edge_to_pulse port map ( CLOCK => CLK, ENABLE_CLOCK_IN => '1', SIGNAL_IN => A_RDO_IN, PULSE_OUT => pulse_a_rdo_in); ------------------------------------------------------------------------------- -- it creates a pulse of 10ns from the input signal. -- After the the firmware is loaded in the FPGA, the begin run trigger is -- generated automatically and the FEE is initialized. ------------------------------------------------------------------------------- BEGIN_RUN_TRIGGER_FROM_RESET : edge_to_pulse port map ( CLOCK => CLK, ENABLE_CLOCK_IN => '1', SIGNAL_IN => not_reset, PULSE_OUT => pulse_begin_run_trigger); not_reset <= not(RESET); ------------------------------------------------------------------------------- -- Register and reset for the FSM -- Signals in the sensitivity list (CLK,RESET) are important for the simulation!! ------------------------------------------------------------------------------- REGISTER_ADDR_DATA_MODE : process (CLK,RESET) begin if (rising_edge(CLK)) then if RESET = '1' then current_state <= idle_state; reg_token_to_trb <= '0'; reg_init_all_buses <= (others => '0'); reg_debug_register <= (others => '0'); reg_LED_CNT_1_OUT <= '0'; reg_LED_CNT_2_OUT <= '0'; reg_LED_ERROR_OUT <= '0'; reg_LED_GOOD_OUT <= '0'; else current_state <= next_state; reg_token_to_trb <= next_token_to_trb; reg_init_all_buses <= next_init_all_buses; reg_debug_register <= next_debug_register; reg_LED_CNT_1_OUT <= next_LED_CNT_1_OUT; reg_LED_CNT_2_OUT <= next_LED_CNT_2_OUT reg_LED_ERROR_OUT <= next_LED_ERROR_OUT reg_LED_GOOD_OUT <= next_LED_GOOD_OUT end if; end if; end process REGISTER_ADDR_DATA_MODE; ------------------------------------------------------------------------------- -- Connections to OUTPUT ports ------------------------------------------------------------------------------- TOKEN_TO_TRB_OUT <= reg_token_to_trb; INIT_ALL_BUSES_OUT <= reg_init_all_buses; DEBUG_REGISTER_OUT <= x"0000000"& reg_debug_register; LED_CNT_1_OUT <= reg_LED_CNT_1_OUT; LED_CNT_2_OUT <= reg_LED_CNT_2_OUT; LED_ERROR_OUT <= reg_LED_ERROR_OUT; LED_GOOD_OUT <= reg_LED_GOOD_OUT; ------------------------------------------------------------------------------- -- FSM: combinatorial part. It takes input trigger and distributes to other -- entities. It sends calibration trigger. -- Take care not to use inferred latches, most likely you don't want that!! -- Check the .srr report! Also here signals in the sensitivity list are -- important for simulation ------------------------------------------------------------------------------- process (current_state, internal_calibration_trigger, reg_trigger_type_in, reg_trigger_in, ROC1_WRITTEN_IN, A_RDO_IN, pulse_begin_run_trigger, counter_wait_after_roc1) begin next_debug_register <= (others => '0'); next_init_all_buses <= (others => '0'); next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '0'; next_LED_CNT_1 <= '1'; --'1' is off, '0' is on next_LED_CNT_2 <= '1'; next_LED_ERROR <= '1'; next_LED_GOOD <= '1'; case current_state is when idle_state => next_debug_register <= x"1"; next_LED_CNT_1 <= '1'; next_LED_CNT_2 <= '1'; next_LED_ERROR <= '1'; next_LED_GOOD <= '1'; next_init_all_buses <= (others => '0'); next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '0'; if pulse_begin_run_trigger = '1' then next_state <= begrun_trigger_state; -- elsif ( (reg_trigger_type_in = '1') and (reg_trigger_in = '1') ) then -- if (internal_calibration_trigger = '1') then -- next_state <= calibration_state; -- else -- next_state <= normal_trigger_state; -- end if; else next_state <= idle_state; end if; ------------------------------------------------------------------------------- --NORMAL TRIGGER ------------------------------------------------------------------------------- when normal_trigger_state => next_debug_register <= x"2"; next_LED_CNT_1 <= '0'; next_LED_CNT_2 <= '1'; next_LED_ERROR <= '1'; next_LED_GOOD <= '1'; next_init_all_buses <= X"1"; next_token_to_trb <= '0'; up_number_of_trigger <= '1'; reset_calibration_counter <= '0'; next_state <= wait_token_back_state; when wait_token_back_state => next_debug_register <= x"3"; next_LED_CNT_1 <= '1'; next_LED_CNT_2 <= '0'; next_LED_ERROR <= '1'; next_LED_GOOD <= '1'; next_init_all_buses <= X"0"; next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '0'; if A_RDO_IN = '1' then next_state <= send_token_state; else next_state <= wait_token_back_state; end if; when send_token_state => next_debug_register <= x"4"; next_LED_CNT_1 <= '0'; next_LED_CNT_2 <= '0'; next_LED_ERROR <= '1'; next_LED_GOOD <= '1'; next_init_all_buses <= X"0"; next_token_to_trb <= '1'; up_number_of_trigger <= '0'; reset_calibration_counter <= '0'; next_state <= normal_trigger_state; ------------------------------------------------------------------------------- -- BEGRUN TRIGGER. -- After FPGA is loaded automatically done. ------------------------------------------------------------------------------- when begrun_trigger_state => next_debug_register <= x"5"; next_LED_CNT_1 <= '1'; next_LED_CNT_2 <= '1'; next_LED_ERROR <= '0'; next_LED_GOOD <= '1'; next_init_all_buses <= X"D"; next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '0'; next_state <= wait_roc1_written; when wait_roc1_written => next_debug_register <= x"6"; next_LED_CNT_1 <= '0'; next_LED_CNT_2 <= '1'; next_LED_ERROR <= '0'; next_LED_GOOD <= '1'; next_init_all_buses <= X"0"; next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '0'; if ROC1_WRITTEN_IN = '1' then next_state <= roc1_written_state; else next_state <= wait_roc1_written; end if; when roc1_written_state => next_debug_register <= x"7"; next_LED_CNT_1 <= '0'; next_LED_CNT_2 <= '0'; next_LED_ERROR <= '0'; next_LED_GOOD <= '1'; next_init_all_buses <= (others => '0'); next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '0'; if counter_wait_after_roc1 = WAIT_AFTER_ROC1_IS_LOADED then next_state <= normal_trigger_state; else next_state <= roc1_written_state; end if; ------------------------------------------------------------------------------- --CALIBRATION TRIGGER. --When the calibration starts the REG2 is --loaded from the RAM to the FEE. Calibration data is retrived in the fifo and --token comes back as for normal event. --In the entity send_token_to_mb.vhd I check the token comes back within 2msec. ------------------------------------------------------------------------------- when calibration_state => next_debug_register <= x"8"; next_LED_CNT_1 <= '1'; next_LED_CNT_2 <= '1'; next_LED_ERROR <= '1'; next_LED_GOOD <= '0'; next_init_all_buses <= X"C"; --start calibration next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '1'; next_state <= wait_cal1_written; when wait_cal1_written => next_debug_register <= x"9"; next_LED_CNT_1 <= '0'; next_LED_CNT_2 <= '1'; next_LED_ERROR <= '1'; next_LED_GOOD <= '0'; next_init_all_buses <= X"0"; next_token_to_trb <= '0'; up_number_of_trigger <= '0'; reset_calibration_counter <= '1'; if A_RDO_IN = '1' then --the token comes back as for normal event next_state <= send_token_state; else next_state <= wait_cal1_written; end if; when others => next_state <= idle_state; end case; end process; ----------------------------------------------------------------------------- --Counts the number of normal trigger. This number is used to generate the --calibration trigger internally. --This counter is resetted after the calibration trigger is executed. ----------------------------------------------------------------------------- process(CLK, RESET, reset_calibration_counter, up_number_of_trigger) begin if (rising_edge(CLK)) then if (RESET = '1' or reset_calibration_counter = '1') then counter_number_of_trigger <= (others => '0'); elsif (up_number_of_trigger = '1') then counter_number_of_trigger <= counter_number_of_trigger + 1; else counter_number_of_trigger <= counter_number_of_trigger; end if; end if; end process; ------------------------------------------------------------------------------- -- CAL_TRIGGER_REGISTER_IN says how often the calibration trigger -- has to be genereted. This register is written by the TRB at startup. ------------------------------------------------------------------------------- process (CLK, RESET) begin if (rising_edge(CLK)) then if RESET = '1' then register_trigger_condition <= (others => '0'); else register_trigger_condition <= CAL_TRIGGER_REGISTER_IN; end if; end if; end process; ------------------------------------------------------------------------------- -- Register input trigger signals. They come from TRB. ------------------------------------------------------------------------------- process (CLK, RESET) begin if (rising_edge(CLK)) then if RESET = '1' then reg_trigger_type_in <= '0'; reg_trigger_in <= '0'; else reg_trigger_type_in <= TRIGGER_TYPE_IN; reg_trigger_in <= TRIGGER_IN; end if; end if; end process; ------------------------------------------------------------------------------- -- The calibration trigger is generated every -- x"register_trigger_condition(15 downto 4)" number of normal trigger ------------------------------------------------------------------------------- process (CLK, RESET, register_trigger_condition) begin if (rising_edge(CLK)) then if (RESET = '1') then internal_calibration_trigger <= '0'; elsif ( (register_trigger_condition(3 downto 0) = x"E") and (counter_number_of_trigger(11 downto 0) = register_trigger_condition(15 downto 4)) ) then --enable cal trigger internal_calibration_trigger <= '1'; elsif (register_trigger_condition(3 downto 0) = x"C") then --only cal trigger internal_calibration_trigger <= '1'; elsif (register_trigger_condition(3 downto 0) = x"D") then --disable cal trigger internal_calibration_trigger <= '0'; else internal_calibration_trigger <= '0'; end if; end if; end process; ------------------------------------------------------------------------------- -- DEBUG INFO PROCESS ------------------------------------------------------------------------------- process (CLK, RESET) begin if (rising_edge(CLK)) then if (RESET = '1') then debug_normal_trigger_number <= (others => '0'); elsif (up_number_of_trigger = '1') then debug_normal_trigger_number <= debug_normal_trigger_number + 1; else debug_normal_trigger_number <= debug_normal_trigger_number; end if; end if; end process; ------------------------------------------------------------------------------- -- DEBUG INFO PROCESS ------------------------------------------------------------------------------- process (CLK, RESET, current_state) begin if (rising_edge(CLK)) then if (RESET = '1') then debug_calibration_trigger_number <= (others => '0'); elsif (current_state = calibration_state) then debug_calibration_trigger_number <= debug_calibration_trigger_number + 1; else debug_calibration_trigger_number <= debug_calibration_trigger_number; end if; end if; end process; ------------------------------------------------------------------------------- -- DEBUG INFO PROCESSES: it counts number of token received from FEE ------------------------------------------------------------------------------- process (CLK, RESET, pulse_a_rdo_in) begin if (rising_edge(CLK)) then if RESET = '1' then debug_token_back_number <= (others => '0'); elsif pulse_a_rdo_in = '1' then debug_token_back_number <= debug_token_back_number + 1; else debug_token_back_number <= debug_token_back_number; end if; end if; end process; ------------------------------------------------------------------------------- -- After the FEE parameters(ROC1) have been loaded an internal signal is -- generated (ROC1_WRITTEN_IN = '1'). -- After this stage the FEE can receive the -- data request. -- counter_wait_after_roc1 separates the configuration stage from the -- acquisition stage. ------------------------------------------------------------------------------- process (CLK, RESET, current_state) begin if (rising_edge(CLK)) then if (RESET = '1') then counter_wait_after_roc1 <= (others => '0'); elsif current_state = roc1_written_state then counter_wait_after_roc1 <= counter_wait_after_roc1 + 1; else counter_wait_after_roc1 <= counter_wait_after_roc1; end if; end if; end process; end behavioral;