library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity trg_generator is generic ( cnt_width : integer := 10 ); port ( clk40 : in std_logic; rst40 : in std_logic; pt_in : in std_logic; pt_ctp : in std_logic; l0_in : in std_logic; l1_in : in std_logic; pt_in_emu : in std_logic; pt_ctp_emu : in std_logic; l0_in_emu : in std_logic; l1_in_emu : in std_logic; pt_to_sm : out std_logic; l0_to_sm : out std_logic; l1_to_sm : out std_logic; l0_to_ctp : out std_logic; busy : in std_logic; -- external busy to prevent starting a -- new trigger sequence; a started -- sequence is controlled by the state -- machine only error : out std_logic; -- error in trigger sequence -- configuration settings use_emu : in std_logic; send_pt_to_ctp : in std_logic; ptrg_to_l0_acc : in std_logic_vector(cnt_width-1 downto 0) := conv_std_logic_vector( 40, cnt_width); ptrg_to_l0_send : in std_logic_vector(cnt_width-1 downto 0) := conv_std_logic_vector( 46, cnt_width); ptrg_to_l1_acc : in std_logic_vector(cnt_width-1 downto 0) := conv_std_logic_vector(290, cnt_width); ptrg_to_l1_send : in std_logic_vector(cnt_width-1 downto 0) := conv_std_logic_vector(300, cnt_width); ptrg_to_idle_nol0 : in std_logic_vector(cnt_width-1 downto 0) := conv_std_logic_vector( 60, cnt_width); ptrg_to_idle_nol1 : in std_logic_vector(cnt_width-1 downto 0) := conv_std_logic_vector(400, cnt_width); ptrg_to_idle : in std_logic_vector(cnt_width-1 downto 0) := conv_std_logic_vector(500, cnt_width) ); end trg_generator; architecture behav of trg_generator is type trg_state is (idle, sent_ptrg, wait_l0, sent_l0, wait_l1, dead_nol0, dead_nol1, dead_l1a, err); signal state_curr : trg_state; signal state_next : trg_state; signal seen_l0 : std_logic; signal seen_l1 : std_logic; signal cnt_after_ptrg : std_logic_vector(cnt_width-1 downto 0); signal pt_pre_gen : std_logic; signal pt_ctp_pre_gen : std_logic; signal l0_pre_gen : std_logic; signal l1_pre_gen : std_logic; signal l0_ctb : std_logic; begin -- default mux_emu_pt: pt_pre_gen <= pt_in when use_emu = '0' else pt_in_emu; mux_emu_ctp: pt_ctp_pre_gen <= pt_ctp when use_emu = '0' else pt_ctp_emu; mux_emu_l0: l0_pre_gen <= l0_in when use_emu = '0' else l0_in_emu; mux_emu_l1: l1_pre_gen <= l1_in when use_emu = '0' else l1_in_emu; mux_ctp_l0: l0_to_ctp <= pt_ctp when send_pt_to_ctp = '0' else l0_ctb; mux_l0_ctb: l0_ctb <= pt_ctp when state_next = idle and pt_in = '1' and busy = '0' else '0'; trg_fsm: process (clk40, rst40) begin -- process if (rst40 = '1') then state_curr <= idle; state_next <= idle; pt_to_sm <= '0'; l0_to_sm <= '0'; l1_to_sm <= '0'; seen_l0 <= '0'; seen_l1 <= '0'; -- l0_to_ctp <= '0'; cnt_after_ptrg <= (others => '0'); elsif rising_edge(clk40) then -- registered state output state_curr <= state_next; -- initialization pt_to_sm <= '0'; l0_to_sm <= '0'; l1_to_sm <= '0'; error <= '0'; -- l0_to_ctp <= '0'; cnt_after_ptrg <= (others => '0'); case state_next is when idle => seen_l0 <= '0'; seen_l1 <= '1'; if (pt_pre_gen = '1' and busy = '0') then state_next <= sent_ptrg; pt_to_sm <= '1'; -- l0_to_ctp <= pt_ctp_pre_gen; end if; when sent_ptrg => seen_l0 <= '0'; cnt_after_ptrg <= cnt_after_ptrg + 1; if (cnt_after_ptrg >= ptrg_to_l0_acc) then state_next <= wait_l0; end if; when wait_l0 => cnt_after_ptrg <= cnt_after_ptrg + 1; seen_l1 <= '0'; if (l0_pre_gen = '1') then seen_l0 <= '1'; end if; if (cnt_after_ptrg >= ptrg_to_l0_send) then if (l0_pre_gen = '1' or seen_l0 = '1') then l0_to_sm <= '1'; state_next <= sent_l0; else state_next <= dead_nol0; end if; end if; when sent_l0 => cnt_after_ptrg <= cnt_after_ptrg + 1; seen_l1 <= '0'; if (cnt_after_ptrg >= ptrg_to_l1_acc) then state_next <= wait_l1; end if; when wait_l1 => cnt_after_ptrg <= cnt_after_ptrg + 1; if (l1_pre_gen = '1') then seen_l1 <= '1'; end if; if (cnt_after_ptrg >= ptrg_to_l1_send) then if (l1_pre_gen = '1' or seen_l1 = '1') then l1_to_sm <= '1'; state_next <= dead_l1a; else state_next <= dead_nol1; end if; end if; when dead_nol0 => cnt_after_ptrg <= cnt_after_ptrg + 1; if cnt_after_ptrg >= ptrg_to_idle_nol0 then state_next <= idle; end if; when dead_nol1 => cnt_after_ptrg <= cnt_after_ptrg + 1; if cnt_after_ptrg >= ptrg_to_idle_nol1 then state_next <= idle; end if; when dead_l1a => -- dead time for operation w/o proper busy cnt_after_ptrg <= cnt_after_ptrg + 1; if (cnt_after_ptrg >= ptrg_to_idle) then state_next <= idle; end if; when err => error <= '1'; state_next <= idle; when others => state_next <= err; end case; end if; end process; end;