-------------------------------------------------------------------------------- -- Paul Scherrer Institute (PSI) -------------------------------------------------------------------------------- -- Unit : evr320_decoder.vhd -- Author : Waldemar Koprek, Section Diagnostic -- Goran Marinkovic, Section Diagnostic -- Patric Bucher, Section DSV -------------------------------------------------------------------------------- -- Copyright© PSI, Section Diagnostic -------------------------------------------------------------------------------- -- Comment : -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_misc.all; library unisim; use unisim.vcomponents.all; library work; use work.evr320_pkg.all; entity evr320_decoder is generic ( FACILITY : string := "SFEL"; -- "HIPA" | "SFEL" EVENT_RECORDER : boolean := false; MEM_DATA_WIDTH : integer := 32; EXP_REC_CLK_FREQ : natural := 142_800_000 -- in Hz ); port ( -------------------------------------------------------------------------- -- Debug interface -------------------------------------------------------------------------- debug_clk : out std_logic; debug : out std_logic_vector(127 downto 0); -------------------------------------------------------------------------- -- GTX parallel interface -------------------------------------------------------------------------- i_mgt_rst : in std_logic; -- GTX loss of sync i_mgt_rx_clk : in std_logic; i_mgt_rx_data : in std_logic_vector(15 downto 0); i_mgt_rx_charisk : in std_logic_vector( 1 downto 0); -------------------------------------------------------------------------- -- User interface CPU clock -------------------------------------------------------------------------- i_usr_clk : in std_logic; i_evr_params : in typ_evr320_params; o_event_recorder_stat : out typ_evt_rec_status; i_event_recorder_ctrl : in typ_evt_rec_ctrl; i_mem_addr : in std_logic_vector(11 downto 0); o_mem_data : out std_logic_vector(MEM_DATA_WIDTH - 1 downto 0); -------------------------------------------------------------------------- -- User stream interface User clock -------------------------------------------------------------------------- i_stream_clk : in std_logic; o_stream_data : out std_logic_vector(7 downto 0); o_stream_addr : out std_logic_vector(10 downto 0); o_stream_valid : out std_logic; -------------------------------------------------------------------------- -- User interface MGT clock -------------------------------------------------------------------------- o_usr_events : out std_logic_vector( 3 downto 0); o_usr_events_ext : out std_logic_vector( 3 downto 0); o_sos_event : out std_logic; o_event : out std_logic_vector( 7 downto 0); o_event_valid : out std_logic ); end evr320_decoder; architecture behavioral of evr320_decoder is ----------------------------------------------------------------------------- -- Constant ----------------------------------------------------------------------------- -- constant HIGH : std_logic := '1'; constant LOW : std_logic := '0'; constant LOW_slv : std_logic_vector(15 downto 0) := (others => '0'); -- Data Width constant MEM_DATA_BYTES : integer := MEM_DATA_WIDTH / 8; constant MEM_ADDR_LSB : integer := MEM_DATA_WIDTH / 64; -- 0 = 32 bit / 1 = 64 bit -- Framing constant C_KCHAR_START : std_logic_vector( 7 downto 0) := X"5C"; constant C_KCHAR_END : std_logic_vector( 7 downto 0) := X"3C"; -- system events constant C_EVENT_NULL : std_logic_vector( 7 downto 0) := X"00"; constant C_EVENT_SEC_0 : std_logic_vector( 7 downto 0) := X"70"; constant C_EVENT_SEC_1 : std_logic_vector( 7 downto 0) := X"71"; constant C_EVENT_STOP_LOG : std_logic_vector( 7 downto 0) := X"79"; constant C_EVENT_HEARTBEAT : std_logic_vector( 7 downto 0) := X"7A"; constant C_EVENT_SYNC_PRESCA : std_logic_vector( 7 downto 0) := X"7B"; constant C_EVENT_TIM_CNT_INC : std_logic_vector( 7 downto 0) := X"7C"; constant C_EVENT_TIM_CNT_RST : std_logic_vector( 7 downto 0) := X"7D"; constant C_EVENT_BEACON : std_logic_vector( 7 downto 0) := X"7E"; constant C_EVENT_END_OF_SEQ : std_logic_vector( 7 downto 0) := X"7F"; -- Events received type usr_events_type is array (0 to 3) of std_logic_vector( 3 downto 0); signal usr_events : usr_events_type := (others => (others => '0')); signal cs_timeout_cnt : unsigned(23 downto 0) := (others => '0'); signal cs_min_cnt : unsigned(31 downto 0) := (others => '0'); signal cs_min_time : unsigned(31 downto 0) := (others => '0'); signal evr_stable : std_logic := '0'; -- Frame fsm -- type frame_fsm_type is -- ( -- frame_idle, -- frame_addr_gap, -- frame_addr, -- frame_data_gap, -- frame_data, -- frame_chk1_gap, -- frame_chk1, -- frame_chk2_gap, -- frame_chk2 -- ); -- signal frame_fsm : frame_fsm_type; constant frame_idle : std_logic_vector( 3 downto 0) := "0000"; constant frame_addr_gap : std_logic_vector( 3 downto 0) := "0001"; constant frame_addr : std_logic_vector( 3 downto 0) := "0010"; constant frame_data_gap : std_logic_vector( 3 downto 0) := "0011"; constant frame_data : std_logic_vector( 3 downto 0) := "0100"; constant frame_chk1_gap : std_logic_vector( 3 downto 0) := "0101"; constant frame_chk1 : std_logic_vector( 3 downto 0) := "0110"; constant frame_chk2_gap : std_logic_vector( 3 downto 0) := "0111"; constant frame_chk2 : std_logic_vector( 3 downto 0) := "1000"; signal frame_fsm : std_logic_vector( 3 downto 0) := "0000"; -- Frame checksum signal frame_chk : unsigned(15 downto 0) := X"FFFF"; signal frame_chk_ok : std_logic := '0'; signal frame_chk1_ok : std_logic := '0'; signal frame_chk2_ok : std_logic := '0'; -- Frame control FIFO signal frame_ctrl_full : std_logic := '0'; signal frame_ctrl_empty : std_logic := '0'; signal frame_ctrl_wren : std_logic := '0'; signal frame_ctrl_di : std_logic_vector(63 downto 0) := (others => '0'); signal frame_ctrl_rden : std_logic := '0'; signal frame_ctrl_do : std_logic_vector(63 downto 0) := (others => '0'); -- Frame control FIFO write port signal frame_ctrl_wr_id : std_logic_vector( 7 downto 0) := (others => '0'); signal frame_ctrl_wr_ok : std_logic := '0'; -- Frame control FIFO read port signal frame_ctrl_rd_id : std_logic_vector( 7 downto 0) := (others => '0'); signal frame_ctrl_rd_ok : std_logic := '0'; -- Frame data FIFO signal frame_data_full : std_logic := '0'; signal frame_data_empty : std_logic := '0'; signal frame_data_wren : std_logic := '0'; signal frame_data_di : std_logic_vector(63 downto 0) := (others => '0'); signal frame_data_rden : std_logic := '0'; signal frame_data_do : std_logic_vector(63 downto 0) := (others => '0'); -- Frame data FIFO write port signal frame_data_wr_id : unsigned( 7 downto 0) := (others => '0'); signal frame_data_wr_addr_cnt: unsigned(15 downto 0) := (others => '0'); signal frame_data_wr_addr : std_logic_vector(10 downto 0) := (others => '0'); signal frame_data_wr_byte : std_logic_vector( 7 downto 0) := (others => '0'); -- Frame data FIFO read port signal frame_data_rd_id : std_logic_vector( 7 downto 0) := (others => '0'); signal frame_data_rd_addr : std_logic_vector(10 downto 0) := (others => '0'); signal frame_data_rd_byte : std_logic_vector( 7 downto 0) := (others => '0'); -- Memory fsm -- type mem_fsm_type is -- ( -- mem_idle, -- mem_data_rd, -- mem_data_del, -- mem_ctrl_rd -- ); -- signal mem_fsm : mem_fsm_type; constant mem_idle : std_logic_vector( 1 downto 0) := "00"; constant mem_data_rd : std_logic_vector( 1 downto 0) := "01"; constant mem_data_del : std_logic_vector( 1 downto 0) := "10"; constant mem_ctrl_rd : std_logic_vector( 1 downto 0) := "11"; signal mem_fsm : std_logic_vector( 1 downto 0) := "00"; -- Data memory address signal mem_addr : std_logic_vector(11 downto 0); signal mem_addr_dly : std_logic_vector(11 downto 0); -- Data memory write signal mem_data_wren : std_logic := '0'; signal mem_data_wr_addr : std_logic_vector(10 downto 0) := (others => '0'); signal mem_data_wr_byte : std_logic_vector( 7 downto 0) := (others => '0'); -- Data memory read signal mem_data_dpram : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_event0 : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_event1 : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_event2 : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_event3 : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); -- Event Recorder signal sos_event : std_logic_vector( 3 downto 0) := (others => '0'); signal usr_events_save : std_logic := '0'; signal usr_events_save_dly : std_logic := '0'; signal usr_events_nr : std_logic_vector( 7 downto 0) := (others => '0'); signal usr_events_nr_dly : std_logic_vector( 7 downto 0) := (others => '0'); signal usr_events_addr : unsigned( 7 downto 0) := (others => '0'); signal usr_events_addr_dly : std_logic_vector( 7 downto 0) := (others => '0'); signal usr_events_cnt : unsigned( 31 downto 0) := (others => '0'); signal usr_events_cnt_d : unsigned( 31 downto 0) := (others => '0'); signal all_events_flags : std_logic_vector(255 downto 0) := (others => '0'); signal all_events_flags_d : std_logic_vector(255 downto 0) := (others => '0'); signal all_events_flags_sync1 : std_logic_vector(255 downto 0) := (others => '0'); signal all_events_flags_sync2 : std_logic_vector(255 downto 0) := (others => '0'); signal timestamp_cnt : unsigned( 31 downto 0) := (others => '0'); signal timestamp_cnt_dly : unsigned( 31 downto 0) := (others => '0'); signal segment_addr_wren : std_logic; signal mem_data_valid : std_logic; signal mem_data_error : std_logic; signal mem_data_read_ack : std_logic_vector( 1 downto 0); signal mem_data_error_ack : std_logic_vector( 1 downto 0); signal mem_data_event_recorder : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_event_flag : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_event_nr : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_event_nr_timestamp : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_dpram_sos : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal mem_data_segment_timestamp : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0'); signal stream_raw : std_logic_vector(18 downto 0); -- attribute safe_implementation: string; -- attribute safe_implementation of frame_fsm : signal is "yes"; -- attribute safe_implementation of mem_fsm : signal is "yes"; -- attribute fsm_safe_state : string; -- attribute fsm_safe_state of frame_fsm : signal is "default_state"; -- attribute fsm_safe_state of mem_fsm : signal is "default_state"; constant evr_stable_time_int_c : natural := EXP_REC_CLK_FREQ/100; constant evr_stable_time_slv_c : std_logic_vector(cs_timeout_cnt'range):= std_logic_vector(to_unsigned(evr_stable_time_int_c, cs_timeout_cnt'length)); begin ----------------------------------------------------------------------------- -- Debug ----------------------------------------------------------------------------- debug_clk <= i_mgt_rx_clk; debug( 15 downto 0) <= i_mgt_rx_data; debug( 17 downto 16) <= i_mgt_rx_charisk; debug(18) <= evr_stable;--new debug(26 downto 19) <= i_evr_params.event_numbers(1); debug(34 downto 27) <= i_evr_params.event_numbers(2); debug(38 downto 35) <= "0001" when (frame_fsm = frame_idle ) else "0010" when (frame_fsm = frame_addr_gap) else "0011" when (frame_fsm = frame_addr ) else "0100" when (frame_fsm = frame_data_gap) else "0101" when (frame_fsm = frame_data ) else "0110" when (frame_fsm = frame_chk1_gap) else "0111" when (frame_fsm = frame_chk1 ) else "1000" when (frame_fsm = frame_chk2_gap) else "1001" when (frame_fsm = frame_chk2 ) else "0000"; debug( 39) <= '0'; debug( 40) <= usr_events( 0)( 3); debug( 41) <= usr_events( 1)( 3); debug( 42) <= usr_events( 2)( 3); debug( 43) <= usr_events( 3)( 3); debug( 44) <= frame_data_wren; debug( 55 downto 45) <= frame_data_wr_addr; debug( 63 downto 56) <= frame_data_wr_byte; dbg_evt_rec: if EVENT_RECORDER generate debug( 64) <= sos_event(3); debug( 65) <= usr_events_save_dly; debug( 73 downto 66) <= usr_events_nr_dly; debug( 81 downto 74) <= usr_events_addr_dly; debug(113 downto 82) <= std_logic_vector(timestamp_cnt_dly); debug(114) <= segment_addr_wren; debug(115) <= mem_data_valid; debug(116) <= mem_data_error; debug(117) <= mem_data_read_ack(0); debug(118) <= mem_data_error_ack(0); debug(119) <= all_events_flags(27); -- event code 27 (photonics) debug(127 downto 120) <= std_logic_vector(usr_events_cnt(7 downto 0)); end generate dbg_evt_rec; dbg_no_evt_rec: if not(EVENT_RECORDER) generate end generate dbg_no_evt_rec; ----------------------------------------------------------------------------- -- Address Alignment for 32/64-bit Data Width ----------------------------------------------------------------------------- gen_addr_align64: if MEM_DATA_WIDTH = 64 generate mem_addr <= i_mem_addr(10 downto 0) & '0'; end generate gen_addr_align64; gen_addr_align32: if MEM_DATA_WIDTH = 32 generate mem_addr <= i_mem_addr; end generate gen_addr_align32; -- Design Rule Check assert (MEM_DATA_WIDTH = 32 or MEM_DATA_WIDTH = 64) report "Invalid Memory Data Width, 32|64 is allowed" severity error; ----------------------------------------------------------------------------- -- evr stable state -- TODO: Perform the sync according to k28.5 ----------------------------------------------------------------------------- prc_evr_stable : process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then evr_stable <= '0'; else if ((std_logic_vector(cs_min_cnt) > i_evr_params.cs_min_cnt) and (std_logic_vector(cs_min_time) > i_evr_params.cs_min_time) and (std_logic_vector(cs_timeout_cnt) < evr_stable_time_slv_c)) then -- make generics depending on recovery_clock evr_stable <= '1'; else evr_stable <= '0'; end if; end if; end if; end process; ----------------------------------------------------------------------------- -- user event decoder -- the process generates 4 clock cycle pulses ----------------------------------------------------------------------------- prc_user_event_decoder : process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then usr_events <= (others => (others => '0')); else for i in 0 to 3 loop if FACILITY = "HIPA" then if ((i_evr_params.event_enable(i) = '1') and (i_mgt_rx_charisk( 0) = '0') and (i_mgt_rx_data( 7 downto 0) = i_evr_params.event_numbers(i))) then usr_events(i) <= "1111"; else usr_events(i) <= usr_events(i)( 2 downto 0) & '0'; end if; else if ((i_evr_params.event_enable(i) = '1') and (i_mgt_rx_charisk( 0) = '0') and (i_mgt_rx_data( 7 downto 0) = i_evr_params.event_numbers(i))and (evr_stable = '1')) then usr_events(i) <= "1111"; else usr_events(i) <= usr_events(i)( 2 downto 0) & '0'; end if; end if; end loop; end if; end if; end process; usr_event_port_map: for i in 0 to 3 generate o_usr_events(i) <= usr_events(i)(0); -- single pulses for evr clock domain o_usr_events_ext(i) <= usr_events(i)(3); -- 4 cycle pulses for clock domain crossing end generate; ----------------------------------------------------------------------------- -- Counting valid window for events after the last check sums was received ----------------------------------------------------------------------------- process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then cs_timeout_cnt <= X"000000"; else if ((frame_ctrl_wren = '1') and (frame_chk_ok = '1')) then cs_timeout_cnt <= X"000000"; else if (cs_timeout_cnt /= X"FFFFFF") then cs_timeout_cnt <= cs_timeout_cnt + X"000001"; end if; end if; end if; end if; end process; ----------------------------------------------------------------------------- -- Counting valid frame check sums received ----------------------------------------------------------------------------- process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then cs_min_cnt <= X"00000000"; else if (frame_ctrl_wren = '1') then if (frame_chk_ok = '1') then if (cs_min_cnt /= X"FFFFFFFF") then cs_min_cnt <= cs_min_cnt + X"00000001"; end if; else cs_min_cnt <= X"00000000"; end if; end if; end if; end if; end process; ----------------------------------------------------------------------------- -- Counting time in which no invalid frame check sums was received ----------------------------------------------------------------------------- process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then cs_min_time <= X"00000000"; else if ((frame_ctrl_wren = '1') and (frame_chk_ok = '0')) then cs_min_time <= X"00000000"; else if (cs_min_time /= X"FFFFFFFF") then cs_min_time <= cs_min_time + X"00000001"; end if; end if; end if; end if; end process; ----------------------------------------------------------------------------- -- Data buffer ----------------------------------------------------------------------------- process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then frame_fsm <= frame_idle; else case frame_fsm is when frame_idle => if ((i_mgt_rx_charisk( 1) = '1') and (i_mgt_rx_data(15 downto 8) = C_KCHAR_START)) then frame_fsm <= frame_addr_gap; end if; when frame_addr_gap => frame_fsm <= frame_addr; when frame_addr => frame_fsm <= frame_data_gap; when frame_data_gap => if (((i_mgt_rx_charisk( 1) = '1') and (i_mgt_rx_data(15 downto 8) = C_KCHAR_END)) or ((i_mgt_rx_charisk( 0) = '1') and (i_mgt_rx_data( 7 downto 0) = C_KCHAR_END))) then frame_fsm <= frame_idle; else frame_fsm <= frame_data; end if; when frame_data => if (((i_mgt_rx_charisk( 1) = '1') and (i_mgt_rx_data(15 downto 8) = C_KCHAR_END)) or ((i_mgt_rx_charisk( 0) = '1') and (i_mgt_rx_data( 7 downto 0) = C_KCHAR_END))) then frame_fsm <= frame_chk1_gap; else frame_fsm <= frame_data_gap; end if; when frame_chk1_gap => frame_fsm <= frame_chk1; when frame_chk1 => frame_fsm <= frame_chk2_gap; when frame_chk2_gap => frame_fsm <= frame_chk2; when frame_chk2 => frame_fsm <= frame_idle; when others => frame_fsm <= frame_idle; end case; end if; end if; end process; process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then segment_addr_wren <= '0'; frame_data_wren <= '0'; frame_data_wr_id <= (others => '0'); frame_data_wr_addr_cnt<= (others => '0'); frame_data_wr_addr <= (others => '0'); frame_data_wr_byte <= (others => '0'); else segment_addr_wren <= '0'; frame_data_wren <= '0'; case frame_fsm is when frame_idle => frame_data_wr_addr_cnt <= (others => '0'); when frame_addr => frame_data_wr_id <= frame_data_wr_id + X"01"; frame_data_wr_addr_cnt <= "0000" & unsigned(i_mgt_rx_data(15 downto 8)) & "0000"; segment_addr_wren <= '1'; when frame_data => if (((i_mgt_rx_charisk( 1) = '1') and (i_mgt_rx_data(15 downto 8) = C_KCHAR_END)) or ((i_mgt_rx_charisk( 0) = '1') and (i_mgt_rx_data( 7 downto 0) = C_KCHAR_END))) then frame_data_wren <= '0'; else frame_data_wren <= not frame_data_full; frame_data_wr_addr_cnt <= frame_data_wr_addr_cnt + X"0001"; frame_data_wr_addr <= std_logic_vector(frame_data_wr_addr_cnt(10 downto 0)); frame_data_wr_byte <= i_mgt_rx_data(15 downto 8); end if; when others => null; end case; end if; end if; end process; ----------------------------------------------------------------------------- -- Frame check sum calculator ----------------------------------------------------------------------------- process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then case frame_fsm is when frame_idle => frame_chk <= X"FFFF"; when frame_addr | frame_data => if (i_mgt_rx_charisk = "00") then frame_chk <= frame_chk - (X"00" & unsigned(i_mgt_rx_data(15 downto 8))); end if; when others => null; end case; end if; end process; process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then case frame_fsm is when frame_idle => frame_chk1_ok <= '0'; frame_chk2_ok <= '0'; when frame_chk1 => if (frame_chk(15 downto 8) = unsigned(i_mgt_rx_data(15 downto 8))) then frame_chk1_ok <= '1'; end if; when frame_chk2 => if (frame_chk( 7 downto 0) = unsigned(i_mgt_rx_data(15 downto 8))) then frame_chk2_ok <= '1'; end if; when others => null; end case; end if; end process; frame_chk_ok <= frame_chk1_ok and frame_chk2_ok; ----------------------------------------------------------------------------- -- Frame FIFO ----------------------------------------------------------------------------- -- Frame control received process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (frame_fsm = frame_chk2) then frame_ctrl_wren <= not frame_ctrl_full; else frame_ctrl_wren <= '0'; end if; end if; end process; frame_ctrl_wr_id <= std_logic_vector(frame_data_wr_id); frame_ctrl_wr_ok <= frame_chk_ok; frame_ctrl_di( 7 downto 0) <= frame_ctrl_wr_id; frame_ctrl_di( 8) <= frame_ctrl_wr_ok; frame_ctrl_di(11 downto 9) <= "000"; frame_ctrl_di(63 downto 12) <= X"0000000000000"; frame_ctrl_inst: FIFO36E1 generic map ( ALMOST_EMPTY_OFFSET => X"0080", ALMOST_FULL_OFFSET => X"0080", DATA_WIDTH => 36, DO_REG => 1, EN_ECC_READ => FALSE, EN_ECC_WRITE => FALSE, EN_SYN => FALSE, FIFO_MODE => "FIFO36", FIRST_WORD_FALL_THROUGH => TRUE, INIT => X"000000000000000000", SIM_DEVICE => "7SERIES", SRVAL => X"000000000000000000" ) port map ( -- Status ALMOSTEMPTY => open, ALMOSTFULL => open, EMPTY => frame_ctrl_empty, FULL => frame_ctrl_full, RDCOUNT => open, RDERR => open, WRCOUNT => open, WRERR => open, -- Write port WRCLK => i_mgt_rx_clk, WREN => frame_ctrl_wren, DI => frame_ctrl_di, DIP => X"00", -- Read port RDCLK => i_mgt_rx_clk, RDEN => frame_ctrl_rden, REGCE => '1', RST => i_mgt_rst, RSTREG => '1', DO => frame_ctrl_do, DOP => open, -- ECC port INJECTDBITERR => '0', INJECTSBITERR => '0', DBITERR => open, ECCPARITY => open, SBITERR => open ); frame_ctrl_rden <= '1' when ((frame_ctrl_empty = '0') and (mem_fsm = mem_ctrl_rd)) else '0'; frame_ctrl_rd_id <= frame_ctrl_do( 7 downto 0); frame_ctrl_rd_ok <= frame_ctrl_do( 8); -- Frame data received frame_data_di( 7 downto 0) <= std_logic_vector(frame_data_wr_id); frame_data_di(18 downto 8) <= frame_data_wr_addr; frame_data_di(23 downto 19) <= "00000"; frame_data_di(31 downto 24) <= frame_data_wr_byte; frame_data_di(63 downto 32) <= X"00000000"; frame_data_inst: FIFO36E1 generic map ( ALMOST_EMPTY_OFFSET => X"0080", ALMOST_FULL_OFFSET => X"0080", DATA_WIDTH => 36, DO_REG => 1, EN_ECC_READ => FALSE, EN_ECC_WRITE => FALSE, EN_SYN => FALSE, FIFO_MODE => "FIFO36", FIRST_WORD_FALL_THROUGH => TRUE, INIT => X"000000000000000000", SIM_DEVICE => "7SERIES", SRVAL => X"000000000000000000" ) port map ( -- Status ALMOSTEMPTY => open, ALMOSTFULL => open, EMPTY => frame_data_empty, FULL => frame_data_full, RDCOUNT => open, RDERR => open, WRCOUNT => open, WRERR => open, -- Write port WRCLK => i_mgt_rx_clk, WREN => frame_data_wren, DI => frame_data_di, DIP => X"00", -- Read port RDCLK => i_mgt_rx_clk, RDEN => frame_data_rden, REGCE => '1', RST => i_mgt_rst, RSTREG => '1', DO => frame_data_do, DOP => open, -- ECC port INJECTDBITERR => '0', INJECTSBITERR => '0', DBITERR => open, ECCPARITY => open, SBITERR => open ); frame_data_rden <= '1' when ((frame_data_empty = '0') and (mem_fsm = mem_data_rd) and (frame_data_rd_id = frame_ctrl_rd_id)) else '1' when ((frame_data_empty = '0') and (mem_fsm = mem_data_del) and (frame_data_rd_id /= frame_ctrl_rd_id)) else '0'; frame_data_rd_id <= frame_data_do( 7 downto 0); frame_data_rd_addr <= frame_data_do(18 downto 8); frame_data_rd_byte <= frame_data_do(31 downto 24); ----------------------------------------------------------------------------- -- Memory fsm ----------------------------------------------------------------------------- process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then mem_fsm <= mem_idle; else case mem_fsm is when mem_idle => if (frame_ctrl_empty = '0') then if (frame_data_empty = '0') then if (frame_data_rd_id = frame_ctrl_rd_id) then mem_fsm <= mem_data_rd; else mem_fsm <= mem_data_del; end if; else mem_fsm <= mem_ctrl_rd; end if; end if; when mem_data_rd => if ((frame_data_empty = '0') and (frame_data_rd_id = frame_ctrl_rd_id)) then mem_fsm <= mem_data_rd; else mem_fsm <= mem_ctrl_rd; end if; when mem_data_del => if ((frame_data_empty = '0') and (frame_data_rd_id /= frame_ctrl_rd_id)) then mem_fsm <= mem_data_del; else mem_fsm <= mem_idle; end if; when mem_ctrl_rd => mem_fsm <= mem_idle; when others => mem_fsm <= mem_idle; end case; end if; end if; end process; ----------------------------------------------------------------------------- -- Data memory write ----------------------------------------------------------------------------- mem_data_wren <= '1' when ((mem_fsm = mem_data_rd) and (frame_data_rd_id = frame_ctrl_rd_id) and (frame_ctrl_empty = '0') and (frame_data_empty = '0') and (frame_ctrl_rd_ok = '1')) else '0'; mem_data_wr_addr <= frame_data_rd_addr; mem_data_wr_byte <= frame_data_rd_byte; ----------------------------------------------------------------------------- -- Address delay for read data mux ----------------------------------------------------------------------------- process(i_usr_clk) begin if (i_usr_clk'event and (i_usr_clk = '1')) then mem_addr_dly <= mem_addr; end if; end process; ----------------------------------------------------------------------------- -- Data memory selector ----------------------------------------------------------------------------- o_mem_data <= mem_data_dpram when (mem_addr_dly(11 downto 9) = "000") else mem_data_event0 when (mem_addr_dly(11 downto 9) = "001") else mem_data_event1 when (mem_addr_dly(11 downto 9) = "010") else mem_data_event2 when (mem_addr_dly(11 downto 9) = "011") else mem_data_event3 when (mem_addr_dly(11 downto 9) = "100") else mem_data_event_recorder; ----------------------------------------------------------------------------- -- Data Memory -- write port - timing decoder -- read port - usr domain ----------------------------------------------------------------------------- evr320_dpram_inst: entity work.evr320_dpram generic map ( MEM_SIZE_BYTE => 2048, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => mem_data_wren, addra => mem_data_wr_addr, dia => mem_data_wr_byte, -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr( 8 downto MEM_ADDR_LSB), dob => mem_data_dpram ); ----------------------------------------------------------------------------- -- Data Memory -- write port - timing decoder -- read port - usr domain ----------------------------------------------------------------------------- evr320_event0_inst: entity work.evr320_buffer generic map ( MEM_SIZE_BYTE => 2048, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => mem_data_wren, addra => mem_data_wr_addr, dia => mem_data_wr_byte, page => usr_events( 0)( 3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr( 8 downto MEM_ADDR_LSB), dob => mem_data_event0 ); evr320_event1_inst: entity work.evr320_buffer generic map ( MEM_SIZE_BYTE => 2048, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => mem_data_wren, addra => mem_data_wr_addr, dia => mem_data_wr_byte, page => usr_events( 1)( 3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr( 8 downto MEM_ADDR_LSB), dob => mem_data_event1 ); evr320_event2_inst: entity work.evr320_buffer generic map ( MEM_SIZE_BYTE => 2048, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => mem_data_wren, addra => mem_data_wr_addr, dia => mem_data_wr_byte, page => usr_events( 2)( 3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr( 8 downto MEM_ADDR_LSB), dob => mem_data_event2 ); evr320_event3_inst: entity work.evr320_buffer generic map ( MEM_SIZE_BYTE => 2048, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => mem_data_wren, addra => mem_data_wr_addr, dia => mem_data_wr_byte, page => usr_events( 3)( 3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr( 8 downto MEM_ADDR_LSB), dob => mem_data_event3 ); ------------------------------------------------------------------------- -- async fifo for streaming interface ------------------------------------------------------------------------- strm_fifo_inst : entity work.psi_common_async_fifo generic map ( width_g => 11+8, depth_g => 2048, afull_on_g => false, afull_lvl_g => 2, aempty_on_g => false, aempty_level_g => 2, ram_style_g => "WBR", ram_behavior_g => "block" -- auto, distributed ) port map ( -- Control Ports in_clk_i => i_mgt_rx_clk, in_rst_i => i_mgt_rst, out_clk_i => i_stream_clk, out_rst_i => '0', -- Input Data in_dat_i => mem_data_wr_addr & mem_data_wr_byte, in_vld_i => mem_data_wren, in_rdy_o => open, -- Output Data out_dat_o => stream_raw, out_vld_o => o_stream_valid, out_rdy_i => '1', -- Input Status in_full_o => open, in_empty_o => open, in_afull_o => open, in_aempty_o => open, in_lvl_o => open, -- Output Status out_full_o => open, out_empty_o => open, out_afull_o => open, out_aempty_o => open, out_lvl_o => open ); o_stream_data <= stream_raw(7 downto 0); o_stream_addr <= stream_raw(18 downto 8); ----------------------------------------------------------------------------- -- Raw Event Output ----------------------------------------------------------------------------- raw_event_output_proc : process(i_mgt_rx_clk) begin if (rising_edge(i_mgt_rx_clk)) then o_event_valid <= '0'; o_event <= (others=>'0'); if ((i_mgt_rx_charisk(0) = '0') and (evr_stable = '1')) then o_event_valid <= '1'; o_event <= i_mgt_rx_data(7 downto 0); end if; end if; end process; ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- EVENT RECORDER ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- gen_evt_rec: if EVENT_RECORDER generate -------------------------------------------------------------------------- -- standard event filter -- user event counter -- start-of-sequence event decoder -------------------------------------------------------------------------- prc_event_recorder : process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then sos_event <= (others => '0'); timestamp_cnt <= (others => '0'); usr_events_save <= '0'; usr_events_nr <= (others => '0'); usr_events_addr <= (others => '0'); usr_events_cnt <= (others => '0'); usr_events_cnt_d <= (others => '0'); all_events_flags <= (others => '0'); all_events_flags_d <= (others => '0'); else -- default assignments sos_event <= sos_event( 2 downto 0) & '0'; usr_events_save <= '0'; -- timestamp for event and segement tagging if (timestamp_cnt /= X"FFFF_FFFF") then timestamp_cnt <= timestamp_cnt + X"0000_0001"; end if; -- only run event recorder when stable operation if ( (i_event_recorder_ctrl.event_enable = '1') and (i_mgt_rx_charisk( 0) = '0') and (evr_stable = '1')) then -- filter standard events (user events = 0x01-0x6F, 0x72-0x78, 0x80-0xFF) if ( or_reduce(i_mgt_rx_data(7 downto 0)) = '1' and (i_mgt_rx_data(7 downto 4) /= X"7")) then -- if ( i_mgt_rx_data(7 downto 0) /= C_EVENT_NULL and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_SEC_0 and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_SEC_1 and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_STOP_LOG and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_HEARTBEAT and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_SYNC_PRESCA and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_TIM_CNT_INC and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_TIM_CNT_RST and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_BEACON and -- i_mgt_rx_data(7 downto 0) /= C_EVENT_END_OF_SEQ ) then usr_events_nr <= i_mgt_rx_data(7 downto 0); -- write event nr memory if (usr_events_addr /= X"FF") then usr_events_save <= '1'; usr_events_addr <= usr_events_addr + X"01"; end if; -- count all user events if (usr_events_cnt /= X"FFFF_FFFF") then usr_events_cnt <= usr_events_cnt + X"0000_0001"; end if; -- start-of-sequence, trigger event for event recorder if (i_mgt_rx_data( 7 downto 0) = i_event_recorder_ctrl.event_number) then sos_event <= "1111"; timestamp_cnt <= (others => '0'); usr_events_cnt <= X"0000_0001"; usr_events_cnt_d <= usr_events_cnt; usr_events_save <= '1'; usr_events_addr <= X"00"; all_events_flags <= (others => '0'); all_events_flags_d <= all_events_flags; end if; end if; -- set flag for appeared event all_events_flags(to_integer(unsigned(i_mgt_rx_data(7 downto 0)))) <= '1'; end if; end if; end if; end process; -------------------------------------------------------------------------- -- delayed event data (write after page switch in buffer) -------------------------------------------------------------------------- prc_dly_event_data : process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then timestamp_cnt_dly <= timestamp_cnt; usr_events_save_dly <= usr_events_save; usr_events_nr_dly <= usr_events_nr; usr_events_addr_dly <= std_logic_vector(usr_events_addr); end if; end process; -------------------------------------------------------------------------- -- memory read handshake -------------------------------------------------------------------------- prc_mem_read_handshake : process(i_mgt_rx_clk) begin if (i_mgt_rx_clk'event and (i_mgt_rx_clk = '1')) then if (i_mgt_rst = '1') then mem_data_error <= '0'; mem_data_valid <= '0'; mem_data_read_ack <= "00"; mem_data_error_ack <= "00"; else -- default assignments mem_data_read_ack <= mem_data_read_ack(0) & i_event_recorder_ctrl.data_ack; mem_data_error_ack <= mem_data_error_ack(0) & i_event_recorder_ctrl.error_ack; if (sos_event(0) = '1') then if (mem_data_valid = '0') then mem_data_valid <= '1'; else --> mem read too slow or not acknowledged, valid is still present mem_data_error <= '1'; end if; end if; -- data read acknowledge if (mem_data_read_ack = "01") then mem_data_valid <= '0'; end if; -- data error acknowledge if (mem_data_error_ack = "01") then mem_data_error <= '0'; end if; end if; end if; end process; -------------------------------------------------------------------------- -- Memory Selector Event Recorder -------------------------------------------------------------------------- mem_data_event_recorder <= mem_data_dpram_sos when (mem_addr_dly(11 downto 9) = B"101") else -- 2K mem_data_event_nr_timestamp when (mem_addr_dly(11 downto 8) = B"1100") else -- 1K mem_data_segment_timestamp when (mem_addr_dly(11 downto 7) = B"1101_0") else -- 512B mem_data_event_nr when (mem_addr_dly(11 downto 6) = B"1101_10") else -- 256B mem_data_event_flag when (mem_addr_dly(11 downto 6) = B"1101_11") else -- 256B (others => '0'); -------------------------------------------------------------------------- -- Event Recorder Data Memories -- write port - timing decoder -- read port - usr domain -------------------------------------------------------------------------- -- Segemented Data Buffer at Start-of-Sequence Event evr320_dpram_sos_inst: entity work.evr320_buffer generic map ( MEM_SIZE_BYTE => 2048, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => mem_data_wren, addra => mem_data_wr_addr, dia => mem_data_wr_byte, page => sos_event(3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr(8 downto MEM_ADDR_LSB), dob => mem_data_dpram_sos ); -------------------------------------------------------------------------- -- Data Buffer Segment Timestamps -------------------------------------------------------------------------- evr320_segment_timestamp_inst: entity work.evr320_timestamp generic map ( MEM_SIZE_BYTE => 512, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => segment_addr_wren, addra => std_logic_vector(frame_data_wr_addr_cnt(10 downto 4)), dia => std_logic_vector(timestamp_cnt), page => sos_event(3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr(6 downto MEM_ADDR_LSB), dob => mem_data_segment_timestamp ); -------------------------------------------------------------------------- -- Event Number Timestamps -------------------------------------------------------------------------- evr320_event_nr_timestamp_inst: entity work.evr320_timestamp generic map ( MEM_SIZE_BYTE => 1024, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => usr_events_save_dly, addra => usr_events_addr_dly, dia => std_logic_vector(timestamp_cnt_dly), page => sos_event(3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr(7 downto MEM_ADDR_LSB), dob => mem_data_event_nr_timestamp ); -------------------------------------------------------------------------- -- Event Numbers (in timeline) -------------------------------------------------------------------------- evr320_event_nr_inst: entity work.evr320_buffer generic map ( MEM_SIZE_BYTE => 256, MEM_DOB_WIDTH => MEM_DATA_WIDTH ) port map ( -- port a clka => i_mgt_rx_clk, ena => HIGH, wea => usr_events_save_dly, addra => usr_events_addr_dly, dia => usr_events_nr_dly, page => sos_event(3), -- port b clkb => i_usr_clk, enb => HIGH, addrb => mem_addr(5 downto MEM_ADDR_LSB), dob => mem_data_event_nr ); -------------------------------------------------------------------------- -- Event Flags of all Events -------------------------------------------------------------------------- prc_event_flags: process(i_usr_clk) variable v_addr : integer range 0 to 255; begin if (i_usr_clk'event and (i_usr_clk = '1')) then -- sync to usr clk all_events_flags_sync1 <= all_events_flags_d; all_events_flags_sync2 <= all_events_flags_sync1; -- address fragment of vector / expand bit to bytes for data read v_addr := to_integer(unsigned(std_logic_vector'(mem_addr(5 downto MEM_ADDR_LSB) & LOW_slv(1 + MEM_ADDR_LSB downto 0)))); mem_data_event_flag <= bit2byte(all_events_flags_sync2(v_addr + MEM_DATA_BYTES - 1 downto v_addr)); end if; end process; -------------------------------------------------------------------------- -- port mapping -------------------------------------------------------------------------- o_sos_event <= sos_event(3); o_event_recorder_stat.usr_events_counter <= std_logic_vector(usr_events_cnt_d); o_event_recorder_stat.data_valid <= mem_data_valid; o_event_recorder_stat.data_error <= mem_data_error; end generate gen_evt_rec; ----------------------------------------------------------------------------- -- NO Event Recorder implemented ----------------------------------------------------------------------------- gen_no_evt_rec: if not(EVENT_RECORDER) generate mem_data_event_recorder <= (others => '0'); o_sos_event <= '0'; o_event_recorder_stat <= c_INIT_EVT_REC_STATUS; end generate gen_no_evt_rec; end behavioral; -------------------------------------------------------------------------------- -- End of file --------------------------------------------------------------------------------