Files
firmware_vhdl_evr320/hdl/evr320_decoder.vhd

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
--------------------------------------------------------------------------------