--library ieee, unisim ; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; --use unisim.vcomponents.all; ---------------------------------------------------- entity channelB_reg is port ( clk : in std_logic; reset_n : in std_logic; data : in std_logic_vector(38 downto 0); data_rdy : in std_logic_vector(1 downto 0); -- strobes are compliant with 'theory of errors' l1m_strobe : out std_logic; l2m_strobe : out std_logic; l2a : out std_logic; l2r : out std_logic; roi_received : out std_logic; err_l1_message : out std_logic; err_l2a_message : out std_logic; err_roi_message : out std_logic; err_bcid : out std_logic; err_cit : out std_logic; err_unknown_addr : out std_logic; l2am_interrupted : out std_logic; l2m_consecutive : out std_logic; l1_message : out std_logic_vector(59 downto 0); l1_message_rdy : out std_logic; l2a_message : out std_logic_vector(95 downto 0); l2r_message : out std_logic_vector(11 downto 0); roi_message : out std_logic_vector(47 downto 0); sod : out std_logic; eod : out std_logic; sod_eod_debug_up : out std_logic_vector(31 downto 0); reset_bc : out std_logic; reset_ec : out std_logic ); end channelB_reg; ---------------------------------------------------- architecture arch of channelB_reg is -- -- TTC receiver constants constant L1M_H : std_logic_vector(3 downto 0) := x"1"; constant L1M_D : std_logic_vector(3 downto 0) := x"2"; constant L2M_H : std_logic_vector(3 downto 0) := x"3"; constant L2M_D : std_logic_vector(3 downto 0) := x"4"; constant L2M_R : std_logic_vector(3 downto 0) := x"5"; constant ROI_H : std_logic_vector(3 downto 0) := x"6"; constant ROI_D : std_logic_vector(3 downto 0) := x"7"; constant RES_CTP0 : std_logic_vector(3 downto 0) := x"8"; constant RES_CTP1 : std_logic_vector(3 downto 0) := x"9"; constant RES_CTP2 : std_logic_vector(3 downto 0) := x"a"; constant RES_CTP3 : std_logic_vector(3 downto 0) := x"b"; constant BRC_MSG_ORBIT : std_logic_vector(7 downto 0) := x"01"; constant BRC_MSG_PREPULSE : std_logic_vector(7 downto 0) := x"f0"; -- -- Trigger timing related constants -- Default L0-L1 window timing -- 223 cyc after l0 seen (values given by A.Jusko, 160408), changed to 258 (230808) -- 225 cyc after l0 seen, changed to 260 (230808) constant C_L0_L1_WINDOW_LOW : std_logic_vector(11 downto 0) := x"102"; constant C_L0_L1_WINDOW_HIGH: std_logic_vector(11 downto 0) := x"104"; constant C_L0_L2_WINDOW_LOW : std_logic_vector(19 downto 0) := x"00c80"; constant C_L0_L2_WINDOW_HIGH: std_logic_vector(19 downto 0) := x"04e20"; -- -- signals signal iac_addr : std_logic_vector(3 downto 0); signal iac_data : std_logic_vector(11 downto 0); signal brc_data : std_logic_vector(7 downto 0); signal brc_data_r : std_logic_vector(7 downto 0); signal prev_iac_addr : std_logic_vector(3 downto 0); signal msg_counter : std_logic_vector(2 downto 0); signal l2a_i : std_logic; -- l2 accept signal l2r_i : std_logic; -- l2 reject signal roi_received_i : std_logic; signal l1_spare : std_logic; signal l1_cit : std_logic; signal l1_roc : std_logic_vector(3 downto 0); signal l1_esr : std_logic; signal l1_swc : std_logic; signal l1_class : std_logic_vector(49 downto 0); signal l2_bcid : std_logic_vector(11 downto 0); signal l2_orbitid : std_logic_vector(23 downto 0); signal l2_spare : std_logic_vector(1 downto 0); signal l2_cit : std_logic; signal l2_swc : std_logic; signal l2_cluster : std_logic_vector(5 downto 0); signal l2_class : std_logic_vector(49 downto 0); signal roi_bcid : std_logic_vector(11 downto 0); signal roi_data : std_logic_vector(35 downto 0); signal reset_bc_r : std_logic; signal reset_bc_r2 : std_logic; signal reset_bc_r3 : std_logic; signal reset_ec_r : std_logic; signal reset_ec_r2 : std_logic; signal reset_ec_r3 : std_logic; signal l1_message_i : std_logic_vector(59 downto 0); signal l2a_message_i : std_logic_vector(95 downto 0); signal l2r_message_i : std_logic_vector(11 downto 0); signal roi_message_i : std_logic_vector(47 downto 0); signal l1_message_rdy_i : std_logic; signal sod_i : std_logic; signal eod_i : std_logic; ---------------------------------------------------- signal l1_swc_cnt : std_logic_vector(7 downto 0); signal l2_swc_cnt : std_logic_vector(7 downto 0); signal l1_roc_e_cnt : std_logic_vector(7 downto 0); signal l1_roc_f_cnt : std_logic_vector(7 downto 0); ---------------------------------------------------- begin iac_data <= data(18 downto 7); iac_addr <= data(22 downto 19); brc_data <= data(12 downto 5); l2a <= l2a_i; l2r <= l2r_i; roi_received <= roi_received_i; l1_message_rdy <= l1_message_rdy_i; reset_bc <= reset_bc_r3; reset_ec <= reset_ec_r3; l1_message <= l1_message_i; l2a_message <= l2a_message_i; l2r_message <= l2r_message_i; roi_message <= roi_message_i; l1_message_i <= l1_spare & l1_cit & l1_roc & l1_esr & l1_swc & l1_class & "00"; l2a_message_i <= l2_bcid & l2_orbitid & l2_spare & l2_cit & l2_swc & l2_cluster & l2_class; sod <= sod_i; eod <= eod_i; -------------------------------------------------------------------------------------------- -- SOD EOD Debugging -------------------------------------------------------------------------------------------- sod_eod_debug_up <= l2_swc_cnt & l1_swc_cnt & l1_roc_f_cnt & l1_roc_e_cnt; process(clk) begin if rising_edge(clk) then if reset_n = '0' then l1_swc_cnt <= (others => '0'); l2_swc_cnt <= (others => '0'); l1_roc_e_cnt <= (others => '0'); l1_roc_f_cnt <= (others => '0'); else if l1_message_rdy_i = '1' and l1_swc = '1' then l1_swc_cnt <= l1_swc_cnt + '1'; end if; if l1_message_rdy_i = '1' and l1_roc = x"e" then l1_roc_e_cnt <= l1_roc_e_cnt + '1'; end if; if l1_message_rdy_i = '1' and l1_roc = x"f" then l1_roc_f_cnt <= l1_roc_f_cnt + '1'; end if; if l2a_i = '1' and l2_swc = '1' then l2_swc_cnt <= l2_swc_cnt + '1'; end if; end if; end if; end process; -------------------------------------------------------------------------------------------- -- Registers for Messages -------------------------------------------------------------------------------------------- message_reg: process(clk) begin if rising_edge(clk) then if reset_n = '0' then l2r_message_i <= (others => '0'); roi_message_i <= (others => '0'); else l2r_message_i <= l2r_message_i; roi_message_i <= roi_message_i; if l2r_i = '1' then l2r_message_i <= l2_bcid; end if; if roi_received_i = '1' then roi_message_i <= roi_bcid & roi_data; end if; end if; end if; end process message_reg; process(clk) begin if rising_edge(clk) then l2a_i <= '0'; l2r_i <= '0'; roi_received_i <= '0'; sod_i <= '0'; eod_i <= '0'; reset_bc_r <= '0'; reset_ec_r <= '0'; l1m_strobe <= '0'; l2m_strobe <= '0'; l1_message_rdy_i <= '0'; err_l1_message <= '0'; err_l2a_message <= '0'; err_roi_message <= '0'; err_cit <= '0'; err_bcid <= '0'; err_unknown_addr <= '0'; l2am_interrupted <= '0'; l2m_consecutive <= '0'; if reset_n = '0' then l1_spare <= '0'; l1_cit <= '0'; l1_roc <= (others => '0'); l1_esr <= '0'; l1_swc <= '0'; l1_class <= (others => '0'); l2_bcid <= (others => '0'); l2_orbitid <= (others => '0'); l2_spare <= (others => '0'); l2_cit <= '0'; l2_swc <= '0'; l2_cluster <= (others => '0'); l2_class <= (others => '0'); roi_bcid <= (others => '0'); roi_data <= (others => '0'); err_l1_message <= '0'; err_l2a_message <= '0'; err_roi_message <= '0'; err_cit <= '0'; err_bcid <= '0'; err_unknown_addr <= '0'; brc_data_r <= (others => '0'); prev_iac_addr <= (others => '0'); msg_counter <= (others => '0'); else if data_rdy(1) = '1' then -- iac received case iac_addr is ----------------------------------------------------------- when L1M_H => -- l1 message, word 0 prev_iac_addr <= L1M_H; msg_counter <= "000"; l1_spare <= iac_data(11); l1_cit <= iac_data(10); l1_roc <= iac_data(9 downto 6); l1_esr <= iac_data(5); l1_swc <= iac_data(4); l1_class(49 downto 46) <= iac_data(3 downto 0); l1m_strobe <= '1'; ----------------------------------------------------------- when L1M_D => prev_iac_addr <= L1M_D; case msg_counter is -------------------------------------------- when "000" => -- l1 message, word 1 if prev_iac_addr = L1M_H then l1_class(45 downto 34) <= iac_data; else err_l1_message <= '1'; end if; -------------------------------------------- when "001" => -- l1 message, word 2 if prev_iac_addr = L1M_D then l1_class(33 downto 22) <= iac_data; else err_l1_message <= '1'; end if; -------------------------------------------- when "010" => -- l1 message, word 3 if prev_iac_addr = L1M_D then l1_class(21 downto 10) <= iac_data; else err_l1_message <= '1'; end if; -------------------------------------------- when "011" => -- l1 message, word 4 if prev_iac_addr = L1M_D then l1_class(9 downto 0) <= iac_data(11 downto 2); l1_message_rdy_i <= '1'; else err_l1_message <= '1'; end if; -------------------------------------------- when others => -- shouldn't happen err_l1_message <= '1'; -------------------------------------------- end case; msg_counter <= msg_counter + 1; ----------------------------------------------------------- when L2M_H => -- l2a message, word 0 if (prev_iac_addr = L1M_D and msg_counter /= "100") or -- interrupted/incomplete L1 message prev_iac_addr = L1M_H then err_l1_message <= '1'; end if; prev_iac_addr <= L2M_H; msg_counter <= "000"; l2_bcid <= iac_data; l2m_strobe <= '1'; if (prev_iac_addr = L2M_D or prev_iac_addr = L2M_R) and l1_esr = '0' then l2m_consecutive <= '1'; end if; ----------------------------------------------------------- when L2M_D => prev_iac_addr <= L2M_D; case msg_counter is -------------------------------------------- when "000" => -- l2a message, word 1 if prev_iac_addr = L2M_H then l2_orbitid(23 downto 12) <= iac_data; else l2am_interrupted <= '1'; end if; -------------------------------------------- when "001" => -- l2a message, word 2 if prev_iac_addr = L2M_D then l2_orbitid(11 downto 0) <= iac_data; else l2am_interrupted <= '1'; end if; -------------------------------------------- when "010" => -- l2a message, word 3 if prev_iac_addr = L2M_D then l2_spare <= iac_data(11 downto 10); l2_cit <= iac_data(9); l2_swc <= iac_data(8); l2_cluster <= iac_data(7 downto 2); l2_class(49 downto 48) <= iac_data(1 downto 0); else l2am_interrupted <= '1'; end if; -------------------------------------------- when "011" => -- l2a message, word 4 if prev_iac_addr = L2M_D then l2_class(47 downto 36) <= iac_data; else l2am_interrupted <= '1'; end if; -------------------------------------------- when "100" => -- l2a message, word 5 if prev_iac_addr = L2M_D then l2_class(35 downto 24) <= iac_data; else l2am_interrupted <= '1'; end if; -------------------------------------------- when "101" => -- l2a message, word 6 if prev_iac_addr = L2M_D then l2_class(23 downto 12) <= iac_data; else l2am_interrupted <= '1'; end if; -------------------------------------------- when "110" => -- l2a message, word 7 if prev_iac_addr = L2M_D then l2_class(11 downto 0) <= iac_data; -- cit should be equal if l2_cit /= l1_cit then err_cit <= '1'; end if; -- bcid's should be equal if roi_bcid /= l2_bcid and l1_esr = '1' then err_bcid <= '1'; end if; -- issue l2 accept l2a_i <= '1'; -- sod/eod -- not to be used of for multi-event mode if l1_roc = x"e" and l1_swc = '1' and l2_swc = '1' then sod_i <= '1'; end if; if l1_roc = x"f" and l1_swc = '1' and l2_swc = '1' then eod_i <= '1'; end if; else l2am_interrupted <= '1'; end if; -------------------------------------------- when others => err_l2a_message <= '1'; -------------------------------------------- end case; msg_counter <= msg_counter + 1; ----------------------------------------------------------- when L2M_R => if ((prev_iac_addr = L1M_D) and msg_counter /= "100") or -- interrupted/incomplete L1 message (prev_iac_addr = L1M_H) then err_l1_message <= '1'; end if; msg_counter <= "000"; l2_bcid <= iac_data; if (prev_iac_addr = L2M_D or prev_iac_addr = L2M_R) and l1_esr = '0' then l2m_consecutive <= '1'; end if; if roi_bcid /= l2_bcid and l1_esr = '1' then err_bcid <= '1'; end if; -- issue l2 reject l2r_i <= '1'; l2m_strobe <= '1'; ----------------------------------------------------------- when ROI_H => -- roi, word 0 if l1_esr = '1' then prev_iac_addr <= ROI_H; roi_bcid <= iac_data; msg_counter <= "000"; end if; if prev_iac_addr /= L1M_D and l1_esr = '1' then err_roi_message <= '1'; end if; ----------------------------------------------------------- when ROI_D => if l1_esr = '1' then prev_iac_addr <= ROI_D; case msg_counter is --------------------------------------- when "000" => -- roi, word 1 if prev_iac_addr = ROI_H then roi_data(35 downto 24) <= iac_data; else err_roi_message <= '1'; end if; --------------------------------------- when "001" => -- roi, word 2 if prev_iac_addr = ROI_D then roi_data(23 downto 12) <= iac_data; else err_roi_message <= '1'; end if; --------------------------------------- when "010" => -- roi, word 3 if prev_iac_addr = ROI_D then roi_data(11 downto 0) <= iac_data; -- issue roi received roi_received_i <= '1'; else err_roi_message <= '1'; end if; --------------------------------------- when others => err_roi_message <= '1'; --------------------------------------- end case; msg_counter <= msg_counter + 1; end if; ----------------------------------------------------------- when RES_CTP0 => prev_iac_addr <= RES_CTP0; when RES_CTP1 => prev_iac_addr <= RES_CTP1; when RES_CTP2 => prev_iac_addr <= RES_CTP2; when RES_CTP3 => prev_iac_addr <= RES_CTP3; ----------------------------------------------------------- when others => err_unknown_addr <= '1'; ----------------------------------------------------------- end case; elsif data_rdy(0) = '1' then -- brc received brc_data_r <= brc_data; reset_bc_r <= brc_data(0); reset_ec_r <= brc_data(1); end if; end if; end if; end process; -- NOTE: match the timing of reset bunch- and eventcounter signals -- to the timing of the ttcrx chip -- FIXME: analog to alme's design, might need adjustment! match_ttcrx: process(clk) begin if rising_edge(clk) then if reset_n = '0' then reset_bc_r2 <= '0'; reset_ec_r2 <= '0'; reset_bc_r3 <= '0'; reset_ec_r3 <= '0'; else reset_bc_r2 <= reset_bc_r; reset_ec_r2 <= reset_ec_r; reset_bc_r3 <= reset_bc_r2; reset_ec_r3 <= reset_ec_r2; end if; end if; end process match_ttcrx; end arch;