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);