Skip to content
Snippets Groups Projects
Commit 57cb9ba9 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Add eth_stream.vhd with test benches.

parent fd25c788
No related branches found
No related tags found
1 merge request!293Rename eth_stream into eth_stream_udp. Create new eth_stream.vhd that contains...
Pipeline #39873 failed
...@@ -22,6 +22,7 @@ synth_files = ...@@ -22,6 +22,7 @@ synth_files =
src/vhdl/eth_control.vhd src/vhdl/eth_control.vhd
src/vhdl/eth_ihl_to_20.vhd src/vhdl/eth_ihl_to_20.vhd
src/vhdl/eth.vhd src/vhdl/eth.vhd
src/vhdl/eth_stream.vhd
src/vhdl/eth_tester_pkg.vhd src/vhdl/eth_tester_pkg.vhd
src/vhdl/eth_tester_tx.vhd src/vhdl/eth_tester_tx.vhd
src/vhdl/eth_tester_rx.vhd src/vhdl/eth_tester_rx.vhd
...@@ -35,8 +36,10 @@ test_bench_files = ...@@ -35,8 +36,10 @@ test_bench_files =
tb/vhdl/tb_eth.vhd tb/vhdl/tb_eth.vhd
tb/vhdl/tb_eth_tester_pkg.vhd tb/vhdl/tb_eth_tester_pkg.vhd
tb/vhdl/tb_eth_tester.vhd tb/vhdl/tb_eth_tester.vhd
tb/vhdl/tb_eth_stream.vhd
tb/vhdl/tb_tb_eth.vhd tb/vhdl/tb_tb_eth.vhd
tb/vhdl/tb_tb_eth_tester.vhd tb/vhdl/tb_tb_eth_tester.vhd
tb/vhdl/tb_tb_eth_stream.vhd
tb/vhdl/tb_eth_udp_offload.vhd tb/vhdl/tb_eth_udp_offload.vhd
tb/vhdl/tb_eth_ihl_to_20.vhd tb/vhdl/tb_eth_ihl_to_20.vhd
tb/vhdl/tb_tb_tb_eth_regression.vhd tb/vhdl/tb_tb_tb_eth_regression.vhd
...@@ -49,6 +52,7 @@ regression_test_vhdl = ...@@ -49,6 +52,7 @@ regression_test_vhdl =
tb/vhdl/tb_eth_ihl_to_20.vhd tb/vhdl/tb_eth_ihl_to_20.vhd
tb/vhdl/tb_tb_eth.vhd tb/vhdl/tb_tb_eth.vhd
tb/vhdl/tb_tb_eth_tester.vhd tb/vhdl/tb_tb_eth_tester.vhd
tb/vhdl/tb_tb_eth_stream.vhd
[modelsim_project_file] [modelsim_project_file]
......
-------------------------------------------------------------------------------
--
-- Copyright (C) 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Author: Eric Kooistra
-- Purpose:
-- Provide Ethernet access to a node for one UDP stream.
-- Description:
-- * This eth_stream.vhd is a stripped down version of eth.vhd.
-- * This eth_stream only contains the components that are needed to send or
-- receive an UDP stream via 1GbE.
-- The IP checksum is filled in for Tx and checked or Rx.
-- The Tx only contains UDP stream data, so no need for a dp_mux.
-- The Rx may contain other packet types, because the 1GbE connects to a
-- network. All Rx packets that are not UDP for g_rx_udp_port are discarded.
-- References:
-- [1] https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+ETH+tester+unit+for+1GbE
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE work.eth_pkg.ALL;
ENTITY eth_stream IS
GENERIC (
g_rx_udp_port : NATURAL
);
PORT (
-- Clocks and reset
st_rst : IN STD_LOGIC;
st_clk : IN STD_LOGIC;
-- User UDP interface
-- . Tx
udp_tx_sosi : IN t_dp_sosi;
udp_tx_siso : OUT t_dp_siso;
-- . Rx
udp_rx_sosi : OUT t_dp_sosi;
udp_rx_siso : IN t_dp_siso := c_dp_siso_rdy;
-- PHY interface
-- . Tx
tse_tx_sosi : OUT t_dp_sosi;
tse_tx_siso : IN t_dp_siso;
-- . Rx
tse_rx_sosi : IN t_dp_sosi;
tse_rx_siso : OUT t_dp_siso
);
END eth_stream;
ARCHITECTURE str OF eth_stream IS
-- ETH Tx
SIGNAL eth_tx_siso : t_dp_siso;
SIGNAL eth_tx_sosi : t_dp_sosi;
-- ETH Rx
SIGNAL rx_adapt_siso : t_dp_siso;
SIGNAL rx_adapt_sosi : t_dp_sosi;
SIGNAL rx_hdr_status : t_eth_hdr_status;
SIGNAL rx_hdr_status_complete : STD_LOGIC;
SIGNAL rx_eth_discard : STD_LOGIC;
SIGNAL rx_eth_discard_val : STD_LOGIC;
BEGIN
------------------------------------------------------------------------------
-- TX
------------------------------------------------------------------------------
-- Insert IP header checksum
u_tx_ip : ENTITY work.eth_hdr
GENERIC MAP (
g_header_store_and_forward => TRUE,
g_ip_header_checksum_calculate => TRUE
)
PORT MAP (
-- Clocks and reset
rst => st_rst,
clk => st_clk,
-- Streaming Sink
snk_in => udp_tx_sosi,
snk_out => udp_tx_siso,
-- Streaming Source
src_in => tse_tx_siso,
src_out => tse_tx_sosi -- with err field value 0 for OK
);
------------------------------------------------------------------------------
-- RX
------------------------------------------------------------------------------
-- Adapt the TSE RX source ready latency from 2 to 1
u_adapt : ENTITY dp_lib.dp_latency_adapter
GENERIC MAP (
g_in_latency => c_eth_rx_ready_latency, -- = 2
g_out_latency => c_eth_ready_latency -- = 1
)
PORT MAP (
rst => st_rst,
clk => st_clk,
-- ST sink
snk_out => tse_rx_siso,
snk_in => tse_rx_sosi,
-- ST source
src_in => rx_adapt_siso,
src_out => rx_adapt_sosi
);
-- Pass on UDP stream for g_rx_udp_port
-- . Verify IP header checksum for IP
u_rx_udp : ENTITY work.eth_hdr
GENERIC MAP (
g_header_store_and_forward => TRUE,
g_ip_header_checksum_calculate => TRUE
)
PORT MAP (
-- Clocks and reset
rst => st_rst,
clk => st_clk,
-- Streaming Sink
snk_in => rx_adapt_sosi,
snk_out => rx_adapt_siso,
-- Streaming Source
src_in => udp_rx_siso,
src_out => udp_rx_sosi,
-- Frame control
frm_discard => rx_eth_discard,
frm_discard_val => rx_eth_discard_val,
-- Header info
hdr_status => rx_hdr_status,
hdr_status_complete => rx_hdr_status_complete
);
-- Discard all Rx data that is not UDP for g_rx_udp_port
p_rx_discard : PROCESS(st_rst, st_clk)
BEGIN
IF st_rst = '1' THEN
rx_eth_discard <= '1'; -- default discard
rx_eth_discard_val <= '0';
ELSIF rising_edge(st_clk) THEN
-- Default keep rx_eth_discard status (instead of '1'), to more clearly
-- see when a change occurs
IF rx_hdr_status_complete = '1' THEN
rx_eth_discard <= '1'; -- default discard
IF rx_hdr_status.is_ip = '1' AND
rx_hdr_status.is_udp = '1' AND
TO_UINT(rx_hdr_status.udp_port) = g_rx_udp_port THEN
rx_eth_discard <= '0'; -- pass on IP/UDP stream for g_rx_udp_port
END IF;
END IF;
rx_eth_discard_val <= rx_hdr_status_complete;
END IF;
END PROCESS;
END str;
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- AUthor: E. Kooistra
-- Purpose: Test bench for eth_stream using eth_tester
-- Description:
-- Similar as tb_eth_tester.vhd, but for only one stream and using streaming
-- interface loop back.
--
-- Usage:
-- > as 8
-- > run -a
--
-- References:
-- [1] https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+ETH+tester+unit+for+1GbE
LIBRARY IEEE, common_lib, dp_lib, diag_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_str_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE common_lib.tb_common_mem_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE diag_lib.diag_pkg.ALL;
USE work.eth_pkg.ALL;
USE work.eth_tester_pkg.ALL;
USE work.tb_eth_tester_pkg.ALL;
ENTITY tb_eth_stream IS
GENERIC (
g_tb_index : NATURAL := 0; -- use to incremental delay logging from tb instances in tb_tb
g_nof_sync : NATURAL := 2; -- number of BG sync intervals to set c_run_time
g_udp_port_match : BOOLEAN := TRUE;
-- t_diag_block_gen_integer =
-- sl: enable
-- sl: enable_sync
-- nat: samples_per_packet
-- nat: blocks_per_sync
-- nat: gapsize
-- nat: mem_low_adrs
-- nat: mem_high_adrs
-- nat: bsn_init
g_bg_ctrl : t_diag_block_gen_integer := ('1', '1', 50, 3, 200, 0, c_diag_bg_mem_max_adr, 0) -- for first stream
);
END tb_eth_stream;
ARCHITECTURE tb OF tb_eth_stream IS
CONSTANT c_tb_str : STRING := "tb-" & NATURAL'IMAGE(g_tb_index) & " : "; -- use to distinguish logging from tb instances in tb_tb
CONSTANT mm_clk_period : TIME := 10 ns; -- 100 MHz
CONSTANT c_nof_st_clk_per_s : NATURAL := 200 * 10**6;
CONSTANT st_clk_period : TIME := (10**9 / c_nof_st_clk_per_s) * 1 ns; -- 5 ns, 200 MHz
CONSTANT c_bg_block_len : NATURAL := g_bg_ctrl.samples_per_packet;
CONSTANT c_bg_slot_len : NATURAL := c_bg_block_len + g_bg_ctrl.gapsize;
CONSTANT c_eth_packet_len : NATURAL := func_eth_tester_eth_packet_length(c_bg_block_len);
-- Use REAL to avoid NATURAL overflow in bps calculation
CONSTANT c_bg_nof_bps : REAL := REAL(c_bg_block_len * c_octet_w) * REAL(c_nof_st_clk_per_s) / REAL(c_bg_slot_len);
CONSTANT c_bg_sync_period : NATURAL := c_bg_slot_len * g_bg_ctrl.blocks_per_sync;
CONSTANT c_run_time : NATURAL := g_nof_sync * c_bg_sync_period;
CONSTANT c_nof_sync : NATURAL := c_run_time / c_bg_sync_period;
-- Destination UDP port
CONSTANT c_rx_udp_port : NATURAL := TO_UINT(c_eth_tester_udp_dst_port);
CONSTANT c_dst_udp_port : NATURAL := sel_a_b(g_udp_port_match, c_rx_udp_port, 17);
-- Expected Tx --> Rx latency values obtained from a tb run
CONSTANT c_tx_exp_latency : NATURAL := 0;
CONSTANT c_rx_exp_latency_en : BOOLEAN := c_bg_block_len >= 50;
CONSTANT c_rx_exp_latency_st : NATURAL := sel_a_b(g_udp_port_match, 58, 0);
CONSTANT c_nof_valid_per_packet : NATURAL := c_bg_block_len;
CONSTANT c_total_count_nof_valid_per_sync : NATURAL := g_bg_ctrl.blocks_per_sync * c_nof_valid_per_packet;
CONSTANT c_mon_nof_sop_tx : NATURAL := g_bg_ctrl.blocks_per_sync;
CONSTANT c_mon_nof_sop_rx : NATURAL := sel_a_b(g_udp_port_match, c_mon_nof_sop_tx, 0);
CONSTANT c_mon_nof_valid_tx : NATURAL := c_mon_nof_sop_tx * ceil_div(c_bg_block_len * c_octet_w, c_word_w);
CONSTANT c_mon_nof_valid_rx : NATURAL := c_mon_nof_sop_rx * c_nof_valid_per_packet;
-- Use sim default src MAC, IP, UDP port from eth_tester_pkg.vhd and based on c_gn_index
CONSTANT c_gn_index : NATURAL := 17; -- global node index
CONSTANT c_gn_eth_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := c_eth_tester_eth_src_mac_47_16 & func_eth_tester_gn_index_to_mac_15_0(c_gn_index);
CONSTANT c_gn_ip_src_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := c_eth_tester_ip_src_addr_31_16 & func_eth_tester_gn_index_to_ip_15_0(c_gn_index);
CONSTANT c_gn_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0) := c_eth_tester_udp_src_port_15_8 & TO_UVEC(c_gn_index, 8);
-- Clocks and reset
SIGNAL mm_rst : STD_LOGIC := '1';
SIGNAL mm_clk : STD_LOGIC := '1';
SIGNAL st_rst : STD_LOGIC := '1';
SIGNAL st_clk : STD_LOGIC := '1';
SIGNAL st_pps : STD_LOGIC := '0';
SIGNAL stimuli_end : STD_LOGIC := '0';
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL tx_fifo_rd_emp : STD_LOGIC;
-- ETH UDP data path interface
SIGNAL tx_udp_sosi : t_dp_sosi;
SIGNAL tx_udp_siso : t_dp_siso := c_dp_siso_rdy;
SIGNAL rx_udp_sosi : t_dp_sosi;
-- MM interface
-- . Tx
SIGNAL reg_bg_ctrl_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_bg_ctrl_cipo : t_mem_cipo;
SIGNAL reg_hdr_dat_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_hdr_dat_cipo : t_mem_cipo;
SIGNAL reg_bsn_monitor_v2_tx_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_bsn_monitor_v2_tx_cipo : t_mem_cipo;
SIGNAL reg_strobe_total_count_tx_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_strobe_total_count_tx_cipo : t_mem_cipo;
-- . Rx
SIGNAL reg_bsn_monitor_v2_rx_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_bsn_monitor_v2_rx_cipo : t_mem_cipo;
SIGNAL reg_strobe_total_count_rx_copi : t_mem_copi := c_mem_copi_rst;
SIGNAL reg_strobe_total_count_rx_cipo : t_mem_cipo;
-- . reg_strobe_total_count
SIGNAL tx_total_count_nof_packet : NATURAL;
SIGNAL rx_total_count_nof_packet : NATURAL;
SIGNAL tx_exp_total_count_nof_packet : NATURAL;
SIGNAL rx_exp_total_count_nof_packet : NATURAL;
SIGNAL rx_total_count_nof_valid : NATURAL;
SIGNAL rx_exp_total_count_nof_valid : NATURAL;
-- . reg_bsn_monitor_v2
SIGNAL tx_mon_nof_sop : NATURAL;
SIGNAL tx_mon_nof_valid : NATURAL;
SIGNAL tx_mon_latency : NATURAL;
SIGNAL rx_mon_nof_sop : NATURAL;
SIGNAL rx_mon_nof_valid : NATURAL;
SIGNAL rx_mon_latency : NATURAL;
-- ETH stream
SIGNAL tse_tx_sosi : t_dp_sosi;
SIGNAL tse_tx_siso : t_dp_siso;
SIGNAL tse_rx_sosi : t_dp_sosi;
SIGNAL tse_rx_siso : t_dp_siso;
-- View in Wave window
SIGNAL dbg_g_bg_ctrl : t_diag_block_gen_integer := g_bg_ctrl;
SIGNAL dbg_c_run_time : NATURAL := c_run_time;
SIGNAL dbg_c_mon_nof_sop_tx : NATURAL := c_mon_nof_sop_tx;
SIGNAL dbg_c_mon_nof_sop_rx : NATURAL := c_mon_nof_sop_rx;
SIGNAL dbg_c_mon_nof_valid_tx : NATURAL := c_mon_nof_valid_tx;
SIGNAL dbg_c_mon_nof_valid_rx : NATURAL := c_mon_nof_valid_rx;
BEGIN
mm_clk <= (NOT mm_clk) OR tb_end AFTER mm_clk_period/2;
st_clk <= (NOT st_clk) OR tb_end AFTER st_clk_period/2;
mm_rst <= '1', '0' AFTER mm_clk_period*5;
st_rst <= '1', '0' AFTER st_clk_period*5;
tx_exp_total_count_nof_packet <= c_nof_sync * g_bg_ctrl.blocks_per_sync;
rx_exp_total_count_nof_packet <= sel_a_b(g_udp_port_match, tx_exp_total_count_nof_packet, 0);
rx_exp_total_count_nof_valid <= sel_a_b(g_udp_port_match, c_nof_sync * c_total_count_nof_valid_per_sync, 0);
-----------------------------------------------------------------------------
-- MM control and monitoring
-----------------------------------------------------------------------------
p_mm : PROCESS
BEGIN
tb_end <= '0';
proc_common_wait_until_low(mm_clk, mm_rst);
proc_common_wait_some_cycles(mm_clk, 10);
---------------------------------------------------------------------------
-- Rx UDP offload port
---------------------------------------------------------------------------
-- Set destination MAC/IP/UDP port in tx header
-- The MM addresses follow from byte address_offset // 4 in eth.peripheral.yaml
proc_mem_mm_bus_wr(16#7#, c_dst_udp_port, mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi);
proc_mem_mm_bus_wr(16#10#, TO_SINT(c_eth_tester_ip_dst_addr), mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi); -- use signed to fit 32 b in INTEGER
proc_mem_mm_bus_wr(16#18#, TO_SINT(c_eth_tester_eth_dst_mac(31 DOWNTO 0)), mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi); -- use signed to fit 32 b in INTEGER
proc_mem_mm_bus_wr(16#19#, TO_UINT(c_eth_tester_eth_dst_mac(47 DOWNTO 32)), mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi);
---------------------------------------------------------------------------
-- Stimuli
---------------------------------------------------------------------------
-- Prepare the BG
proc_mem_mm_bus_wr(1, g_bg_ctrl.samples_per_packet, mm_clk, reg_bg_ctrl_copi);
proc_mem_mm_bus_wr(2, g_bg_ctrl.blocks_per_sync, mm_clk, reg_bg_ctrl_copi);
proc_mem_mm_bus_wr(3, g_bg_ctrl.gapsize, mm_clk, reg_bg_ctrl_copi);
proc_mem_mm_bus_wr(4, g_bg_ctrl.mem_low_adrs, mm_clk, reg_bg_ctrl_copi);
proc_mem_mm_bus_wr(5, g_bg_ctrl.mem_high_adrs, mm_clk, reg_bg_ctrl_copi);
proc_mem_mm_bus_wr(6, g_bg_ctrl.bsn_init, mm_clk, reg_bg_ctrl_copi); -- low part
proc_mem_mm_bus_wr(7, 0, mm_clk, reg_bg_ctrl_copi); -- high part
-- Enable the BG at st_pps pulse.
proc_mem_mm_bus_wr(0, 3, mm_clk, reg_bg_ctrl_copi);
proc_common_wait_some_cycles(mm_clk, 10);
-- Issue an st_pps pulse to start the enabled BG
proc_common_gen_pulse(st_clk, st_pps);
-- Run test
proc_common_wait_some_cycles(st_clk, c_run_time);
-- Disable the BG
proc_mem_mm_bus_wr(0, 0, mm_clk, reg_bg_ctrl_copi);
-- Wait until Tx FIFO has emptied for the stream
WHILE tx_fifo_rd_emp /= '1' LOOP
proc_common_wait_some_cycles(st_clk, 1);
END LOOP;
proc_common_wait_some_cycles(st_clk, c_bg_sync_period);
stimuli_end <= '1';
-- Delay logging between different tb instances
proc_common_wait_some_cycles(st_clk, g_tb_index * 100);
-- Print logging
print_str(""); -- log empty line between tb results
print_str(c_tb_str &
"ETH bit rate :" &
" c_bg_nof_bps = " & REAL'IMAGE(c_bg_nof_bps) & " bps");
ASSERT c_bg_nof_bps < 10.0**9 REPORT "Tx flow control will keep ETH bitrate < 1Gbps." SEVERITY NOTE;
-------------------------------------------------------------------------
-- Verification: Total counts
-------------------------------------------------------------------------
-- . read low part, ignore high part (= 0) of two word total counts
-- Tx total nof packets
proc_mem_mm_bus_rd(0, mm_clk, reg_strobe_total_count_tx_cipo, reg_strobe_total_count_tx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
tx_total_count_nof_packet <= TO_UINT(reg_strobe_total_count_tx_cipo.rddata(c_word_w-1 DOWNTO 0));
-- Rx total nof packets
proc_mem_mm_bus_rd(0, mm_clk, reg_strobe_total_count_rx_cipo, reg_strobe_total_count_rx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
rx_total_count_nof_packet <= TO_UINT(reg_strobe_total_count_rx_cipo.rddata(c_word_w-1 DOWNTO 0));
-- Rx total nof valids
proc_mem_mm_bus_rd(2, mm_clk, reg_strobe_total_count_rx_cipo, reg_strobe_total_count_rx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
rx_total_count_nof_valid <= TO_UINT(reg_strobe_total_count_rx_cipo.rddata(c_word_w-1 DOWNTO 0));
proc_common_wait_some_cycles(mm_clk, 1);
-- Print logging
print_str(c_tb_str &
"Tx total counts monitor :" &
" nof_packet = " & NATURAL'IMAGE(tx_total_count_nof_packet));
print_str(c_tb_str &
"Rx total counts monitor :" &
" nof_packet = " & NATURAL'IMAGE(rx_total_count_nof_packet) &
", nof_valid = " & NATURAL'IMAGE(rx_total_count_nof_valid));
-- Verify, only log when wrong
IF c_bg_nof_bps < 10.0**9 THEN
ASSERT tx_total_count_nof_packet = tx_exp_total_count_nof_packet REPORT c_tb_str &
"Wrong Tx total nof packets count, Tx count = " & NATURAL'IMAGE(tx_total_count_nof_packet) &
" /= " & NATURAL'IMAGE(tx_exp_total_count_nof_packet) &
" = Expected count" SEVERITY ERROR;
ASSERT rx_total_count_nof_packet = rx_exp_total_count_nof_packet REPORT c_tb_str &
"Wrong Rx total nof packets count, Rx count = " & NATURAL'IMAGE(rx_total_count_nof_packet) &
" /= " & NATURAL'IMAGE(rx_exp_total_count_nof_packet) &
" = Expected count" SEVERITY ERROR;
ASSERT rx_total_count_nof_valid = rx_exp_total_count_nof_valid REPORT c_tb_str &
"Wrong Rx total nof valids count, Rx count = " & NATURAL'IMAGE(rx_total_count_nof_valid) &
" /= " & NATURAL'IMAGE(rx_exp_total_count_nof_valid) &
" = Expected count" SEVERITY ERROR;
END IF;
-------------------------------------------------------------------------
-- Verification: BSN monitors (yield same values in every sync interval)
-------------------------------------------------------------------------
-- 3 = nof_sop
-- 4 = nof_valid
-- 6 = latency
-- . Tx
proc_mem_mm_bus_rd(3, mm_clk, reg_bsn_monitor_v2_tx_cipo, reg_bsn_monitor_v2_tx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
tx_mon_nof_sop <= TO_UINT(reg_bsn_monitor_v2_tx_cipo.rddata(c_word_w-1 DOWNTO 0));
proc_mem_mm_bus_rd(4, mm_clk, reg_bsn_monitor_v2_tx_cipo, reg_bsn_monitor_v2_tx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
tx_mon_nof_valid <= TO_UINT(reg_bsn_monitor_v2_tx_cipo.rddata(c_word_w-1 DOWNTO 0));
proc_mem_mm_bus_rd(6, mm_clk, reg_bsn_monitor_v2_tx_cipo, reg_bsn_monitor_v2_tx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
tx_mon_latency <= TO_UINT(reg_bsn_monitor_v2_tx_cipo.rddata(c_word_w-1 DOWNTO 0));
-- . Rx
proc_mem_mm_bus_rd(3, mm_clk, reg_bsn_monitor_v2_rx_cipo, reg_bsn_monitor_v2_rx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
rx_mon_nof_sop <= TO_UINT(reg_bsn_monitor_v2_rx_cipo.rddata(c_word_w-1 DOWNTO 0));
proc_mem_mm_bus_rd(4, mm_clk, reg_bsn_monitor_v2_rx_cipo, reg_bsn_monitor_v2_rx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
rx_mon_nof_valid <= TO_UINT(reg_bsn_monitor_v2_rx_cipo.rddata(c_word_w-1 DOWNTO 0));
proc_mem_mm_bus_rd(6, mm_clk, reg_bsn_monitor_v2_rx_cipo, reg_bsn_monitor_v2_rx_copi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
rx_mon_latency <= TO_UINT(reg_bsn_monitor_v2_rx_cipo.rddata(c_word_w-1 DOWNTO 0));
proc_common_wait_some_cycles(mm_clk, 1);
-- Print logging
print_str(c_tb_str &
"Tx BSN monitor :" &
" nof_sop = " & NATURAL'IMAGE(tx_mon_nof_sop) &
", nof_valid = " & NATURAL'IMAGE(tx_mon_nof_valid) &
", latency = " & NATURAL'IMAGE(tx_mon_latency));
print_str(c_tb_str &
"Rx BSN monitor :" &
" nof_sop = " & NATURAL'IMAGE(rx_mon_nof_sop) &
", nof_valid = " & NATURAL'IMAGE(rx_mon_nof_valid) &
", latency = " & NATURAL'IMAGE(rx_mon_latency));
IF c_bg_nof_bps < 10.0**9 THEN
-- Verify BSN monitors only when the BG sync interval is stable, so
-- the ETH data rate < 1 Gbps and no BG block flow control.
-- Verify, only log when wrong
ASSERT tx_mon_nof_sop = c_mon_nof_sop_tx REPORT c_tb_str & "Wrong tx nof_sop" SEVERITY ERROR;
ASSERT rx_mon_nof_sop = c_mon_nof_sop_rx REPORT c_tb_str & "Wrong rx nof_sop" SEVERITY ERROR;
ASSERT tx_mon_nof_valid = c_mon_nof_valid_tx REPORT c_tb_str & "Wrong tx nof_valid" SEVERITY ERROR;
ASSERT rx_mon_nof_valid = c_mon_nof_valid_rx REPORT c_tb_str & "Wrong rx nof_valid" SEVERITY ERROR;
ASSERT tx_mon_latency = c_tx_exp_latency REPORT c_tb_str & "Wrong tx latency" SEVERITY ERROR;
-- For short block lengths the Rx latency appears to become less, the
-- exact Rx latency is therefore hard to predetermine. The actual
-- latency is not critical, therefore it is sufficient to only very
-- the latency when it is more or less fixed.
IF c_rx_exp_latency_en THEN
ASSERT almost_equal(rx_mon_latency, c_rx_exp_latency_st, 0) REPORT
c_tb_str & "Wrong rx latency using st interface" SEVERITY ERROR;
END IF;
END IF;
-------------------------------------------------------------------------
-- End of test
-------------------------------------------------------------------------
proc_common_wait_some_cycles(mm_clk, 100);
tb_end <= '1';
WAIT;
END PROCESS;
u_eth_tester : ENTITY work.eth_tester
GENERIC MAP (
g_nof_streams => 1,
g_bg_sync_timeout => c_eth_tester_sync_timeout,
g_remove_crc => FALSE -- no CRC with streaming loopback
)
PORT MAP (
-- Clocks and reset
mm_rst => mm_rst,
mm_clk => mm_clk,
st_rst => st_rst,
st_clk => st_clk,
st_pps => st_pps,
-- UDP transmit interface
eth_src_mac => c_gn_eth_src_mac,
ip_src_addr => c_gn_ip_src_addr,
udp_src_port => c_gn_udp_src_port,
sl(tx_fifo_rd_emp_arr) => tx_fifo_rd_emp,
TO_DP_ONE(tx_udp_sosi_arr) => tx_udp_sosi,
tx_udp_siso_arr => TO_DP_ARR(tx_udp_siso),
-- UDP receive interface
rx_udp_sosi_arr => TO_DP_ARR(rx_udp_sosi),
-- Memory Mapped Slaves (one per stream)
-- . Tx
reg_bg_ctrl_copi => reg_bg_ctrl_copi,
reg_bg_ctrl_cipo => reg_bg_ctrl_cipo,
reg_hdr_dat_copi => reg_hdr_dat_copi,
reg_hdr_dat_cipo => reg_hdr_dat_cipo,
reg_bsn_monitor_v2_tx_copi => reg_bsn_monitor_v2_tx_copi,
reg_bsn_monitor_v2_tx_cipo => reg_bsn_monitor_v2_tx_cipo,
reg_strobe_total_count_tx_copi => reg_strobe_total_count_tx_copi,
reg_strobe_total_count_tx_cipo => reg_strobe_total_count_tx_cipo,
-- . Rx
reg_bsn_monitor_v2_rx_copi => reg_bsn_monitor_v2_rx_copi,
reg_bsn_monitor_v2_rx_cipo => reg_bsn_monitor_v2_rx_cipo,
reg_strobe_total_count_rx_copi => reg_strobe_total_count_rx_copi,
reg_strobe_total_count_rx_cipo => reg_strobe_total_count_rx_cipo
);
-- ETH stream
u_dut : ENTITY work.eth_stream
GENERIC MAP (
g_rx_udp_port => c_rx_udp_port
)
PORT MAP (
-- Clocks and reset
st_rst => st_rst,
st_clk => st_clk,
-- User UDP interface
-- . Tx
udp_tx_sosi => tx_udp_sosi,
udp_tx_siso => tx_udp_siso,
-- . Rx
udp_rx_sosi => rx_udp_sosi,
udp_rx_siso => c_dp_siso_rdy,
-- PHY interface
-- . Tx
tse_tx_sosi => tse_tx_sosi,
tse_tx_siso => tse_tx_siso,
-- . Rx
tse_rx_sosi => tse_rx_sosi,
tse_rx_siso => tse_rx_siso
);
-- Loopback wire Tx to Rx, register to increasy ready latency from 1 to 2
tse_rx_sosi <= tse_tx_sosi WHEN rising_edge(st_clk);
tse_tx_siso <= tse_rx_siso;
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Author: E. Kooistra
-- Purpose: Multi test bench for eth_stream
-- Description:
--
-- Usage:
-- > as 8
-- > run -all
LIBRARY IEEE, diag_lib;
USE IEEE.std_logic_1164.ALL;
USE diag_lib.diag_pkg.ALL;
USE work.tb_eth_tester_pkg.ALL;
ENTITY tb_tb_eth_stream IS
END tb_tb_eth_stream;
ARCHITECTURE tb OF tb_tb_eth_stream IS
-- Tb
CONSTANT c_eth_clk_MHz : NATURAL := 125;
CONSTANT c_st_clk_MHz : NATURAL := 200;
CONSTANT c_nof_sync : NATURAL := 2;
CONSTANT c_nof_blk : NATURAL := 3; -- nof_blk per sync
-- Tx packet size and gap size in octets
CONSTANT c_block_len : NATURAL := 50;
CONSTANT c_link_len : NATURAL := func_eth_tester_eth_packet_on_link_length(c_block_len);
-- For near maximum 1Gbps link rate the c_block_len + c_gap_len_min time
-- in the st_clk domain equals c_link_len time in eth_clk domain.
CONSTANT c_gap_len_min : NATURAL := c_link_len * c_st_clk_MHz / c_eth_clk_MHz - c_block_len;
-- Choose c_gap_len somewhat larger to have packet link rate < 1 Gbps
CONSTANT c_gap_len : NATURAL := c_gap_len_min * 2; -- for g_nof_streams = 1
-- BG ctrl
CONSTANT c_high : NATURAL := c_diag_bg_mem_max_adr; -- = 2**24
CONSTANT c_bg_ctrl : t_diag_block_gen_integer := ('1', '1', c_block_len, c_nof_blk, c_gap_len, 0, c_high, 0); -- for first stream
BEGIN
-- g_tb_index : NATURAL := 0; -- use to incremental delay logging from tb instances in tb_tb
-- g_nof_sync : NATURAL := 2; -- number of BG sync intervals to set c_run_time
-- g_udp_port_match : BOOLEAN := TRUE;
--
-- -- t_diag_block_gen_integer =
-- -- sl: enable
-- -- sl: enable_sync
-- -- nat: samples_per_packet
-- -- nat: blocks_per_sync
-- -- nat: gapsize
-- -- nat: mem_low_adrs
-- -- nat: mem_high_adrs
-- -- nat: bsn_init
-- g_bg_ctrl : t_diag_block_gen_integer := ('1', '1', 50, 3, 200, 0, c_diag_bg_mem_max_adr, 0) -- for first stream
u_udp : ENTITY work.tb_eth_stream GENERIC MAP (0, c_nof_sync, TRUE, c_bg_ctrl);
u_udp_mismatch : ENTITY work.tb_eth_stream GENERIC MAP (1, c_nof_sync, FALSE, c_bg_ctrl);
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment