Compare commits
26 Commits
2.3
...
latency_me
| Author | SHA1 | Date | |
|---|---|---|---|
| 36a99d0bf4 | |||
| 4322debe14 | |||
| 83c3a4d910 | |||
| 98ba65bc62 | |||
| 5bf9caae3a | |||
| 13d42baf14 | |||
|
|
d135fbddca | ||
|
|
badd801839 | ||
| df8522473d | |||
|
|
50860b9e20 | ||
| 5bebe6dc41 | |||
| 83b6d6562d | |||
| 34b221f62a | |||
| 26cc7548a3 | |||
| 6d3fa8708a | |||
| 95a88cbba0 | |||
| e6a3441a7a | |||
| 287bfde2e0 | |||
| 3f1b7acc50 | |||
| fdcadda6ed | |||
| 0d6457cb77 | |||
| 83a4435e41 | |||
| b77484c659 | |||
| 071cf50ded | |||
| 5a060a160c | |||
| 6b1f4fbcbc |
BIN
doc/evr320.odt
Normal file
BIN
doc/evr320.odt
Normal file
Binary file not shown.
BIN
doc/evr320.pdf
BIN
doc/evr320.pdf
Binary file not shown.
12526
doc/evr320.rtf
12526
doc/evr320.rtf
File diff suppressed because it is too large
Load Diff
BIN
doc/evr320.vsd
BIN
doc/evr320.vsd
Binary file not shown.
@@ -4,65 +4,89 @@
|
||||
-- Project: evr320
|
||||
-- Authors: Jonas Purtschert
|
||||
-- Description: Filter a specific data field from data buffer stream of the decoder:
|
||||
-- Modif: Benoit Stef
|
||||
-- not based on counter anymore but map to LSB into a generic array
|
||||
------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
use work.psi_common_math_pkg.all;
|
||||
|
||||
entity evr320_data_filter is
|
||||
generic (
|
||||
ADDRESS : std_logic_vector(11 downto 0);
|
||||
NUM_BYTES : integer := 8
|
||||
);
|
||||
port (
|
||||
-- User stream interface
|
||||
i_stream_clk : in std_logic; -- user clock
|
||||
i_stream_data : in std_logic_vector(7 downto 0);
|
||||
i_stream_addr : in std_logic_vector(10 downto 0);
|
||||
i_stream_valid : in std_logic;
|
||||
-- filter output:
|
||||
o_data : out std_logic_vector(NUM_BYTES*8-1 downto 0) := (others=>'0');
|
||||
o_valid : out std_logic := '0'
|
||||
);
|
||||
end evr320_data_filter;
|
||||
|
||||
generic (NUM_BYTES : integer := 8;
|
||||
SWAP : boolean := false ); -- if true byte are swpped at output
|
||||
port ( -- User stream interface
|
||||
i_stream_clk : in std_logic; -- user clock
|
||||
i_stream_data : in std_logic_vector(7 downto 0);
|
||||
i_stream_addr : in std_logic_vector(10 downto 0);
|
||||
i_stream_valid : in std_logic;
|
||||
i_address : in std_logic_vector(11 downto 0);
|
||||
-- filter output:
|
||||
o_data : out std_logic_vector(NUM_BYTES*8-1 downto 0) := (others=>'0');
|
||||
o_valid : out std_logic := '0'
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture behavioral of evr320_data_filter is
|
||||
|
||||
signal data_shift : std_logic_vector(NUM_BYTES*8-1 downto 0) := (others=>'0');
|
||||
signal match : std_logic := '0';
|
||||
signal shift_cnt : integer range 0 to NUM_BYTES;
|
||||
|
||||
-- array to store data value prior to map to output
|
||||
type byte_array_t is array (NUM_BYTES-1 downto 0) of std_logic_vector(i_stream_data'range);
|
||||
signal table_s : byte_array_t;
|
||||
--pipe help
|
||||
signal addr_dff_s : std_logic_vector(10 downto 0) := (others=>'0');
|
||||
signal data_dff_s : std_logic_vector(i_stream_data'range) := (others=>'0');
|
||||
signal filt_dff_s : std_logic_vector(i_address'range);
|
||||
--helper
|
||||
constant low_bd_c : integer := log2ceil(NUM_BYTES); --compute LSB for address decoding
|
||||
signal ena_s : std_logic_vector(1 downto 0); --clock enable vector
|
||||
|
||||
begin
|
||||
process(i_stream_clk)
|
||||
variable addr : std_logic_vector(10 downto 0) := (others=>'0');
|
||||
variable data : std_logic_vector(7 downto 0) := (others=>'0');
|
||||
|
||||
p : process(i_stream_clk)
|
||||
begin
|
||||
if (rising_edge(i_stream_clk)) then
|
||||
o_valid <= '0';
|
||||
|
||||
if (rising_edge(i_stream_clk)) then
|
||||
|
||||
--*** 1st pipe stage ***
|
||||
ena_s(0) <= i_stream_valid;
|
||||
filt_dff_s <= i_address;
|
||||
if (i_stream_valid = '1') then
|
||||
addr := i_stream_addr;
|
||||
data := i_stream_data;
|
||||
|
||||
if (addr = ADDRESS(10 downto 0) or match = '1') then
|
||||
match <= '1';
|
||||
if (shift_cnt < NUM_BYTES) then
|
||||
data_shift <= data_shift((data_shift'high - data'length) downto 0) & data;
|
||||
shift_cnt <= shift_cnt + 1;
|
||||
else -- all data fetched, send to out
|
||||
match <= '0';
|
||||
shift_cnt <= 0;
|
||||
o_valid <= '1';
|
||||
o_data <= data_shift;
|
||||
end if;
|
||||
end if; -- if addr match
|
||||
end if; -- if valid
|
||||
|
||||
addr_dff_s <= i_stream_addr;
|
||||
data_dff_s <= i_stream_data;
|
||||
end if;
|
||||
|
||||
--*** filling the array ***
|
||||
if ena_s(0) = '1' then
|
||||
if addr_dff_s(10 downto low_bd_c) = filt_dff_s(10 downto low_bd_c) then
|
||||
--*** spatial loop ***
|
||||
ena_s(1) <= '1';
|
||||
for i in 0 to NUM_BYTES-1 loop
|
||||
if addr_dff_s(low_bd_c-1 downto 0) = to_uslv(i,low_bd_c) then
|
||||
table_s(i) <= data_dff_s ;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
else
|
||||
ena_s(1) <= '0';
|
||||
end if;
|
||||
|
||||
--*** set the output & valid accordingly***
|
||||
if ena_s(1) = '1' then
|
||||
if (from_uslv(addr_dff_s) = (from_uslv(filt_dff_s) + NUM_BYTES -1)) then
|
||||
o_valid <= '1';
|
||||
--*** spatial loop map output ***
|
||||
for i in 0 to NUM_BYTES-1 loop
|
||||
if SWAP then
|
||||
o_data(NUM_BYTES+i*NUM_BYTES-1 downto 0+i*NUM_BYTES) <= table_s(NUM_BYTES-1-i);
|
||||
else
|
||||
o_data(NUM_BYTES+i*NUM_BYTES-1 downto 0+i*NUM_BYTES) <= table_s(i);
|
||||
end if;
|
||||
end loop;
|
||||
else
|
||||
o_valid <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end behavioral;
|
||||
|
||||
end architecture;
|
||||
|
||||
@@ -180,6 +180,7 @@ architecture behavioral of evr320_decoder is
|
||||
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');
|
||||
@@ -709,6 +710,9 @@ begin
|
||||
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
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -870,7 +874,7 @@ begin
|
||||
OutRst => '0',
|
||||
|
||||
-- Input Data
|
||||
InData => mem_data_wr_addr & mem_data_wr_byte,
|
||||
InData => mem_data,
|
||||
InVld => mem_data_wren,
|
||||
InRdy => open,
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- Paul Scherrer Institute (PSI)
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Unit : evr320_ifc1210_wrapper.vhd
|
||||
-- Author : Patric Bucher
|
||||
-- Author : Patric Bucher, Benoit Stef
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Copyright© PSI, Section DSV
|
||||
-- ---------------------------------------------------------------------------
|
||||
@@ -20,371 +20,357 @@ 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
|
||||
g_EVT_DURATION : typ_arr_pos := (1, 1, 1, 1, 1); -- output extend in clock recovery clock cycles event 0,1,2,3
|
||||
g_EVT_HOLDOFF : typ_arr_nat := (0, 0, 0, 0, 0); -- Minimum number of clock cycles between input pulses event sos,0,1,2,3
|
||||
g_EVT_DELAY : typ_arr_pos := (4, 4, 4, 4, 4) -- delay in recovery clock cycles event sos,0,1,2,3
|
||||
);
|
||||
port(
|
||||
tick1sec_i : in std_logic;
|
||||
-- ------------------------------------------------------------------------
|
||||
-- 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
|
||||
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
|
||||
-- new features adjusted in delay & length
|
||||
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
|
||||
);
|
||||
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
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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);
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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_A_stat : typ_rec_latency_measure_stat;
|
||||
signal evr_latency_measure_A_ctrl : typ_rec_latency_measure_ctrl;
|
||||
signal evr_latency_measure_B_stat : typ_rec_latency_measure_stat;
|
||||
signal evr_latency_measure_B_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;
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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 /////////////////////////
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- //////////////////// Main Body /////////////////////////
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- ----------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- static signal assignments
|
||||
-- --------------------------------------------------------------------------
|
||||
mgt_lossofsync <= mgt_status(15);
|
||||
rst_evr <= mgt_status(15);
|
||||
mem_addr_evr <= '0' & mem_addr_tosca;
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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);
|
||||
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;
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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
|
||||
);
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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;
|
||||
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 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
|
||||
-- --------------------------------------------------------------------------
|
||||
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
|
||||
);
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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_A_stat_i => evr_latency_measure_A_stat,
|
||||
evr_latency_measure_A_ctrl_o => evr_latency_measure_A_ctrl,
|
||||
evr_latency_measure_B_stat_i => evr_latency_measure_B_stat,
|
||||
evr_latency_measure_B_ctrl_o => evr_latency_measure_B_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
|
||||
);
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Latency Measurement for IFC1210 Interrupts
|
||||
-- --------------------------------------------------------------------------
|
||||
latency_meas_A_inst : entity work.latency_measurement
|
||||
generic map(
|
||||
CLK_FREQ_HZ => g_XUSER_CLK_FREQ
|
||||
)
|
||||
port map(
|
||||
evr_clk_i => clk_evr,
|
||||
xuser_clk_i => xuser_CLK,
|
||||
decoder_event_valid_i => decoder_event_valid,
|
||||
decoder_event_i => decoder_event,
|
||||
status_o => evr_latency_measure_A_stat,
|
||||
ctrl_i => evr_latency_measure_A_ctrl
|
||||
);
|
||||
|
||||
-- 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;
|
||||
latency_meas_B_inst : entity work.latency_measurement
|
||||
generic map(
|
||||
CLK_FREQ_HZ => g_XUSER_CLK_FREQ
|
||||
)
|
||||
port map(
|
||||
evr_clk_i => clk_evr,
|
||||
xuser_clk_i => xuser_CLK,
|
||||
decoder_event_valid_i => decoder_event_valid,
|
||||
decoder_event_i => decoder_event,
|
||||
status_o => evr_latency_measure_B_stat,
|
||||
ctrl_i => evr_latency_measure_B_ctrl
|
||||
);
|
||||
|
||||
-- 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;
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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;
|
||||
|
||||
-- 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);
|
||||
begin
|
||||
|
||||
-- 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;
|
||||
rxpll_locked <= mgt_status(1);
|
||||
mmcm_locked <= mgt_status(2);
|
||||
evr_rst_in <= xuser_RESET or (not rxpll_locked) or (not mmcm_locked);
|
||||
|
||||
-- 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;
|
||||
--*** 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_latency_measure_stat.counter_val <= std_logic_vector(counter);
|
||||
end process;
|
||||
evr_rst_s <= rst1_s;
|
||||
|
||||
end block;
|
||||
usr_events_concat_s <= usr_events_s & sos_event_s;
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 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
|
||||
--*** double stage sync for reset ***--
|
||||
proc_rst : process(clk_evr)
|
||||
begin
|
||||
if rising_edge(clk_evr) then
|
||||
rst0_s <= xuser_RESET;
|
||||
rst1_s <= rst0_s;
|
||||
end if;
|
||||
end process;
|
||||
gene_adj_out : for i in 0 to 4 generate
|
||||
|
||||
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
|
||||
generic map(Duration_g => g_EVT_DURATION(i),
|
||||
HoldIn_g => false,
|
||||
HoldOff_g => g_EVT_HOLDOFF(i))
|
||||
port map(Clk => clk_evr,
|
||||
Rst => rst1_s,
|
||||
InPulse => usr_events_concat_s(i),
|
||||
OutPulse => usr_evt_shaped_s(i));
|
||||
--*** 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
|
||||
generic map(Width_g => 1,
|
||||
Delay_g => g_EVT_DELAY(i),
|
||||
Resource_g => "AUTO",
|
||||
BramThreshold_g => 128,
|
||||
RstState_g => True,
|
||||
RamBehavior_g => "RBW")
|
||||
port map(Clk => clk_evr,
|
||||
Rst => rst1_s,
|
||||
InData(0) => usr_evt_shaped_s(i),
|
||||
InVld => '1',
|
||||
OutData(0)=> usr_events_adj_s(i));
|
||||
end generate;
|
||||
--*** 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;
|
||||
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;
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
@@ -12,15 +12,17 @@
|
||||
--------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use work.psi_common_math_pkg.all;
|
||||
|
||||
package evr320_pkg is
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Constants
|
||||
-- --------------------------------------------------------------------------
|
||||
constant c_CHECKSUM_MIN_EVT : std_logic_vector(31 downto 0) := X"00000064"; -- Check sum min count for events 100
|
||||
constant c_CHECKSUM_MIN_TIME : std_logic_vector(31 downto 0) := X"0015CA20"; -- Check sum min time for events 10 ms
|
||||
constant c_SOS_EVENT_DEFAULT : std_logic_vector( 7 downto 0) := X"20"; -- decimal 32
|
||||
constant c_CHECKSUM_MIN_EVT : std_logic_vector(31 downto 0) := X"00000064"; -- Check sum min count for events 100
|
||||
constant c_CHECKSUM_MIN_TIME : std_logic_vector(31 downto 0) := X"0015CA20"; -- Check sum min time for events 10 ms
|
||||
constant c_SOS_EVENT_DEFAULT : std_logic_vector( 7 downto 0) := X"26"; -- default start-of-sequence (SOS) event
|
||||
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
@@ -59,10 +61,15 @@ package evr320_pkg is
|
||||
|
||||
type typ_rec_latency_measure_stat is record
|
||||
counter_val : std_logic_vector(31 downto 0);
|
||||
event_detected : std_logic;
|
||||
end record;
|
||||
|
||||
type typ_arr_nat is array (4 downto 0) of natural;
|
||||
type typ_arr_pos is array (4 downto 0) of positive;
|
||||
--*** Type record and constant for new feature pulse width & delay ***
|
||||
constant MaxDuration_c : positive := 2**16-1; -- defines maximum pulse width to add on user events pulse output, in recovery clock cycles
|
||||
constant MaxDelay_c : positive := 2**16-1; -- defines maximum delay to add on user events pulse output, in recovery clock cycles
|
||||
constant UsrEventWidthDefault_c : std_logic_vector(log2ceil(MaxDuration_c)-1 downto 0) := std_logic_vector(to_unsigned(4, log2ceil(MaxDuration_c))); -- default pulse width of usr_events_adj_o
|
||||
type typ_arr_width is array (4 downto 0) of std_logic_vector(log2ceil(MaxDuration_c)-1 downto 0);
|
||||
type typ_arr_delay is array (4 downto 0) of std_logic_vector(log2ceil(MaxDelay_c)-1 downto 0);
|
||||
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
@@ -79,7 +86,8 @@ package evr320_pkg is
|
||||
|
||||
constant c_INIT_REC_LATENCY_MEASURE_CTRL : typ_rec_latency_measure_ctrl := (event_nr => (others =>'0'),
|
||||
counter_arm => '1');
|
||||
constant c_INIT_REC_LATENCY_MEASURE_STAT : typ_rec_latency_measure_stat := (counter_val => (others =>'0'));
|
||||
constant c_INIT_REC_LATENCY_MEASURE_STAT : typ_rec_latency_measure_stat := (counter_val => (others =>'0'),
|
||||
event_detected => '0');
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Function Prototypes
|
||||
-- --------------------------------------------------------------------------
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
-- Paul Scherrer Institute (PSI)
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Unit : evr320_tmem.vhd
|
||||
-- Author : Patric Bucher
|
||||
-- Author : Patric Bucher, Benoit Stef
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Copyright© PSI, Section DSV
|
||||
-- Copyright (c) PSI, Section DSV
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Comment : TMEM address decoding for register and memory access to evr320.
|
||||
-- ---------------------------------------------------------------------------
|
||||
@@ -18,7 +18,6 @@ use tosca2.tosca2_glb_pkg.all;
|
||||
|
||||
use work.evr320_pkg.all;
|
||||
|
||||
|
||||
entity evr320_tmem is
|
||||
port(
|
||||
-- ------------------------------------------------------------------------
|
||||
@@ -38,13 +37,22 @@ entity evr320_tmem is
|
||||
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);
|
||||
evr_latency_measure_A_stat_i : in typ_rec_latency_measure_stat;
|
||||
evr_latency_measure_A_ctrl_o : out typ_rec_latency_measure_ctrl;
|
||||
evr_latency_measure_B_stat_i : in typ_rec_latency_measure_stat;
|
||||
evr_latency_measure_B_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)
|
||||
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;
|
||||
|
||||
@@ -96,15 +104,15 @@ architecture rtl of evr320_tmem is
|
||||
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 lat_A_counter_arm, lat_B_counter_arm : std_logic := '0';
|
||||
signal lat_A_event_nr, lat_B_event_nr : std_logic_vector(7 downto 0) := c_SOS_EVENT_DEFAULT;
|
||||
signal lat_A_event_detected, lat_B_event_detected : std_logic_vector(7 downto 0);
|
||||
signal lat_A_arm, lat_B_arm : std_logic := '0';
|
||||
signal lat_A_arm_edge, lat_B_arm_edge : std_logic_vector(1 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 => UsrEventWidthDefault_c);
|
||||
signal evr_puls_delay_cfg_s : typ_arr_delay := (others => (others => '0'));
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- ----------------------------------------------------------------------------
|
||||
@@ -119,7 +127,34 @@ begin
|
||||
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;
|
||||
|
||||
-- -----------------------------
|
||||
-- latency measurement, arm
|
||||
-- -----------------------------
|
||||
process (xuser_CLK)
|
||||
begin
|
||||
if rising_edge(xuser_CLK) then
|
||||
-- edge detection of latency arm:
|
||||
lat_A_arm_edge <= lat_A_arm_edge(0) & lat_A_arm;
|
||||
lat_A_counter_arm <= lat_A_arm_edge(0) and not lat_A_arm_edge(1);
|
||||
lat_B_arm_edge <= lat_B_arm_edge(0) & lat_B_arm;
|
||||
lat_B_counter_arm <= lat_B_arm_edge(0) and not lat_B_arm_edge(1);
|
||||
|
||||
if (evr_latency_measure_A_stat_i.event_detected = '1') then
|
||||
lat_A_event_detected <= (others=>'1');
|
||||
end if;
|
||||
if (lat_A_counter_arm = '1') then
|
||||
lat_A_event_detected <= (others=>'0');
|
||||
end if;
|
||||
|
||||
if (evr_latency_measure_B_stat_i.event_detected = '1') then
|
||||
lat_B_event_detected <= (others=>'1');
|
||||
end if;
|
||||
if (lat_B_counter_arm = '1') then
|
||||
lat_B_event_detected <= (others=>'0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Synchronisation to xuser_CLK
|
||||
@@ -148,23 +183,29 @@ begin
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Read operation
|
||||
-- --------------------------------------------------------------------------
|
||||
blk_tmemrd : block
|
||||
|
||||
begin
|
||||
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"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"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"6" => xuser_TMEM_DATR <= evr_latency_measure_A_stat_i.counter_val &
|
||||
lat_B_event_detected & lat_A_event_detected & lat_B_event_nr & lat_A_event_nr; -- 64bit / ByteAddr 030
|
||||
when X"7" => xuser_TMEM_DATR <= evr_latency_measure_B_stat_i.counter_val & 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
|
||||
@@ -174,6 +215,7 @@ begin
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end block;
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Write operation - Byte control
|
||||
@@ -185,6 +227,8 @@ begin
|
||||
-- default assignments
|
||||
er_data_ack <= er_data_ack(2 downto 0) & '0';
|
||||
er_error_ack <= er_error_ack(2 downto 0) & '0';
|
||||
lat_A_arm <= '0';
|
||||
lat_B_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
|
||||
@@ -234,8 +278,21 @@ begin
|
||||
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(0) = '1' then lat_A_event_nr ( 7 downto 0) <= xuser_TMEM_DATW_reg( 7 downto 0); end if;
|
||||
if xuser_TMEM_WE_reg(1) = '1' then lat_B_event_nr ( 7 downto 0) <= xuser_TMEM_DATW_reg(15 downto 8); 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_A_arm <= xuser_TMEM_DATW_reg(0); end if;
|
||||
if xuser_TMEM_WE_reg(1) = '1' then lat_B_arm <= xuser_TMEM_DATW_reg(8); 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;
|
||||
@@ -255,6 +312,24 @@ begin
|
||||
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;
|
||||
@@ -268,11 +343,56 @@ begin
|
||||
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);
|
||||
|
||||
evr_latency_measure_A_ctrl_o <= (lat_A_event_nr, lat_A_counter_arm);
|
||||
evr_latency_measure_B_ctrl_o <= (lat_B_event_nr, lat_B_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;
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- ////////////////////////////////////////////////////////////////////////////
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
98
hdl/latency_measurement.vhd
Normal file
98
hdl/latency_measurement.vhd
Normal file
@@ -0,0 +1,98 @@
|
||||
---------------------------------------------------------------------------
|
||||
-- Paul Scherrer Institute (PSI)
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Unit : latency_measurement.vhd
|
||||
-- Author : Jonas Purtschert
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Copyright© PSI, Section DSV
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Comment : Latency Measurement for IFC1210 Interrupt latency debugging
|
||||
-- ---------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.math_real.all;
|
||||
|
||||
use work.evr320_pkg.all;
|
||||
|
||||
entity latency_measurement is
|
||||
generic (
|
||||
CLK_FREQ_HZ : natural := 125000000 -- Xuser Clk Frequency in Hz
|
||||
);
|
||||
port (
|
||||
evr_clk_i : in std_logic;
|
||||
xuser_clk_i : in std_logic;
|
||||
decoder_event_valid_i : in std_logic;
|
||||
decoder_event_i : in std_logic_vector(7 downto 0);
|
||||
status_o : out typ_rec_latency_measure_stat;
|
||||
ctrl_i : in typ_rec_latency_measure_ctrl
|
||||
);
|
||||
end latency_measurement;
|
||||
|
||||
architecture rtl of latency_measurement is
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Signal, Types, Constants
|
||||
-- --------------------------------------------------------------------------
|
||||
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(CLK_FREQ_HZ / 100, 32); -- MAX 10ms
|
||||
|
||||
begin
|
||||
|
||||
-- Process: filter events for matching event_nr register:
|
||||
---------------------------------------------------------
|
||||
ext_event_proc : process(evr_clk_i)
|
||||
begin
|
||||
if (rising_edge(evr_clk_i)) then
|
||||
-- sync to MGT clock domain:
|
||||
event_nr_sync <= ctrl_i.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_i = '1' and decoder_event_i = 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_i, counter)
|
||||
begin
|
||||
if rising_edge(xuser_clk_i) 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 (ctrl_i.counter_arm = '1') then
|
||||
state <= armed;
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
status_o.counter_val <= std_logic_vector(counter);
|
||||
status_o.event_detected <= event_detected_sync(event_detected_sync'left);
|
||||
end process;
|
||||
|
||||
end rtl;
|
||||
@@ -260,7 +260,7 @@ begin
|
||||
else
|
||||
case s_align_fsm is
|
||||
when align_idle =>
|
||||
if o_mgt.rx.RXLOSSOFSYNC( 1) = '1' then
|
||||
if o_mgt.rx.RXLOSSOFSYNC( 1) = '1' or o_mgt.rx.RXBYTEISALIGNED = '0' then
|
||||
s_align_fsm <= align_slide;
|
||||
end if;
|
||||
when align_slide =>
|
||||
|
||||
@@ -33,8 +33,10 @@ add_sources $LibPath/Firmware/VHDL/psi_common/hdl {
|
||||
psi_common_pulse_cc.vhd \
|
||||
psi_common_async_fifo.vhd \
|
||||
psi_common_clk_meas.vhd \
|
||||
psi_common_pulse_shaper.vhd \
|
||||
psi_common_delay.vhd \
|
||||
psi_common_pulse_shaper_cfg.vhd \
|
||||
psi_common_delay_cfg.vhd \
|
||||
psi_common_simple_cc.vhd \
|
||||
psi_common_status_cc.vhd \
|
||||
} -tag psi_common
|
||||
|
||||
# EVR320 Decoder
|
||||
@@ -62,7 +64,6 @@ add_sources $LibPath/Firmware/VHDL/evr320/hdl {
|
||||
# EVR320 Decoder Testbench
|
||||
add_sources $LibPath/Firmware/VHDL/evr320/tb {
|
||||
evr320_decoder_tb.vhd \
|
||||
evr320_ifc1210_wrapper_tb.vhd \
|
||||
} -tag evr320_tb
|
||||
|
||||
# EVR320 IFC1210 Wrapper Testbench
|
||||
|
||||
@@ -80,7 +80,7 @@ architecture testbench of evr320_decoder_tb is
|
||||
signal usr_clk : std_logic := '0';
|
||||
signal evr_params : typ_evr320_params;
|
||||
signal mem_addr : std_logic_vector(11 downto 0) := (others => '0');
|
||||
signal mem_data : std_logic_vector(31 downto 0) := (others => '0');
|
||||
signal mem_data : std_logic_vector(C_MEM_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
|
||||
-- Decoder stream
|
||||
type dec_stream_type is record
|
||||
@@ -169,12 +169,14 @@ begin
|
||||
--------------------------------------------------------------------------
|
||||
o_usr_events => usr_events,
|
||||
o_usr_events_ext => open,
|
||||
o_sos_event => sos_event
|
||||
o_sos_event => sos_event,
|
||||
o_event => open,
|
||||
o_event_valid => open
|
||||
);
|
||||
|
||||
evr320_data_filter_inst: entity work.evr320_data_filter
|
||||
generic map (
|
||||
ADDRESS => FILTER_ADDRESS,
|
||||
SWAP => true, -- non-swapped uses LE layout; our check below converts to BE
|
||||
NUM_BYTES => 8
|
||||
)
|
||||
port map (
|
||||
@@ -182,6 +184,7 @@ begin
|
||||
i_stream_data => dec_stream_data,
|
||||
i_stream_addr => dec_stream_addr,
|
||||
i_stream_valid => dec_stream_valid,
|
||||
i_address => FILTER_ADDRESS,
|
||||
o_data => filter_data,
|
||||
o_valid => filter_valid
|
||||
);
|
||||
@@ -398,7 +401,7 @@ begin
|
||||
variable i : integer := 0;
|
||||
type state is (idle, payload, frame_end, segment_nr);
|
||||
variable mem_base : integer range 0 to 127;
|
||||
variable segment_data_word : std_logic_vector(31 downto 0);
|
||||
variable segment_data_word : std_logic_vector(C_MEM_DATA_WIDTH-1 downto 0);
|
||||
variable var_filter_offset : integer range 0 to 2047;
|
||||
variable var_filter_word : std_logic_vector(FILTER_NUM_BYTES*8-1 downto 0);
|
||||
variable expected_evt_rec_events : integer range 0 to 255 := 0;
|
||||
@@ -485,37 +488,51 @@ begin
|
||||
log(ID_DATA, "Check expected Event Flags after SOS Event detected");
|
||||
----------------------------------------------------------------------
|
||||
wait until rising_edge(usr_clk);
|
||||
for addr in 0 to 63 loop
|
||||
mem_addr <= C_EVENT_REC_FLAGS & std_logic_vector(to_unsigned(addr, 6));
|
||||
wait until rising_edge(usr_clk);
|
||||
await_value(mem_data(0), all_expected_events(4*addr), 0 ns, 1 ns, ERROR, "Event " & to_string(4*addr) & " Flag");
|
||||
await_value(mem_data(8), all_expected_events(4*addr + 1), 0 ns, 1 ns, ERROR, "Event " & to_string(4*addr + 1) & " Flag");
|
||||
await_value(mem_data(16), all_expected_events(4*addr + 2), 0 ns, 1 ns, ERROR, "Event " & to_string(4*addr + 2) & " Flag");
|
||||
await_value(mem_data(24), all_expected_events(4*addr + 3), 0 ns, 1 ns, ERROR, "Event " & to_string(4*addr + 3) & " Flag");
|
||||
end loop;
|
||||
|
||||
----------------------------------------------------------------------
|
||||
log(ID_DATA, "Check Memory block border");
|
||||
----------------------------------------------------------------------
|
||||
-- read data mux switching made visible with delayed address.
|
||||
mem_addr <= C_EVENT_REC_FLAGS & "000000";
|
||||
wait until rising_edge(usr_clk);
|
||||
wait for C_USRCLK_CYCLE/4;
|
||||
for addr in 62 to 65 loop
|
||||
mem_addr <= (C_EVENT_REC_FLAGS & "000000") + std_logic_vector(to_unsigned(addr, 7));
|
||||
wait until rising_edge(usr_clk);
|
||||
check_stable(mem_data, C_USRCLK_CYCLE, ERROR, "Read Data stable on Output");
|
||||
wait for C_USRCLK_CYCLE/4;
|
||||
if (addr < 64) then
|
||||
if (C_MEM_DATA_WIDTH = 32) then
|
||||
for addr in 0 to 63 loop
|
||||
mem_addr <= C_EVENT_REC_FLAGS & std_logic_vector(to_unsigned(addr, 6));
|
||||
wait_num_rising_edge_plus_margin(usr_clk, 1, 1 ns);
|
||||
check_value(mem_data(0), all_expected_events(4*addr), ERROR, "Event " & to_string(4*addr) & " Flag");
|
||||
check_value(mem_data(8), all_expected_events(4*addr + 1), ERROR, "Event " & to_string(4*addr + 1) & " Flag");
|
||||
check_value(mem_data(16), all_expected_events(4*addr + 2), ERROR, "Event " & to_string(4*addr + 2) & " Flag");
|
||||
check_value(mem_data(24), all_expected_events(4*addr + 3), ERROR, "Event " & to_string(4*addr + 3) & " Flag");
|
||||
else
|
||||
check_value(mem_data, X"0000_0000", ERROR, "After Event Recorder Mem Map");
|
||||
end if;
|
||||
end loop;
|
||||
wait until rising_edge(usr_clk);
|
||||
end loop;
|
||||
elsif (C_MEM_DATA_WIDTH = 64) then
|
||||
for addr in 0 to 31 loop
|
||||
mem_addr <= '0' & C_EVENT_REC_FLAGS & std_logic_vector(to_unsigned(addr, 5));
|
||||
wait_num_rising_edge_plus_margin(usr_clk, 1, 1 ns);
|
||||
for j in 0 to C_MEM_DATA_WIDTH/8 loop
|
||||
check_value(mem_data(8*j), all_expected_events(8*addr + j), ERROR, "Event " & to_string(8*addr + j) & " Flag");
|
||||
end loop;
|
||||
end loop;
|
||||
else
|
||||
error("Unsupported width of C_MEM_DATA_WIDTH");
|
||||
end if;
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- log(ID_DATA, "Check Memory block border");
|
||||
-- ----------------------------------------------------------------------
|
||||
if (C_MEM_DATA_WIDTH = 32) then
|
||||
-- read data mux switching made visible with delayed address.
|
||||
mem_addr <= C_EVENT_REC_FLAGS & "000000";
|
||||
wait until rising_edge(usr_clk);
|
||||
wait for C_USRCLK_CYCLE/4;
|
||||
for addr in 62 to 65 loop
|
||||
mem_addr <= (C_EVENT_REC_FLAGS & "000000") + std_logic_vector(to_unsigned(addr, 7));
|
||||
wait until rising_edge(usr_clk);
|
||||
check_stable(mem_data, C_USRCLK_CYCLE, ERROR, "Read Data stable on Output");
|
||||
wait for C_USRCLK_CYCLE/4;
|
||||
if (addr < 64) then
|
||||
check_value(mem_data(0), all_expected_events(4*addr), ERROR, "Event " & to_string(4*addr) & " Flag");
|
||||
check_value(mem_data(8), all_expected_events(4*addr + 1), ERROR, "Event " & to_string(4*addr + 1) & " Flag");
|
||||
check_value(mem_data(16), all_expected_events(4*addr + 2), ERROR, "Event " & to_string(4*addr + 2) & " Flag");
|
||||
check_value(mem_data(24), all_expected_events(4*addr + 3), ERROR, "Event " & to_string(4*addr + 3) & " Flag");
|
||||
else
|
||||
check_value(mem_data, X"0000_0000", ERROR, "After Event Recorder Mem Map");
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
----------------------------------------------------------------------
|
||||
log(ID_DATA, "Check expected Event Recorder User Events");
|
||||
----------------------------------------------------------------------
|
||||
@@ -527,22 +544,24 @@ begin
|
||||
--------------------------------------------------------------------------
|
||||
log(ID_LOG_HDR, "Read DPRAM buffer", C_SCOPE);
|
||||
--------------------------------------------------------------------------
|
||||
wait for 50 * C_USRCLK_CYCLE;
|
||||
log(ID_DATA, "Read Segment from DPRAM");
|
||||
-- print 16 words from dpram data buffer:
|
||||
for offset in 0 to segment_length/4-1 loop
|
||||
mem_base := to_integer(unsigned(segment_addr));
|
||||
mem_addr <= std_logic_vector(to_unsigned(4*mem_base + offset , 12));
|
||||
wait until rising_edge(usr_clk);
|
||||
wait until rising_edge(usr_clk);
|
||||
wait until rising_edge(usr_clk);
|
||||
segment_data_word := segment_data(offset*4+3)
|
||||
& segment_data(offset*4+2)
|
||||
& segment_data(offset*4+1)
|
||||
& segment_data(offset*4);
|
||||
check_value(mem_data, segment_data_word, ERROR, "Compare DPRAM with Sent Segment");
|
||||
--log(ID_PACKET_DATA, "Data buffer DPRAM: addr=0x" & to_string(mem_addr, HEX) & " data=0x" & to_string(mem_data, HEX));
|
||||
end loop;
|
||||
if (C_MEM_DATA_WIDTH = 32) then
|
||||
wait for 50 * C_USRCLK_CYCLE;
|
||||
log(ID_DATA, "Read Segment from DPRAM");
|
||||
-- print 16 words from dpram data buffer:
|
||||
for offset in 0 to segment_length/4-1 loop
|
||||
mem_base := to_integer(unsigned(segment_addr));
|
||||
mem_addr <= std_logic_vector(to_unsigned(4*mem_base + offset , 12));
|
||||
wait until rising_edge(usr_clk);
|
||||
wait until rising_edge(usr_clk);
|
||||
wait until rising_edge(usr_clk);
|
||||
segment_data_word := segment_data(offset*4+3)
|
||||
& segment_data(offset*4+2)
|
||||
& segment_data(offset*4+1)
|
||||
& segment_data(offset*4);
|
||||
check_value(mem_data, segment_data_word, ERROR, "Compare DPRAM with Sent Segment");
|
||||
--log(ID_PACKET_DATA, "Data buffer DPRAM: addr=0x" & to_string(mem_addr, HEX) & " data=0x" & to_string(mem_data, HEX));
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Test Done
|
||||
|
||||
@@ -21,459 +21,573 @@ context uvvm_util.uvvm_util_context;
|
||||
-- Work library (application) --------------------------------------------------
|
||||
library work;
|
||||
use work.evr320_pkg.all;
|
||||
use work.psi_common_math_pkg.all;
|
||||
|
||||
entity evr320_ifc1210_wrapper_tb is
|
||||
end entity;
|
||||
|
||||
architecture testbench of evr320_ifc1210_wrapper_tb is
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- System
|
||||
---------------------------------------------------------------------------
|
||||
constant C_RXUSRCLK_CYCLE : time := 7 ns;
|
||||
constant C_USRCLK_CYCLE : time := 8 ns;
|
||||
constant C_EVT_NR : integer := 4;
|
||||
constant C_MEM_DATA_WIDTH : integer := 32; -- 32|64 (64 bit used for tosca2 on ifc1210)
|
||||
constant C_EVENT_RECORDER : boolean := true;
|
||||
constant C_EVENT_REC_FLAGS : std_logic_vector(11 downto 6) := B"1101_11";
|
||||
constant g_EVENT_NR_SOS : integer range 0 to 255 := 16#20#;
|
||||
constant g_EVENT_NR_0 : integer range 0 to 255 := 16#00#;
|
||||
constant g_EVENT_NR_1 : integer range 0 to 255 := 16#04#;
|
||||
constant g_EVENT_NR_2 : integer range 0 to 255 := 16#00#;
|
||||
constant g_EVENT_NR_3 : integer range 0 to 255 := 16#00#;
|
||||
---------------------------------------------------------------------------
|
||||
-- System
|
||||
---------------------------------------------------------------------------
|
||||
constant C_RXUSRCLK_CYCLE : time := 7 ns;
|
||||
constant C_USRCLK_CYCLE : time := 8 ns;
|
||||
constant C_EVT_NR : integer := 4;
|
||||
constant C_MEM_DATA_WIDTH : integer := 32; -- 32|64 (64 bit used for tosca2 on ifc1210)
|
||||
constant C_EVENT_RECORDER : boolean := true;
|
||||
constant C_EVENT_REC_FLAGS : std_logic_vector(11 downto 6) := B"1101_11";
|
||||
constant g_EVENT_NR_SOS : integer range 0 to 255 := 16#20#;
|
||||
constant g_EVENT_NR_0 : integer range 0 to 255 := 16#00#;
|
||||
constant g_EVENT_NR_1 : integer range 0 to 255 := 16#04#;
|
||||
constant g_EVENT_NR_2 : integer range 0 to 255 := 16#00#;
|
||||
constant g_EVENT_NR_3 : integer range 0 to 255 := 16#00#;
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- MGT stream
|
||||
---------------------------------------------------------------------------
|
||||
type mgt_stream_sample_type is record
|
||||
data : std_logic_vector(7 downto 0);
|
||||
data_k : std_logic_vector(0 downto 0);
|
||||
event : std_logic_vector(7 downto 0);
|
||||
event_k : std_logic_vector(0 downto 0);
|
||||
end record mgt_stream_sample_type;
|
||||
---------------------------------------------------------------------------
|
||||
-- MGT stream
|
||||
---------------------------------------------------------------------------
|
||||
type mgt_stream_sample_type is record
|
||||
data : std_logic_vector(7 downto 0);
|
||||
data_k : std_logic_vector(0 downto 0);
|
||||
event : std_logic_vector(7 downto 0);
|
||||
event_k : std_logic_vector(0 downto 0);
|
||||
end record mgt_stream_sample_type;
|
||||
|
||||
type mgt_stream_type is array (natural range <>) of mgt_stream_sample_type;
|
||||
type mgt_stream_type is array (natural range <>) of mgt_stream_sample_type;
|
||||
|
||||
signal mgt_stream_index : integer range 0 to 511 := 0;
|
||||
signal mgt_stream : mgt_stream_type(511 downto 0) := (others => (others => (others => '0')));
|
||||
signal mgt_stream_index : integer range 0 to 511 := 0;
|
||||
signal mgt_stream : mgt_stream_type(511 downto 0) := (others => (others => (others => '0')));
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Timing decoder interface
|
||||
-----------------------------------------------------------------------------
|
||||
signal usr_clk : std_logic := '0';
|
||||
signal evr_params : typ_evr320_params;
|
||||
signal mem_addr : std_logic_vector(11 downto 0) := (others => '0');
|
||||
signal mem_data : std_logic_vector(31 downto 0) := (others => '0');
|
||||
-----------------------------------------------------------------------------
|
||||
-- Timing decoder interface
|
||||
-----------------------------------------------------------------------------
|
||||
signal usr_clk : std_logic := '0';
|
||||
signal evr_params : typ_evr320_params;
|
||||
signal mem_addr : std_logic_vector(11 downto 0) := (others => '0');
|
||||
signal mem_data : std_logic_vector(31 downto 0) := (others => '0');
|
||||
|
||||
-- Decoder stream
|
||||
type dec_stream_type is record
|
||||
data : std_logic_vector(7 downto 0);
|
||||
addr : std_logic_vector(10 downto 0);
|
||||
end record dec_stream_type;
|
||||
type dec_stream_check_arr is array (natural range <>) of dec_stream_type;
|
||||
-- Decoder stream
|
||||
type dec_stream_type is record
|
||||
data : std_logic_vector(7 downto 0);
|
||||
addr : std_logic_vector(10 downto 0);
|
||||
end record dec_stream_type;
|
||||
type dec_stream_check_arr is array (natural range <>) of dec_stream_type;
|
||||
|
||||
signal dec_stream_data : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal dec_stream_addr : std_logic_vector(10 downto 0) := (others => '0');
|
||||
signal dec_stream_valid : std_logic;
|
||||
signal dec_stream_check : dec_stream_check_arr(0 to 2047);
|
||||
signal dec_stream_recv_bytes : integer range 0 to 2047;
|
||||
signal dec_stream_data : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal dec_stream_addr : std_logic_vector(10 downto 0) := (others => '0');
|
||||
signal dec_stream_valid : std_logic;
|
||||
signal dec_stream_check : dec_stream_check_arr(0 to 2047);
|
||||
signal dec_stream_recv_bytes : integer range 0 to 2047;
|
||||
|
||||
type segment_data_arr is array (natural range <>) of std_logic_vector(7 downto 0);
|
||||
signal segment_addr : std_logic_vector(7 downto 0);
|
||||
signal segment_data : segment_data_arr(0 to 2047);
|
||||
signal segment_length : natural range 0 to 2047;
|
||||
type segment_data_arr is array (natural range <>) of std_logic_vector(7 downto 0);
|
||||
signal segment_addr : std_logic_vector(7 downto 0);
|
||||
signal segment_data : segment_data_arr(0 to 2047);
|
||||
signal segment_length : natural range 0 to 2047;
|
||||
|
||||
constant FILTER_ADDRESS : std_logic_vector(11 downto 0) := x"028";
|
||||
constant FILTER_NUM_BYTES : integer := 8;
|
||||
constant STIMULI_RUNS : integer := 2;
|
||||
constant FILTER_ADDRESS : std_logic_vector(11 downto 0) := x"028";
|
||||
constant FILTER_NUM_BYTES : integer := 8;
|
||||
constant STIMULI_RUNS : integer := 2;
|
||||
|
||||
signal filter_data, filter_data_check : std_logic_vector(63 downto 0) := (others => '0');
|
||||
signal filter_valid : std_logic := '0';
|
||||
signal filter_data, filter_data_check : std_logic_vector(63 downto 0) := (others => '0');
|
||||
signal filter_valid : std_logic := '0';
|
||||
|
||||
signal tmem_i : tmem_bus_in_t;
|
||||
signal tmem_o : tmem_bus_out_t;
|
||||
signal tmem_clk : std_logic;
|
||||
signal tmem_rst : std_logic;
|
||||
signal tmem_data_rd : std_logic_vector(63 downto 0);
|
||||
signal tmem_i : tmem_bus_in_t;
|
||||
signal tmem_o : tmem_bus_out_t;
|
||||
signal tmem_clk : std_logic;
|
||||
signal tmem_rst : std_logic;
|
||||
signal tmem_data_rd : std_logic_vector(63 downto 0);
|
||||
|
||||
signal tick1sec : std_logic;
|
||||
signal tick1sec : std_logic;
|
||||
|
||||
alias rxlos is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rst : std_logic>>;
|
||||
alias clk_evr is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.clk_evr : std_logic>>;
|
||||
alias rxdata is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_data : std_logic_vector(15 downto 0)>>;
|
||||
alias rxcharisk is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_charisk : std_logic_vector(1 downto 0)>>;
|
||||
alias sos_event is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_sos_event : std_logic>>;
|
||||
alias usr_events is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_usr_events : std_logic_vector(3 downto 0)>>;
|
||||
alias evr_stable is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.evr_stable : std_logic>>;
|
||||
alias rxlos is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rst : std_logic>>;
|
||||
alias clk_evr is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.clk_evr : std_logic>>;
|
||||
alias rxdata is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_data : std_logic_vector(15 downto 0)>>;
|
||||
alias rxcharisk is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_charisk : std_logic_vector(1 downto 0)>>;
|
||||
alias sos_event is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_sos_event : std_logic>>;
|
||||
alias usr_events is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_usr_events : std_logic_vector(3 downto 0)>>;
|
||||
alias evr_stable is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.evr_stable : std_logic>>;
|
||||
|
||||
--*** stimuli for delay & pulse width ***
|
||||
signal usr_event_width_sti : typ_arr_width := (to_uslv(2, log2ceil(MaxDuration_c)), --sos set to 2
|
||||
to_uslv(3, log2ceil(MaxDuration_c)), --0
|
||||
to_uslv(4, log2ceil(MaxDuration_c)), --1
|
||||
to_uslv(5, log2ceil(MaxDuration_c)), --2
|
||||
to_uslv(6, log2ceil(MaxDuration_c)) --3
|
||||
);
|
||||
|
||||
signal usr_event_delay_sti : typ_arr_delay := (to_uslv(2, log2ceil(MaxDelay_c)), --sos set to 2
|
||||
to_uslv(3, log2ceil(MaxDelay_c)), --0
|
||||
to_uslv(4, log2ceil(MaxDelay_c)), --1
|
||||
to_uslv(5, log2ceil(MaxDelay_c)), --2
|
||||
to_uslv(6, log2ceil(MaxDelay_c)) --3
|
||||
);
|
||||
|
||||
begin
|
||||
|
||||
tmem_o.TMEM_BUSY_o <= '0';
|
||||
tmem_o.TMEM_PIPE_o <= "10";
|
||||
tmem_o.TMEM_BUSY_o <= '0';
|
||||
tmem_o.TMEM_PIPE_o <= "10";
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Timing decoder
|
||||
-----------------------------------------------------------------------------
|
||||
evr320_ifc1210_wrapper_inst : entity work.evr320_ifc1210_wrapper
|
||||
generic map(
|
||||
g_EVT_DURATION => (1, 1, 1, 1, 1),
|
||||
g_EVT_HOLDOFF => (0, 0, 0, 0, 0),
|
||||
g_EVT_DELAY => (1, 1, 1, 1, 1),
|
||||
g_MGT_LOCATION => "GTXE1_X0Y16", -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
|
||||
g_FACILITY => "SFEL", -- "HIPA" | "SFEL"
|
||||
g_EVENT_RECORDER => C_EVENT_RECORDER, -- enable/disable Event Recorder functionality
|
||||
g_XUSER_CLK_FREQ => 125000000 -- Xuser Clk Frequency in Hz
|
||||
)
|
||||
port map(
|
||||
tick1sec_i => tick1sec,
|
||||
--------------------------------------------------------------------------
|
||||
-- Debug interface
|
||||
--------------------------------------------------------------------------
|
||||
debug_clk => open,
|
||||
debug => open,
|
||||
--------------------------------------------------------------------------
|
||||
-- TOSCA2 TMEM interface
|
||||
--------------------------------------------------------------------------
|
||||
xuser_CLK => tmem_clk,
|
||||
xuser_RESET => tmem_rst,
|
||||
xuser_TMEM_ENA => tmem_i.TMEM_ENA_i,
|
||||
xuser_TMEM_WE => tmem_i.TMEM_WE_i,
|
||||
xuser_TMEM_ADD => tmem_i.TMEM_ADD_i(13 downto 3),
|
||||
xuser_TMEM_DATW => tmem_i.TMEM_DATW_i,
|
||||
xuser_TMEM_DATR => tmem_o.TMEM_DATR_o,
|
||||
-- ------------------------------------------------------------------------
|
||||
-- MGT Interface
|
||||
-- ------------------------------------------------------------------------
|
||||
mgt_refclk_i => '0',
|
||||
mgt_sfp_los_i => '0',
|
||||
mgt_rx_n => '0',
|
||||
mgt_rx_p => '0',
|
||||
mgt_tx_n => open,
|
||||
mgt_tx_p => open,
|
||||
mgt_status_o => open,
|
||||
mgt_control_i => (others => '0'),
|
||||
---------------------------------------------------------------------------
|
||||
-- User interface MGT clock
|
||||
---------------------------------------------------------------------------
|
||||
clk_evr_o => open,
|
||||
usr_events_o => open,
|
||||
sos_event_o => open,
|
||||
usr_events_adj_o => open,
|
||||
sos_events_adj_o => open,
|
||||
--------------------------------------------------------------------------
|
||||
-- Decoder axi stream interface, User clock
|
||||
--------------------------------------------------------------------------
|
||||
stream_clk_i => '1',
|
||||
stream_data_o => open,
|
||||
stream_addr_o => open,
|
||||
stream_valid_o => open
|
||||
);
|
||||
-----------------------------------------------------------------------------
|
||||
-- Timing decoder
|
||||
-----------------------------------------------------------------------------
|
||||
evr320_ifc1210_wrapper_inst : entity work.evr320_ifc1210_wrapper
|
||||
generic map(
|
||||
g_MGT_LOCATION => "GTXE1_X0Y16", -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
|
||||
g_FACILITY => "SFEL", -- "HIPA" | "SFEL"
|
||||
g_EVENT_RECORDER => C_EVENT_RECORDER, -- enable/disable Event Recorder functionality
|
||||
g_XUSER_CLK_FREQ => 125000000 -- Xuser Clk Frequency in Hz
|
||||
)
|
||||
port map(
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Debug interface
|
||||
--------------------------------------------------------------------------
|
||||
debug_clk => open,
|
||||
debug => open,
|
||||
--------------------------------------------------------------------------
|
||||
-- TOSCA2 TMEM interface
|
||||
--------------------------------------------------------------------------
|
||||
xuser_CLK => tmem_clk,
|
||||
xuser_RESET => tmem_rst,
|
||||
xuser_TMEM_ENA => tmem_i.TMEM_ENA_i,
|
||||
xuser_TMEM_WE => tmem_i.TMEM_WE_i,
|
||||
xuser_TMEM_ADD => tmem_i.TMEM_ADD_i(13 downto 3),
|
||||
xuser_TMEM_DATW => tmem_i.TMEM_DATW_i,
|
||||
xuser_TMEM_DATR => tmem_o.TMEM_DATR_o,
|
||||
-- ------------------------------------------------------------------------
|
||||
-- MGT Interface
|
||||
-- ------------------------------------------------------------------------
|
||||
mgt_refclk_i => '0',
|
||||
mgt_sfp_los_i => '0',
|
||||
mgt_rx_n => '0',
|
||||
mgt_rx_p => '0',
|
||||
mgt_tx_n => open,
|
||||
mgt_tx_p => open,
|
||||
mgt_status_o => open,
|
||||
mgt_control_i => (others => '0'),
|
||||
---------------------------------------------------------------------------
|
||||
-- User interface MGT clock
|
||||
---------------------------------------------------------------------------
|
||||
clk_evr_o => open,
|
||||
usr_events_o => open,
|
||||
sos_event_o => open,
|
||||
usr_events_adj_o => open,
|
||||
sos_events_adj_o => open,
|
||||
--------------------------------------------------------------------------
|
||||
-- Decoder axi stream interface, User clock
|
||||
--------------------------------------------------------------------------
|
||||
stream_clk_i => '1',
|
||||
stream_data_o => open,
|
||||
stream_addr_o => open,
|
||||
stream_valid_o => open
|
||||
);
|
||||
|
||||
gen_pulse(tick1sec, '1', usr_clk, 1, "");
|
||||
-----------------------------------------------------------------------------
|
||||
-- MGT / User clock
|
||||
-----------------------------------------------------------------------------
|
||||
clock_generator(usr_clk, C_USRCLK_CYCLE);
|
||||
tmem_clk <= usr_clk;
|
||||
gen_pulse(tick1sec, '1', usr_clk, 1, "");
|
||||
-----------------------------------------------------------------------------
|
||||
-- MGT / User clock
|
||||
-----------------------------------------------------------------------------
|
||||
clock_generator(usr_clk, C_USRCLK_CYCLE);
|
||||
tmem_clk <= usr_clk;
|
||||
|
||||
-- Simulate MGT Clock
|
||||
mgt_clk_proc : process
|
||||
begin
|
||||
clk_evr <= force in '0';
|
||||
loop
|
||||
wait for C_RXUSRCLK_CYCLE / 2;
|
||||
clk_evr <= force in not (clk_evr);
|
||||
end loop;
|
||||
end process;
|
||||
-- Simulate MGT Clock
|
||||
mgt_clk_proc : process
|
||||
begin
|
||||
clk_evr <= force in '0';
|
||||
loop
|
||||
wait for C_RXUSRCLK_CYCLE / 2;
|
||||
clk_evr <= force in not (clk_evr);
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Decoder reset due to MGT main status
|
||||
-----------------------------------------------------------------------------
|
||||
process
|
||||
begin
|
||||
rxlos <= force in '1';
|
||||
tmem_rst <= '1';
|
||||
wait for 50 ns;
|
||||
wait until (falling_edge(clk_evr));
|
||||
rxlos <= force in '0';
|
||||
tmem_rst <= '0';
|
||||
wait;
|
||||
end process;
|
||||
-----------------------------------------------------------------------------
|
||||
-- Decoder reset due to MGT main status
|
||||
-----------------------------------------------------------------------------
|
||||
process
|
||||
begin
|
||||
rxlos <= force in '1';
|
||||
tmem_rst <= '1';
|
||||
wait for 50 ns;
|
||||
wait until (falling_edge(clk_evr));
|
||||
rxlos <= force in '0';
|
||||
tmem_rst <= '0';
|
||||
wait;
|
||||
end process;
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Read stimuli file
|
||||
-----------------------------------------------------------------------------
|
||||
file_blk : block
|
||||
file file_stimuli : text;
|
||||
type parse_fsm_state is (idle, seg_start, seg_addr, seg_Wait, seg_payload, seg_payload_wait, seg_done);
|
||||
begin
|
||||
process
|
||||
variable file_line : line;
|
||||
variable data, event : std_logic_vector(7 downto 0);
|
||||
variable data_k, event_k : std_logic_vector(0 downto 0);
|
||||
variable space : character;
|
||||
variable i : integer;
|
||||
variable parse_fsm : parse_fsm_state := idle;
|
||||
variable payload_cnt : integer range 0 to 2047;
|
||||
variable event_cnt_total : integer := 0;
|
||||
variable event_cnt_0 : integer := 0;
|
||||
variable event_cnt_1 : integer := 0;
|
||||
variable event_cnt_2 : integer := 0;
|
||||
variable event_cnt_3 : integer := 0;
|
||||
variable event_cnt_user : integer := 0;
|
||||
begin
|
||||
file_open(file_stimuli, "../tb/stimuli_mgt.dat", read_mode);
|
||||
readline(file_stimuli, file_line); -- comment
|
||||
readline(file_stimuli, file_line); -- comment
|
||||
i := 0;
|
||||
-- read line by line from .dat file:
|
||||
while not endfile(file_stimuli) loop
|
||||
readline(file_stimuli, file_line);
|
||||
hread(file_line, event);
|
||||
read(file_line, event_k);
|
||||
read(file_line, space);
|
||||
read(file_line, space);
|
||||
hread(file_line, data);
|
||||
read(file_line, space);
|
||||
read(file_line, data_k);
|
||||
-- write to array:
|
||||
mgt_stream(i).data <= data;
|
||||
mgt_stream(i).data_k <= data_k;
|
||||
mgt_stream(i).event <= event;
|
||||
mgt_stream(i).event_k <= event_k;
|
||||
mgt_stream_index <= i;
|
||||
--debug output:
|
||||
--log(ID_SEGMENT_DATA, "stimuli file: i=" & integer'image(i) & " event=0x" & to_string(event, HEX) & " k=" & to_string(event_k, HEX)
|
||||
-- & " data=0x" & to_string(data, HEX) & " k=" & to_string(data_k, HEX) & " ");
|
||||
-----------------------------------------------------------------------------
|
||||
-- Read stimuli file
|
||||
-----------------------------------------------------------------------------
|
||||
file_blk : block
|
||||
file file_stimuli : text;
|
||||
type parse_fsm_state is (idle, seg_start, seg_addr, seg_Wait, seg_payload, seg_payload_wait, seg_done);
|
||||
begin
|
||||
process
|
||||
variable file_line : line;
|
||||
variable data, event : std_logic_vector(7 downto 0);
|
||||
variable data_k, event_k : std_logic_vector(0 downto 0);
|
||||
variable space : character;
|
||||
variable i : integer;
|
||||
variable parse_fsm : parse_fsm_state := idle;
|
||||
variable payload_cnt : integer range 0 to 2047;
|
||||
variable event_cnt_total : integer := 0;
|
||||
variable event_cnt_0 : integer := 0;
|
||||
variable event_cnt_1 : integer := 0;
|
||||
variable event_cnt_2 : integer := 0;
|
||||
variable event_cnt_3 : integer := 0;
|
||||
variable event_cnt_user : integer := 0;
|
||||
begin
|
||||
file_open(file_stimuli, "../tb/stimuli_mgt.dat", read_mode);
|
||||
readline(file_stimuli, file_line); -- comment
|
||||
readline(file_stimuli, file_line); -- comment
|
||||
i := 0;
|
||||
-- read line by line from .dat file:
|
||||
while not endfile(file_stimuli) loop
|
||||
readline(file_stimuli, file_line);
|
||||
hread(file_line, event);
|
||||
read(file_line, event_k);
|
||||
read(file_line, space);
|
||||
read(file_line, space);
|
||||
hread(file_line, data);
|
||||
read(file_line, space);
|
||||
read(file_line, data_k);
|
||||
-- write to array:
|
||||
mgt_stream(i).data <= data;
|
||||
mgt_stream(i).data_k <= data_k;
|
||||
mgt_stream(i).event <= event;
|
||||
mgt_stream(i).event_k <= event_k;
|
||||
mgt_stream_index <= i;
|
||||
--debug output:
|
||||
--log(ID_SEGMENT_DATA, "stimuli file: i=" & integer'image(i) & " event=0x" & to_string(event, HEX) & " k=" & to_string(event_k, HEX)
|
||||
-- & " data=0x" & to_string(data, HEX) & " k=" & to_string(data_k, HEX) & " ");
|
||||
|
||||
-- Parse only segment:
|
||||
----------------------
|
||||
case (parse_fsm) is
|
||||
when idle =>
|
||||
if (data = x"5C" and data_k = "1") then -- check if frame start
|
||||
parse_fsm := seg_start;
|
||||
end if;
|
||||
when seg_start =>
|
||||
parse_fsm := seg_addr;
|
||||
when seg_addr =>
|
||||
segment_addr <= data;
|
||||
parse_fsm := seg_wait;
|
||||
when seg_wait =>
|
||||
parse_fsm := seg_payload;
|
||||
payload_cnt := 0;
|
||||
when seg_payload =>
|
||||
if (data = x"3C" and data_k = "1") then -- check if frame end
|
||||
parse_fsm := seg_done;
|
||||
else
|
||||
segment_data(payload_cnt) <= data;
|
||||
parse_fsm := seg_payload_wait;
|
||||
segment_length <= payload_cnt + 1;
|
||||
end if;
|
||||
when seg_payload_wait =>
|
||||
payload_cnt := payload_cnt + 1;
|
||||
parse_fsm := seg_payload;
|
||||
when seg_done =>
|
||||
-- done
|
||||
end case;
|
||||
i := i + 1;
|
||||
end loop;
|
||||
file_close(file_stimuli);
|
||||
wait;
|
||||
end process;
|
||||
end block;
|
||||
-- Parse only segment:
|
||||
----------------------
|
||||
case (parse_fsm) is
|
||||
when idle =>
|
||||
if (data = x"5C" and data_k = "1") then -- check if frame start
|
||||
parse_fsm := seg_start;
|
||||
end if;
|
||||
when seg_start =>
|
||||
parse_fsm := seg_addr;
|
||||
when seg_addr =>
|
||||
segment_addr <= data;
|
||||
parse_fsm := seg_wait;
|
||||
when seg_wait =>
|
||||
parse_fsm := seg_payload;
|
||||
payload_cnt := 0;
|
||||
when seg_payload =>
|
||||
if (data = x"3C" and data_k = "1") then -- check if frame end
|
||||
parse_fsm := seg_done;
|
||||
else
|
||||
segment_data(payload_cnt) <= data;
|
||||
parse_fsm := seg_payload_wait;
|
||||
segment_length <= payload_cnt + 1;
|
||||
end if;
|
||||
when seg_payload_wait =>
|
||||
payload_cnt := payload_cnt + 1;
|
||||
parse_fsm := seg_payload;
|
||||
when seg_done =>
|
||||
-- done
|
||||
end case;
|
||||
i := i + 1;
|
||||
end loop;
|
||||
file_close(file_stimuli);
|
||||
wait;
|
||||
end process;
|
||||
end block;
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Wait for Start of Sequence Event
|
||||
---------------------------------------------------------
|
||||
process
|
||||
begin
|
||||
wait until rising_edge(sos_event);
|
||||
log(ID_CTRL, "Start of Sequence Event Received: " & to_string(std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8)), HEX, AS_IS, INCL_RADIX)); -- change to await_value
|
||||
end process;
|
||||
---------------------------------------------------------
|
||||
-- Wait for Start of Sequence Event
|
||||
---------------------------------------------------------
|
||||
process
|
||||
begin
|
||||
wait until rising_edge(sos_event);
|
||||
log(ID_CTRL, "Start of Sequence Event Received: " & to_string(std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8)), HEX, AS_IS, INCL_RADIX)); -- change to await_value
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Stimuli MGT
|
||||
--------------------------------------------------------------------------
|
||||
process
|
||||
begin
|
||||
wait until rising_edge(clk_evr);
|
||||
for b in 0 to STIMULI_RUNS - 1 loop
|
||||
log(ID_LOG_HDR, "Send stimuli stream to MGT - RUN " & to_string(b + 1));
|
||||
for idx in 0 to mgt_stream_index loop
|
||||
--log(ID_FRAME_DATA, to_string(mgt_stream(idx).data, HEX), to_string(mgt_stream(idx).event, HEX));
|
||||
wait until rising_edge(clk_evr);
|
||||
rxdata <= force out mgt_stream(idx).data & mgt_stream(idx).event;
|
||||
rxcharisk <= force out mgt_stream(idx).data_k & mgt_stream(idx).event_k;
|
||||
end loop;
|
||||
wait for 3 us;
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
--------------------------------------------------------------------------
|
||||
-- Stimuli MGT
|
||||
--------------------------------------------------------------------------
|
||||
process
|
||||
begin
|
||||
wait until rising_edge(clk_evr);
|
||||
for b in 0 to STIMULI_RUNS - 1 loop
|
||||
log(ID_LOG_HDR, "Send stimuli stream to MGT - RUN " & to_string(b + 1));
|
||||
for idx in 0 to mgt_stream_index loop
|
||||
--log(ID_FRAME_DATA, to_string(mgt_stream(idx).data, HEX), to_string(mgt_stream(idx).event, HEX));
|
||||
wait until rising_edge(clk_evr);
|
||||
rxdata <= force out mgt_stream(idx).data & mgt_stream(idx).event;
|
||||
rxcharisk <= force out mgt_stream(idx).data_k & mgt_stream(idx).event_k;
|
||||
end loop;
|
||||
wait for 3 us;
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Main Process
|
||||
-----------------------------------------------------------------------------
|
||||
process
|
||||
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
|
||||
constant c_TB_NAME : string := "evr320_decoder_tb";
|
||||
variable latency_cnt_val : unsigned(31 downto 0);
|
||||
-----------------------------------------------------------------------------
|
||||
-- Main Process
|
||||
-----------------------------------------------------------------------------
|
||||
process
|
||||
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
|
||||
constant c_TB_NAME : string := "evr320_decoder_tb";
|
||||
variable latency_cnt_val : unsigned(31 downto 0);
|
||||
|
||||
begin
|
||||
disable_log_msg(ID_GEN_PULSE);
|
||||
--------------------------------------------------------------------------
|
||||
log(ID_LOG_HDR, "Start Simulation of evr320 decoder", C_SCOPE);
|
||||
--------------------------------------------------------------------------
|
||||
begin
|
||||
disable_log_msg(ID_GEN_PULSE);
|
||||
--------------------------------------------------------------------------
|
||||
log(ID_LOG_HDR, "Start Simulation of evr320 decoder", C_SCOPE);
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Get out of reset, enable events
|
||||
--------------------------------------------------------------------------
|
||||
evr_params.event_enable(0) <= '0' when g_EVENT_NR_0 = 0 else '1';
|
||||
evr_params.event_enable(1) <= '0' when g_EVENT_NR_1 = 0 else '1';
|
||||
evr_params.event_enable(2) <= '0' when g_EVENT_NR_2 = 0 else '1';
|
||||
evr_params.event_enable(3) <= '0' when g_EVENT_NR_3 = 0 else '1';
|
||||
evr_params.event_numbers(0) <= std_logic_vector(to_unsigned(g_EVENT_NR_0, 8));
|
||||
evr_params.event_numbers(1) <= std_logic_vector(to_unsigned(g_EVENT_NR_1, 8));
|
||||
evr_params.event_numbers(2) <= std_logic_vector(to_unsigned(g_EVENT_NR_2, 8));
|
||||
evr_params.event_numbers(3) <= std_logic_vector(to_unsigned(g_EVENT_NR_3, 8));
|
||||
evr_params.cs_min_cnt <= X"00000000";
|
||||
evr_params.cs_min_time <= X"00000000";
|
||||
mem_addr <= x"000";
|
||||
await_value(rxlos, '0', 0 ns, 10 us, FAILURE, "wait for release RX LOS");
|
||||
--------------------------------------------------------------------------
|
||||
-- Get out of reset, enable events
|
||||
--------------------------------------------------------------------------
|
||||
evr_params.event_enable(0) <= '0' when g_EVENT_NR_0 = 0 else '1';
|
||||
evr_params.event_enable(1) <= '0' when g_EVENT_NR_1 = 0 else '1';
|
||||
evr_params.event_enable(2) <= '0' when g_EVENT_NR_2 = 0 else '1';
|
||||
evr_params.event_enable(3) <= '0' when g_EVENT_NR_3 = 0 else '1';
|
||||
evr_params.event_numbers(0) <= std_logic_vector(to_unsigned(g_EVENT_NR_0, 8));
|
||||
evr_params.event_numbers(1) <= std_logic_vector(to_unsigned(g_EVENT_NR_1, 8));
|
||||
evr_params.event_numbers(2) <= std_logic_vector(to_unsigned(g_EVENT_NR_2, 8));
|
||||
evr_params.event_numbers(3) <= std_logic_vector(to_unsigned(g_EVENT_NR_3, 8));
|
||||
evr_params.cs_min_cnt <= X"00000000";
|
||||
evr_params.cs_min_time <= X"00000000";
|
||||
mem_addr <= x"000";
|
||||
await_value(rxlos, '0', 0 ns, 10 us, FAILURE, "wait for release RX LOS");
|
||||
|
||||
-- overwrite evr_stable flag:
|
||||
evr_stable <= force '1';
|
||||
-- overwrite evr_stable flag:
|
||||
evr_stable <= force '1';
|
||||
|
||||
-- enable sos event and set event number:
|
||||
TMEM_BUS_WRITE(seqid => "A00_001",
|
||||
tmem_add => x"00_0040",
|
||||
tmem_we => x"0F",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0000_0000_0000_2001",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
-- enable sos event and set event number:
|
||||
TMEM_BUS_WRITE(seqid => "A00_001",
|
||||
tmem_add => x"00_0040",
|
||||
tmem_we => x"0F",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0000_0000_0000_2001",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
wait for 20 ns;
|
||||
wait for 20 ns;
|
||||
|
||||
-- read back sos event and event number:
|
||||
TMEM_BUS_READ(seqid => "A00_001",
|
||||
tmem_add => x"00_0040",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
-- read back sos event and event number:
|
||||
TMEM_BUS_READ(seqid => "A00_001",
|
||||
tmem_add => x"00_0040",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
wait for 20 ns;
|
||||
wait for 20 ns;
|
||||
-- ---------------------------------------------------------
|
||||
-- send delay and width parameters:
|
||||
TMEM_BUS_WRITE(seqid => "A00_002",
|
||||
tmem_add => x"00_0050",
|
||||
tmem_we => x"FF",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0005_0004_0003_0002",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
check_value(tmem_data_rd, x"0000_0000_0000_2001", ERROR, "TMEM Write/Read check: EVR SOS Event Cfg");
|
||||
wait for 20 ns;
|
||||
|
||||
-- latency measurement: set event nr:
|
||||
TMEM_BUS_WRITE(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_we => x"0F",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0000_0000_0000_0020",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
-- read back delay parameters:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0050",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
wait for 20 ns;
|
||||
wait for 20 ns;
|
||||
|
||||
-- read back sos event and event number:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
check_value(tmem_data_rd, x"0005_0004_0003_0002", ERROR, "TMEM Write/Read check: EVR Puls delay Event Cfg");
|
||||
-- ---------------------------------------------------------
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
-- send width and width parameters:
|
||||
TMEM_BUS_WRITE(seqid => "A00_003",
|
||||
tmem_add => x"00_0058",
|
||||
tmem_we => x"FF",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0009_0008_0007_0006",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
wait for 20 ns;
|
||||
wait for 20 ns;
|
||||
|
||||
check_value(tmem_data_rd, x"0000_0000_0000_0020", ERROR, "TMEM Write/Read check: lat. meas. event nr");
|
||||
-- read back delay parameters:
|
||||
TMEM_BUS_READ(seqid => "A00_003",
|
||||
tmem_add => x"00_0058",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
-- 1. check latency measurement counter:
|
||||
----------------------------------------
|
||||
await_value(sos_event, '1', 0 ns, 2 us, ERROR, "wait for sos event");
|
||||
wait for 2000 ns;
|
||||
latency_cnt_val := x"00000000";
|
||||
wait for 20 ns;
|
||||
|
||||
-- read latency measurement counter without rearm:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(63 downto 32));
|
||||
check_value(tmem_data_rd, x"0009_0008_0007_0006", ERROR, "TMEM Write/Read check: EVR Puls Width Event Cfg");
|
||||
-- ---------------------------------------------------------
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
-- send width and width parameters for SOS:
|
||||
TMEM_BUS_WRITE(seqid => "A00_004",
|
||||
tmem_add => x"00_0060",
|
||||
tmem_we => x"FF",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0000_0000_0001_0001",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
|
||||
check_value_in_range(latency_cnt_val, x"000000F5", x"000000FE", ERROR, "Latency Counter Value (no-rearm) Check after 2us");
|
||||
wait for 20 ns;
|
||||
|
||||
-- 2. read latency measurement counter again with rearm:
|
||||
--------------------------------------------------------
|
||||
latency_cnt_val := x"00000000";
|
||||
-- read back delay parameters:
|
||||
TMEM_BUS_READ(seqid => "A00_004",
|
||||
tmem_add => x"00_0060",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0038",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
|
||||
wait for 20 ns;
|
||||
|
||||
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
|
||||
check_value_in_range(latency_cnt_val, x"000000FA", x"00000102", ERROR, "Latency Counter Value (rearm) Check directly after first read");
|
||||
check_value(tmem_data_rd, x"0000_0000_0001_0001", ERROR, "TMEM Write/Read check: SOS width & delay Event Cfg");
|
||||
-- ---------------------------------------------------------
|
||||
|
||||
-- latency measurement: set event nr:
|
||||
TMEM_BUS_WRITE(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_we => x"0F",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0000_0000_0000_0020",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
-- read 2. time rearm latency counter which should be cleared now:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0038",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
|
||||
check_value(latency_cnt_val, x"00000000", ERROR, "Check if counter is cleared");
|
||||
wait for 20 ns;
|
||||
|
||||
-- 4. read latency measurement counter with rearm:
|
||||
--------------------------------------------------
|
||||
await_value(sos_event, '1', 0 ns, 3 us, ERROR, "wait for sos event");
|
||||
wait for 1 us;
|
||||
-- read back sos event and event number:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
-- read counter and rearm:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0038",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
|
||||
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
|
||||
check_value_in_range(latency_cnt_val, x"0000007A", x"00000080", ERROR, "Latency Counter Value (rearm) Check after 1us");
|
||||
wait for 20 ns;
|
||||
|
||||
-- latency measurement: set event nr:
|
||||
TMEM_BUS_WRITE(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_we => x"0F",
|
||||
tmem_burst => 1,
|
||||
tmem_data_wr => x"0000_0000_0000_0020",
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Test Done
|
||||
--------------------------------------------------------------------------
|
||||
wait for 1000 ns; -- to allow some time for completion
|
||||
report_alert_counters(FINAL); -- Report final counters and print conclusion for simulation (Success/Fail)
|
||||
-- ------------------------------------------------------------------------
|
||||
log(ID_LOG_HDR, "SIMULATION COMPLETED", C_SCOPE);
|
||||
-- ------------------------------------------------------------------------
|
||||
-- assert error if UVVM mismatch flag is 1 => upstream info for scripts/jenkins
|
||||
assert shared_uvvm_status.mismatch_on_expected_simulation_errors_or_worse = 0 report "###ERROR### - UVVM Mismatch Errors with Expected Errors -> Check Log for details" severity ERROR;
|
||||
std.env.stop(0);
|
||||
wait; -- stop simulation
|
||||
wait for 20 ns;
|
||||
|
||||
end process;
|
||||
-- read back sos event and event number:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
|
||||
wait for 20 ns;
|
||||
|
||||
check_value(tmem_data_rd, x"0000_0000_0000_0020", ERROR, "TMEM Write/Read check: lat. meas. event nr");
|
||||
|
||||
-- 1. check latency measurement counter:
|
||||
----------------------------------------
|
||||
await_value(sos_event, '1', 0 ns, 2 us, ERROR, "wait for sos event");
|
||||
wait for 2000 ns;
|
||||
latency_cnt_val := x"00000000";
|
||||
|
||||
-- read latency measurement counter without rearm:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0030",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(63 downto 32));
|
||||
|
||||
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
|
||||
check_value_in_range(latency_cnt_val, x"000000F5", x"000000FE", ERROR, "Latency Counter Value (no-rearm) Check after 2us");
|
||||
|
||||
-- 2. read latency measurement counter again with rearm:
|
||||
--------------------------------------------------------
|
||||
latency_cnt_val := x"00000000";
|
||||
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0038",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
|
||||
|
||||
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
|
||||
check_value_in_range(latency_cnt_val, x"000000FA", x"00000102", ERROR, "Latency Counter Value (rearm) Check directly after first read");
|
||||
|
||||
-- read 2. time rearm latency counter which should be cleared now:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0038",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
|
||||
check_value(latency_cnt_val, x"00000000", ERROR, "Check if counter is cleared");
|
||||
|
||||
-- 4. read latency measurement counter with rearm:
|
||||
--------------------------------------------------
|
||||
await_value(sos_event, '1', 0 ns, 3 us, ERROR, "wait for sos event");
|
||||
wait for 1 us;
|
||||
|
||||
-- read counter and rearm:
|
||||
TMEM_BUS_READ(seqid => "A00_002",
|
||||
tmem_add => x"00_0038",
|
||||
tmem_burst => 1,
|
||||
tmem_data_rd => tmem_data_rd,
|
||||
xuser_clk_i => tmem_clk,
|
||||
xuser_tmem_bus_o => tmem_i,
|
||||
xuser_tmem_bus_i => tmem_o);
|
||||
wait for 20 ns;
|
||||
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
|
||||
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
|
||||
check_value_in_range(latency_cnt_val, x"0000007A", x"00000080", ERROR, "Latency Counter Value (rearm) Check after 1us");
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Test Done
|
||||
--------------------------------------------------------------------------
|
||||
wait for 1000 ns; -- to allow some time for completion
|
||||
report_alert_counters(FINAL); -- Report final counters and print conclusion for simulation (Success/Fail)
|
||||
-- ------------------------------------------------------------------------
|
||||
log(ID_LOG_HDR, "SIMULATION COMPLETED", C_SCOPE);
|
||||
-- ------------------------------------------------------------------------
|
||||
-- assert error if UVVM mismatch flag is 1 => upstream info for scripts/jenkins
|
||||
assert shared_uvvm_status.mismatch_on_expected_simulation_errors_or_worse = 0 report "###ERROR### - UVVM Mismatch Errors with Expected Errors -> Check Log for details" severity ERROR;
|
||||
std.env.stop(0);
|
||||
wait; -- stop simulation
|
||||
|
||||
end process;
|
||||
|
||||
end architecture testbench;
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ FE 0 00 0 event 254
|
||||
FF 0 00 0 event 255
|
||||
BC 1 00 0 align
|
||||
00 0 00 0 gap
|
||||
0F 0 00 0 gap
|
||||
00 0 00 0 gap
|
||||
00 0 00 0 gap
|
||||
BC 1 00 0 align
|
||||
00 0 00 0 gap
|
||||
|
||||
Reference in New Issue
Block a user