diff --git a/hdl/evr320_decoder.vhd b/hdl/evr320_decoder.vhd index 2008496..5f53092 100644 --- a/hdl/evr320_decoder.vhd +++ b/hdl/evr320_decoder.vhd @@ -1,1219 +1,1230 @@ --------------------------------------------------------------------------------- --- 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 - ( - EVENT_RECORDER : boolean := false; - MEM_DATA_WIDTH : integer := 32 - ); - 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'); - signal mem_data : std_logic_vector(11+8-1 downto 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"; - -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( 23 downto 18) <= (others=>'0'); - debug( 31 downto 24) <= (others => '0'); - debug( 35 downto 32) <= "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 downto 36) <= (others => '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 - debug(127 downto 64) <= (others => '0'); - 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 - ----------------------------------------------------------------------------- - 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) < X"15CA20")) then - 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 ((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 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; - - -- concatenate - this avoids an internal error in ghdl v0.37! - mem_data <= mem_data_wr_addr & mem_data_wr_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, - AlmFullOn_g => false, - AlmFullLevel_g => 2, - AlmEmptyOn_g => false, - AlmEmptyLevel_g => 2, - RamStyle_g => "WBR", - RamBehavior_g => "block" -- auto, distributed - ) - port map ( - -- Control Ports - InClk => i_mgt_rx_clk, - InRst => i_mgt_rst, - OutClk => i_stream_clk, - OutRst => '0', - - -- Input Data - InData => mem_data, - InVld => mem_data_wren, - InRdy => open, - - -- Output Data - OutData => stream_raw, - OutVld => o_stream_valid, - OutRdy => '1', - - -- Input Status - InFull => open, - InEmpty => open, - InAlmFull => open, - InAlmEmpty => open, - InLevel => open, - - -- Output Status - OutFull => open, - OutEmpty => open, - OutAlmFull => open, - OutAlmEmpty => open, - OutLevel => 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 --------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-- 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 +-------------------------------------------------------------------------------- diff --git a/hdl/evr320_ifc1210_wrapper.vhd b/hdl/evr320_ifc1210_wrapper.vhd index c245d11..ba98d44 100644 --- a/hdl/evr320_ifc1210_wrapper.vhd +++ b/hdl/evr320_ifc1210_wrapper.vhd @@ -1,411 +1,400 @@ - --------------------------------------------------------------------------- --- Paul Scherrer Institute (PSI) --- --------------------------------------------------------------------------- --- Unit : evr320_ifc1210_wrapper.vhd --- Author : Patric Bucher, Benoit Stef --- --------------------------------------------------------------------------- --- Copyright© PSI, Section DSV --- --------------------------------------------------------------------------- --- Comment : Wraps evr320 decoder together with GTX component and TMEM registers. --- --------------------------------------------------------------------------- -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; -use ieee.math_real.all; - -library tosca2; -use tosca2.tosca2_glb_pkg.all; - -use work.evr320_pkg.all; -use work.v6vlx_gtxe1_pkg.all; - -entity evr320_ifc1210_wrapper is - generic( - g_MGT_LOCATION : string := "GTXE1_X0Y16"; -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19" - g_FACILITY : string := "SFEL"; -- "HIPA" | "SFEL" - g_EVENT_RECORDER : boolean := false; -- enable/disable Event Recorder functionality - g_XUSER_CLK_FREQ : natural := 125000000 -- Xuser Clk Frequency in Hz - ); - port( - -- ------------------------------------------------------------------------ - -- Debug interface - -- ------------------------------------------------------------------------ - debug_clk : out std_logic; - debug : out std_logic_vector(127 downto 0); - -- ------------------------------------------------------------------------ - -- TOSCA2 TMEM Interface (xuser clock domain, 100-250MHz) - -- ------------------------------------------------------------------------ - xuser_CLK : in std_logic; - xuser_RESET : in std_logic; - xuser_TMEM_ENA : in std_logic; - xuser_TMEM_WE : in std_logic_vector(7 downto 0); - xuser_TMEM_ADD : in std_logic_vector(13 downto 3); - xuser_TMEM_DATW : in std_logic_vector(63 downto 0); - xuser_TMEM_DATR : out std_logic_vector(63 downto 0); - -- ------------------------------------------------------------------------ - -- MGT Interface - -- ------------------------------------------------------------------------ - mgt_refclk_i : in std_logic; -- MGT Reference Clock - mgt_sfp_los_i : in std_logic; -- SFP Loss of Signal (light on receiver) - mgt_rx_n : in std_logic; -- MGT RX N - mgt_rx_p : in std_logic; -- MGT RX P - mgt_tx_n : out std_logic; -- MGT TX N - mgt_tx_p : out std_logic; -- MGT TX P - mgt_status_o : out std_logic_vector(31 downto 0); -- MGT Status - mgt_control_i : in std_logic_vector(31 downto 0); -- MGT Control - --------------------------------------------------------------------------- - -- User interface MGT clock - --------------------------------------------------------------------------- - clk_evr_o : out std_logic; -- Recovered parallel clock from MGT - rst_evr_o : out std_logic; -- reset according to RX Loss of sync - usr_events_o : out std_logic_vector(3 downto 0); -- User defined event pulses with one clock cycles length & no delay - sos_event_o : out std_logic; -- Start-of-Sequence Event - usr_events_adj_o : out std_logic_vector(3 downto 0); -- User defined event pulses adjusted in delay & length - sos_events_adj_o : out std_logic; -- Start-of-Sequence adjusted in delay & length - -------------------------------------------------------------------------- - -- Decoder axi stream interface, User clock - -------------------------------------------------------------------------- - stream_clk_i : in std_logic := '0'; - stream_data_o : out std_logic_vector(7 downto 0); - stream_addr_o : out std_logic_vector(10 downto 0); - stream_valid_o : out std_logic - ); -end evr320_ifc1210_wrapper; - -architecture rtl of evr320_ifc1210_wrapper is - - -- -------------------------------------------------------------------------- - -- Parameters - -- -------------------------------------------------------------------------- - constant c_TOSCA2_DATA_WIDTH : integer := 64; - constant c_EVR_REG64_COUNT : integer := 16; -- unused, only documentation - constant c_EVR_MEM_SIZE : integer := 16384; -- unused, only documentation - - -- -------------------------------------------------------------------------- - -- Signal definitions - -- -------------------------------------------------------------------------- - signal clk_evr : std_logic; - --signal clk_evr_monitor : std_logic; -- for debugging - signal rst_evr : std_logic; - signal mgt_control : std_logic_vector(31 downto 0) := (others => '0'); - signal mgt_status : std_logic_vector(31 downto 0); - signal mgt_rx_data : std_logic_vector(15 downto 0); - signal mgt_rx_charisk : std_logic_vector(1 downto 0); - signal mgt_lossofsync : std_logic; - signal mgt_reset_tmem_evr : std_logic; -- for legacy reasons, ifc1210 mgt control is in tmem_psi_generic part - signal mem_clk : std_logic; - signal mem_addr_evr : std_logic_vector(11 downto 0); - signal mem_addr_tosca : std_logic_vector(10 downto 0); - signal mem_data : std_logic_vector(c_TOSCA2_DATA_WIDTH - 1 downto 0); - signal evr_params : typ_evr320_params; - signal evr_params_sync : typ_evr320_params; - signal evr_params_xuser : typ_evr320_params; - signal event_recorder_status : typ_evt_rec_status; - signal event_recorder_control : typ_evt_rec_ctrl; - signal event_recorder_control_sync : typ_evt_rec_ctrl; - signal event_recorder_control_xuser : typ_evt_rec_ctrl; - signal evr_latency_measure_stat : typ_rec_latency_measure_stat; - signal evr_latency_measure_ctrl : typ_rec_latency_measure_ctrl; - signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0'); - signal debug_data : std_logic_vector(127 downto 0); - signal decoder_event_valid : std_logic; - signal decoder_event : std_logic_vector(7 downto 0); - - -- -------------------------------------------------------------------------- - -- Attribute definitions - -- -------------------------------------------------------------------------- - attribute keep : string; - attribute keep of clk_evr : signal is "TRUE"; - attribute keep of debug_data : signal is "TRUE"; - signal usr_events_s : std_logic_vector(3 downto 0); - signal sos_event_s : std_logic; - signal evr_rst_s : std_logic; - signal usr_event_delay_s : typ_arr_delay; - signal usr_event_width_s : typ_arr_width; - - -- ---------------------------------------------------------------------------- - -- ---------------------------------------------------------------------------- - -- //////////////////// Main Body ///////////////////////// - -- ---------------------------------------------------------------------------- - -- ---------------------------------------------------------------------------- -begin - - -- -------------------------------------------------------------------------- - -- static signal assignments - -- -------------------------------------------------------------------------- - mgt_lossofsync <= mgt_status(15); - rst_evr_o <= mgt_status(15); - mem_addr_evr <= '0' & mem_addr_tosca; - - mgt_control(c_GTXRESET) <= mgt_control_i(c_GTXRESET) or mgt_sfp_los_i or mgt_reset_tmem_evr; - mgt_control(4 downto 1) <= mgt_control_i(4 downto 1); - mgt_control(c_RXCDRRESET) <= mgt_control_i(c_RXCDRRESET); - mgt_control(31 downto 6) <= mgt_control_i(31 downto 6); - - -- -------------------------------------------------------------------------- - -- Synchronisation to EVR Clock - -- -------------------------------------------------------------------------- - prc_sync_evr : process(clk_evr) - begin - if rising_edge(clk_evr) then - --- - evr_params_sync <= evr_params_xuser; - evr_params <= evr_params_sync; - --- - event_recorder_control_sync <= event_recorder_control_xuser; - event_recorder_control <= event_recorder_control_sync; - --- - end if; - end process; - - -- -------------------------------------------------------------------------- - -- EVR320 Decoder - -- -------------------------------------------------------------------------- - evr320_decoder_inst : entity work.evr320_decoder - generic map( - EVENT_RECORDER => g_EVENT_RECORDER, - MEM_DATA_WIDTH => c_TOSCA2_DATA_WIDTH) - port map( - -- Debug interface - debug_clk => debug_clk, - debug => debug_data, - -- GTX parallel interface - i_mgt_rst => mgt_lossofsync, - i_mgt_rx_clk => clk_evr, - i_mgt_rx_data => mgt_rx_data, - i_mgt_rx_charisk => mgt_rx_charisk, - -- User interface CPU clock - i_usr_clk => mem_clk, - i_evr_params => evr_params, - o_event_recorder_stat => event_recorder_status, - i_event_recorder_ctrl => event_recorder_control, - i_mem_addr => mem_addr_evr, - o_mem_data => mem_data, - -- user stream interface, user clock - i_stream_clk => stream_clk_i, - o_stream_data => stream_data_o, - o_stream_addr => stream_addr_o, - o_stream_valid => stream_valid_o, - -- User interface MGT clock - o_usr_events => usr_events_s, - -- o_usr_events_ext => usr_events_ext_o, -- not in use anymore - o_sos_event => sos_event_s, - o_event => decoder_event, - o_event_valid => decoder_event_valid - ); - - usr_events_o <= usr_events_s; - sos_event_o <= sos_event_s; - - -- -------------------------------------------------------------------------- - -- MGT Wrapper for GTX Virtex-6 - -- -------------------------------------------------------------------------- - mgt_wrapper_inst : entity work.v6vlx_gtxe1_wrapper - generic map( - g_MGT_LOCATION => g_MGT_LOCATION, - g_FACILITY => g_FACILITY) - port map( - -- MGT serial interface - i_mgt_refclk => mgt_refclk_i, - o_mgt_refclk => open, - i_mgt_rx_p => mgt_rx_p, - i_mgt_rx_n => mgt_rx_n, - o_mgt_tx_p => mgt_tx_p, - o_mgt_tx_n => mgt_tx_n, - -- MGT parallel interface - o_mgt_status => mgt_status, - i_mgt_control => mgt_control, - o_mgt_recclk => clk_evr, - o_mgt_rx_data => mgt_rx_data, - o_mgt_rx_charisk => mgt_rx_charisk - ); - - -- -------------------------------------------------------------------------- - -- TMEM - -- -------------------------------------------------------------------------- - --formatter:off - evr320_tmem_inst : entity work.evr320_tmem - port map( - -- TOSCA2 TMEM Interface - xuser_CLK => xuser_CLK, - xuser_RESET => xuser_RESET, - xuser_TMEM_ENA => xuser_TMEM_ENA, - xuser_TMEM_WE => xuser_TMEM_WE, - xuser_TMEM_ADD => xuser_TMEM_ADD, - xuser_TMEM_DATW => xuser_TMEM_DATW, - xuser_TMEM_DATR => xuser_TMEM_DATR, - -- EVR320 Memory/Parameter Interface - evr_params_o => evr_params_xuser, - evr_frequency_i => evr_frequency, - evr_evt_rec_status_i => event_recorder_status, - evr_evt_rec_control_o => event_recorder_control_xuser, - evr_latency_measure_stat_i => evr_latency_measure_stat, - evr_latency_measure_ctrl_o => evr_latency_measure_ctrl, - mgt_status_i => mgt_status, - mgt_reset_o => mgt_reset_tmem_evr, - mem_clk_o => mem_clk, - mem_addr_o => mem_addr_tosca, - mem_data_i => mem_data, - -- - evr_clk_i => clk_evr, - evr_rst_i => evr_rst_s, - evr_pulse_delay_o => usr_event_delay_s, - evr_pulse_width_o => usr_event_width_s); - - -- -------------------------------------------------------------------------- - -- Measure EVR Clock (based on xuser_CLK) - -- -------------------------------------------------------------------------- - clock_meas_inst : entity work.psi_common_clk_meas - generic map( - MasterFrequency_g => g_XUSER_CLK_FREQ, - MaxMeasFrequency_g => 150000000 - ) - port map( - ClkMaster => xuser_CLK, - Rst => xuser_RESET, - ClkTest => clk_evr, - FrequencyHz => evr_frequency - ); - - -- -------------------------------------------------------------------------- - -- Event Latency Measurement for SW tests - -- -------------------------------------------------------------------------- - lat_meas_block : block - type state_type is (armed, count); - signal state : state_type; - signal counter : unsigned(31 downto 0); - signal event_nr_sync, event_nr : std_logic_vector(7 downto 0); - signal event_detected : std_logic_vector(3 downto 0); - signal event_detected_sync : std_logic_vector(1 downto 0); - constant MAX_COUNT : unsigned(31 downto 0) := to_unsigned(g_XUSER_CLK_FREQ / 100, 32); -- MAX 10ms - begin - - -- Process: filter events for matching event_nr register: - --------------------------------------------------------- - ext_event_proc : process(clk_evr) - begin - if (rising_edge(clk_evr)) then - -- sync to MGT clock domain: - event_nr_sync <= evr_latency_measure_ctrl.event_nr; - event_nr <= event_nr_sync; - - -- check if event has been detected and stretch pulse: - event_detected <= event_detected(2 downto 0) & '0'; - if (decoder_event_valid = '1' and decoder_event = event_nr) then - event_detected <= (others => '1'); - end if; - end if; - end process; - - -- Process: Counter when configured event has been detected: - ------------------------------------------------------------ - lat_meas_proc : process(xuser_CLK, counter) - begin - if rising_edge(xuser_CLK) then - -- sync to user clock domain: - event_detected_sync <= event_detected_sync(0) & event_detected(3); - - -- counter FSM: - --------------- - case state is - -- counter is armed: - when armed => - counter <= (others => '0'); - -- start counting when event detected (rising edge): - if (event_detected_sync(1) = '0' and event_detected_sync(0) = '1') then - state <= count; - end if; - - -- counting: - when count => - -- count only up to 10ms, and stop: - if (counter < MAX_COUNT) then - counter <= counter + 1; - end if; - if (evr_latency_measure_ctrl.counter_arm = '1') then - state <= armed; - end if; - end case; - end if; - evr_latency_measure_stat.counter_val <= std_logic_vector(counter); - evr_latency_measure_stat.event_detected <= event_detected_sync(event_detected_sync'left); - end process; - - end block; - - -- -------------------------------------------------------------------------- - -- Add delay output - -- -------------------------------------------------------------------------- - output_delay_block : block - signal rst0_s, rst1_s : std_logic; -- double stage sync for reset - signal usr_evt_shaped_s : std_logic_vector(4 downto 0); - signal usr_events_adj_s : std_logic_vector(4 downto 0); - signal usr_events_concat_s : std_logic_vector(4 downto 0); - signal mmcm_locked : std_logic; - signal rxpll_locked : std_logic; - signal evr_rst_in : std_logic; - - begin - - rxpll_locked <= mgt_status(1); - mmcm_locked <= mgt_status(2); - evr_rst_in <= xuser_RESET or (not rxpll_locked) or (not mmcm_locked); - - --*** double stage sync for reset ***-- - proc_rst : process(clk_evr) - begin - if rising_edge(clk_evr) then - rst0_s <= evr_rst_in; - rst1_s <= rst0_s; - end if; - end process; - - evr_rst_s <= rst1_s; - - usr_events_concat_s <= usr_events_s & sos_event_s; - - gene_adj_out : for i in 0 to 4 generate - - --*** Adjust pulse length in clk cycles EVENT 0,1,2,3 *** - inst_pulslength_evt0 : entity work.psi_common_pulse_shaper_cfg - generic map(HoldIn_g => false, - HoldOffEna_g => false, - MaxHoldOff_g => 10, - MaxDuration_g => MaxDuration_c, - RstPol_g => '1') - port map(clk_i => clk_evr, - rst_i => rst1_s, - width_i => usr_event_width_s(i), - hold_i => (others => '0'), - dat_i => usr_events_concat_s(i), - dat_o => usr_evt_shaped_s(i)); - - --*** delay adjust EVENT 0,1,2,3*** - inst_adjdelay_evt0 : entity work.psi_common_delay_cfg - generic map(Width_g => 1, - MaxDelay_g => MaxDelay_c, - RStPol_g => '1', - RamBehavior_g => "RBW", - Hold_g => True) - port map( clk_i => clk_evr, - rst_i => rst1_s, - dat_i(0) => usr_evt_shaped_s(i), - str_i => '1', - del_i => usr_event_delay_s(i), - dat_o(0) => usr_events_adj_s(i)); - end generate; - - usr_events_adj_o <= usr_events_adj_s(4 downto 1); - sos_events_adj_o <= usr_events_adj_s(0); - end block; - -- -------------------------------------------------------------------------- - -- port mapping - -- -------------------------------------------------------------------------- - clk_evr_o <= clk_evr; - mgt_status_o <= mgt_status; - debug <= debug_data; - -end rtl; --- ---------------------------------------------------------------------------- --- //////////////////////////////////////////////////////////////////////////// --- ---------------------------------------------------------------------------- + --------------------------------------------------------------------------- +-- Paul Scherrer Institute (PSI) +-- --------------------------------------------------------------------------- +-- Unit : evr320_ifc1210_wrapper.vhd +-- Author : Patric Bucher, Benoit Stef +-- --------------------------------------------------------------------------- +-- Copyright© PSI, Section DSV +-- --------------------------------------------------------------------------- +-- Comment : Wraps evr320 decoder together with GTX component and TMEM registers. +-- --------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +library tosca2; +use tosca2.tosca2_glb_pkg.all; + +use work.evr320_pkg.all; +use work.v6vlx_gtxe1_pkg.all; + +entity evr320_ifc1210_wrapper is + generic( + g_MGT_LOCATION : string := "GTXE1_X0Y16"; -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19" + g_FACILITY : string := "SFEL"; -- "HIPA" | "SFEL" + g_EVENT_RECORDER : boolean := false; -- enable/disable Event Recorder functionality + g_XUSER_CLK_FREQ : natural := 125000000 -- Xuser Clk Frequency in Hz + ); + port( + -- ------------------------------------------------------------------------ + -- Debug interface + -- ------------------------------------------------------------------------ + debug_clk : out std_logic; + debug : out std_logic_vector(127 downto 0); + -- ------------------------------------------------------------------------ + -- TOSCA2 TMEM Interface (xuser clock domain, 100-250MHz) + -- ------------------------------------------------------------------------ + xuser_CLK : in std_logic; + xuser_RESET : in std_logic; + xuser_TMEM_ENA : in std_logic; + xuser_TMEM_WE : in std_logic_vector(7 downto 0); + xuser_TMEM_ADD : in std_logic_vector(13 downto 3); + xuser_TMEM_DATW : in std_logic_vector(63 downto 0); + xuser_TMEM_DATR : out std_logic_vector(63 downto 0); + -- ------------------------------------------------------------------------ + -- MGT Interface + -- ------------------------------------------------------------------------ + mgt_refclk_i : in std_logic; -- MGT Reference Clock + mgt_sfp_los_i : in std_logic; -- SFP Loss of Signal (light on receiver) + mgt_rx_n : in std_logic; -- MGT RX N + mgt_rx_p : in std_logic; -- MGT RX P + mgt_tx_n : out std_logic; -- MGT TX N + mgt_tx_p : out std_logic; -- MGT TX P + mgt_status_o : out std_logic_vector(31 downto 0); -- MGT Status + mgt_control_i : in std_logic_vector(31 downto 0); -- MGT Control + mgt_rx_data_o : out std_logic_Vector(15 downto 0); -- for debug purpose + mgt_rx_charisk_o : out std_logic_vector(1 downto 0); -- for debug purpose + + --------------------------------------------------------------------------- + -- User interface MGT clock + --------------------------------------------------------------------------- + clk_evr_o : out std_logic; -- Recovered parallel clock from MGT + rst_evr_o : out std_logic; -- reset according to RX Loss of sync + usr_events_o : out std_logic_vector(3 downto 0); -- User defined event pulses with one clock cycles length & no delay + sos_event_o : out std_logic; -- Start-of-Sequence Event + usr_events_adj_o : out std_logic_vector(3 downto 0); -- User defined event pulses adjusted in delay & length + sos_events_adj_o : out std_logic; -- Start-of-Sequence adjusted in delay & length + -------------------------------------------------------------------------- + -- Decoder axi stream interface, User clock + -------------------------------------------------------------------------- + stream_clk_i : in std_logic := '0'; + stream_data_o : out std_logic_vector(7 downto 0); + stream_addr_o : out std_logic_vector(10 downto 0); + stream_valid_o : out std_logic + ); +end evr320_ifc1210_wrapper; + +architecture rtl of evr320_ifc1210_wrapper is + + -- -------------------------------------------------------------------------- + -- Parameters + -- -------------------------------------------------------------------------- + constant c_TOSCA2_DATA_WIDTH : integer := 64; + constant c_EVR_REG64_COUNT : integer := 16; -- unused, only documentation + constant c_EVR_MEM_SIZE : integer := 16384; -- unused, only documentation + + -- -------------------------------------------------------------------------- + -- Signal definitions + -- -------------------------------------------------------------------------- + signal clk_evr : std_logic; + --signal clk_evr_monitor : std_logic; -- for debugging + signal rst_evr : std_logic; + signal mgt_control : std_logic_vector(31 downto 0) := (others => '0'); + signal mgt_status : std_logic_vector(31 downto 0); + signal mgt_rx_data : std_logic_vector(15 downto 0); + signal mgt_rx_charisk : std_logic_vector(1 downto 0); + signal mgt_lossofsync : std_logic; + signal mgt_reset_tmem_evr : std_logic; -- for legacy reasons, ifc1210 mgt control is in tmem_psi_generic part + signal mem_clk : std_logic; + signal mem_addr_evr : std_logic_vector(11 downto 0); + signal mem_addr_tosca : std_logic_vector(10 downto 0); + signal mem_data : std_logic_vector(c_TOSCA2_DATA_WIDTH - 1 downto 0); + signal evr_params : typ_evr320_params; + signal evr_params_sync : typ_evr320_params; + signal evr_params_xuser : typ_evr320_params; + signal event_recorder_status : typ_evt_rec_status; + signal event_recorder_control : typ_evt_rec_ctrl; + signal event_recorder_control_sync : typ_evt_rec_ctrl; + signal event_recorder_control_xuser : typ_evt_rec_ctrl; + signal evr_latency_measure_stat : typ_rec_latency_measure_stat; + signal evr_latency_measure_ctrl : typ_rec_latency_measure_ctrl; + signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0'); + signal debug_data : std_logic_vector(127 downto 0); + signal decoder_event_valid : std_logic; + signal decoder_event : std_logic_vector(7 downto 0); + + -- -------------------------------------------------------------------------- + -- Attribute definitions + -- -------------------------------------------------------------------------- + attribute keep : string; + attribute keep of clk_evr : signal is "TRUE"; + attribute keep of debug_data : signal is "TRUE"; + signal usr_events_s : std_logic_vector(3 downto 0); + signal sos_event_s : std_logic; + signal evr_rst_s : std_logic; + signal usr_event_delay_s : typ_arr_delay; + signal usr_event_width_s : typ_arr_width; + + -- ---------------------------------------------------------------------------- + -- ---------------------------------------------------------------------------- + -- //////////////////// Main Body ///////////////////////// + -- ---------------------------------------------------------------------------- + -- ---------------------------------------------------------------------------- +begin + + -- -------------------------------------------------------------------------- + -- static signal assignments + -- -------------------------------------------------------------------------- + mgt_lossofsync <= mgt_status(15); + rst_evr_o <= mgt_status(15); + mem_addr_evr <= '0' & mem_addr_tosca; + + mgt_control(c_GTXRESET) <= mgt_control_i(c_GTXRESET) or mgt_sfp_los_i or mgt_reset_tmem_evr; + mgt_control(4 downto 1) <= mgt_control_i(4 downto 1); + mgt_control(c_RXCDRRESET) <= mgt_control_i(c_RXCDRRESET); + mgt_control(31 downto 6) <= mgt_control_i(31 downto 6); + + -- -------------------------------------------------------------------------- + -- Synchronisation to EVR Clock + -- -------------------------------------------------------------------------- + prc_sync_evr : process(clk_evr) + begin + if rising_edge(clk_evr) then + --- + evr_params_sync <= evr_params_xuser; + evr_params <= evr_params_sync; + --- + event_recorder_control_sync <= event_recorder_control_xuser; + event_recorder_control <= event_recorder_control_sync; + --- + end if; + end process; + + -- -------------------------------------------------------------------------- + -- EVR320 Decoder + -- -------------------------------------------------------------------------- + evr320_decoder_inst : entity work.evr320_decoder + generic map( + FACILITY => g_FACILITY, + EVENT_RECORDER => g_EVENT_RECORDER, + MEM_DATA_WIDTH => c_TOSCA2_DATA_WIDTH, + EXP_REC_CLK_FREQ => 50_632_820) + port map( + -- Debug interface + debug_clk => debug_clk, + debug => debug_data, + -- GTX parallel interface + i_mgt_rst => mgt_lossofsync, + i_mgt_rx_clk => clk_evr, + i_mgt_rx_data => mgt_rx_data, + i_mgt_rx_charisk => mgt_rx_charisk, + -- User interface CPU clock + i_usr_clk => mem_clk, + i_evr_params => evr_params, + o_event_recorder_stat => event_recorder_status, + i_event_recorder_ctrl => event_recorder_control, + i_mem_addr => mem_addr_evr, + o_mem_data => mem_data, + -- user stream interface, user clock + i_stream_clk => stream_clk_i, + o_stream_data => stream_data_o, + o_stream_addr => stream_addr_o, + o_stream_valid => stream_valid_o, + -- User interface MGT clock + o_usr_events => usr_events_s, + -- o_usr_events_ext => usr_events_ext_o, -- not in use anymore + o_sos_event => sos_event_s, + o_event => decoder_event, + o_event_valid => decoder_event_valid + ); + + usr_events_o <= usr_events_s; + sos_event_o <= sos_event_s; + + -- -------------------------------------------------------------------------- + -- MGT Wrapper for GTX Virtex-6 + -- -------------------------------------------------------------------------- + mgt_wrapper_inst : entity work.v6vlx_gtxe1_wrapper + generic map( + g_MGT_LOCATION => g_MGT_LOCATION, + g_FACILITY => g_FACILITY) + port map( + -- MGT serial interface + i_mgt_refclk => mgt_refclk_i, + o_mgt_refclk => open, + i_mgt_rx_p => mgt_rx_p, + i_mgt_rx_n => mgt_rx_n, + o_mgt_tx_p => mgt_tx_p, + o_mgt_tx_n => mgt_tx_n, + -- MGT parallel interface + o_mgt_status => mgt_status, + i_mgt_control => mgt_control, + o_mgt_recclk => clk_evr, + o_mgt_rx_data => mgt_rx_data, + o_mgt_rx_charisk => mgt_rx_charisk + ); + mgt_rx_charisk_o <= mgt_rx_charisk; + mgt_rx_data_o <= mgt_rx_data; + -- -------------------------------------------------------------------------- + -- TMEM + -- -------------------------------------------------------------------------- + --formatter:off + evr320_tmem_inst : entity work.evr320_tmem + port map( + -- TOSCA2 TMEM Interface + xuser_CLK => xuser_CLK, + xuser_RESET => xuser_RESET, + xuser_TMEM_ENA => xuser_TMEM_ENA, + xuser_TMEM_WE => xuser_TMEM_WE, + xuser_TMEM_ADD => xuser_TMEM_ADD, + xuser_TMEM_DATW => xuser_TMEM_DATW, + xuser_TMEM_DATR => xuser_TMEM_DATR, + -- EVR320 Memory/Parameter Interface + evr_params_o => evr_params_xuser, + evr_frequency_i => evr_frequency, + evr_evt_rec_status_i => event_recorder_status, + evr_evt_rec_control_o => event_recorder_control_xuser, + evr_latency_measure_stat_i => evr_latency_measure_stat, + evr_latency_measure_ctrl_o => evr_latency_measure_ctrl, + mgt_status_i => mgt_status, + mgt_reset_o => mgt_reset_tmem_evr, + mem_clk_o => mem_clk, + mem_addr_o => mem_addr_tosca, + mem_data_i => mem_data, + -- + evr_clk_i => clk_evr, + evr_rst_i => evr_rst_s, + evr_pulse_delay_o => usr_event_delay_s, + evr_pulse_width_o => usr_event_width_s); + + -- -------------------------------------------------------------------------- + -- Measure EVR Clock (based on xuser_CLK) + -- -------------------------------------------------------------------------- + clock_meas_inst : entity work.psi_common_clk_meas + generic map( + master_frequency_g => g_XUSER_CLK_FREQ, + max_meas_frequency_g => 150000000 + ) + port map( + clk_master_i => xuser_CLK, + rst_i => xuser_RESET, + clk_test_i => clk_evr, + frequency_hz_o => evr_frequency + ); + + -- -------------------------------------------------------------------------- + -- Event Latency Measurement for SW tests + -- -------------------------------------------------------------------------- + lat_meas_block : block + type state_type is (armed, count); + signal state : state_type; + signal counter : unsigned(31 downto 0); + signal event_nr_sync, event_nr : std_logic_vector(7 downto 0); + signal event_detected : std_logic_vector(3 downto 0); + signal event_detected_sync : std_logic_vector(1 downto 0); + constant MAX_COUNT : unsigned(31 downto 0) := to_unsigned(g_XUSER_CLK_FREQ / 10, 32); -- MAX 100ms ~ 10Hz + begin + + -- Process: filter events for matching event_nr register: + --------------------------------------------------------- + ext_event_proc : process(clk_evr) + begin + if (rising_edge(clk_evr)) then + -- sync to MGT clock domain: + event_nr_sync <= evr_latency_measure_ctrl.event_nr; + event_nr <= event_nr_sync; + + -- check if event has been detected and stretch pulse: + event_detected <= event_detected(2 downto 0) & '0'; + if (decoder_event_valid = '1' and decoder_event = event_nr) then + event_detected <= (others => '1'); + end if; + end if; + end process; + + -- Process: Counter when configured event has been detected: + ------------------------------------------------------------ + lat_meas_proc : process(xuser_CLK, counter) + begin + if rising_edge(xuser_CLK) then + -- sync to user clock domain: + event_detected_sync <= event_detected_sync(0) & event_detected(3); + + -- counter FSM: + --------------- + case state is + -- counter is armed: + when armed => + counter <= (others => '0'); + -- start counting when event detected (rising edge): + if (event_detected_sync(1) = '0' and event_detected_sync(0) = '1') then + state <= count; + end if; + + -- counting: + when count => + -- count only up to 10ms, and stop: + if (counter < MAX_COUNT) then + counter <= counter + 1; + end if; + if (evr_latency_measure_ctrl.counter_arm = '1') then + state <= armed; + end if; + end case; + end if; + + evr_latency_measure_stat.counter_val <= std_logic_vector(counter); + end process; + + end block; + + -- -------------------------------------------------------------------------- + -- Add delay output + -- -------------------------------------------------------------------------- + output_delay_block : block + --signal rst0_s, rst1_s : std_logic; -- double stage sync for reset + signal usr_evt_shaped_s : std_logic_vector(4 downto 0); + signal usr_events_adj_s : std_logic_vector(4 downto 0); + signal usr_events_concat_s : std_logic_vector(4 downto 0); + + begin + + evr_rst_s <= mgt_status(15); -- RXLOSSOFSYNC + usr_events_concat_s <= usr_events_s & sos_event_s; + + gene_adj_out : for i in 0 to 4 generate + + --*** Adjust pulse length in clk cycles EVENT 0,1,2,3 *** + inst_pulslength_evt0 : entity work.psi_common_pulse_shaper_cfg + generic map(HoldIn_g => false, + hold_off_ena_g => false, + max_hold_off_g => 10, + max_duration_g => MaxDuration_c, + Rst_Pol_g => '1') + port map(clk_i => clk_evr, + rst_i => evr_rst_s, + width_i => usr_event_width_s(i), + hold_i => (others => '0'), + dat_i => usr_events_concat_s(i), + dat_o => usr_evt_shaped_s(i)); + + --*** delay adjust EVENT 0,1,2,3*** + inst_adjdelay_evt0 : entity work.psi_common_delay_cfg + generic map(width_g => 1, + max_delay_g => MaxDelay_c, + rst_pol_g => '1', + ram_behavior_g => "RBW", + hold_g => True) + port map(clk_i => clk_evr, + rst_i => evr_rst_s, + dat_i(0) => usr_evt_shaped_s(i), + vld_i => '1', + del_i => usr_event_delay_s(i), + dat_o(0) => usr_events_adj_s(i)); + end generate; + + usr_events_adj_o <= usr_events_adj_s(4 downto 1); + sos_events_adj_o <= usr_events_adj_s(0); + end block; + -- -------------------------------------------------------------------------- + -- port mapping + -- -------------------------------------------------------------------------- + clk_evr_o <= clk_evr; + mgt_status_o <= mgt_status; + debug <= debug_data; + +end rtl; +-- ---------------------------------------------------------------------------- +-- //////////////////////////////////////////////////////////////////////////// +-- ---------------------------------------------------------------------------- diff --git a/hdl/evr320_tmem.vhd b/hdl/evr320_tmem.vhd index 988acfe..aedf8ba 100644 --- a/hdl/evr320_tmem.vhd +++ b/hdl/evr320_tmem.vhd @@ -1,382 +1,403 @@ --- --------------------------------------------------------------------------- --- Paul Scherrer Institute (PSI) --- --------------------------------------------------------------------------- --- Unit : evr320_tmem.vhd --- Author : Patric Bucher, Benoit Stef --- --------------------------------------------------------------------------- --- Copyright (c) PSI, Section DSV --- --------------------------------------------------------------------------- --- Comment : TMEM address decoding for register and memory access to evr320. --- --------------------------------------------------------------------------- -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; -use ieee.math_real.all; - -library tosca2; -use tosca2.tosca2_glb_pkg.all; - -use work.evr320_pkg.all; - -entity evr320_tmem is - port( - -- ------------------------------------------------------------------------ - -- TOSCA2 TMEM Interface (xuser clock domain, 100-250MHz) - -- ------------------------------------------------------------------------ - xuser_CLK : in std_logic; - xuser_RESET : in std_logic; - xuser_TMEM_ENA : in std_logic; - xuser_TMEM_WE : in std_logic_vector( 7 downto 0); - xuser_TMEM_ADD : in std_logic_vector(13 downto 3); - xuser_TMEM_DATW : in std_logic_vector(63 downto 0); - xuser_TMEM_DATR : out std_logic_vector(63 downto 0); - --------------------------------------------------------------------------- - -- EVR320 Memory/Parameter Interface - --------------------------------------------------------------------------- - evr_params_o : out typ_evr320_params; - evr_frequency_i : in std_logic_vector(31 downto 0); - evr_evt_rec_status_i : in typ_evt_rec_status; - evr_evt_rec_control_o : out typ_evt_rec_ctrl; - evr_latency_measure_stat_i : in typ_rec_latency_measure_stat; - evr_latency_measure_ctrl_o : out typ_rec_latency_measure_ctrl; - mgt_status_i : in std_logic_vector(31 downto 0) := (others=>'0'); - mgt_reset_o : out std_logic; - mem_clk_o : out std_logic; - mem_addr_o : out std_logic_vector(10 downto 0); - mem_data_i : in std_logic_vector(63 downto 0); - --------------------------------------------------------------------------- - -- EVR320 pulse output paremters - --------------------------------------------------------------------------- - evr_clk_i : in std_logic; - evr_rst_i : in std_logic; - evr_pulse_delay_o : out typ_arr_delay; - evr_pulse_width_o : out typ_arr_width - ); -end evr320_tmem; - - -architecture rtl of evr320_tmem is - - -- --------------------------------------------------------------------------- - -- Constants - -- --------------------------------------------------------------------------- - constant reserved : std_logic_vector(63 downto 0) := X"0000_0000_0000_0000"; - constant c_LOW : std_logic_vector(63 downto 0) := X"0000_0000_0000_0000"; - constant NUM_REG64 : integer := 16; - constant TMEM_ADDR_LSB : integer := 3; -- 64 bit - constant REG_ADDR_WIDTH : integer := integer(ceil(log2(real(NUM_REG64)))) + TMEM_ADDR_LSB; - constant REG_ADDR_MSB : integer := REG_ADDR_WIDTH - 1; - constant MEM_ADDR_START : std_logic_vector(7 downto 0) := X"10"; - - - - -- -------------------------------------------------------------------------- - -- Signal definitions - -- -------------------------------------------------------------------------- - -- xuser tmem signals - signal xuser_TMEM_WE_reg : std_logic_vector( 7 downto 0) := (others => '0'); - signal xuser_TMEM_ENA_reg : std_logic := '0'; - signal xuser_TMEM_ADD_reg : std_logic_vector(13 downto 3) := (others => '0'); - signal xuser_TMEM_DATW_reg : std_logic_vector(63 downto 0) := (others => '0'); - - -- evr params - signal mgt_status_evr : std_logic_vector(15 downto 0) := (others => '0'); - signal mgt_status_evr_sync : std_logic_vector(15 downto 0) := (others => '0'); - signal mgt_reset : std_logic := '0'; - signal event_enable : std_logic_vector( 3 downto 0) := (others => '0'); - signal event_numbers : typ_arr8(3 downto 0) := (others => (others => '0')); - signal event_numbers_concat : std_logic_vector(31 downto 0); - signal cs_min_cnt : std_logic_vector(31 downto 0) := c_CHECKSUM_MIN_EVT; - signal cs_min_time : std_logic_vector(31 downto 0) := c_CHECKSUM_MIN_TIME; - signal evr_frequency_sync : std_logic_vector(31 downto 0) := (others => '0'); - signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0'); - - -- event recorder - signal er_status : typ_evt_rec_status := c_INIT_EVT_REC_STATUS; - signal er_status_sync : typ_evt_rec_status := c_INIT_EVT_REC_STATUS; - signal er_event_enable : std_logic := '0'; - signal er_event_number : std_logic_vector( 7 downto 0) := c_SOS_EVENT_DEFAULT; - signal er_data_ack : std_logic_vector( 3 downto 0) := (others => '0'); - signal er_error_ack : std_logic_vector( 3 downto 0) := (others => '0'); - signal er_handshake_status : std_logic_vector(31 downto 0) := (others => '0'); - signal er_control_concat : std_logic_vector(31 downto 0) := (others => '0'); - - -- latency measurement - signal lat_counter_arm : std_logic := '0'; - signal lat_event_nr : std_logic_vector(7 downto 0) := c_SOS_EVENT_DEFAULT; - signal lat_counter_val : std_logic_vector(31 downto 0) := (others=>'0'); - signal lat_event_detected : std_logic_vector(7 downto 0); - signal lat_arm : std_logic := '0'; - signal lat_arm_edge : std_logic_vector(1 downto 0) := (others=>'0'); - - -- event pulse config - signal evr_puls_width_cfg_s : typ_arr_width :=(others => UsrEventWidthDefault_c); - signal evr_puls_delay_cfg_s : typ_arr_delay :=(others => (others => '0')); - --- ---------------------------------------------------------------------------- --- ---------------------------------------------------------------------------- --- //////////////////// Main Body ///////////////////////// --- ---------------------------------------------------------------------------- --- ---------------------------------------------------------------------------- -begin - - -- -------------------------------------------------------------------------- - -- static signal assignments - -- -------------------------------------------------------------------------- - event_numbers_concat <= event_numbers(3) & event_numbers(2) & event_numbers(1) & event_numbers(0); - er_handshake_status <= X"0000" & bit2byte(er_status.data_error) & bit2byte(er_status.data_valid); - er_control_concat <= X"0000" & er_event_number & bit2byte(er_event_enable); - lat_counter_val <= evr_latency_measure_stat_i.counter_val; - - process (xuser_CLK) - begin - if rising_edge(xuser_CLK) then - -- edge detection of latency arm: - lat_arm_edge <= lat_arm_edge(0) & lat_arm; - lat_counter_arm <= lat_arm_edge(0) and not lat_arm_edge(1); - - - if (evr_latency_measure_stat_i.event_detected = '1') then - lat_event_detected <= (others=>'1'); - end if; - if (lat_counter_arm = '1') then - lat_event_detected <= (others=>'0'); - end if; - end if; - end process; - - -- -------------------------------------------------------------------------- - -- Synchronisation to xuser_CLK - -- -------------------------------------------------------------------------- - prc_sync_xuser: process (xuser_CLK) - begin - if rising_edge(xuser_CLK) then - --- - xuser_TMEM_WE_reg <= xuser_TMEM_WE; - xuser_TMEM_ENA_reg <= xuser_TMEM_ENA; - xuser_TMEM_DATW_reg <= xuser_TMEM_DATW; - xuser_TMEM_ADD_reg <= xuser_TMEM_ADD; - --- - mgt_status_evr_sync <= "000000" & mgt_status_i(c_RXRESETDONE) & mgt_status_i(c_RXLOSSOFSYNC) & "000000" & mgt_status_i(c_RXRESETDONE) & mgt_status_i(c_RXPLLLKDET); - mgt_status_evr <= mgt_status_evr_sync; - --- - er_status_sync <= evr_evt_rec_status_i; - er_status <= er_status_sync; - --- - evr_frequency_sync <= evr_frequency_i; - evr_frequency <= evr_frequency_sync; - --- - end if; - end process; - - -- -------------------------------------------------------------------------- - -- Read operation - -- -------------------------------------------------------------------------- - blk_tmemrd : block - - begin - read_tmem_evr: process(xuser_CLK) - begin - if (rising_edge(xuser_CLK)) then - if (xuser_TMEM_ENA_reg = '1') then - if (xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = c_LOW(13 downto REG_ADDR_WIDTH)) then - case xuser_TMEM_ADD_reg(REG_ADDR_MSB downto TMEM_ADDR_LSB) is - when X"0" => xuser_TMEM_DATR <= event_numbers_concat & X"0000" & mgt_status_evr; -- 64bit / ByteAddr 000 - when X"1" => xuser_TMEM_DATR <= reserved(63 downto 32) & X"0000_00" & bit2byte(mgt_reset); -- 64bit / ByteAddr 008 --> 0x00C = not implemented in ifc1210 - when X"2" => xuser_TMEM_DATR <= reserved(63 downto 32) & bit2byte(event_enable); -- 64bit / ByteAddr 010 --> 0x014 = Bit0 SW Trigger Event 0, Bit8 SW Trigger Event 1, ... - when X"3" => xuser_TMEM_DATR <= evr_frequency & reserved(31 downto 0); -- 64bit / ByteAddr 018 --> 0x018 = Implementation Options + c_EVR_Location_vec - when X"4" => xuser_TMEM_DATR <= cs_min_time & cs_min_cnt; -- 64bit / ByteAddr 020 - when X"5" => xuser_TMEM_DATR <= reserved(63 downto 0); -- 64bit / ByteAddr 028 - when X"6" => xuser_TMEM_DATR <= lat_counter_val & x"00" & lat_event_detected & X"00" & lat_event_nr; -- 64bit / ByteAddr 030 - when X"7" => xuser_TMEM_DATR <= reserved(63 downto 32) & reserved(31 downto 0); -- 64bit / ByteAddr 038 - when X"8" => xuser_TMEM_DATR <= er_handshake_status & er_control_concat; -- 64bit / ByteAddr 040 - when X"9" => xuser_TMEM_DATR <= reserved(63 downto 32) & er_status.usr_events_counter; -- 64bit / ByteAddr 048 - when X"A" => xuser_TMEM_DATR <= evr_puls_delay_cfg_s(4) & evr_puls_delay_cfg_s(3) & evr_puls_delay_cfg_s(2) & evr_puls_delay_cfg_s(1) ; -- 64bit / ByteAddr 050 - when X"B" => xuser_TMEM_DATR <= evr_puls_width_cfg_s(4) & evr_puls_width_cfg_s(3) & evr_puls_width_cfg_s(2) & evr_puls_width_cfg_s(1) ; --64 bit / ByteAddr 054 - when X"C" => xuser_TMEM_DATR <= reserved(63 downto 32) & evr_puls_width_cfg_s(0) & evr_puls_delay_cfg_s(0); -- 64bit / ByteAddr 058 - when others => xuser_TMEM_DATR <= (others => '0'); - end case; - else --> 0x0080-0x4000 - xuser_TMEM_DATR <= mem_data_i; - end if; - end if; - end if; - end process; - - end block; - - -- -------------------------------------------------------------------------- - -- Write operation - Byte control - -- -------------------------------------------------------------------------- - write_tmem_evr: process(xuser_CLK) - begin - if rising_edge(xuser_CLK) then - - -- default assignments - er_data_ack <= er_data_ack(2 downto 0) & '0'; - er_error_ack <= er_error_ack(2 downto 0) & '0'; - lat_arm <= '0'; - - - if (xuser_TMEM_ENA_reg = '1' and xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = c_LOW(13 downto REG_ADDR_WIDTH)) then - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"0" then --ByteAddr 000 - -- if xuser_TMEM_WE_reg(0) = '1' then -read only- <= xuser_TMEM_DATW_reg( 7 downto 0); end if; - -- if xuser_TMEM_WE_reg(1) = '1' then -read only- <= xuser_TMEM_DATW_reg(15 downto 8); end if; - -- if xuser_TMEM_WE_reg(2) = '1' then -read only- <= xuser_TMEM_DATW_reg(23 downto 16); end if; - -- if xuser_TMEM_WE_reg(3) = '1' then -read only- <= xuser_TMEM_DATW_reg(31 downto 24); end if; - if xuser_TMEM_WE_reg(4) = '1' then event_numbers(0) <= xuser_TMEM_DATW_reg(39 downto 32); end if; - if xuser_TMEM_WE_reg(5) = '1' then event_numbers(1) <= xuser_TMEM_DATW_reg(47 downto 40); end if; - if xuser_TMEM_WE_reg(6) = '1' then event_numbers(2) <= xuser_TMEM_DATW_reg(55 downto 48); end if; - if xuser_TMEM_WE_reg(7) = '1' then event_numbers(3) <= xuser_TMEM_DATW_reg(63 downto 56); end if; - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"1" then --ByteAddr 008 - if xuser_TMEM_WE_reg(0) = '1' then mgt_reset <= xuser_TMEM_DATW_reg(0); end if; - -- if xuser_TMEM_WE_reg(1) = '1' then -reserved- <= xuser_TMEM_DATW_reg(15 downto 8); end if; - -- if xuser_TMEM_WE_reg(2) = '1' then -reserved- <= xuser_TMEM_DATW_reg(23 downto 16); end if; - -- if xuser_TMEM_WE_reg(3) = '1' then -reserved- <= xuser_TMEM_DATW_reg(31 downto 24); end if; - -- if xuser_TMEM_WE_reg(4) = '1' then -reserved- <= xuser_TMEM_DATW_reg(39 downto 32); end if; - -- if xuser_TMEM_WE_reg(5) = '1' then -reserved- <= xuser_TMEM_DATW_reg(47 downto 40); end if; - -- if xuser_TMEM_WE_reg(6) = '1' then -reserved- <= xuser_TMEM_DATW_reg(55 downto 48); end if; - -- if xuser_TMEM_WE_reg(7) = '1' then -reserved- <= xuser_TMEM_DATW_reg(63 downto 56); end if; - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"2" then --ByteAddr 010 - if xuser_TMEM_WE_reg(0) = '1' then event_enable(0) <= xuser_TMEM_DATW_reg( 0); end if; - if xuser_TMEM_WE_reg(1) = '1' then event_enable(1) <= xuser_TMEM_DATW_reg( 8); end if; - if xuser_TMEM_WE_reg(2) = '1' then event_enable(2) <= xuser_TMEM_DATW_reg(16); end if; - if xuser_TMEM_WE_reg(3) = '1' then event_enable(3) <= xuser_TMEM_DATW_reg(24); end if; - -- if xuser_TMEM_WE_reg(4) = '1' then -reserved- <= xuser_TMEM_DATW_reg(39 downto 32); end if; - -- if xuser_TMEM_WE_reg(5) = '1' then -reserved- <= xuser_TMEM_DATW_reg(47 downto 40); end if; - -- if xuser_TMEM_WE_reg(6) = '1' then -reserved- <= xuser_TMEM_DATW_reg(55 downto 48); end if; - -- if xuser_TMEM_WE_reg(7) = '1' then -reserved- <= xuser_TMEM_DATW_reg(63 downto 56); end if; - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"4" then --ByteAddr 020 - if xuser_TMEM_WE_reg(0) = '1' then cs_min_cnt ( 7 downto 0) <= xuser_TMEM_DATW_reg( 7 downto 0); end if; - if xuser_TMEM_WE_reg(1) = '1' then cs_min_cnt (15 downto 8) <= xuser_TMEM_DATW_reg(15 downto 8); end if; - if xuser_TMEM_WE_reg(2) = '1' then cs_min_cnt (23 downto 16) <= xuser_TMEM_DATW_reg(23 downto 16); end if; - if xuser_TMEM_WE_reg(3) = '1' then cs_min_cnt (31 downto 24) <= xuser_TMEM_DATW_reg(31 downto 24); end if; - if xuser_TMEM_WE_reg(4) = '1' then cs_min_time( 7 downto 0) <= xuser_TMEM_DATW_reg(39 downto 32); end if; - if xuser_TMEM_WE_reg(5) = '1' then cs_min_time(15 downto 8) <= xuser_TMEM_DATW_reg(47 downto 40); end if; - if xuser_TMEM_WE_reg(6) = '1' then cs_min_time(23 downto 16) <= xuser_TMEM_DATW_reg(55 downto 48); end if; - if xuser_TMEM_WE_reg(7) = '1' then cs_min_time(31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if; - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"6" then --ByteAddr 030 Latency Measurement - if xuser_TMEM_WE_reg(0) = '1' then lat_event_nr ( 7 downto 0) <= xuser_TMEM_DATW_reg( 7 downto 0); end if; - -- if xuser_TMEM_WE_reg(1) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(15 downto 8); end if; - -- if xuser_TMEM_WE_reg(2) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(23 downto 16); end if; - -- if xuser_TMEM_WE_reg(3) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(31 downto 24); end if; - -- if xuser_TMEM_WE_reg(4) = '1' then -reserved- ( 7 downto 0) <= xuser_TMEM_DATW_reg(39 downto 32); end if; - -- if xuser_TMEM_WE_reg(5) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(47 downto 40); end if; - -- if xuser_TMEM_WE_reg(6) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(55 downto 48); end if; - -- if xuser_TMEM_WE_reg(7) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if; - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"7" then --ByteAddr 038 Latency Measurement - if xuser_TMEM_WE_reg(0) = '1' then lat_arm <= xuser_TMEM_DATW_reg(0); end if; - -- if xuser_TMEM_WE_reg(1) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(15 downto 8); end if; - -- if xuser_TMEM_WE_reg(2) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(23 downto 16); end if; - -- if xuser_TMEM_WE_reg(3) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(31 downto 24); end if; - -- if xuser_TMEM_WE_reg(4) = '1' then -reserved- ( 7 downto 0) <= xuser_TMEM_DATW_reg(39 downto 32); end if; - -- if xuser_TMEM_WE_reg(5) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(47 downto 40); end if; - -- if xuser_TMEM_WE_reg(6) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(55 downto 48); end if; - -- if xuser_TMEM_WE_reg(7) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if; - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"8" then --ByteAddr 040 - if xuser_TMEM_WE_reg(0) = '1' then er_event_enable <= xuser_TMEM_DATW_reg(0); end if; - if xuser_TMEM_WE_reg(1) = '1' then er_event_number <= xuser_TMEM_DATW_reg(15 downto 8); end if; - -- if xuser_TMEM_WE_reg(2) = '1' then -reserved- <= xuser_TMEM_DATW_reg(23 downto 16); end if; - -- if xuser_TMEM_WE_reg(3) = '1' then -reserved- <= xuser_TMEM_DATW_reg(31 downto 24); end if; - -- if xuser_TMEM_WE_reg(4) = '1' then -read only- <= xuser_TMEM_DATW_reg(39 downto 32); end if; - -- if xuser_TMEM_WE_reg(5) = '1' then -read only- <= xuser_TMEM_DATW_reg(47 downto 40); end if; - if xuser_TMEM_WE_reg(6) = '1' and xuser_TMEM_DATW_reg(48) = '1' then er_data_ack <= (others => '1'); end if; - if xuser_TMEM_WE_reg(7) = '1' and xuser_TMEM_DATW_reg(56) = '1' then er_error_ack <= (others => '1'); end if; - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"A" then --ByteAddr 050 - if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_delay_cfg_s(1) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- usr evt 0 del - if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_delay_cfg_s(2) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- usr evt 1 del - if xuser_TMEM_WE_reg(5 downto 4) = "11" then evr_puls_delay_cfg_s(3) <= xuser_TMEM_DATW_reg(47 downto 32); end if; -- usr evt 2 del - if xuser_TMEM_WE_reg(7 downto 6) = "11" then evr_puls_delay_cfg_s(4) <= xuser_TMEM_DATW_reg(63 downto 48); end if; -- usr evt 3 del - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"B" then --ByteAddr 058 - if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_width_cfg_s(1) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- usr evt 0 width - if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_width_cfg_s(2) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- usr evt 1 width - if xuser_TMEM_WE_reg(5 downto 4) = "11" then evr_puls_width_cfg_s(3) <= xuser_TMEM_DATW_reg(47 downto 32); end if; -- usr evt 2 width - if xuser_TMEM_WE_reg(7 downto 6) = "11" then evr_puls_width_cfg_s(4) <= xuser_TMEM_DATW_reg(63 downto 48); end if; -- usr evt 3 width - end if; - ----------------------------------------------------------------------------------------------------------------- - if xuser_TMEM_ADD_reg(6 downto 3) = X"C" then --ByteAddr 060 - if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_delay_cfg_s(0) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- sos evt del - if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_width_cfg_s(0) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- sos evt width - end if; - end if; - end if; - end process; - - - -- -------------------------------------------------------------------------- - -- Port mapping - -- -------------------------------------------------------------------------- - mem_clk_o <= xuser_CLK; - mem_addr_o <= std_logic_vector(unsigned(xuser_TMEM_ADD) - unsigned(MEM_ADDR_START)); - evr_params_o <= (event_numbers, event_enable, cs_min_cnt, cs_min_time); - evr_evt_rec_control_o <= (er_event_number, er_event_enable, er_data_ack(3), er_error_ack(3)); - mgt_reset_o <= mgt_reset; - evr_latency_measure_ctrl_o <= (lat_event_nr, lat_counter_arm); - - -- -------------------------------------------------------------------------- - -- add CDC output - -- -------------------------------------------------------------------------- - block_cdc_evr_puls_param : block - signal input_s, output_s : std_logic_vector(10 * 16 - 1 downto 0); - begin - -- ------------------------------------------------------------------------ - -- Assemble Input - -- ------------------------------------------------------------------------ - --** pulse delay parameters ** - input_s(15 downto 0) <= evr_puls_delay_cfg_s(0); - input_s(31 downto 16) <= evr_puls_delay_cfg_s(1); - input_s(47 downto 32) <= evr_puls_delay_cfg_s(2); - input_s(63 downto 48) <= evr_puls_delay_cfg_s(3); - input_s(79 downto 64) <= evr_puls_delay_cfg_s(4); - --** pulse width parameters ** - input_s(95 downto 80) <= evr_puls_width_cfg_s(0); - input_s(111 downto 96) <= evr_puls_width_cfg_s(1); - input_s(127 downto 112) <= evr_puls_width_cfg_s(2); - input_s(143 downto 128) <= evr_puls_width_cfg_s(3); - input_s(159 downto 144) <= evr_puls_width_cfg_s(4); - - -- Instance - inst_cdc_fast_stat : entity work.psi_common_status_cc - generic map(DataWidth_g => input_s'length) - port map(ClkA => xuser_CLK, - RstInA => xuser_RESET, - DataA => input_s, - ClkB => evr_clk_i, - RstInB => evr_rst_i, - DataB => output_s); - -- ------------------------------------------------------------------------ - -- Disassemble Output - -- ------------------------------------------------------------------------ - --** pulse delay parameters ** - evr_pulse_delay_o(0) <= output_s(15 downto 0); - evr_pulse_delay_o(1) <= output_s(31 downto 16); - evr_pulse_delay_o(2) <= output_s(47 downto 32); - evr_pulse_delay_o(3) <= output_s(63 downto 48); - evr_pulse_delay_o(4) <= output_s(79 downto 64); - --** pulse width parameters ** - evr_pulse_width_o(0) <= output_s(95 downto 80); - evr_pulse_width_o(1) <= output_s(111 downto 96); - evr_pulse_width_o(2) <= output_s(127 downto 112); - evr_pulse_width_o(3) <= output_s(143 downto 128); - evr_pulse_width_o(4) <= output_s(159 downto 144); - end block; - -end rtl; - +-- --------------------------------------------------------------------------- +-- Paul Scherrer Institute (PSI) +-- --------------------------------------------------------------------------- +-- Unit : evr320_tmem.vhd +-- Author : Patric Bucher, Benoit Stef +-- --------------------------------------------------------------------------- +-- Copyright (c) PSI, Section DSV +-- --------------------------------------------------------------------------- +-- Comment : TMEM address decoding for register and memory access to evr320. +-- --------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +library tosca2; +use tosca2.tosca2_glb_pkg.all; + +use work.evr320_pkg.all; + +entity evr320_tmem is + port( + -- ------------------------------------------------------------------------ + -- TOSCA2 TMEM Interface (xuser clock domain, 100-250MHz) + -- ------------------------------------------------------------------------ + xuser_CLK : in std_logic; + xuser_RESET : in std_logic; + xuser_TMEM_ENA : in std_logic; + xuser_TMEM_WE : in std_logic_vector( 7 downto 0); + xuser_TMEM_ADD : in std_logic_vector(13 downto 3); + xuser_TMEM_DATW : in std_logic_vector(63 downto 0); + xuser_TMEM_DATR : out std_logic_vector(63 downto 0); + --------------------------------------------------------------------------- + -- EVR320 Memory/Parameter Interface + --------------------------------------------------------------------------- + evr_params_o : out typ_evr320_params; + evr_frequency_i : in std_logic_vector(31 downto 0); + evr_evt_rec_status_i : in typ_evt_rec_status; + evr_evt_rec_control_o : out typ_evt_rec_ctrl; + evr_latency_measure_stat_i : in typ_rec_latency_measure_stat; + evr_latency_measure_ctrl_o : out typ_rec_latency_measure_ctrl; + mgt_status_i : in std_logic_vector(31 downto 0); + mgt_reset_o : out std_logic; + mem_clk_o : out std_logic; + mem_addr_o : out std_logic_vector(10 downto 0); + mem_data_i : in std_logic_vector(63 downto 0); + --------------------------------------------------------------------------- + -- EVR320 pulse output paremters + --------------------------------------------------------------------------- + evr_clk_i : in std_logic; + evr_rst_i : in std_logic; + evr_pulse_delay_o : out typ_arr_delay; + evr_pulse_width_o : out typ_arr_width + ); +end evr320_tmem; + + +architecture rtl of evr320_tmem is + + -- --------------------------------------------------------------------------- + -- Constants + -- --------------------------------------------------------------------------- + constant reserved : std_logic_vector(63 downto 0) := X"0000_0000_0000_0000"; + constant c_LOW : std_logic_vector(63 downto 0) := X"0000_0000_0000_0000"; + constant NUM_REG64 : integer := 16; + constant TMEM_ADDR_LSB : integer := 3; -- 64 bit + constant REG_ADDR_WIDTH : integer := integer(ceil(log2(real(NUM_REG64)))) + TMEM_ADDR_LSB; + constant REG_ADDR_MSB : integer := REG_ADDR_WIDTH - 1; + constant MEM_ADDR_START : std_logic_vector(7 downto 0) := X"10"; + + + + -- -------------------------------------------------------------------------- + -- Signal definitions + -- -------------------------------------------------------------------------- + -- xuser tmem signals + signal xuser_TMEM_WE_reg : std_logic_vector( 7 downto 0) := (others => '0'); + signal xuser_TMEM_ENA_reg : std_logic := '0'; + signal xuser_TMEM_ADD_reg : std_logic_vector(13 downto 3) := (others => '0'); + signal xuser_TMEM_DATW_reg : std_logic_vector(63 downto 0) := (others => '0'); + + -- evr params + signal mgt_status_evr : std_logic_vector(15 downto 0) := (others => '0'); + signal mgt_status_evr_sync : std_logic_vector(15 downto 0) := (others => '0'); + signal mgt_reset : std_logic := '0'; + signal event_enable : std_logic_vector( 3 downto 0) := (others => '0'); + signal event_numbers : typ_arr8(3 downto 0) := (others => (others => '0')); + signal event_numbers_concat : std_logic_vector(31 downto 0); + signal cs_min_cnt : std_logic_vector(31 downto 0) := c_CHECKSUM_MIN_EVT; + signal cs_min_time : std_logic_vector(31 downto 0) := c_CHECKSUM_MIN_TIME; + signal evr_frequency_sync : std_logic_vector(31 downto 0) := (others => '0'); + signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0'); + + -- event recorder + signal er_status : typ_evt_rec_status := c_INIT_EVT_REC_STATUS; + signal er_status_sync : typ_evt_rec_status := c_INIT_EVT_REC_STATUS; + signal er_event_enable : std_logic := '0'; + signal er_event_number : std_logic_vector( 7 downto 0) := c_SOS_EVENT_DEFAULT; + signal er_data_ack : std_logic_vector( 3 downto 0) := (others => '0'); + signal er_error_ack : std_logic_vector( 3 downto 0) := (others => '0'); + signal er_handshake_status : std_logic_vector(31 downto 0) := (others => '0'); + signal er_control_concat : std_logic_vector(31 downto 0) := (others => '0'); + + -- latency measurement + signal lat_counter_arm : std_logic := '0'; + signal lat_event_nr : std_logic_vector(7 downto 0) := x"26"; -- default SOS event + signal lat_counter_val : std_logic_vector(31 downto 0) := (others=>'0'); + + -- signal evr_force : std_logic_vector(3 downto 0) := (others => '0'); + -- signal evr_force_rd : std_logic_vector(3 downto 0) := (others => '0'); -- readback + -- signal evr_force_pulse : typ_arr4(3 downto 0) := (others => (others => '0')); + + -- event pulse config + + signal evr_puls_width_cfg_s : typ_arr_width :=((others=>(others=>'0'))); + signal evr_puls_delay_cfg_s : typ_arr_delay :=((others=>(others=>'0'))); + +-- ---------------------------------------------------------------------------- +-- ---------------------------------------------------------------------------- +-- //////////////////// Main Body ///////////////////////// +-- ---------------------------------------------------------------------------- +-- ---------------------------------------------------------------------------- +begin + + -- -------------------------------------------------------------------------- + -- static signal assignments + -- -------------------------------------------------------------------------- + event_numbers_concat <= event_numbers(3) & event_numbers(2) & event_numbers(1) & event_numbers(0); + er_handshake_status <= X"0000" & bit2byte(er_status.data_error) & bit2byte(er_status.data_valid); + er_control_concat <= X"0000" & er_event_number & bit2byte(er_event_enable); + lat_counter_val <= evr_latency_measure_stat_i.counter_val; + + -- -------------------------------------------------------------------------- + -- TODO: proper CDC + -- Synchronisation to xuser_CLK + -- -------------------------------------------------------------------------- + prc_sync_xuser: process (xuser_CLK) + begin + if rising_edge(xuser_CLK) then + --- + xuser_TMEM_WE_reg <= xuser_TMEM_WE; + xuser_TMEM_ENA_reg <= xuser_TMEM_ENA; + xuser_TMEM_DATW_reg <= xuser_TMEM_DATW; + xuser_TMEM_ADD_reg <= xuser_TMEM_ADD; + --- + mgt_status_evr_sync <= "000000" & mgt_status_i(c_RXRESETDONE) & mgt_status_i(c_RXLOSSOFSYNC) & "000000" & mgt_status_i(c_RXRESETDONE) & mgt_status_i(c_RXPLLLKDET); + mgt_status_evr <= mgt_status_evr_sync; + --- + er_status_sync <= evr_evt_rec_status_i; + er_status <= er_status_sync; + --- + evr_frequency_sync <= evr_frequency_i; + evr_frequency <= evr_frequency_sync; + --- + end if; + end process; + + -- -------------------------------------------------------------------------- + -- Read operation + -- -------------------------------------------------------------------------- + read_tmem_evr: process(xuser_CLK) + begin + if (rising_edge(xuser_CLK)) then + lat_counter_arm <= '0'; + if (xuser_TMEM_ENA_reg = '1') then + if (xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = c_LOW(13 downto REG_ADDR_WIDTH)) then + case xuser_TMEM_ADD_reg(REG_ADDR_MSB downto TMEM_ADDR_LSB) is + when X"0" => xuser_TMEM_DATR <= event_numbers_concat & X"0000" & mgt_status_evr; -- 64bit / ByteAddr 000 + when X"1" => xuser_TMEM_DATR <= reserved(63 downto 32) & X"0000_00" & bit2byte(mgt_reset); -- 64bit / ByteAddr 008 --> 0x00C = not implemented in ifc1210 + when X"2" => xuser_TMEM_DATR <= reserved(63 downto 32) & bit2byte(event_enable); -- 64bit / ByteAddr 010 --> 0x014 = Bit0 SW Trigger Event 0, Bit8 SW Trigger Event 1, ... evr_force + when X"3" => xuser_TMEM_DATR <= evr_frequency & reserved(31 downto 0); -- 64bit / ByteAddr 018 --> 0x018 = Implementation Options + c_EVR_Location_vec + when X"4" => xuser_TMEM_DATR <= cs_min_time & cs_min_cnt; -- 64bit / ByteAddr 020 + when X"5" => xuser_TMEM_DATR <= reserved(63 downto 0); -- 64bit / ByteAddr 028 + when X"6" => xuser_TMEM_DATR <= lat_counter_val & X"000000" & lat_event_nr; -- 64bit / ByteAddr 030 + when X"7" => xuser_TMEM_DATR <= reserved(63 downto 32) & lat_counter_val; lat_counter_arm <= '1'; -- 64bit / ByteAddr 038 + when X"8" => xuser_TMEM_DATR <= er_handshake_status & er_control_concat; -- 64bit / ByteAddr 040 + when X"9" => xuser_TMEM_DATR <= reserved(63 downto 32) & er_status.usr_events_counter; -- 64bit / ByteAddr 048 + when X"A" => xuser_TMEM_DATR <= evr_puls_delay_cfg_s(4) & evr_puls_delay_cfg_s(3) & evr_puls_delay_cfg_s(2) & evr_puls_delay_cfg_s(1) ; -- 64bit / ByteAddr 050 + when X"B" => xuser_TMEM_DATR <= evr_puls_width_cfg_s(4) & evr_puls_width_cfg_s(3) & evr_puls_width_cfg_s(2) & evr_puls_width_cfg_s(1) ; --64 bit / ByteAddr 054 + when X"C" => xuser_TMEM_DATR <= reserved(63 downto 32) & evr_puls_width_cfg_s(0) & evr_puls_delay_cfg_s(0); -- 64bit / ByteAddr 058 + when others => xuser_TMEM_DATR <= (others => '0'); + end case; + else --> 0x0080-0x4000 + xuser_TMEM_DATR <= mem_data_i; + end if; + end if; + end if; + end process; + + + -- -------------------------------------------------------------------------- + -- Write operation - Byte control + -- -------------------------------------------------------------------------- + write_tmem_evr: process(xuser_CLK) + begin + if rising_edge(xuser_CLK) then + + -- default assignments + er_data_ack <= er_data_ack(2 downto 0) & '0'; + er_error_ack <= er_error_ack(2 downto 0) & '0'; + + + if (xuser_TMEM_ENA_reg = '1' and xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = c_LOW(13 downto REG_ADDR_WIDTH)) then + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"0" then --ByteAddr 000 + -- if xuser_TMEM_WE_reg(0) = '1' then -read only- <= xuser_TMEM_DATW_reg( 7 downto 0); end if; + -- if xuser_TMEM_WE_reg(1) = '1' then -read only- <= xuser_TMEM_DATW_reg(15 downto 8); end if; + -- if xuser_TMEM_WE_reg(2) = '1' then -read only- <= xuser_TMEM_DATW_reg(23 downto 16); end if; + -- if xuser_TMEM_WE_reg(3) = '1' then -read only- <= xuser_TMEM_DATW_reg(31 downto 24); end if; + if xuser_TMEM_WE_reg(4) = '1' then event_numbers(0) <= xuser_TMEM_DATW_reg(39 downto 32); end if; + if xuser_TMEM_WE_reg(5) = '1' then event_numbers(1) <= xuser_TMEM_DATW_reg(47 downto 40); end if; + if xuser_TMEM_WE_reg(6) = '1' then event_numbers(2) <= xuser_TMEM_DATW_reg(55 downto 48); end if; + if xuser_TMEM_WE_reg(7) = '1' then event_numbers(3) <= xuser_TMEM_DATW_reg(63 downto 56); end if; + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"1" then --ByteAddr 008 + if xuser_TMEM_WE_reg(0) = '1' then mgt_reset <= xuser_TMEM_DATW_reg(0); end if; + -- if xuser_TMEM_WE_reg(1) = '1' then -reserved- <= xuser_TMEM_DATW_reg(15 downto 8); end if; + -- if xuser_TMEM_WE_reg(2) = '1' then -reserved- <= xuser_TMEM_DATW_reg(23 downto 16); end if; + -- if xuser_TMEM_WE_reg(3) = '1' then -reserved- <= xuser_TMEM_DATW_reg(31 downto 24); end if; + -- if xuser_TMEM_WE_reg(4) = '1' then -reserved- <= xuser_TMEM_DATW_reg(39 downto 32); end if; + -- if xuser_TMEM_WE_reg(5) = '1' then -reserved- <= xuser_TMEM_DATW_reg(47 downto 40); end if; + -- if xuser_TMEM_WE_reg(6) = '1' then -reserved- <= xuser_TMEM_DATW_reg(55 downto 48); end if; + -- if xuser_TMEM_WE_reg(7) = '1' then -reserved- <= xuser_TMEM_DATW_reg(63 downto 56); end if; + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"2" then --ByteAddr 010 + if xuser_TMEM_WE_reg(0) = '1' then event_enable(0) <= xuser_TMEM_DATW_reg( 0); end if; + if xuser_TMEM_WE_reg(1) = '1' then event_enable(1) <= xuser_TMEM_DATW_reg( 8); end if; + if xuser_TMEM_WE_reg(2) = '1' then event_enable(2) <= xuser_TMEM_DATW_reg(16); end if; + if xuser_TMEM_WE_reg(3) = '1' then event_enable(3) <= xuser_TMEM_DATW_reg(24); end if; + -- if xuser_TMEM_WE_reg(4) = '1' then -reserved- <= xuser_TMEM_DATW_reg(39 downto 32); end if; + -- if xuser_TMEM_WE_reg(5) = '1' then -reserved- <= xuser_TMEM_DATW_reg(47 downto 40); end if; + -- if xuser_TMEM_WE_reg(6) = '1' then -reserved- <= xuser_TMEM_DATW_reg(55 downto 48); end if; + -- if xuser_TMEM_WE_reg(7) = '1' then -reserved- <= xuser_TMEM_DATW_reg(63 downto 56); end if; + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"4" then --ByteAddr 020 + if xuser_TMEM_WE_reg(0) = '1' then cs_min_cnt ( 7 downto 0) <= xuser_TMEM_DATW_reg( 7 downto 0); end if; + if xuser_TMEM_WE_reg(1) = '1' then cs_min_cnt (15 downto 8) <= xuser_TMEM_DATW_reg(15 downto 8); end if; + if xuser_TMEM_WE_reg(2) = '1' then cs_min_cnt (23 downto 16) <= xuser_TMEM_DATW_reg(23 downto 16); end if; + if xuser_TMEM_WE_reg(3) = '1' then cs_min_cnt (31 downto 24) <= xuser_TMEM_DATW_reg(31 downto 24); end if; + if xuser_TMEM_WE_reg(4) = '1' then cs_min_time( 7 downto 0) <= xuser_TMEM_DATW_reg(39 downto 32); end if; + if xuser_TMEM_WE_reg(5) = '1' then cs_min_time(15 downto 8) <= xuser_TMEM_DATW_reg(47 downto 40); end if; + if xuser_TMEM_WE_reg(6) = '1' then cs_min_time(23 downto 16) <= xuser_TMEM_DATW_reg(55 downto 48); end if; + if xuser_TMEM_WE_reg(7) = '1' then cs_min_time(31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if; + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"6" then --ByteAddr 030 Latency Measurement + if xuser_TMEM_WE_reg(0) = '1' then lat_event_nr ( 7 downto 0) <= xuser_TMEM_DATW_reg( 7 downto 0); end if; + -- if xuser_TMEM_WE_reg(1) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(15 downto 8); end if; + -- if xuser_TMEM_WE_reg(2) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(23 downto 16); end if; + -- if xuser_TMEM_WE_reg(3) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(31 downto 24); end if; + -- if xuser_TMEM_WE_reg(4) = '1' then -reserved- ( 7 downto 0) <= xuser_TMEM_DATW_reg(39 downto 32); end if; + -- if xuser_TMEM_WE_reg(5) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(47 downto 40); end if; + -- if xuser_TMEM_WE_reg(6) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(55 downto 48); end if; + -- if xuser_TMEM_WE_reg(7) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if; + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"8" then --ByteAddr 040 + if xuser_TMEM_WE_reg(0) = '1' then er_event_enable <= xuser_TMEM_DATW_reg(0); end if; + if xuser_TMEM_WE_reg(1) = '1' then er_event_number <= xuser_TMEM_DATW_reg(15 downto 8); end if; + -- if xuser_TMEM_WE_reg(2) = '1' then -reserved- <= xuser_TMEM_DATW_reg(23 downto 16); end if; + -- if xuser_TMEM_WE_reg(3) = '1' then -reserved- <= xuser_TMEM_DATW_reg(31 downto 24); end if; + -- if xuser_TMEM_WE_reg(4) = '1' then -read only- <= xuser_TMEM_DATW_reg(39 downto 32); end if; + -- if xuser_TMEM_WE_reg(5) = '1' then -read only- <= xuser_TMEM_DATW_reg(47 downto 40); end if; + if xuser_TMEM_WE_reg(6) = '1' and xuser_TMEM_DATW_reg(48) = '1' then er_data_ack <= (others => '1'); end if; + if xuser_TMEM_WE_reg(7) = '1' and xuser_TMEM_DATW_reg(56) = '1' then er_error_ack <= (others => '1'); end if; + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"A" then --ByteAddr 050 + if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_delay_cfg_s(1) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- usr evt 0 del + if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_delay_cfg_s(2) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- usr evt 1 del + if xuser_TMEM_WE_reg(5 downto 4) = "11" then evr_puls_delay_cfg_s(3) <= xuser_TMEM_DATW_reg(47 downto 32); end if; -- usr evt 2 del + if xuser_TMEM_WE_reg(7 downto 6) = "11" then evr_puls_delay_cfg_s(4) <= xuser_TMEM_DATW_reg(63 downto 48); end if; -- usr evt 3 del + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"B" then --ByteAddr 058 + if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_width_cfg_s(1) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- usr evt 0 width + if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_width_cfg_s(2) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- usr evt 1 width + if xuser_TMEM_WE_reg(5 downto 4) = "11" then evr_puls_width_cfg_s(3) <= xuser_TMEM_DATW_reg(47 downto 32); end if; -- usr evt 2 width + if xuser_TMEM_WE_reg(7 downto 6) = "11" then evr_puls_width_cfg_s(4) <= xuser_TMEM_DATW_reg(63 downto 48); end if; -- usr evt 3 width + end if; + ----------------------------------------------------------------------------------------------------------------- + if xuser_TMEM_ADD_reg(6 downto 3) = X"C" then --ByteAddr 060 + if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_delay_cfg_s(0) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- sos evt del + if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_width_cfg_s(0) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- sos evt width + end if; + end if; + end if; + end process; + + + -- -------------------------------------------------------------------------- + -- Port mapping + -- -------------------------------------------------------------------------- + mem_clk_o <= xuser_CLK; + mem_addr_o <= std_logic_vector(unsigned(xuser_TMEM_ADD) - unsigned(MEM_ADDR_START)); + --event recorder had to be also added to cdc + evr_evt_rec_control_o <= (er_event_number, er_event_enable, er_data_ack(3), er_error_ack(3)); + mgt_reset_o <= mgt_reset; + + -- -------------------------------------------------------------------------- + -- add CDC output + -- -------------------------------------------------------------------------- + block_cdc_evr_puls_param : block + signal input_s, output_s : std_logic_vector(10 * 16 - 1 downto 0); + begin + -- ------------------------------------------------------------------------ + -- Assemble Input + -- ------------------------------------------------------------------------ + --** pulse delay parameters ** + input_s(15 downto 0) <= evr_puls_delay_cfg_s(0); + input_s(31 downto 16) <= evr_puls_delay_cfg_s(1); + input_s(47 downto 32) <= evr_puls_delay_cfg_s(2); + input_s(63 downto 48) <= evr_puls_delay_cfg_s(3); + input_s(79 downto 64) <= evr_puls_delay_cfg_s(4); + --** pulse width parameters ** + input_s(95 downto 80) <= evr_puls_width_cfg_s(0); + input_s(111 downto 96) <= evr_puls_width_cfg_s(1); + input_s(127 downto 112) <= evr_puls_width_cfg_s(2); + input_s(143 downto 128) <= evr_puls_width_cfg_s(3); + input_s(159 downto 144) <= evr_puls_width_cfg_s(4); + + -- Instance + inst_cdc_fast_stat : entity work.psi_common_status_cc + generic map(width_g => input_s'length) + port map(a_clk_i => xuser_CLK, + a_rst_i => xuser_RESET, + a_dat_i => input_s, + b_clk_i => evr_clk_i, + b_rst_i => evr_rst_i, + b_dat_o => output_s); + -- ------------------------------------------------------------------------ + -- Disassemble Output + -- ------------------------------------------------------------------------ + --** pulse delay parameters ** + evr_pulse_delay_o(0) <= output_s(15 downto 0); + evr_pulse_delay_o(1) <= output_s(31 downto 16); + evr_pulse_delay_o(2) <= output_s(47 downto 32); + evr_pulse_delay_o(3) <= output_s(63 downto 48); + evr_pulse_delay_o(4) <= output_s(79 downto 64); + --** pulse width parameters ** + evr_pulse_width_o(0) <= output_s(95 downto 80); + evr_pulse_width_o(1) <= output_s(111 downto 96); + evr_pulse_width_o(2) <= output_s(127 downto 112); + evr_pulse_width_o(3) <= output_s(143 downto 128); + evr_pulse_width_o(4) <= output_s(159 downto 144); + end block; + + block_cdc_evr_code_param : block + signal input_s, output_s : std_logic_vector(108 downto 0); + begin + -- ------------------------------------------------------------------------ + -- Assemble Input + -- ------------------------------------------------------------------------ + --** event numbers ** + input_s( 7 downto 0) <= event_numbers(0); + input_s(15 downto 8) <= event_numbers(1); + input_s(23 downto 16) <= event_numbers(2); + input_s(31 downto 24) <= event_numbers(3); + --** event pulse enable ** + input_s(35 downto 32) <= event_enable; + --** time counter ** + input_s(67 downto 36) <= cs_min_time; + input_s(99 downto 68) <= cs_min_cnt; + --** latency counter ** + input_s(100) <= lat_counter_arm; + input_s(108 downto 101) <= lat_event_nr; + + -- Instance + inst_cdc_fast_stat : entity work.psi_common_status_cc + generic map(width_g => input_s'length) + port map(a_clk_i => xuser_CLK, + a_rst_i => xuser_RESET, + a_rst_o => open, + a_dat_i => input_s, + b_clk_i => evr_clk_i, + b_rst_i => evr_rst_i, + b_rst_o => open, + b_dat_o => output_s); + -- ------------------------------------------------------------------------ + -- Disassemble Output + -- ------------------------------------------------------------------------ + --** event numbers ** + evr_params_o.event_numbers(0) <= output_s( 7 downto 0) ; + evr_params_o.event_numbers(1) <= output_s(15 downto 8) ; + evr_params_o.event_numbers(2) <= output_s(23 downto 16); + evr_params_o.event_numbers(3) <= output_s(31 downto 24); + --** event pulse enable ** + evr_params_o.event_enable <= output_s(35 downto 32); + --** time counter ** + evr_params_o.cs_min_time <= output_s(67 downto 36); + evr_params_o.cs_min_cnt <= output_s(99 downto 68); + --** latency counter ** + evr_latency_measure_ctrl_o.counter_arm <= output_s(100) ; + evr_latency_measure_ctrl_o.event_nr <= output_s(108 downto 101) ; + end block; + +end rtl; +-- ---------------------------------------------------------------------------- +-- //////////////////////////////////////////////////////////////////////////// +-- ----------------------------------------------------------------------------