1231 lines
56 KiB
VHDL
1231 lines
56 KiB
VHDL
--------------------------------------------------------------------------------
|
|
-- 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
|
|
--------------------------------------------------------------------------------
|