---------------------------------------------------------------------------------- -- Company: ETH Zurich, Institute for Particle Physics -- Engineer: Q. Weitzel -- -- Create Date: 04/13/2011 -- Design Name: -- Module Name: FTM_fad_broadcast - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: Broadcast of trigger ID to FAD boards -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library ftm_definitions; USE ftm_definitions.ftm_array_types.all; USE ftm_definitions.ftm_constants.all; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity FTM_fad_broadcast is port( clk_50MHz : in std_logic; -- main clock -- global bus 2 enables for crates 0-3 rx_en : out STD_LOGIC; -- receiver enable tx_en : out STD_LOGIC; -- transmitter enable -- crate 0 data I/O rx_d_0 : in STD_LOGIC; tx_d_0 : out STD_LOGIC; -- crate 1 data I/O rx_d_1 : in STD_LOGIC; tx_d_1 : out STD_LOGIC; -- crate 2 data I/O rx_d_2 : in STD_LOGIC; tx_d_2 : out STD_LOGIC; -- crate 3 data I/O rx_d_3 : in STD_LOGIC; tx_d_3 : out STD_LOGIC; -- start/stop run from central control enable_ID_sending : in std_logic; -- missing information for trigger ID TIM_source : in std_logic; LP_settings : in std_logic_vector(3 downto 0); -- communication with trigger_manager trigger_ID_ready : in std_logic; trigger_ID : in std_logic_vector(FAD_RS485_BLOCK_WIDTH - 1 downto 0); trigger_ID_read : out std_logic ); end FTM_fad_broadcast; architecture Behavioral of FTM_fad_broadcast is -- internal registers to store trigger ID signal trigger_ID_sig : std_logic_vector(FAD_RS485_BLOCK_WIDTH - 1 downto 0) := (others => '0'); signal TIM_source_sig : std_logic := '0'; signal LP_settings_sig : std_logic_vector(3 downto 0) := (others => '0'); signal tx_start_sig : std_logic := '0'; signal tx_data_sig : std_logic_vector (7 DOWNTO 0) := (others => '0'); -- rx_enable and tx_enable lines from different FTM_fad_rs485_interface -- initialized in corresponding interface -- the signals from interface 0 are used to drive the global enables signal rx_en_0_sig : STD_LOGIC; signal tx_en_0_sig : STD_LOGIC; signal rx_en_1_sig : STD_LOGIC; signal tx_en_1_sig : STD_LOGIC; signal rx_en_2_sig : STD_LOGIC; signal tx_en_2_sig : STD_LOGIC; signal rx_en_3_sig : STD_LOGIC; signal tx_en_3_sig : STD_LOGIC; signal tx_busy_0_sig : std_logic; -- initialized in FTM_fad_rs485_interface_0 signal rx_valid_0_sig : std_logic; -- initialized in FTM_fad_rs485_interface_0 signal rx_data_0_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_fad_rs485_interface_0 signal rx_busy_0_sig : std_logic; -- initialized in FTU_fad_rs485_interface_0 signal tx_busy_1_sig : std_logic; -- initialized in FTM_fad_rs485_interface_1 signal rx_valid_1_sig : std_logic; -- initialized in FTM_fad_rs485_interface_1 signal rx_data_1_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_fad_rs485_interface_1 signal rx_busy_1_sig : std_logic; -- initialized in FTU_fad_rs485_interface_1 signal tx_busy_2_sig : std_logic; -- initialized in FTM_fad_rs485_interface_2 signal rx_valid_2_sig : std_logic; -- initialized in FTM_fad_rs485_interface_2 signal rx_data_2_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_fad_rs485_interface_2 signal rx_busy_2_sig : std_logic; -- initialized in FTU_fad_rs485_interface_2 signal tx_busy_3_sig : std_logic; -- initialized in FTM_fad_rs485_interface_3 signal rx_valid_3_sig : std_logic; -- initialized in FTM_fad_rs485_interface_3 signal rx_data_3_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_fad_rs485_interface_3 signal rx_busy_3_sig : std_logic; -- initialized in FTU_fad_rs485_interface_3 -- signals to control and read out CRC signal reset_crc_sig : std_logic; signal enable_crc_sig : std_logic; signal crc_data_sig : std_logic_vector (FAD_RS485_BLOCK_WIDTH - 9 downto 0) := (others => '0'); signal crc_sig : std_logic_vector(CRC_POLYNOMIAL'length - 1 downto 0); signal crc_sig_inv : std_logic_vector(CRC_POLYNOMIAL'length - 1 downto 0); -- various loop counters signal frame_cnt : integer range 0 to (FAD_RS485_BLOCK_WIDTH / 8) := 0; component FTM_fad_rs485_interface port( clk : IN std_logic; -- RS485 rx_d : IN std_logic; rx_en : OUT std_logic; tx_d : OUT std_logic; tx_en : OUT std_logic; -- FPGA rx_data : OUT std_logic_vector (7 DOWNTO 0); rx_busy : OUT std_logic := '0'; rx_valid : OUT std_logic := '0'; tx_data : IN std_logic_vector (7 DOWNTO 0); tx_busy : OUT std_logic := '0'; tx_start : IN std_logic ); end component; component ucrc_par generic( POLYNOMIAL : std_logic_vector; INIT_VALUE : std_logic_vector; DATA_WIDTH : integer range 2 to 256; SYNC_RESET : integer range 0 to 1 ); port( clk_i : in std_logic; rst_i : in std_logic; clken_i : in std_logic; data_i : in std_logic_vector(DATA_WIDTH - 1 downto 0); match_o : out std_logic; crc_o : out std_logic_vector(POLYNOMIAL'length - 1 downto 0) ); end component; type FTM_fad_broadcast_StateType is (INIT, IDLE, ACK, SEND_01, SEND_02, SEND_03); signal FTM_fad_broadcast_State : FTM_fad_broadcast_StateType; begin Inst_FTM_fad_rs485_interface_0 : FTM_fad_rs485_interface -- crate 0 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_0, rx_en => rx_en_0_sig, tx_d => tx_d_0, tx_en => tx_en_0_sig, -- FPGA rx_data => rx_data_0_sig, rx_busy => rx_busy_0_sig, rx_valid => rx_valid_0_sig, tx_data => tx_data_sig, tx_busy => tx_busy_0_sig, tx_start => tx_start_sig ); Inst_FTM_fad_rs485_interface_1 : FTM_fad_rs485_interface -- crate 1 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_1, rx_en => rx_en_1_sig, tx_d => tx_d_1, tx_en => tx_en_1_sig, -- FPGA rx_data => rx_data_1_sig, rx_busy => rx_busy_1_sig, rx_valid => rx_valid_1_sig, tx_data => tx_data_sig, tx_busy => tx_busy_1_sig, tx_start => tx_start_sig ); Inst_FTM_fad_rs485_interface_2 : FTM_fad_rs485_interface -- crate 2 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_2, rx_en => rx_en_2_sig, tx_d => tx_d_2, tx_en => tx_en_2_sig, -- FPGA rx_data => rx_data_2_sig, rx_busy => rx_busy_2_sig, rx_valid => rx_valid_2_sig, tx_data => tx_data_sig, tx_busy => tx_busy_2_sig, tx_start => tx_start_sig ); Inst_FTM_fad_rs485_interface_3 : FTM_fad_rs485_interface -- crate 3 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_3, rx_en => rx_en_3_sig, tx_d => tx_d_3, tx_en => tx_en_3_sig, -- FPGA rx_data => rx_data_3_sig, rx_busy => rx_busy_3_sig, rx_valid => rx_valid_3_sig, tx_data => tx_data_sig, tx_busy => tx_busy_3_sig, tx_start => tx_start_sig ); Inst_ucrc_par : ucrc_par generic map( POLYNOMIAL => CRC_POLYNOMIAL, INIT_VALUE => CRC_INIT_VALUE, DATA_WIDTH => (FAD_RS485_BLOCK_WIDTH - 8), SYNC_RESET => 1 ) port map( clk_i => clk_50MHz, rst_i => reset_crc_sig, clken_i => enable_crc_sig, data_i => crc_data_sig, match_o => open, crc_o => crc_sig_inv ); -- Main finite state machine to control all 40 FTUs FTM_fad_broadcast_FSM: process (clk_50MHz) begin if Rising_edge(clk_50MHz) then case FTM_fad_broadcast_State is when INIT => -- reset CRC register reset_crc_sig <= '1'; FTM_fad_broadcast_State <= IDLE; when IDLE => -- wait for trigger_ID_ready flag reset_crc_sig <= '0'; enable_crc_sig <= '0'; trigger_ID_read <= '0'; if (trigger_ID_ready = '1') then TIM_source_sig <= TIM_source; LP_settings_sig <= LP_settings; trigger_ID_sig <= trigger_ID; if (enable_ID_sending = '0') then FTM_fad_broadcast_State <= ACK; else FTM_fad_broadcast_State <= SEND_01; end if; end if; when ACK => -- just acknowledge trigger ID without sending it trigger_ID_read <= '1'; reset_crc_sig <= '0'; if (trigger_ID_ready = '0') then FTM_fad_broadcast_State <= IDLE; end if; when SEND_01 => -- prepare CRC calculation enable_crc_sig <= '1'; crc_data_sig <= TIM_source & LP_settings & trigger_ID(42 downto 0); FTM_fad_broadcast_State <= SEND_02; when SEND_02 => -- wait one cycle for CRC calculation enable_crc_sig <= '0'; FTM_fad_broadcast_State <= SEND_03; when SEND_03 => -- transmit byte by byte if ( (tx_busy_0_sig = '0') and (tx_busy_1_sig = '0') and (tx_busy_2_sig = '0') and (tx_busy_3_sig = '0') ) then if (frame_cnt < 6) then frame_cnt <= frame_cnt + 1; tx_data_sig <= crc_data_sig (7 downto 0); crc_data_sig <= "00000000" & crc_data_sig ((FAD_RS485_BLOCK_WIDTH - 9) downto 8); tx_start_sig <= '1'; FTM_fad_broadcast_State <= SEND_03; elsif (frame_cnt = 6) then frame_cnt <= frame_cnt + 1; tx_data_sig <= crc_sig; tx_start_sig <= '1'; FTM_fad_broadcast_State <= SEND_03; else frame_cnt <= 0; reset_crc_sig <= '1'; FTM_fad_broadcast_State <= ACK; end if; else tx_start_sig <= '0'; FTM_fad_broadcast_State <= SEND_03; end if; end case; end if; end process FTM_fad_broadcast_FSM; rx_en <= rx_en_0_sig; tx_en <= tx_en_0_sig; crc_sig <= crc_sig_inv(0) & crc_sig_inv(1) & crc_sig_inv(2) & crc_sig_inv(3) & crc_sig_inv(4) & crc_sig_inv(5) & crc_sig_inv(6) & crc_sig_inv(7); end Behavioral;