diff --git a/libraries/io/eth/eth.peripheral.yaml b/libraries/io/eth/eth.peripheral.yaml
index 083ec80cfba988b8619e5670e503529677c8e853..321706436eb9bc52210d67d1da407f3fb5c71fb5 100644
--- a/libraries/io/eth/eth.peripheral.yaml
+++ b/libraries/io/eth/eth.peripheral.yaml
@@ -251,30 +251,31 @@ peripherals:
           "
         fields:
           # eth field group
-          - - { field_name: word_align,             mm_width: 16,                                access_mode: RW, address_offset: 0x64 }
-          - - { field_name: eth_destination_mac,    mm_width: 32, user_width: 48, radix: uint64, access_mode: RW, address_offset: 0x5c }
-          - - { field_name: eth_source_mac,         mm_width: 32, user_width: 48, radix: uint64, access_mode: RW, address_offset: 0x54 }
-          - - { field_name: eth_type,               mm_width: 16,                                access_mode: RW, address_offset: 0x50 }
+          - - { field_name: word_align,             mm_width: 16,                                access_mode: RW, address_offset: 0x68 }
+          - - { field_name: eth_destination_mac,    mm_width: 32, user_width: 48, radix: uint64, access_mode: RW, address_offset: 0x60 }
+          - - { field_name: eth_source_mac,         mm_width: 32, user_width: 48, radix: uint64, access_mode: RW, address_offset: 0x58 }
+          - - { field_name: eth_type,               mm_width: 16,                                access_mode: RW, address_offset: 0x54 }
           # ip field group
-          - - { field_name: ip_version,             mm_width:  4,                                access_mode: RW, address_offset: 0x4c }
-          - - { field_name: ip_header_length,       mm_width:  4,                                access_mode: RW, address_offset: 0x48 }
-          - - { field_name: ip_services,            mm_width:  8,                                access_mode: RW, address_offset: 0x44 }
-          - - { field_name: ip_total_length,        mm_width: 16,                                access_mode: RW, address_offset: 0x40 }
-          - - { field_name: ip_identification,      mm_width: 16,                                access_mode: RW, address_offset: 0x3c }
-          - - { field_name: ip_flags,               mm_width:  3,                                access_mode: RW, address_offset: 0x38 }
-          - - { field_name: ip_fragment_offset,     mm_width: 13,                                access_mode: RW, address_offset: 0x34 }
-          - - { field_name: ip_time_to_live,        mm_width:  8,                                access_mode: RW, address_offset: 0x30 }
-          - - { field_name: ip_protocol,            mm_width:  8,                                access_mode: RW, address_offset: 0x2c }
-          - - { field_name: ip_header_checksum,     mm_width: 16,                                access_mode: RW, address_offset: 0x28 }
-          - - { field_name: ip_source_address,      mm_width: 32,                                access_mode: RW, address_offset: 0x24 }
-          - - { field_name: ip_destination_address, mm_width: 32,                                access_mode: RW, address_offset: 0x20 }
+          - - { field_name: ip_version,             mm_width:  4,                                access_mode: RW, address_offset: 0x50 }
+          - - { field_name: ip_header_length,       mm_width:  4,                                access_mode: RW, address_offset: 0x4c }
+          - - { field_name: ip_services,            mm_width:  8,                                access_mode: RW, address_offset: 0x48 }
+          - - { field_name: ip_total_length,        mm_width: 16,                                access_mode: RW, address_offset: 0x44 }
+          - - { field_name: ip_identification,      mm_width: 16,                                access_mode: RW, address_offset: 0x40 }
+          - - { field_name: ip_flags,               mm_width:  3,                                access_mode: RW, address_offset: 0x3c }
+          - - { field_name: ip_fragment_offset,     mm_width: 13,                                access_mode: RW, address_offset: 0x38 }
+          - - { field_name: ip_time_to_live,        mm_width:  8,                                access_mode: RW, address_offset: 0x34 }
+          - - { field_name: ip_protocol,            mm_width:  8,                                access_mode: RW, address_offset: 0x30 }
+          - - { field_name: ip_header_checksum,     mm_width: 16,                                access_mode: RW, address_offset: 0x2c }
+          - - { field_name: ip_source_address,      mm_width: 32,                                access_mode: RW, address_offset: 0x28 }
+          - - { field_name: ip_destination_address, mm_width: 32,                                access_mode: RW, address_offset: 0x24 }
           # udp field group
-          - - { field_name: udp_source_port,        mm_width: 16,                                access_mode: RW, address_offset: 0x1c }
-          - - { field_name: udp_destination_port,   mm_width: 16,                                access_mode: RW, address_offset: 0x18 }
-          - - { field_name: udp_length,             mm_width: 16,                                access_mode: RW, address_offset: 0x14 }
-          - - { field_name: udp_checksum,           mm_width: 16,                                access_mode: RW, address_offset: 0x10 }
+          - - { field_name: udp_source_port,        mm_width: 16,                                access_mode: RW, address_offset: 0x20 }
+          - - { field_name: udp_destination_port,   mm_width: 16,                                access_mode: RW, address_offset: 0x1c }
+          - - { field_name: udp_length,             mm_width: 16,                                access_mode: RW, address_offset: 0x18 }
+          - - { field_name: udp_checksum,           mm_width: 16,                                access_mode: RW, address_offset: 0x14 }
           # application field group
-          - - { field_name: dp_reserved,            mm_width: 31,                                access_mode: RW, address_offset: 0xC }
+          - - { field_name: dp_length,              mm_width: 16,                                access_mode: RW, address_offset: 0x10 }
+          - - { field_name: dp_reserved,            mm_width: 15,                                access_mode: RW, address_offset: 0xC }
           - - { field_name: dp_sync,                mm_width:  1,                                access_mode: RW, address_offset: 0x8 }
           - - { field_name: dp_bsn,                 mm_width: 32, user_width: 64, radix: uint64, access_mode: RW, address_offset: 0x0 }
 
diff --git a/libraries/io/eth/src/vhdl/eth_tester.vhd b/libraries/io/eth/src/vhdl/eth_tester.vhd
index f765e75a038d59cb58c006a2c1fd5c5c75085137..ccc63fb866d92cd1a8f313779ebce2babcff7cf2 100644
--- a/libraries/io/eth/src/vhdl/eth_tester.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester.vhd
@@ -82,7 +82,9 @@ END eth_tester;
 
 ARCHITECTURE str OF eth_tester IS
 
-  SIGNAL ref_sync_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
+  SIGNAL ref_sync_arr  : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
+
+  SIGNAL dp_length_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0);  -- tx block length
 
   -- MM port multiplexers
   -- . Tx
@@ -121,6 +123,7 @@ BEGIN
       ip_src_addr        => ip_src_addr,
       udp_src_port       => udp_src_port,
 
+      tx_length          => dp_length_arr(I),
       tx_fifo_rd_emp     => tx_fifo_rd_emp_arr(I),
 
       tx_udp_sosi        => tx_udp_sosi_arr(I),
@@ -149,6 +152,8 @@ BEGIN
       st_clk             => st_clk,
       ref_sync           => ref_sync_arr(I),
 
+      exp_length         => dp_length_arr(I),
+
       -- UDP transmit interface
       rx_udp_sosi        => rx_udp_sosi_arr(I),
 
diff --git a/libraries/io/eth/src/vhdl/eth_tester_pkg.vhd b/libraries/io/eth/src/vhdl/eth_tester_pkg.vhd
index 64a0e4e8eca3571ecb703b6b638df2eb49d7b293..b55bd87250ba78766eda73ae384df2e26fe3602d 100644
--- a/libraries/io/eth/src/vhdl/eth_tester_pkg.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester_pkg.vhd
@@ -55,8 +55,8 @@ PACKAGE eth_tester_pkg is
   --   to 0 by declaring hdr_fields_in_arr with all 0. Hence e.g. udp_checksum
   --   = 0 can be achieve via data path and default hdr_fields_in_arr = 0 or
   --   via MM controlled and field_default(0).
-  CONSTANT c_eth_tester_nof_hdr_fields    : NATURAL := 1+3+12+4+3;
-  CONSTANT c_eth_tester_hdr_field_sel     : STD_LOGIC_VECTOR(c_eth_tester_nof_hdr_fields-1 DOWNTO 0) := "1"&"101"&"111011111001"&"0100"&"100";
+  CONSTANT c_eth_tester_nof_hdr_fields    : NATURAL := 1+3+12+4+4;
+  CONSTANT c_eth_tester_hdr_field_sel     : STD_LOGIC_VECTOR(c_eth_tester_nof_hdr_fields-1 DOWNTO 0) := "1"&"101"&"111011111001"&"0100"&"0100";
 
   -- Default use destination MAC/IP/UDP = 0, so these have to be MM programmed
   -- before eth_tester packets can be send.
@@ -84,7 +84,8 @@ PACKAGE eth_tester_pkg is
       ( field_name_pad("udp_total_length"                        ), "RW", 16, field_default(0) ),  -- depends on BG block size, so set by data path
       ( field_name_pad("udp_checksum"                            ), "RW", 16, field_default(0) ),
 
-      ( field_name_pad("dp_reserved"                             ), "RW", 31, field_default(0) ),
+      ( field_name_pad("dp_length"                               ), "RW", 16, field_default(0) ),
+      ( field_name_pad("dp_reserved"                             ), "RW", 15, field_default(0) ),
       ( field_name_pad("dp_sync"                                 ), "RW",  1, field_default(0) ),
       ( field_name_pad("dp_bsn"                                  ), "RW", 64, field_default(0) )
   );
@@ -104,7 +105,8 @@ PACKAGE eth_tester_pkg is
   CONSTANT c_eth_tester_udp_src_port_15_8 : STD_LOGIC_VECTOR( 7 DOWNTO 0) := x"E0";
 
   TYPE t_eth_tester_app_header IS RECORD
-    dp_reserved : STD_LOGIC_VECTOR(30 DOWNTO 0);
+    dp_length   : STD_LOGIC_VECTOR(15 DOWNTO 0);
+    dp_reserved : STD_LOGIC_VECTOR(14 DOWNTO 0);
     dp_sync     : STD_LOGIC;
     dp_bsn      : STD_LOGIC_VECTOR(63 DOWNTO 0);
   END RECORD;
@@ -152,6 +154,7 @@ PACKAGE BODY eth_tester_pkg IS
     v.udp.checksum       := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "udp_checksum")     DOWNTO field_lo(c_eth_tester_hdr_field_arr, "udp_checksum"));
 
     -- app header
+    v.app.dp_length      :=    hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "dp_length")   DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_length"));
     v.app.dp_reserved    :=    hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "dp_reserved") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_reserved"));
     v.app.dp_sync        := sl(hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "dp_sync")     DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_sync")));
     v.app.dp_bsn         :=    hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "dp_bsn")      DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_bsn"));
diff --git a/libraries/io/eth/src/vhdl/eth_tester_rx.vhd b/libraries/io/eth/src/vhdl/eth_tester_rx.vhd
index 425f3f39f17fa73f62e02ddafa34300f53917efe..e4012c32f33201dea5808737ace2a779555d7483 100644
--- a/libraries/io/eth/src/vhdl/eth_tester_rx.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester_rx.vhd
@@ -46,6 +46,8 @@ ENTITY eth_tester_rx IS
     st_clk             : IN  STD_LOGIC;
     ref_sync           : IN  STD_LOGIC;
 
+    exp_length         : IN NATURAL RANGE 0 TO 2**c_halfword_w - 1;  -- 16 bit
+
     -- UDP receive interface
     rx_udp_sosi        : IN  t_dp_sosi;
 
@@ -75,6 +77,7 @@ ARCHITECTURE str OF eth_tester_rx IS
   SIGNAL rx_offload_data     : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
   SIGNAL decoded_sosi        : t_dp_sosi;
   SIGNAL decoded_data        : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+  SIGNAL decoded_length      : NATURAL;
   SIGNAL rx_fifo_siso        : t_dp_siso;
   SIGNAL rx_fifo_sosi        : t_dp_sosi;
   SIGNAL rx_fifo_data        : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
@@ -134,10 +137,22 @@ BEGIN
   p_set_meta: PROCESS(rx_offload_sosi, hdr_fields_out_slv, hdr_fields_raw_slv)
   BEGIN
     decoded_sosi      <= rx_offload_sosi;
+    decoded_length    <=       TO_UINT(hdr_fields_raw_slv(field_hi(c_eth_tester_hdr_field_arr, "dp_length") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_length")));
     decoded_sosi.sync <=            sl(hdr_fields_out_slv(field_hi(c_eth_tester_hdr_field_arr, "dp_sync") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_sync")));
     decoded_sosi.bsn  <= RESIZE_DP_BSN(hdr_fields_raw_slv(field_hi(c_eth_tester_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_bsn")));
   END PROCESS;
 
+  -- synthesis translate_off
+  p_verify_length : PROCESS(st_clk)
+  BEGIN
+    IF rising_edge(st_clk) THEN
+      IF decoded_sosi.sop = '1' THEN
+        ASSERT decoded_length = exp_length REPORT "Unexpected Rx length" & NATURAL'IMAGE(decoded_length) & " /= " & NATURAL'IMAGE(exp_length) & " expected length from Tx" SEVERITY ERROR;
+      END IF;
+    END IF;
+  END PROCESS;
+  -- synthesis translate_on
+
   u_rx_fifo : ENTITY dp_lib.dp_fifo_sc
   GENERIC MAP (
     g_data_w         => c_word_w,
diff --git a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
index 8d5dace234f77b58714d4b3d949c6de114f00d92..37008bab10974097d5d3a9f047d53060a1cfb81b 100644
--- a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
@@ -52,6 +52,7 @@ ENTITY eth_tester_tx IS
     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_length          : OUT NATURAL RANGE 0 TO 2**c_halfword_w - 1;  -- 16 bit
     tx_fifo_rd_emp     : OUT STD_LOGIC;
 
     tx_udp_sosi        : OUT t_dp_sosi;
@@ -116,6 +117,7 @@ ARCHITECTURE str OF eth_tester_tx IS
 BEGIN
 
   ref_sync <= i_ref_sync;
+  tx_length <= app_total_length;
   tx_fifo_rd_emp <= i_tx_fifo_rd_emp;
   tx_udp_sosi <= i_tx_udp_sosi;
 
@@ -246,6 +248,7 @@ BEGIN
   --        DP    udp_checksum --> default fixed 0, so not used, not calculated
   --                               here or in 1GbE eth component because would
   --                               require store and forward
+  --        DP    dp_length
   --     MM       dp_reserved
   --        DP    dp_sync
   --        DP    dp_bsn
@@ -263,6 +266,7 @@ BEGIN
   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_length"       ) DOWNTO field_lo(c_eth_tester_hdr_field_arr,  "dp_length"       )) <= TO_UVEC(app_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;
 
diff --git a/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd b/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd
index 08948c5d67f616ba11f685ca0394f2f799049dd9..0468da2e97b1c7044b6b589d621036255d4ce9c3 100644
--- a/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd
+++ b/libraries/io/eth/tb/vhdl/tb_eth_tester.vhd
@@ -25,6 +25,9 @@
 --
 -- Usage:
 -- > as 8
+-- # Cannot use run -a when g_loopback_eth=TRUE and g_eth_sim_level=0, because
+-- # the TSE IP model remains active internally after tb_end
+-- > run 100 us  # when g_loopback_eth=TRUE and g_eth_sim_level=0, else:
 -- > run -a
 --
 -- References:
@@ -54,10 +57,10 @@ USE tech_tse_lib.tb_tech_tse_pkg.ALL;
 ENTITY tb_eth_tester IS
   GENERIC (
     g_tb_index         : NATURAL := 0;  -- use to incremental delay logging from tb instances in tb_tb
-    g_nof_sync         : NATURAL := 93;  -- number of BG sync intervals to set c_run_time
+    g_nof_sync         : NATURAL := 3;  -- number of BG sync intervals to set c_run_time
     g_nof_streams      : NATURAL := 1;  -- <= c_eth_nof_udp_ports = 4 when g_loopback_tx_rx = 1
-    g_loopback_eth     : BOOLEAN := FALSE;  -- FALSE = sosi loopback, TRUE = eth loopback
-    g_eth_sim_level    : NATURAL := 1;  -- when g_loopback_eth = TRUE, then 0 = use tech_tse IP; 1 = use fast sim_tse model
+    g_loopback_eth     : BOOLEAN := TRUE;  -- FALSE = sosi loopback, TRUE = eth loopback
+    g_eth_sim_level    : NATURAL := 0;  -- when g_loopback_eth = TRUE, then 0 = use tech_tse IP; 1 = use fast sim_tse model
 
     -- t_diag_block_gen_integer =
     --   sl:  enable
@@ -70,7 +73,7 @@ ENTITY tb_eth_tester IS
     --   nat: bsn_init
     --g_bg_ctrl_first    : t_diag_block_gen_integer := ('1', '1', 50, 8, 100, 0, c_diag_bg_mem_max_adr, 0);  -- for first stream
     --g_bg_ctrl_others   : t_diag_block_gen_integer := ('1', '1', 30, 8, 10, 0, c_diag_bg_mem_max_adr, 0)   -- for other streams
-    g_bg_ctrl_first    : t_diag_block_gen_integer := ('1', '1', 50, 8, 660, 0, c_diag_bg_mem_max_adr, 0);  -- for first stream
+    g_bg_ctrl_first    : t_diag_block_gen_integer := ('1', '1', 50, 8, 200, 0, c_diag_bg_mem_max_adr, 0);  -- for first stream
     g_bg_ctrl_others   : t_diag_block_gen_integer := ('1', '1', 30, 8, 10, 0, c_diag_bg_mem_max_adr, 0)   -- for other streams
   );
   PORT (
@@ -282,10 +285,10 @@ BEGIN
       v_offset := I * c_eth_tester_reg_hdr_dat_addr_span;
       -- Set destination MAC/IP/UDP port in tx header, increment udp_dst_port per stream
       -- The MM addresses follow from byte address_offset // 4 in eth.peripheral.yaml
-      proc_mem_mm_bus_wr(v_offset + 16#6#, v_udp_dst_port + I, mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi);
-      proc_mem_mm_bus_wr(v_offset + 16#9#, 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(v_offset + 16#17#, 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(v_offset + 16#18#, TO_UINT(c_eth_tester_eth_dst_mac(47 DOWNTO 32)), mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi);
+      proc_mem_mm_bus_wr(v_offset + 16#7#, v_udp_dst_port + I, mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi);
+      proc_mem_mm_bus_wr(v_offset + 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(v_offset + 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(v_offset + 16#19#, TO_UINT(c_eth_tester_eth_dst_mac(47 DOWNTO 32)), mm_clk, reg_hdr_dat_cipo, reg_hdr_dat_copi);
     END LOOP;
 
     ---------------------------------------------------------------------------
@@ -413,9 +416,9 @@ BEGIN
         -- BG experiences siso.xon block level flow control, to stay below
         -- 1 Gbps of the 1GbE link rate.
         ASSERT tx_total_count_nof_packet_arr(I) = rx_total_count_nof_packet_arr(I) REPORT c_tb_str &
-            "Wrong Tx total nof packets count(" & NATURAL'IMAGE(I) &
+            "Wrong Tx-Rx total nof packets count(" & NATURAL'IMAGE(I) &
             "), Tx count = " & NATURAL'IMAGE(tx_total_count_nof_packet_arr(I)) &
-            " /= " & NATURAL'IMAGE(tx_total_count_nof_packet_arr(I)) &
+            " /= " & NATURAL'IMAGE(rx_total_count_nof_packet_arr(I)) &
             " = Rx count" SEVERITY ERROR;
        END IF;
     END LOOP;