
This parameter is a local enhancement and not present on the master branch. Also: two small changes which address GHDL issues.
586 lines
27 KiB
VHDL
586 lines
27 KiB
VHDL
--------------------------------------------------------------------------------
|
|
-- Paul Scherrer Institute (PSI)
|
|
--------------------------------------------------------------------------------
|
|
-- Unit : evr320_decoder_tb.vhd
|
|
-- Author : Goran Marinkovic, Section Diagnostic, Jonas Purtschert
|
|
-- Version : $Revision: 1.1 $
|
|
--------------------------------------------------------------------------------
|
|
-- Copyright© PSI, Section Diagnostic
|
|
--------------------------------------------------------------------------------
|
|
-- Comment : This is the test bench for the evr component.
|
|
--------------------------------------------------------------------------------
|
|
-- Std. library (platform) -----------------------------------------------------
|
|
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 uvvm_util;
|
|
context uvvm_util.uvvm_util_context;
|
|
|
|
-- Work library (application) --------------------------------------------------
|
|
library work;
|
|
use work.evr320_pkg.all;
|
|
|
|
entity evr320_decoder_tb is
|
|
generic (
|
|
g_EVENT_NR_0 : integer range 0 to 255 := 16#00#;
|
|
g_EVENT_NR_1 : integer range 0 to 255 := 16#04#;
|
|
g_EVENT_NR_2 : integer range 0 to 255 := 16#00#;
|
|
g_EVENT_NR_3 : integer range 0 to 255 := 16#00#;
|
|
g_EVENT_NR_SOS : integer range 0 to 255 := 16#20#
|
|
);
|
|
end entity;
|
|
|
|
architecture testbench of evr320_decoder_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";
|
|
|
|
---------------------------------------------------------------------------
|
|
-- 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
|
|
-----------------------------------------------------------------------------
|
|
-- Link status
|
|
signal rxlos : std_logic := '0';
|
|
-- Clock
|
|
signal rxusrclk : std_logic := '0';
|
|
-- Data
|
|
signal rxdata : std_logic_vector(15 downto 0) := (others => '0');
|
|
-- Status 8B/10B decoder
|
|
signal rxcharisk : std_logic_vector( 1 downto 0) := (others => '0');
|
|
|
|
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(C_MEM_DATA_WIDTH-1 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';
|
|
|
|
-- Events
|
|
signal usr_events : std_logic_vector( 3 downto 0) := (others => '0');
|
|
signal sos_event : std_logic := '0';
|
|
|
|
type typ_arrint is array (natural range <>) of integer;
|
|
signal received_events : typ_arrint(0 to C_EVT_NR-1) := (others => 0);
|
|
signal expect_events : typ_arrint(0 to C_EVT_NR-1) := (others => 0);
|
|
signal expect_events_total : integer := 0;
|
|
|
|
-- Event Recorder
|
|
signal event_recorder_status : typ_evt_rec_status;
|
|
signal event_recorder_ctrl : typ_evt_rec_ctrl := c_INIT_EVT_REC_CTRL;
|
|
signal check_evt_rec_events : std_logic := '0';
|
|
signal all_expected_events : std_logic_vector(255 downto 0) := (others => '0');
|
|
signal expected_user_events : integer range 0 to 255 := 0;
|
|
|
|
begin
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Timing decoder
|
|
-----------------------------------------------------------------------------
|
|
evr320_decoder_inst: entity work.evr320_decoder
|
|
generic map
|
|
(
|
|
EVENT_RECORDER => C_EVENT_RECORDER,
|
|
MEM_DATA_WIDTH => C_MEM_DATA_WIDTH
|
|
)
|
|
port map
|
|
(
|
|
--------------------------------------------------------------------------
|
|
-- Debug interface
|
|
--------------------------------------------------------------------------
|
|
debug_clk => open,
|
|
debug => open,
|
|
--------------------------------------------------------------------------
|
|
-- GTX parallel interface
|
|
--------------------------------------------------------------------------
|
|
i_mgt_rst => rxlos,
|
|
i_mgt_rx_clk => rxusrclk,
|
|
i_mgt_rx_data => rxdata,
|
|
i_mgt_rx_charisk => rxcharisk,
|
|
--------------------------------------------------------------------------
|
|
-- User interface CPU clock
|
|
--------------------------------------------------------------------------
|
|
i_usr_clk => usr_clk,
|
|
i_evr_params => evr_params,
|
|
o_event_recorder_stat => event_recorder_status,
|
|
i_event_recorder_ctrl => event_recorder_ctrl,
|
|
i_mem_addr => mem_addr,
|
|
o_mem_data => mem_data,
|
|
--------------------------------------------------------------------------
|
|
-- User stream interface User clock
|
|
--------------------------------------------------------------------------
|
|
i_stream_clk => usr_clk,
|
|
o_stream_data => dec_stream_data,
|
|
o_stream_addr => dec_stream_addr,
|
|
o_stream_valid => dec_stream_valid,
|
|
--------------------------------------------------------------------------
|
|
-- User interface MGT clock
|
|
--------------------------------------------------------------------------
|
|
o_usr_events => usr_events,
|
|
o_usr_events_ext => open,
|
|
o_sos_event => sos_event,
|
|
o_event => open,
|
|
o_event_valid => open
|
|
);
|
|
|
|
evr320_data_filter_inst: entity work.evr320_data_filter
|
|
generic map (
|
|
SWAP => true, -- non-swapped uses LE layout; our check below converts to BE
|
|
NUM_BYTES => 8
|
|
)
|
|
port map (
|
|
i_stream_clk => usr_clk,
|
|
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
|
|
);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- MGT / User clock
|
|
-----------------------------------------------------------------------------
|
|
clock_generator(rxusrclk, C_RXUSRCLK_CYCLE);
|
|
clock_generator(usr_clk, C_USRCLK_CYCLE);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Decoder reset due to MGT main status
|
|
-----------------------------------------------------------------------------
|
|
process
|
|
begin
|
|
rxlos <= '1';
|
|
wait for 50 ns;
|
|
wait until (falling_edge(rxusrclk));
|
|
rxlos <= '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) & " ");
|
|
-- Count Events:
|
|
----------------
|
|
if (event /= x"00" and event_k = "0") then
|
|
event_cnt_total := event_cnt_total + 1;
|
|
|
|
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_0, 8))) then
|
|
event_cnt_0 := event_cnt_0 + 1;
|
|
end if;
|
|
|
|
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_1, 8))) then
|
|
event_cnt_1 := event_cnt_1 + 1;
|
|
end if;
|
|
|
|
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_2, 8))) then
|
|
event_cnt_2 := event_cnt_2 + 1;
|
|
end if;
|
|
|
|
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_3, 8))) then
|
|
event_cnt_3 := event_cnt_3 + 1;
|
|
end if;
|
|
end if;
|
|
|
|
expect_events_total <= event_cnt_total * STIMULI_RUNS;
|
|
expect_events(0) <= event_cnt_0 * STIMULI_RUNS;
|
|
expect_events(1) <= event_cnt_1 * STIMULI_RUNS;
|
|
expect_events(2) <= event_cnt_2 * STIMULI_RUNS;
|
|
expect_events(3) <= event_cnt_3 * STIMULI_RUNS;
|
|
|
|
-- Event Recorder:
|
|
------------------
|
|
if (event_k = "0") then
|
|
all_expected_events(to_integer(unsigned(event))) <= '1';
|
|
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8))) then
|
|
log("Start-of-Sequence Event in Stimuli present");
|
|
end if;
|
|
if (event /= X"00" and event(7 downto 4) /= X"7") then
|
|
event_cnt_user := event_cnt_user + 1;
|
|
end if;
|
|
end if;
|
|
|
|
expected_user_events <= event_cnt_user;
|
|
|
|
-- 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;
|
|
|
|
---------------------------------------------------------
|
|
-- Receive decoder data stream
|
|
---------------------------------------------------------
|
|
process
|
|
variable addr : std_logic_vector(10 downto 0);
|
|
variable data : std_logic_vector(7 downto 0);
|
|
variable i : integer := 0;
|
|
begin
|
|
wait until rising_edge(usr_clk);
|
|
if (dec_stream_valid = '1') then
|
|
addr := dec_stream_addr;
|
|
data := dec_stream_data;
|
|
i := to_integer(unsigned(addr)) - to_integer(unsigned(segment_addr))*16;
|
|
-- save stream for later comparision:
|
|
dec_stream_check(i).addr <= addr;
|
|
dec_stream_check(i).data <= data;
|
|
log(ID_SEGMENT_DATA, "Recv Decoder Stream: count=" & integer'image(i) & " addr=0x" & to_string(addr, HEX) & " data=0x" & to_string(data, HEX));
|
|
i := i + 1;
|
|
dec_stream_recv_bytes <= i;
|
|
end if;
|
|
end process;
|
|
|
|
---------------------------------------------------------
|
|
-- Fetch filter data
|
|
---------------------------------------------------------
|
|
process
|
|
begin
|
|
wait until rising_edge(usr_clk);
|
|
if (filter_valid = '1') then
|
|
filter_data_check <= filter_data;
|
|
log(ID_SEGMENT_DATA, "Filter Valid: data=" & to_string(filter_data, HEX, AS_IS, INCL_RADIX));
|
|
end if;
|
|
end process;
|
|
|
|
---------------------------------------------------------
|
|
-- Wait for User Events
|
|
---------------------------------------------------------
|
|
process
|
|
begin
|
|
wait until rising_edge(rxusrclk);
|
|
for i in 0 to C_EVT_NR-1 loop
|
|
if (usr_events(i) = '1') then
|
|
log(ID_CTRL, "Event Received: " & to_string(evr_params.event_numbers(i), HEX, AS_IS, INCL_RADIX) );
|
|
received_events(i) <= received_events(i) + 1;
|
|
end if;
|
|
end loop;
|
|
end process;
|
|
|
|
---------------------------------------------------------
|
|
-- Wait for Start of Sequence Event
|
|
---------------------------------------------------------
|
|
process
|
|
begin
|
|
wait until rising_edge(rxusrclk);
|
|
if (sos_event = '1') then
|
|
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
|
|
check_evt_rec_events <= '1';
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Stimulus CPU interface
|
|
-----------------------------------------------------------------------------
|
|
process
|
|
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
|
|
constant c_TB_NAME : string := "evr320_decoder_tb";
|
|
variable mgt_stream_rep_var : integer := 0;
|
|
variable mgt_stream_index_var : integer := 0;
|
|
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(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;
|
|
begin
|
|
-- init uvvm:
|
|
set_log_file_name(c_TB_NAME & "_LOG.txt");
|
|
set_alert_file_name(c_TB_NAME & "_ALERT.txt");
|
|
set_alert_stop_limit(ERROR, 0); -- never(0) pause simulator on error
|
|
set_alert_stop_limit(TB_ERROR, 0); -- never(0) pause simulator on error
|
|
enable_log_msg(ALL_MESSAGES);
|
|
--------------------------------------------------------------------------
|
|
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';
|
|
event_recorder_ctrl.event_enable <= '0' when g_EVENT_NR_SOS = 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));
|
|
event_recorder_ctrl.event_number <= std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 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");
|
|
--wait until (rxlos = '0');
|
|
|
|
--------------------------------------------------------------------------
|
|
-- Stimuli MGT
|
|
--------------------------------------------------------------------------
|
|
wait until rising_edge(rxusrclk);
|
|
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(rxusrclk);
|
|
rxdata <= mgt_stream(idx).data & mgt_stream(idx).event;
|
|
rxcharisk <= mgt_stream(idx).data_k & mgt_stream(idx).event_k;
|
|
end loop;
|
|
end loop;
|
|
|
|
--------------------------------------------------------------------------
|
|
log(ID_LOG_HDR, "Check if decoder stream is correct", C_SCOPE);
|
|
--------------------------------------------------------------------------
|
|
await_value(dec_stream_recv_bytes, segment_length, 0 ns, 5 us, ERROR, "Wait for right number of bytes streamed");
|
|
-- loop through segment and compare frame bytes with received decoder-stream:
|
|
for idx in 0 to segment_length-1 loop
|
|
check_value(dec_stream_check(idx).data, segment_data(idx), ERROR, "Compare Sent and Received Decoder Stream Data");
|
|
end loop;
|
|
|
|
--------------------------------------------------------------------------
|
|
log(ID_LOG_HDR, "Check if filter data is correct", C_SCOPE);
|
|
--------------------------------------------------------------------------
|
|
var_filter_offset := to_integer(unsigned(FILTER_ADDRESS)) - (to_integer(unsigned(segment_addr))*16);
|
|
--log(ID_CTRL, "var_filter_offset=" & integer'image(var_filter_offset) & " : " & to_string(FILTER_ADDRESS,HEX) & " : " & to_string(segment_addr, HEX));
|
|
for idx in 0 to FILTER_NUM_BYTES-1 loop
|
|
var_filter_word := var_filter_word(var_filter_word'high-8 downto 0) & segment_data(var_filter_offset + idx);
|
|
end loop;
|
|
check_value(filter_data_check, var_filter_word, ERROR, "Check Data Stream Filter "
|
|
& "addr=0x" & to_string(FILTER_ADDRESS, HEX)
|
|
& " bytes=" & integer'image(FILTER_NUM_BYTES));
|
|
|
|
--------------------------------------------------------------------------
|
|
-- Check if correct number of events has been detected
|
|
--------------------------------------------------------------------------
|
|
for i in 0 to C_EVT_NR-1 loop
|
|
check_value(received_events(i), expect_events(i), ERROR, "Event " & to_string(i) & ": received = " & to_string(received_events(i)) & ", expected = " & to_string(expect_events(i)));
|
|
end loop;
|
|
|
|
--------------------------------------------------------------------------
|
|
log(ID_LOG_HDR, "Event Recorder Checks", C_SCOPE);
|
|
--------------------------------------------------------------------------
|
|
wait for 1 us;
|
|
if (C_EVENT_RECORDER) then
|
|
if (check_evt_rec_events = '1' and STIMULI_RUNS > 1) then
|
|
|
|
----------------------------------------------------------------------
|
|
log(ID_DATA, "Check expected Event Flags after SOS Event detected");
|
|
----------------------------------------------------------------------
|
|
wait until rising_edge(usr_clk);
|
|
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");
|
|
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");
|
|
----------------------------------------------------------------------
|
|
check_value(to_integer(unsigned(event_recorder_status.usr_events_counter)), expected_user_events, ERROR, "Total User Events: received = " & to_string(to_integer(unsigned(event_recorder_status.usr_events_counter))) & ", expected = " & to_string(expected_user_events));
|
|
|
|
end if;
|
|
end if;
|
|
|
|
--------------------------------------------------------------------------
|
|
log(ID_LOG_HDR, "Read DPRAM buffer", C_SCOPE);
|
|
--------------------------------------------------------------------------
|
|
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
|
|
--------------------------------------------------------------------------
|
|
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
|
|
--------------------------------------------------------------------------------
|