diff --git a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
index e4ae9c2c1596302083f695dfad1218497d9d20ce..39558725013ee5c264751152b4376254da429b0a 100644
--- a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
+++ b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd
@@ -52,6 +52,8 @@ 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_fifo_rd_emp     : OUT STD_LOGIC;
+
     tx_udp_sosi        : OUT t_dp_sosi;
     tx_udp_siso        : IN  t_dp_siso := c_dp_siso_rdy;
 
@@ -72,8 +74,12 @@ ARCHITECTURE str OF eth_tester_tx IS
 
   CONSTANT c_empty_w              : NATURAL := 2;  -- for 0, 1, 2, 3 empty octets per word
 
-  CONSTANT c_fifo_fill            : NATURAL := c_eth_tester_bg_block_len_max / c_word_sz;  -- = 9000 / 4 = 2250
-  CONSTANT c_fifo_size            : NATURAL := true_log_pow2(c_fifo_fill);  -- = 4096
+  -- Choose 10% extra margin for FIFO fill level that will result in BG block
+  -- level flow control via  bg_siso.xon. The input eop will release blocks
+  -- for FIFO output already before the FIFO is fill level is reached.
+  -- Choose FIFO size to fit one more packet on top of FIFO fill level.
+  CONSTANT c_fifo_fill            : NATURAL := c_eth_tester_bg_block_len_max * 11 / c_word_sz / 10;
+  CONSTANT c_fifo_size            : NATURAL := true_log_pow2(c_fifo_fill + c_eth_tester_bg_block_len_max);  -- = 8192
 
   CONSTANT c_nof_total_counts     : NATURAL := 1;  -- one to count Tx packets
 
@@ -81,6 +87,7 @@ ARCHITECTURE str OF eth_tester_tx IS
   SIGNAL udp_total_length         : NATURAL;
   SIGNAL app_total_length         : NATURAL;
 
+  SIGNAL bg_siso                  : t_dp_siso := c_dp_siso_rdy;
   SIGNAL bg_sosi                  : t_dp_sosi;
   SIGNAL bg_data                  : STD_LOGIC_VECTOR(c_octet_w-1 DOWNTO 0);
   SIGNAL bg_ctrl_hold             : t_diag_block_gen;
@@ -90,6 +97,10 @@ ARCHITECTURE str OF eth_tester_tx IS
   SIGNAL tx_fifo_sosi             : t_dp_sosi;
   SIGNAL tx_fifo_data             : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
   SIGNAL tx_fifo_siso             : t_dp_siso;
+  SIGNAL tx_fifo_wr_ful           : STD_LOGIC;
+  SIGNAL tx_fifo_wr_usedw         : STD_LOGIC_VECTOR(ceil_log2(c_fifo_size)-1 DOWNTO 0);
+  SIGNAL i_tx_fifo_rd_emp         : STD_LOGIC;
+
   SIGNAL i_ref_sync               : STD_LOGIC := '0';
   SIGNAL in_strobe_arr            : STD_LOGIC_VECTOR(c_nof_total_counts-1 DOWNTO 0);
   SIGNAL i_tx_udp_sosi            : t_dp_sosi;
@@ -104,6 +115,7 @@ ARCHITECTURE str OF eth_tester_tx IS
 BEGIN
 
   ref_sync <= i_ref_sync;
+  tx_fifo_rd_emp <= i_tx_fifo_rd_emp;
   tx_udp_sosi <= i_tx_udp_sosi;
 
   -- View sosi.data in Wave Window
@@ -133,9 +145,22 @@ BEGIN
     reg_bg_ctrl_miso      => reg_bg_ctrl_cipo,
     -- ST interface
     bg_ctrl_hold_arr(0)   => bg_ctrl_hold,
-    out_sosi_arr(0)       => bg_sosi
+    out_sosi_arr(0)       => bg_sosi,
+    out_siso_arr(0)       => bg_siso
   );
 
+  -- BG block level flow control, needed in case BG settings result in eth bit
+  -- rate > 1 Gbps, to avoid u_tx_fifo overflow.
+  p_bg_siso_xon : PROCESS(st_clk)
+  BEGIN
+    IF rising_edge(st_clk) THEN
+      bg_siso.xon <= '1';
+      IF TO_UINT(tx_fifo_wr_usedw) > c_fifo_fill THEN
+        bg_siso.xon <= '0';
+      END IF;
+    END IF;
+  END PROCESS;
+
   u_pack : ENTITY dp_lib.dp_repack_data  -- pack 8b octets into 32b words
   GENERIC MAP (
     g_in_dat_w       => c_octet_w,  -- = 8
@@ -168,6 +193,10 @@ BEGIN
     wr_clk      => st_clk,
     rd_rst      => st_rst,
     rd_clk      => st_clk,
+    -- Monitor FIFO filling
+    wr_ful      => tx_fifo_wr_ful,
+    wr_usedw    => tx_fifo_wr_usedw,
+    rd_emp      => i_tx_fifo_rd_emp,
     -- ST sink
     snk_in      => tx_packed_sosi,
     -- ST source
@@ -220,8 +249,8 @@ BEGIN
   -- field in u_fifo.
   bg_block_len <= TO_UINT(bg_ctrl_hold.samples_per_packet(15 DOWNTO 0));  -- packet lenghts fit in 16b
   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);
+  udp_total_length <= c_network_udp_header_len + app_total_length WHEN rising_edge(st_clk);
+  ip_total_length <= c_network_ip_header_len + udp_total_length 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);