From 4b0c28befe652bdbb9a520a589b386b19c87da39 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Thu, 20 Oct 2022 18:56:02 +0200
Subject: [PATCH] Fill in str.

---
 libraries/io/eth/src/vhdl/eth_tester.vhd    | 199 +++++++++++++----
 libraries/io/eth/src/vhdl/eth_tester_rx.vhd |  81 ++++++-
 libraries/io/eth/src/vhdl/eth_tester_tx.vhd | 228 +++++++++++++++++++-
 libraries/io/eth/tb/vhdl/tb_eth_tester.vhd  |  39 ++--
 4 files changed, 469 insertions(+), 78 deletions(-)

diff --git a/libraries/io/eth/src/vhdl/eth_tester.vhd b/libraries/io/eth/src/vhdl/eth_tester.vhd
index 9fbebf2be3..ce3a648c16 100644
--- a/libraries/io/eth/src/vhdl/eth_tester.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester.vhd
@@ -24,16 +24,21 @@
 -- 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;
+LIBRARY IEEE, common_lib, dp_lib, diag_lib;
 USE IEEE.std_logic_1164.ALL;
 USE common_lib.common_pkg.ALL;
 USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
 USE dp_lib.dp_stream_pkg.ALL;
+USE dp_lib.dp_components_pkg.ALL;
+USE diag_lib.diag_pkg.ALL;
 USE work.eth_pkg.ALL;
+USE work.eth_tester_pkg.ALL;
 
 ENTITY eth_tester IS
   GENERIC (
-    g_nof_streams      : NATURAL := 1
+    g_nof_streams      : NATURAL := 1;
+    g_bg_sync_timeout  : NATURAL := 220*10**6  -- 10% margin for nominal 1 s with st_clk at 200MHz
   );
   PORT (
     -- Clocks and reset
@@ -44,11 +49,15 @@ ENTITY eth_tester IS
     st_pps             : IN  STD_LOGIC;
 
     -- UDP transmit interface
-    tx_udp_sosi_arr    : OUT t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0);
-    tx_udp_siso_arr    : IN  t_dp_siso_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS=> c_dp_siso_rdy);
+    eth_src_mac        : IN  STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+    ip_src_addr        : IN  STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0);
+    udp_src_port       : IN  STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0);
+
+    tx_udp_sosi_arr    : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
+    tx_udp_siso_arr    : IN  t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=> c_dp_siso_rdy);
 
     -- UDP receive interface
-    rx_udp_sosi_arr    : IN  t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS=> c_dp_sosi_rst);
+    rx_udp_sosi_arr    : IN  t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=> c_dp_sosi_rst);
 
     -- Memory Mapped Slaves (one per stream)
     -- . Tx
@@ -64,69 +73,165 @@ ENTITY eth_tester IS
     reg_bsn_monitor_v2_rx_copi             : IN  t_mem_copi := c_mem_copi_rst;
     reg_bsn_monitor_v2_rx_cipo             : OUT t_mem_cipo;
     reg_strobe_total_count_rx_copi         : IN  t_mem_copi := c_mem_copi_rst;
-    reg_strobe_total_count_rx_cipo         : OUT t_mem_cipo;
-    reg_strobe_total_count_rx_corrupt_copi : IN  t_mem_copi := c_mem_copi_rst;
-    reg_strobe_total_count_rx_corrupt_cipo : OUT t_mem_cipo
+    reg_strobe_total_count_rx_cipo         : OUT t_mem_cipo
   );
 END eth_tester;
 
 
 ARCHITECTURE str OF eth_tester IS
 
-  SIGNAL ref_sync : STD_LOGIC;
+  SIGNAL ref_sync_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
+
+  -- MM port multiplexers
+  -- . Tx
+  SIGNAL reg_bg_ctrl_copi_arr               : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_copi_rst);
+  SIGNAL reg_bg_ctrl_cipo_arr               : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst);
+  SIGNAL reg_hdr_dat_copi_arr               : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_copi_rst);
+  SIGNAL reg_hdr_dat_cipo_arr               : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst);
+  SIGNAL reg_bsn_monitor_v2_tx_copi_arr     : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_copi_rst);
+  SIGNAL reg_bsn_monitor_v2_tx_cipo_arr     : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst);
+  SIGNAL reg_strobe_total_count_tx_copi_arr : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_copi_rst);
+  SIGNAL reg_strobe_total_count_tx_cipo_arr : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst);
+  -- . Rx
+  SIGNAL reg_bsn_monitor_v2_rx_copi_arr     : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_copi_rst);
+  SIGNAL reg_bsn_monitor_v2_rx_cipo_arr     : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst);
+  SIGNAL reg_strobe_total_count_rx_copi_arr : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_copi_rst);
+  SIGNAL reg_strobe_total_count_rx_cipo_arr : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst);
 
 BEGIN
 
-  u_tx : ENTITY work.eth_tester_tx
+  gen_streams : FOR I IN 0 TO g_nof_streams-1 GENERATE
+    u_tx : ENTITY work.eth_tester_tx
+    GENERIC MAP (
+      g_bg_sync_timeout  => g_bg_sync_timeout
+    )
+    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,
+      ref_sync           => ref_sync_arr(I),
+
+      -- UDP transmit interface
+      eth_src_mac        => eth_src_mac,
+      ip_src_addr        => ip_src_addr,
+      udp_src_port       => udp_src_port,
+
+      tx_udp_sosi        => tx_udp_sosi_arr(I),
+      tx_udp_siso        => tx_udp_siso_arr(I),
+
+      -- Memory Mapped Slaves (one per stream)
+      reg_bg_ctrl_copi               => reg_bg_ctrl_copi_arr(I),
+      reg_bg_ctrl_cipo               => reg_bg_ctrl_cipo_arr(I),
+      reg_hdr_dat_copi               => reg_hdr_dat_copi_arr(I),
+      reg_hdr_dat_cipo               => reg_hdr_dat_cipo_arr(I),
+      reg_bsn_monitor_v2_tx_copi     => reg_bsn_monitor_v2_tx_copi_arr(I),
+      reg_bsn_monitor_v2_tx_cipo     => reg_bsn_monitor_v2_tx_cipo_arr(I),
+      reg_strobe_total_count_tx_copi => reg_strobe_total_count_tx_copi_arr(I),
+      reg_strobe_total_count_tx_cipo => reg_strobe_total_count_tx_cipo_arr(I)
+    );
+
+    u_rx : ENTITY work.eth_tester_rx
+    GENERIC MAP (
+      g_bg_sync_timeout  => g_bg_sync_timeout
+    )
+    PORT MAP (
+      -- Clocks and reset
+      mm_rst             => mm_rst,
+      mm_clk             => mm_clk,
+      st_rst             => st_rst,
+      st_clk             => st_clk,
+      ref_sync           => ref_sync_arr(I),
+
+      -- UDP transmit interface
+      rx_udp_sosi        => rx_udp_sosi_arr(I),
+
+      -- Memory Mapped Slaves (one per stream)
+      reg_bsn_monitor_v2_rx_copi     => reg_bsn_monitor_v2_rx_copi_arr(I),
+      reg_bsn_monitor_v2_rx_cipo     => reg_bsn_monitor_v2_rx_cipo_arr(I),
+      reg_strobe_total_count_rx_copi => reg_strobe_total_count_rx_copi_arr(I),
+      reg_strobe_total_count_rx_cipo => reg_strobe_total_count_rx_cipo_arr(I)
+    );
+  END GENERATE;
+
+  -----------------------------------------------------------------------------
+  -- MM port multiplexers for g_nof_streams
+  -----------------------------------------------------------------------------
+
+  -- Tx
+  u_common_mem_mux_bg : ENTITY common_lib.common_mem_mux
   GENERIC MAP (
-    g_nof_streams      => g_nof_streams
+    g_nof_mosi    => g_nof_streams,
+    g_mult_addr_w => c_diag_bg_reg_adr_w
   )
   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,
-    ref_sync           => ref_sync,
+    mosi     => reg_bg_ctrl_copi,
+    miso     => reg_bg_ctrl_cipo,
+    mosi_arr => reg_bg_ctrl_copi_arr,
+    miso_arr => reg_bg_ctrl_cipo_arr
+  );
 
-    -- UDP transmit interface
-    tx_udp_sosi_arr    => tx_udp_sosi_arr,
-    tx_udp_siso_arr    => tx_udp_siso_arr,
+  u_common_mem_mux_hdr_dat : ENTITY common_lib.common_mem_mux
+  GENERIC MAP (
+    g_nof_mosi    => g_nof_streams,
+    g_mult_addr_w => c_eth_tester_reg_hdr_dat_addr_w
+  )
+  PORT MAP (
+    mosi     => reg_hdr_dat_copi,
+    miso     => reg_hdr_dat_cipo,
+    mosi_arr => reg_hdr_dat_copi_arr,
+    miso_arr => reg_hdr_dat_cipo_arr
+  );
 
-    -- Memory Mapped Slaves (one per stream)
-    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
+  u_common_mem_mux_bsn_monitor_v2_tx : ENTITY common_lib.common_mem_mux
+  GENERIC MAP (
+    g_nof_mosi    => g_nof_streams,
+    g_mult_addr_w => c_dp_bsn_monitor_v2_reg_adr_w
+  )
+  PORT MAP (
+    mosi     => reg_bsn_monitor_v2_tx_copi,
+    miso     => reg_bsn_monitor_v2_tx_cipo,
+    mosi_arr => reg_bsn_monitor_v2_tx_copi_arr,
+    miso_arr => reg_bsn_monitor_v2_tx_cipo_arr
   );
 
-  u_rx : ENTITY work.eth_tester_rx
+  u_common_mem_mux_strobe_total_count_tx : ENTITY common_lib.common_mem_mux
   GENERIC MAP (
-    g_nof_streams      => g_nof_streams
+    g_nof_mosi    => g_nof_streams,
+    g_mult_addr_w => c_dp_strobe_total_count_reg_adr_w
   )
   PORT MAP (
-    -- Clocks and reset
-    mm_rst             => mm_rst,
-    mm_clk             => mm_clk,
-    st_rst             => st_rst,
-    st_clk             => st_clk,
-    ref_sync           => ref_sync,
+    mosi     => reg_strobe_total_count_tx_copi,
+    miso     => reg_strobe_total_count_tx_cipo,
+    mosi_arr => reg_strobe_total_count_tx_copi_arr,
+    miso_arr => reg_strobe_total_count_tx_cipo_arr
+  );
 
-    -- UDP transmit interface
-    rx_udp_sosi_arr    => rx_udp_sosi_arr,
+  -- Rx
+  u_common_mem_mux_bsn_monitor_v2_rx : ENTITY common_lib.common_mem_mux
+  GENERIC MAP (
+    g_nof_mosi    => g_nof_streams,
+    g_mult_addr_w => c_dp_bsn_monitor_v2_reg_adr_w
+  )
+  PORT MAP (
+    mosi     => reg_bsn_monitor_v2_rx_copi,
+    miso     => reg_bsn_monitor_v2_rx_cipo,
+    mosi_arr => reg_bsn_monitor_v2_rx_copi_arr,
+    miso_arr => reg_bsn_monitor_v2_rx_cipo_arr
+  );
 
-    -- Memory Mapped Slaves (one per stream)
-    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,
-    reg_strobe_total_count_rx_corrupt_copi => reg_strobe_total_count_rx_corrupt_copi,
-    reg_strobe_total_count_rx_corrupt_cipo => reg_strobe_total_count_rx_corrupt_cipo
+  u_common_mem_mux_strobe_total_count_rx : ENTITY common_lib.common_mem_mux
+  GENERIC MAP (
+    g_nof_mosi    => g_nof_streams,
+    g_mult_addr_w => c_dp_strobe_total_count_reg_adr_w
+  )
+  PORT MAP (
+    mosi     => reg_strobe_total_count_rx_copi,
+    miso     => reg_strobe_total_count_rx_cipo,
+    mosi_arr => reg_strobe_total_count_rx_copi_arr,
+    miso_arr => reg_strobe_total_count_rx_cipo_arr
   );
 
 END str;
diff --git a/libraries/io/eth/src/vhdl/eth_tester_rx.vhd b/libraries/io/eth/src/vhdl/eth_tester_rx.vhd
index 3f113791ad..7342cbedfa 100644
--- a/libraries/io/eth/src/vhdl/eth_tester_rx.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester_rx.vhd
@@ -26,14 +26,15 @@
 
 LIBRARY IEEE, common_lib, dp_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 dp_lib.dp_stream_pkg.ALL;
-USE work.eth_pkg.ALL;
+USE work.eth_tester_pkg.ALL;
 
 ENTITY eth_tester_rx IS
   GENERIC (
-    g_nof_streams      : NATURAL := 1
+    g_bg_sync_timeout  : NATURAL := 220*10**6  -- 10% margin for nominal 1 s with st_clk at 200MHz
   );
   PORT (
     -- Clocks and reset
@@ -44,22 +45,84 @@ ENTITY eth_tester_rx IS
     ref_sync           : IN  STD_LOGIC;
 
     -- UDP receive interface
-    rx_udp_sosi_arr    : IN  t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS=> c_dp_sosi_rst);
+    rx_udp_sosi        : IN  t_dp_sosi;
 
     -- Memory Mapped Slaves (one per stream)
-    reg_bsn_monitor_v2_rx_copi             : IN  t_mem_copi := c_mem_copi_rst;
-    reg_bsn_monitor_v2_rx_cipo             : OUT t_mem_cipo;
-    reg_strobe_total_count_rx_copi         : IN  t_mem_copi := c_mem_copi_rst;
-    reg_strobe_total_count_rx_cipo         : OUT t_mem_cipo;
-    reg_strobe_total_count_rx_corrupt_copi : IN  t_mem_copi := c_mem_copi_rst;
-    reg_strobe_total_count_rx_corrupt_cipo : OUT t_mem_cipo
+    reg_bsn_monitor_v2_rx_copi     : IN  t_mem_copi := c_mem_copi_rst;
+    reg_bsn_monitor_v2_rx_cipo     : OUT t_mem_cipo;
+    reg_strobe_total_count_rx_copi : IN  t_mem_copi := c_mem_copi_rst;
+    reg_strobe_total_count_rx_cipo : OUT t_mem_cipo
   );
 END eth_tester_rx;
 
 
 ARCHITECTURE str OF eth_tester_rx IS
 
+  CONSTANT c_nof_total_counts     : NATURAL := 2;
+
+  SIGNAL decoded_sosi             : t_dp_sosi;
+  SIGNAL crc_corrupt              : STD_LOGIC := '0';
+
+  SIGNAL in_strobe_arr            : STD_LOGIC_VECTOR(c_nof_total_counts-1 DOWNTO 0);
+
 BEGIN
 
 
+  u_mms_dp_bsn_monitor_v2 : ENTITY dp_lib.mms_dp_bsn_monitor_v2
+  GENERIC MAP (
+    g_nof_streams  => 1,
+    g_sync_timeout => g_bg_sync_timeout
+  )
+  PORT MAP (
+    -- Memory-mapped clock domain
+    mm_rst         => mm_rst,
+    mm_clk         => mm_clk,
+    reg_mosi       => reg_bsn_monitor_v2_rx_copi,
+    reg_miso       => reg_bsn_monitor_v2_rx_cipo,
+
+    -- Streaming clock domain
+    dp_rst         => st_rst,
+    dp_clk         => st_clk,
+    ref_sync       => ref_sync,
+
+    in_sosi_arr(0) => decoded_sosi
+  );
+
+  p_crc_corrupt : PROCESS(st_clk)
+     VARIABLE v_I   : NATURAL;
+     VARIABLE v_crc : STD_LOGIC_VECTOR(c_octet_w-1 DOWNTO 0);
+  BEGIN
+    IF rising_edge(st_clk) THEN
+      v_I := TO_UINT(decoded_sosi.empty(1 DOWNTO 0));
+      v_crc := decoded_sosi.data((v_I + 1)*c_octet_w-1 DOWNTO v_I*c_octet_w);
+      crc_corrupt <= '0';
+      IF decoded_sosi.eop = '1' AND UNSIGNED(v_crc) /= 0 THEN
+        crc_corrupt <= '1';
+      END IF;
+    END IF;
+  END PROCESS;
+
+  in_strobe_arr(0) <= decoded_sosi.sop;
+  in_strobe_arr(1) <= crc_corrupt;
+
+  u_dp_strobe_total_count : ENTITY dp_lib.dp_strobe_total_count
+  GENERIC MAP (
+    g_nof_counts  => c_nof_total_counts,
+    g_count_w     => c_longword_w,
+    g_clip        => TRUE
+  )
+  PORT MAP (
+    dp_rst        => st_rst,
+    dp_clk        => st_clk,
+
+    ref_sync      => decoded_sosi.sync,
+    in_strobe_arr => in_strobe_arr,
+
+    mm_rst        => mm_rst,
+    mm_clk        => mm_clk,
+
+    reg_mosi      => reg_strobe_total_count_rx_copi,
+    reg_miso      => reg_strobe_total_count_rx_cipo
+  );
+
 END str;
diff --git a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
index eb7918eaf5..7a851056ab 100644
--- a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
@@ -24,16 +24,19 @@
 -- 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;
+LIBRARY IEEE, common_lib, dp_lib, diag_lib;
 USE IEEE.std_logic_1164.ALL;
 USE common_lib.common_pkg.ALL;
 USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
 USE dp_lib.dp_stream_pkg.ALL;
-USE work.eth_pkg.ALL;
+USE diag_lib.diag_pkg.ALL;
+USE work.eth_tester_pkg.ALL;
 
 ENTITY eth_tester_tx IS
   GENERIC (
-    g_nof_streams      : NATURAL := 1
+    g_bg_sync_timeout  : NATURAL := 220*10**6  -- 10% margin for nominal 1 s with st_clk at 200MHz
   );
   PORT (
     -- Clocks and reset
@@ -45,8 +48,12 @@ ENTITY eth_tester_tx IS
     ref_sync           : OUT STD_LOGIC;
 
     -- UDP transmit interface
-    tx_udp_sosi_arr    : OUT t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0);
-    tx_udp_siso_arr    : IN  t_dp_siso_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS=> c_dp_siso_rdy);
+    eth_src_mac        : IN  STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+    ip_src_addr        : IN  STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0);
+    udp_src_port       : IN  STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0);
+
+    tx_udp_sosi        : OUT t_dp_sosi;
+    tx_udp_siso        : IN  t_dp_siso := c_dp_siso_rdy;
 
     -- Memory Mapped Slaves (one per stream)
     reg_bg_ctrl_copi               : IN  t_mem_copi := c_mem_copi_rst;
@@ -63,8 +70,219 @@ END eth_tester_tx;
 
 ARCHITECTURE str OF eth_tester_tx IS
 
+  CONSTANT c_bg_block_len_max     : NATURAL := c_network_eth_payload_jumbo_max;  -- 9000 octets
+  CONSTANT c_bg_block_len_w       : NATURAL := ceil_log2(c_bg_block_len_max);
+
+  CONSTANT c_fifo_fill            : NATURAL := c_network_eth_payload_jumbo_max / c_word_sz;  -- = 9000 / 4 = 2250
+  CONSTANT c_fifo_size            : NATURAL := true_log_pow2(c_fifo_fill);  -- = 4096
+
+  CONSTANT c_nof_total_counts     : NATURAL := 1;
+
+  SIGNAL ip_total_length          : NATURAL;
+  SIGNAL udp_total_length         : NATURAL;
+  SIGNAL app_total_length         : NATURAL;
+
+  SIGNAL bg_sosi                  : t_dp_sosi;
+  SIGNAL bg_ctrl_active           : t_diag_block_gen;
+  SIGNAL bg_block_len             : NATURAL;
+  SIGNAL tx_packed_sosi           : t_dp_sosi;
+  SIGNAL tx_fifo_sosi             : t_dp_sosi;
+  SIGNAL tx_fifo_siso             : t_dp_siso;
+  SIGNAL i_ref_sync               : STD_LOGIC;
+  SIGNAL in_strobe_arr            : STD_LOGIC_VECTOR(c_nof_total_counts-1 DOWNTO 0);
+
+  SIGNAL hdr_fields_slv_in        : STD_LOGIC_VECTOR(1023 DOWNTO 0);
+  SIGNAL hdr_fields_slv_tx        : STD_LOGIC_VECTOR(1023 DOWNTO 0);
+  SIGNAL hdr_fields_rec_in        : t_eth_tester_header;
+  SIGNAL hdr_fields_rec_tx        : t_eth_tester_header;
+
 BEGIN
 
+  ref_sync <= i_ref_sync;
+
+  u_bg : ENTITY diag_lib.mms_diag_block_gen
+  GENERIC MAP (
+    g_nof_streams        => 1,
+    g_use_bg_buffer_ram  => FALSE
+  )
+  PORT MAP (
+    -- System
+    mm_rst           => mm_rst,
+    mm_clk           => mm_clk,
+    dp_rst           => st_rst,
+    dp_clk           => st_clk,
+    en_sync          => st_pps,  -- block generator enable sync pulse in ST clock domain
+    -- MM interface
+    reg_bg_ctrl_mosi      => reg_bg_ctrl_copi,  -- BG control register (one for all streams)
+    reg_bg_ctrl_miso      => reg_bg_ctrl_cipo,
+    -- ST interface
+    bg_ctrl_active_arr(0) => bg_ctrl_active,
+    out_sosi_arr(0)       => bg_sosi
+  );
+
+  bg_block_len <= TO_UINT(bg_ctrl_active.samples_per_packet(15 DOWNTO 0));  -- packet lenghts fit in 16b
+
+  u_repack : ENTITY dp_lib.dp_repack_data  -- pack 8b octets into 32b words
+  GENERIC MAP (
+    g_in_dat_w       => c_octet_w,  -- = 8
+    g_in_nof_words   => c_word_sz,  -- = 4
+    g_out_dat_w      => c_word_w,  -- = 32
+    g_out_nof_words  => 1
+  )
+  PORT MAP (
+    rst              => st_rst,
+    clk              => st_clk,
+    snk_in           => bg_sosi,
+    src_out          => tx_packed_sosi
+  );
+
+  u_fifo : ENTITY dp_lib.dp_fifo_fill_eop
+  GENERIC MAP (
+    g_data_w         => c_word_w,
+    g_bsn_w          => c_diag_bg_bsn_init_w,  -- = 64 bit
+    g_use_bsn        => TRUE,
+    g_use_empty      => TRUE,
+    g_use_sync       => TRUE,
+    g_fifo_fill      => c_fifo_fill,
+    g_fifo_size      => c_fifo_size
+  )
+  PORT MAP (
+    wr_rst      => st_rst,
+    wr_clk      => st_clk,
+    rd_rst      => st_rst,
+    rd_clk      => st_clk,
+    -- ST sink
+    snk_in      => tx_packed_sosi,
+    -- ST source
+    src_in      => tx_fifo_siso,
+    src_out     => tx_fifo_sosi
+  );
+
+  -------------------------------------------------------------------------------
+  -- Assemble header info
+  -------------------------------------------------------------------------------
+  -- Whether the dp_offload_tx_hdr_fields value is actually used in the Tx header depends on:
+  --   c_eth_tester_hdr_field_sel = "1"&"101"&"111011111001"&"0100"&"100"
+  --                                     eth   ip             udp    app
+  --   where 0 = data path, 1 = MM controlled. The '0' fields are assigned here in hdr_fields_slv_in
+  --   in order:
+  --     access   field
+  --     MM       word_align
+  --
+  --     MM       eth_dst_mac
+  --        DP    eth_src_mac
+  --     MM       eth_type
+  --
+  --     MM       ip_version
+  --     MM       ip_header_length
+  --     MM       ip_services
+  --        DP    ip_total_length
+  --     MM       ip_identification
+  --     MM       ip_flags
+  --     MM       ip_fragment_offset
+  --     MM       ip_time_to_live
+  --     MM       ip_protocol
+  --        DP    ip_header_checksum --> not here, will be filled in by 1GbE eth component
+  --        DP    ip_src_addr
+  --     MM       ip_dst_addr
+  --
+  --        DP    udp_src_port
+  --     MM       udp_dst_port
+  --        DP    udp_total_length
+  --        DP    udp_checksum --> default fixed 0, so not used, not calculated here or in 1GbE
+  --                               eth component because would require store and forward
+  --
+  --     MM       dp_reserved
+  --        DP    dp_sync
+  --        DP    dp_bsn
+
+  -- assume bg_block_len is still valid, no need to pass bg_block_len on via channel field in u_fifo
+  app_total_length <= c_eth_tester_app_hdr_len + bg_block_len WHEN rising_edge(st_clk);
+  udp_total_length <= app_total_length + c_network_udp_header_len WHEN rising_edge(st_clk);
+  ip_total_length <= udp_total_length + c_network_ip_header_len WHEN rising_edge(st_clk);
+
+  hdr_fields_slv_in(field_hi(c_eth_tester_hdr_field_arr, "eth_src_mac"     ) DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "eth_src_mac"     )) <= eth_src_mac;
+  hdr_fields_slv_in(field_hi(c_eth_tester_hdr_field_arr, "ip_total_length" ) DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "ip_total_length" )) <= TO_UVEC(ip_total_length, 16);
+  hdr_fields_slv_in(field_hi(c_eth_tester_hdr_field_arr, "ip_src_addr"     ) DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "ip_src_addr"     )) <= ip_src_addr;
+  hdr_fields_slv_in(field_hi(c_eth_tester_hdr_field_arr, "udp_src_port"    ) DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "udp_src_port"    )) <= udp_src_port;
+  hdr_fields_slv_in(field_hi(c_eth_tester_hdr_field_arr, "udp_total_length") DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "udp_total_length")) <= TO_UVEC(udp_total_length, 16);
+  hdr_fields_slv_in(field_hi(c_eth_tester_hdr_field_arr, "dp_sync"         ) DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "dp_sync"         )) <= slv(tx_fifo_sosi.sync);
+  hdr_fields_slv_in(field_hi(c_eth_tester_hdr_field_arr, "dp_bsn"          ) DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "dp_bsn"          )) <= tx_fifo_sosi.bsn;
 
+  u_dp_offload_tx : ENTITY dp_lib.dp_offload_tx_v3
+  GENERIC MAP (
+    g_nof_streams    => 1,
+    g_data_w         => c_word_w,
+    g_symbol_w       => c_octet_w,
+    g_hdr_field_arr  => c_eth_tester_hdr_field_arr,
+    g_hdr_field_sel  => c_eth_tester_hdr_field_sel,
+    g_pipeline_ready => TRUE
+  )
+  PORT MAP (
+    mm_rst                => mm_rst,
+    mm_clk                => mm_clk,
+    dp_rst                => st_rst,
+    dp_clk                => st_clk,
+
+    reg_hdr_dat_mosi      => reg_hdr_dat_copi,
+    reg_hdr_dat_miso      => reg_hdr_dat_cipo,
+
+    snk_in_arr(0)         => tx_fifo_sosi,
+    snk_out_arr(0)        => tx_fifo_siso,
+
+    src_out_arr(0)        => tx_udp_sosi,
+    src_in_arr(0)         => tx_udp_siso,
+
+    hdr_fields_in_arr(0)  => hdr_fields_slv_in,  -- hdr_fields_slv_in_arr(i) is considered valid @ snk_in_arr(i).sop
+    hdr_fields_out_arr(0) => hdr_fields_slv_tx
+  );
+
+  hdr_fields_rec_in <= func_eth_tester_map_header(hdr_fields_slv_in);
+  hdr_fields_rec_tx <= func_eth_tester_map_header(hdr_fields_slv_tx);
+
+  i_ref_sync <= tx_fifo_sosi.sync WHEN rising_edge(st_clk);
+
+  u_mms_dp_bsn_monitor_v2 : ENTITY dp_lib.mms_dp_bsn_monitor_v2
+  GENERIC MAP (
+    g_nof_streams  => 1,
+    g_sync_timeout => g_bg_sync_timeout
+  )
+  PORT MAP (
+    -- Memory-mapped clock domain
+    mm_rst         => mm_rst,
+    mm_clk         => mm_clk,
+    reg_mosi       => reg_bsn_monitor_v2_tx_copi,
+    reg_miso       => reg_bsn_monitor_v2_tx_cipo,
+
+    -- Streaming clock domain
+    dp_rst         => st_rst,
+    dp_clk         => st_clk,
+    ref_sync       => i_ref_sync,
+
+    in_siso_arr(0) => tx_fifo_siso,
+    in_sosi_arr(0) => tx_fifo_sosi
+  );
+
+  in_strobe_arr(0) <= tx_fifo_sosi.sop;
+
+  u_dp_strobe_total_count : ENTITY dp_lib.dp_strobe_total_count
+  GENERIC MAP (
+    g_nof_counts  => c_nof_total_counts,
+    g_count_w     => c_longword_w,
+    g_clip        => TRUE
+  )
+  PORT MAP (
+    dp_rst        => st_rst,
+    dp_clk        => st_clk,
+
+    ref_sync      => i_ref_sync,
+    in_strobe_arr => in_strobe_arr,
+
+    mm_rst        => mm_rst,
+    mm_clk        => mm_clk,
+
+    reg_mosi      => reg_strobe_total_count_tx_copi,
+    reg_miso      => reg_strobe_total_count_tx_cipo
+  );
 
 END str;
diff --git a/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd b/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd
index 8748f01f55..0966b345eb 100644
--- a/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd
+++ b/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd
@@ -30,6 +30,7 @@ USE IEEE.numeric_std.ALL;
 USE common_lib.common_pkg.ALL;
 USE common_lib.common_mem_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;
 
 
@@ -53,27 +54,29 @@ ARCHITECTURE tb OF tb_eth_tester IS
   SIGNAL st_pps              : STD_LOGIC := '0';
 
   -- ETH UDP data path interface
+  SIGNAL eth_src_mac         : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+  SIGNAL udp_src_port        : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0);
+  SIGNAL ip_src_addr         : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0);
+
   SIGNAL tx_udp_sosi_arr     : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
   SIGNAL tx_udp_siso_arr     : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=> c_dp_siso_rdy);
   SIGNAL rx_udp_sosi_arr     : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
 
   -- 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;
+  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;
-  SIGNAL reg_strobe_total_count_rx_corrupt_copi : t_mem_copi := c_mem_copi_rst;
-  SIGNAL reg_strobe_total_count_rx_corrupt_cipo : t_mem_cipo;
+  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;
 
 BEGIN
 
@@ -96,6 +99,10 @@ BEGIN
     st_pps             => st_pps,
 
     -- UDP transmit interface
+    eth_src_mac        => eth_src_mac,
+    ip_src_addr        => ip_src_addr,
+    udp_src_port       => udp_src_port,
+
     tx_udp_sosi_arr    => tx_udp_sosi_arr,
     tx_udp_siso_arr    => tx_udp_siso_arr,
 
@@ -116,9 +123,7 @@ BEGIN
     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,
-    reg_strobe_total_count_rx_corrupt_copi => reg_strobe_total_count_rx_corrupt_copi,
-    reg_strobe_total_count_rx_corrupt_cipo => reg_strobe_total_count_rx_corrupt_cipo
+    reg_strobe_total_count_rx_cipo         => reg_strobe_total_count_rx_cipo
   );
   
 END tb;
-- 
GitLab