597 lines
26 KiB
VHDL
597 lines
26 KiB
VHDL
--------------------------------------------------------------------------------
|
|
-- ifc1210_wrapper testbench
|
|
--------------------------------------------------------------------------------
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
use ieee.std_logic_textio.all;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library std;
|
|
use std.env.all;
|
|
use std.textio.all;
|
|
|
|
library tosca2;
|
|
use tosca2.ifc1210_simu_procedures_pkg.all;
|
|
|
|
library uvvm_util;
|
|
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#;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- 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;
|
|
|
|
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');
|
|
|
|
-- 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;
|
|
|
|
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;
|
|
|
|
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 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>>;
|
|
|
|
--*** 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";
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- 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;
|
|
|
|
-- 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;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- 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;
|
|
|
|
---------------------------------------------------------
|
|
-- 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;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- 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);
|
|
--------------------------------------------------------------------------
|
|
|
|
--------------------------------------------------------------------------
|
|
-- 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';
|
|
|
|
-- 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;
|
|
|
|
-- 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;
|
|
-- ---------------------------------------------------------
|
|
-- 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);
|
|
|
|
wait for 20 ns;
|
|
|
|
-- 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;
|
|
|
|
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;
|
|
|
|
-- 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);
|
|
|
|
wait for 20 ns;
|
|
|
|
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);
|
|
|
|
wait for 20 ns;
|
|
|
|
-- 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);
|
|
|
|
wait for 20 ns;
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- End of file
|
|
--------------------------------------------------------------------------------
|