diff --git a/applications/rdma_demo/hdllib.cfg b/applications/rdma_demo/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..eecdcb43a3072f940e2b96c89e6045fa99ba1d2f --- /dev/null +++ b/applications/rdma_demo/hdllib.cfg @@ -0,0 +1,19 @@ +hdl_lib_name = rdma_demo +hdl_library_clause_name = rdma_demo_lib +hdl_lib_uses_synth = common dp eth axi4 +hdl_lib_uses_sim = +hdl_lib_technology = + +synth_files = + src/vhdl/rdma_demo_pkg.vhd + src/vhdl/rdma_demo_eth_tester_wrapper.vhd + +test_bench_files = + +regression_test_vhdl = + + +[modelsim_project_file] + +[quartus_project_file] + diff --git a/libraries/io/eth/src/vhdl/eth_tester_vivado_ip_wrapper.vhd b/applications/rdma_demo/src/vhdl/rdma_demo_eth_tester_wrapper.vhd similarity index 50% rename from libraries/io/eth/src/vhdl/eth_tester_vivado_ip_wrapper.vhd rename to applications/rdma_demo/src/vhdl/rdma_demo_eth_tester_wrapper.vhd index 4df04597d9bf2abb3f495f6be34b743555a6a895..4f50982eaefbe88db5d32b4baff19f1491aa00c4 100644 --- a/libraries/io/eth/src/vhdl/eth_tester_vivado_ip_wrapper.vhd +++ b/applications/rdma_demo/src/vhdl/rdma_demo_eth_tester_wrapper.vhd @@ -21,7 +21,7 @@ -- Purpose: Provide AXI-4-stream interfaces + standard avalon MM interfaces for -- eth_tester.vhd such that it can be used to create a Vivado IP block. -- Description: --- . The eth_tester_vivado_ip_wrapper uses axi4_stream_dp_bridge to convert the dp +-- . The rdma_demo_eth_tester_wrapper uses axi4_stream_dp_bridge to convert the dp -- sosi/siso interfaces of the eth_tester into AXI4-Stream interfaces. -- . In order for this component to be suitable as a Vivado IP, the ports are -- exclusively STD_LOGIC(_VECTOR) where the widths are hard-coded as demanded @@ -30,19 +30,19 @@ -- . Avalon is used for all MM interfaces, which can be bridged to AXI4-Lite in -- vivado using the AXI AMM Bridge IP. -LIBRARY IEEE, common_lib, dp_lib, diag_lib, axi4_lib; +LIBRARY IEEE, common_lib, dp_lib, axi4_lib, eth_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 axi4_lib.axi4_stream_pkg.ALL; -USE work.eth_pkg.ALL; -USE work.eth_tester_pkg.ALL; +USE eth_lib.eth_pkg.ALL; +USE eth_lib.eth_tester_pkg.ALL; +USE work.rdma_demo_pkg.ALL; -ENTITY eth_tester_vivado_ip_wrapper IS +ENTITY rdma_demo_eth_tester_wrapper IS PORT ( -- Clocks and reset mm_clk : IN STD_LOGIC; @@ -85,64 +85,75 @@ ENTITY eth_tester_vivado_ip_wrapper IS rx_udp_tuser : IN STD_LOGIC_VECTOR(70-1 DOWNTO 0); -- reg_bg_ctrl - reg_bg_ctrl_avm_address : IN STD_LOGIC_VECTOR(32-1 downto 0); - reg_bg_ctrl_avm_read : IN STD_LOGIC; - reg_bg_ctrl_avm_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); - reg_bg_ctrl_avm_readdatavalid : OUT STD_LOGIC; - reg_bg_ctrl_avm_waitrequest : OUT STD_LOGIC; - reg_bg_ctrl_avm_write : IN STD_LOGIC; - reg_bg_ctrl_avm_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_bg_ctrl_avs_address : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_bg_ctrl_avs_read : IN STD_LOGIC; + reg_bg_ctrl_avs_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); + reg_bg_ctrl_avs_readdatavalid : OUT STD_LOGIC; + reg_bg_ctrl_avs_waitrequest : OUT STD_LOGIC; + reg_bg_ctrl_avs_write : IN STD_LOGIC; + reg_bg_ctrl_avs_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); -- reg_hdr_dat - reg_hdr_dat_avm_address : IN STD_LOGIC_VECTOR(32-1 downto 0); - reg_hdr_dat_avm_read : IN STD_LOGIC; - reg_hdr_dat_avm_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); - reg_hdr_dat_avm_readdatavalid : OUT STD_LOGIC; - reg_hdr_dat_avm_waitrequest : OUT STD_LOGIC; - reg_hdr_dat_avm_write : IN STD_LOGIC; - reg_hdr_dat_avm_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_hdr_dat_avs_address : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_hdr_dat_avs_read : IN STD_LOGIC; + reg_hdr_dat_avs_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); + reg_hdr_dat_avs_readdatavalid : OUT STD_LOGIC; + reg_hdr_dat_avs_waitrequest : OUT STD_LOGIC; + reg_hdr_dat_avs_write : IN STD_LOGIC; + reg_hdr_dat_avs_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); -- reg_bsn_monitor_v2_tx - reg_bsn_monitor_v2_tx_avm_address : IN STD_LOGIC_VECTOR(32-1 downto 0); - reg_bsn_monitor_v2_tx_avm_read : IN STD_LOGIC; - reg_bsn_monitor_v2_tx_avm_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); - reg_bsn_monitor_v2_tx_avm_readdatavalid : OUT STD_LOGIC; - reg_bsn_monitor_v2_tx_avm_waitrequest : OUT STD_LOGIC; - reg_bsn_monitor_v2_tx_avm_write : IN STD_LOGIC; - reg_bsn_monitor_v2_tx_avm_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_bsn_monitor_v2_tx_avs_address : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_bsn_monitor_v2_tx_avs_read : IN STD_LOGIC; + reg_bsn_monitor_v2_tx_avs_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); + reg_bsn_monitor_v2_tx_avs_readdatavalid : OUT STD_LOGIC; + reg_bsn_monitor_v2_tx_avs_waitrequest : OUT STD_LOGIC; + reg_bsn_monitor_v2_tx_avs_write : IN STD_LOGIC; + reg_bsn_monitor_v2_tx_avs_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); -- reg_strobe_total_count_tx - reg_strobe_total_count_tx_avm_address : IN STD_LOGIC_VECTOR(32-1 downto 0); - reg_strobe_total_count_tx_avm_read : IN STD_LOGIC; - reg_strobe_total_count_tx_avm_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); - reg_strobe_total_count_tx_avm_readdatavalid : OUT STD_LOGIC; - reg_strobe_total_count_tx_avm_waitrequest : OUT STD_LOGIC; - reg_strobe_total_count_tx_avm_write : IN STD_LOGIC; - reg_strobe_total_count_tx_avm_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_strobe_total_count_tx_avs_address : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_strobe_total_count_tx_avs_read : IN STD_LOGIC; + reg_strobe_total_count_tx_avs_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); + reg_strobe_total_count_tx_avs_readdatavalid : OUT STD_LOGIC; + reg_strobe_total_count_tx_avs_waitrequest : OUT STD_LOGIC; + reg_strobe_total_count_tx_avs_write : IN STD_LOGIC; + reg_strobe_total_count_tx_avs_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); + + -- reg_dp_split + reg_dp_split_avs_address : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_dp_split_avs_read : IN STD_LOGIC; + reg_dp_split_avs_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); + reg_dp_split_avs_readdatavalid : OUT STD_LOGIC; + reg_dp_split_avs_waitrequest : OUT STD_LOGIC; + reg_dp_split_avs_write : IN STD_LOGIC; + reg_dp_split_avs_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); -- reg_bsn_monitor_v2_rx - reg_bsn_monitor_v2_rx_avm_address : IN STD_LOGIC_VECTOR(32-1 downto 0); - reg_bsn_monitor_v2_rx_avm_read : IN STD_LOGIC; - reg_bsn_monitor_v2_rx_avm_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); - reg_bsn_monitor_v2_rx_avm_readdatavalid : OUT STD_LOGIC; - reg_bsn_monitor_v2_rx_avm_waitrequest : OUT STD_LOGIC; - reg_bsn_monitor_v2_rx_avm_write : IN STD_LOGIC; - reg_bsn_monitor_v2_rx_avm_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_bsn_monitor_v2_rx_avs_address : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_bsn_monitor_v2_rx_avs_read : IN STD_LOGIC; + reg_bsn_monitor_v2_rx_avs_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); + reg_bsn_monitor_v2_rx_avs_readdatavalid : OUT STD_LOGIC; + reg_bsn_monitor_v2_rx_avs_waitrequest : OUT STD_LOGIC; + reg_bsn_monitor_v2_rx_avs_write : IN STD_LOGIC; + reg_bsn_monitor_v2_rx_avs_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0); -- reg_strobe_total_count_rx - reg_strobe_total_count_rx_avm_address : IN STD_LOGIC_VECTOR(32-1 downto 0); - reg_strobe_total_count_rx_avm_read : IN STD_LOGIC; - reg_strobe_total_count_rx_avm_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); - reg_strobe_total_count_rx_avm_readdatavalid : OUT STD_LOGIC; - reg_strobe_total_count_rx_avm_waitrequest : OUT STD_LOGIC; - reg_strobe_total_count_rx_avm_write : IN STD_LOGIC; - reg_strobe_total_count_rx_avm_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0) + reg_strobe_total_count_rx_avs_address : IN STD_LOGIC_VECTOR(32-1 downto 0); + reg_strobe_total_count_rx_avs_read : IN STD_LOGIC; + reg_strobe_total_count_rx_avs_readdata : OUT STD_LOGIC_VECTOR(32-1 downto 0); + reg_strobe_total_count_rx_avs_readdatavalid : OUT STD_LOGIC; + reg_strobe_total_count_rx_avs_waitrequest : OUT STD_LOGIC; + reg_strobe_total_count_rx_avs_write : IN STD_LOGIC; + reg_strobe_total_count_rx_avs_writedata : IN STD_LOGIC_VECTOR(32-1 downto 0) ); -END eth_tester_vivado_ip_wrapper; +END rdma_demo_eth_tester_wrapper; -ARCHITECTURE str OF eth_tester_vivado_ip_wrapper IS +ARCHITECTURE str OF rdma_demo_eth_tester_wrapper IS + CONSTANT c_nof_byte : NATURAL := c_rdma_demo_nof_octet_output_100gbe; + SIGNAL rx_udp_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL rx_udp_siso_arr : t_dp_siso_arr(0 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); SIGNAL tx_udp_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); @@ -161,6 +172,8 @@ ARCHITECTURE str OF eth_tester_vivado_ip_wrapper IS 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_dp_split_copi : t_mem_copi := c_mem_copi_rst; + SIGNAL reg_dp_split_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; @@ -172,9 +185,15 @@ ARCHITECTURE str OF eth_tester_vivado_ip_wrapper IS BEGIN - u_eth_tester : ENTITY work.eth_tester + u_eth_tester : ENTITY eth_lib.eth_tester GENERIC MAP ( - g_remove_crc => FALSE + g_nof_octet_generate => c_rdma_demo_nof_octet_generate_100gbe, + g_nof_octet_output => c_rdma_demo_nof_octet_output_100gbe, + g_use_network_header => FALSE, + g_use_dp_header => TRUE, + g_hdr_field_arr => c_rdma_demo_hdr_field_arr, + g_hdr_field_sel => c_rdma_demo_hdr_field_sel, + g_remove_crc => FALSE ) PORT MAP ( -- Clocks and reset @@ -206,6 +225,8 @@ BEGIN 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, + reg_dp_split_copi => reg_dp_split_copi, + reg_dp_split_cipo => reg_dp_split_cipo, reg_bsn_monitor_v2_rx_copi => reg_bsn_monitor_v2_rx_copi, reg_bsn_monitor_v2_rx_cipo => reg_bsn_monitor_v2_rx_cipo, @@ -250,96 +271,112 @@ BEGIN dp_out_siso => rx_udp_siso_arr(0) ); - -- Wire Records to IN/OUT ports. -- tx_udp tx_udp_axi4_siso.tready <= tx_udp_tready; tx_udp_tvalid <= tx_udp_axi4_sosi.tvalid; - tx_udp_tdata <= tx_udp_axi4_sosi.tdata; tx_udp_tstrb <= tx_udp_axi4_sosi.tstrb; - tx_udp_tkeep <= tx_udp_axi4_sosi.tkeep; tx_udp_tlast <= tx_udp_axi4_sosi.tlast; tx_udp_tid <= tx_udp_axi4_sosi.tid; tx_udp_tdest <= tx_udp_axi4_sosi.tdest; tx_udp_tuser <= tx_udp_axi4_sosi.tuser; + -- reverse order of bytes + gen_tx_data : FOR I IN 0 TO c_nof_byte - 1 GENERATE + tx_udp_tdata( (I+1) * c_octet_w - 1 DOWNTO I * c_octet_w) <= tx_udp_axi4_sosi.tdata((c_nof_byte - I) * c_octet_w - 1 DOWNTO (c_nof_byte - 1 - I) * c_octet_w); + tx_udp_tkeep(I) <= tx_udp_axi4_sosi.tkeep(c_nof_byte - 1 - I); + END GENERATE; -- rx_udp rx_udp_tready <= rx_udp_axi4_siso.tready; rx_udp_axi4_sosi.tvalid <= rx_udp_tvalid; - rx_udp_axi4_sosi.tdata <= rx_udp_tdata; rx_udp_axi4_sosi.tstrb <= rx_udp_tstrb; - rx_udp_axi4_sosi.tkeep <= rx_udp_tkeep; rx_udp_axi4_sosi.tlast <= rx_udp_tlast; rx_udp_axi4_sosi.tid <= rx_udp_tid; rx_udp_axi4_sosi.tdest <= rx_udp_tdest; rx_udp_axi4_sosi.tuser <= rx_udp_tuser; + -- reverse order of bytes + gen_rx_data : FOR I IN 0 TO c_nof_byte - 1 GENERATE + rx_udp_axi4_sosi.tdata( (I+1) * c_octet_w - 1 DOWNTO I * c_octet_w) <= rx_udp_tdata((c_nof_byte - I) * c_octet_w - 1 DOWNTO (c_nof_byte - 1 - I) * c_octet_w); + rx_udp_axi4_sosi.tkeep(I) <= rx_udp_tkeep(c_nof_byte - 1 - I); + END GENERATE; -- reg_bg_ctrl -- copi - reg_bg_ctrl_copi.address <= reg_bg_ctrl_avm_address; - reg_bg_ctrl_copi.wrdata <= RESIZE_UVEC(reg_bg_ctrl_avm_writedata, c_mem_data_w); - reg_bg_ctrl_copi.wr <= reg_bg_ctrl_avm_write; - reg_bg_ctrl_copi.rd <= reg_bg_ctrl_avm_read; + reg_bg_ctrl_copi.address <= reg_bg_ctrl_avs_address; + reg_bg_ctrl_copi.wrdata <= RESIZE_UVEC(reg_bg_ctrl_avs_writedata, c_mem_data_w); + reg_bg_ctrl_copi.wr <= reg_bg_ctrl_avs_write; + reg_bg_ctrl_copi.rd <= reg_bg_ctrl_avs_read; -- cipo - reg_bg_ctrl_avm_readdata <= RESIZE_UVEC_32(reg_bg_ctrl_cipo.rddata); - reg_bg_ctrl_avm_readdatavalid <= reg_bg_ctrl_cipo.rdval; - reg_bg_ctrl_avm_waitrequest <= reg_bg_ctrl_cipo.waitrequest; + reg_bg_ctrl_avs_readdata <= RESIZE_UVEC_32(reg_bg_ctrl_cipo.rddata); + reg_bg_ctrl_avs_readdatavalid <= reg_bg_ctrl_cipo.rdval; + reg_bg_ctrl_avs_waitrequest <= reg_bg_ctrl_cipo.waitrequest; -- reg_hdr_dat -- copi - reg_hdr_dat_copi.address <= reg_hdr_dat_avm_address; - reg_hdr_dat_copi.wrdata <= RESIZE_UVEC(reg_hdr_dat_avm_writedata, c_mem_data_w); - reg_hdr_dat_copi.wr <= reg_hdr_dat_avm_write; - reg_hdr_dat_copi.rd <= reg_hdr_dat_avm_read; + reg_hdr_dat_copi.address <= reg_hdr_dat_avs_address; + reg_hdr_dat_copi.wrdata <= RESIZE_UVEC(reg_hdr_dat_avs_writedata, c_mem_data_w); + reg_hdr_dat_copi.wr <= reg_hdr_dat_avs_write; + reg_hdr_dat_copi.rd <= reg_hdr_dat_avs_read; -- cipo - reg_hdr_dat_avm_readdata <= RESIZE_UVEC_32(reg_hdr_dat_cipo.rddata); - reg_hdr_dat_avm_readdatavalid <= reg_hdr_dat_cipo.rdval; - reg_hdr_dat_avm_waitrequest <= reg_hdr_dat_cipo.waitrequest; + reg_hdr_dat_avs_readdata <= RESIZE_UVEC_32(reg_hdr_dat_cipo.rddata); + reg_hdr_dat_avs_readdatavalid <= reg_hdr_dat_cipo.rdval; + reg_hdr_dat_avs_waitrequest <= reg_hdr_dat_cipo.waitrequest; -- reg_bsn_monitor_v2_tx -- copi - reg_bsn_monitor_v2_tx_copi.address <= reg_bsn_monitor_v2_tx_avm_address; - reg_bsn_monitor_v2_tx_copi.wrdata <= RESIZE_UVEC(reg_bsn_monitor_v2_tx_avm_writedata, c_mem_data_w); - reg_bsn_monitor_v2_tx_copi.wr <= reg_bsn_monitor_v2_tx_avm_write; - reg_bsn_monitor_v2_tx_copi.rd <= reg_bsn_monitor_v2_tx_avm_read; + reg_bsn_monitor_v2_tx_copi.address <= reg_bsn_monitor_v2_tx_avs_address; + reg_bsn_monitor_v2_tx_copi.wrdata <= RESIZE_UVEC(reg_bsn_monitor_v2_tx_avs_writedata, c_mem_data_w); + reg_bsn_monitor_v2_tx_copi.wr <= reg_bsn_monitor_v2_tx_avs_write; + reg_bsn_monitor_v2_tx_copi.rd <= reg_bsn_monitor_v2_tx_avs_read; -- cipo - reg_bsn_monitor_v2_tx_avm_readdata <= RESIZE_UVEC_32(reg_bsn_monitor_v2_tx_cipo.rddata); - reg_bsn_monitor_v2_tx_avm_readdatavalid <= reg_bsn_monitor_v2_tx_cipo.rdval; - reg_bsn_monitor_v2_tx_avm_waitrequest <= reg_bsn_monitor_v2_tx_cipo.waitrequest; + reg_bsn_monitor_v2_tx_avs_readdata <= RESIZE_UVEC_32(reg_bsn_monitor_v2_tx_cipo.rddata); + reg_bsn_monitor_v2_tx_avs_readdatavalid <= reg_bsn_monitor_v2_tx_cipo.rdval; + reg_bsn_monitor_v2_tx_avs_waitrequest <= reg_bsn_monitor_v2_tx_cipo.waitrequest; -- reg_strobe_total_count_tx -- copi - reg_strobe_total_count_tx_copi.address <= reg_strobe_total_count_tx_avm_address; - reg_strobe_total_count_tx_copi.wrdata <= RESIZE_UVEC(reg_strobe_total_count_tx_avm_writedata, c_mem_data_w); - reg_strobe_total_count_tx_copi.wr <= reg_strobe_total_count_tx_avm_write; - reg_strobe_total_count_tx_copi.rd <= reg_strobe_total_count_tx_avm_read; + reg_strobe_total_count_tx_copi.address <= reg_strobe_total_count_tx_avs_address; + reg_strobe_total_count_tx_copi.wrdata <= RESIZE_UVEC(reg_strobe_total_count_tx_avs_writedata, c_mem_data_w); + reg_strobe_total_count_tx_copi.wr <= reg_strobe_total_count_tx_avs_write; + reg_strobe_total_count_tx_copi.rd <= reg_strobe_total_count_tx_avs_read; + -- cipo + reg_strobe_total_count_tx_avs_readdata <= RESIZE_UVEC_32(reg_strobe_total_count_tx_cipo.rddata); + reg_strobe_total_count_tx_avs_readdatavalid <= reg_strobe_total_count_tx_cipo.rdval; + reg_strobe_total_count_tx_avs_waitrequest <= reg_strobe_total_count_tx_cipo.waitrequest; + + -- reg_dp_split + -- copi + reg_dp_split_copi.address <= reg_dp_split_avs_address; + reg_dp_split_copi.wrdata <= RESIZE_UVEC(reg_dp_split_avs_writedata, c_mem_data_w); + reg_dp_split_copi.wr <= reg_dp_split_avs_write; + reg_dp_split_copi.rd <= reg_dp_split_avs_read; -- cipo - reg_strobe_total_count_tx_avm_readdata <= RESIZE_UVEC_32(reg_strobe_total_count_tx_cipo.rddata); - reg_strobe_total_count_tx_avm_readdatavalid <= reg_strobe_total_count_tx_cipo.rdval; - reg_strobe_total_count_tx_avm_waitrequest <= reg_strobe_total_count_tx_cipo.waitrequest; + reg_dp_split_avs_readdata <= RESIZE_UVEC_32(reg_dp_split_cipo.rddata); + reg_dp_split_avs_readdatavalid <= reg_dp_split_cipo.rdval; + reg_dp_split_avs_waitrequest <= reg_dp_split_cipo.waitrequest; -- reg_bsn_monitor_v2_rx -- copi - reg_bsn_monitor_v2_rx_copi.address <= reg_bsn_monitor_v2_rx_avm_address; - reg_bsn_monitor_v2_rx_copi.wrdata <= RESIZE_UVEC(reg_bsn_monitor_v2_rx_avm_writedata, c_mem_data_w); - reg_bsn_monitor_v2_rx_copi.wr <= reg_bsn_monitor_v2_rx_avm_write; - reg_bsn_monitor_v2_rx_copi.rd <= reg_bsn_monitor_v2_rx_avm_read; + reg_bsn_monitor_v2_rx_copi.address <= reg_bsn_monitor_v2_rx_avs_address; + reg_bsn_monitor_v2_rx_copi.wrdata <= RESIZE_UVEC(reg_bsn_monitor_v2_rx_avs_writedata, c_mem_data_w); + reg_bsn_monitor_v2_rx_copi.wr <= reg_bsn_monitor_v2_rx_avs_write; + reg_bsn_monitor_v2_rx_copi.rd <= reg_bsn_monitor_v2_rx_avs_read; -- cipo - reg_bsn_monitor_v2_rx_avm_readdata <= RESIZE_UVEC_32(reg_bsn_monitor_v2_rx_cipo.rddata); - reg_bsn_monitor_v2_rx_avm_readdatavalid <= reg_bsn_monitor_v2_rx_cipo.rdval; - reg_bsn_monitor_v2_rx_avm_waitrequest <= reg_bsn_monitor_v2_rx_cipo.waitrequest; + reg_bsn_monitor_v2_rx_avs_readdata <= RESIZE_UVEC_32(reg_bsn_monitor_v2_rx_cipo.rddata); + reg_bsn_monitor_v2_rx_avs_readdatavalid <= reg_bsn_monitor_v2_rx_cipo.rdval; + reg_bsn_monitor_v2_rx_avs_waitrequest <= reg_bsn_monitor_v2_rx_cipo.waitrequest; -- reg_strobe_total_count_rx -- copi - reg_strobe_total_count_rx_copi.address <= reg_strobe_total_count_rx_avm_address; - reg_strobe_total_count_rx_copi.wrdata <= RESIZE_UVEC(reg_strobe_total_count_rx_avm_writedata, c_mem_data_w); - reg_strobe_total_count_rx_copi.wr <= reg_strobe_total_count_rx_avm_write; - reg_strobe_total_count_rx_copi.rd <= reg_strobe_total_count_rx_avm_read; + reg_strobe_total_count_rx_copi.address <= reg_strobe_total_count_rx_avs_address; + reg_strobe_total_count_rx_copi.wrdata <= RESIZE_UVEC(reg_strobe_total_count_rx_avs_writedata, c_mem_data_w); + reg_strobe_total_count_rx_copi.wr <= reg_strobe_total_count_rx_avs_write; + reg_strobe_total_count_rx_copi.rd <= reg_strobe_total_count_rx_avs_read; -- cipo - reg_strobe_total_count_rx_avm_readdata <= RESIZE_UVEC_32(reg_strobe_total_count_rx_cipo.rddata); - reg_strobe_total_count_rx_avm_readdatavalid <= reg_strobe_total_count_rx_cipo.rdval; - reg_strobe_total_count_rx_avm_waitrequest <= reg_strobe_total_count_rx_cipo.waitrequest; + reg_strobe_total_count_rx_avs_readdata <= RESIZE_UVEC_32(reg_strobe_total_count_rx_cipo.rddata); + reg_strobe_total_count_rx_avs_readdatavalid <= reg_strobe_total_count_rx_cipo.rdval; + reg_strobe_total_count_rx_avs_waitrequest <= reg_strobe_total_count_rx_cipo.waitrequest; END str; diff --git a/applications/rdma_demo/src/vhdl/rdma_demo_pkg.vhd b/applications/rdma_demo/src/vhdl/rdma_demo_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8afd1a81d4ea92d9d0a730c984934fdfa7950348 --- /dev/null +++ b/applications/rdma_demo/src/vhdl/rdma_demo_pkg.vhd @@ -0,0 +1,75 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2023 +-- 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: R. vd Walle +-- Purpose: This package contains rdma_demo specific constants and/or functions +-- Description: +-- +LIBRARY IEEE, common_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; + +PACKAGE rdma_demo_pkg is + + CONSTANT c_rdma_demo_nof_octet_generate_100gbe : NATURAL := 64; + CONSTANT c_rdma_demo_nof_octet_output_100gbe : NATURAL := 64; + + + -- hdr_field_sel bit selects where the hdr_field value is set: + -- . 0 = data path controlled, value is set in data path, so field_default() + -- is not used. + -- . 1 = MM controlled, value is set via MM or by the field_default(), so any + -- data path setting in eth_tester.vhd is not used. + -- Remarks: + -- . For constant values it is convenient to use MM controlled, because then + -- the field_default() is used that can be set here in + -- c_rdma_demo_hdr_field_arr. + -- . For reserved values it is convenient to use MM controlled, because then + -- in future they could still be changed via MM without having to recompile + -- the FW. + -- . Typically only use data path controlled if the value has to be set + -- dynamically, so dependent on the state of the FW. + -- . If a data path controlled field is not set in the FW, then it defaults + -- 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_rdma_demo_nof_hdr_fields : NATURAL := 4; + CONSTANT c_rdma_demo_hdr_field_sel : STD_LOGIC_VECTOR(c_rdma_demo_nof_hdr_fields-1 DOWNTO 0) := "0100"; + + CONSTANT c_rdma_demo_hdr_field_arr : t_common_field_arr(c_rdma_demo_nof_hdr_fields-1 DOWNTO 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) ) + ); + CONSTANT c_rdma_demo_reg_hdr_dat_addr_w : NATURAL := ceil_log2(field_nof_words(c_rdma_demo_hdr_field_arr, c_word_w)); -- = 5 + CONSTANT c_rdma_demo_reg_hdr_dat_addr_span : NATURAL := 2**c_rdma_demo_reg_hdr_dat_addr_w; -- = 32 + + CONSTANT c_rdma_demo_app_hdr_len : NATURAL := 12; -- octets + +END rdma_demo_pkg; + +PACKAGE BODY rdma_demo_pkg IS + +END rdma_demo_pkg; + diff --git a/libraries/base/dp/src/vhdl/dp_field_blk.vhd b/libraries/base/dp/src/vhdl/dp_field_blk.vhd index 477e36e314b1cf985d314f5d26f07ef7b4e1ec56..f778f6c181aef52db57f807726063f2959ae2dba 100644 --- a/libraries/base/dp/src/vhdl/dp_field_blk.vhd +++ b/libraries/base/dp/src/vhdl/dp_field_blk.vhd @@ -35,7 +35,16 @@ USE work.dp_stream_pkg.ALL; -- if override = '0' the field is taken from snk_in.data. -- . The initial (default) values of the override bits are passed via g_field_sel(one bit per field); -- . Both the SLV as the override (ovr) fields can be read back via MM; - +-- . g_mode can be used to select in which mode dp_field_blk should work. Most of the time, the +-- default g_mode = 0 can be used. When using g_mode = 0, it is assumed that dp_field_blk must be +-- used in source mode when g_snk_data_w > g_src_data_w, else in sink mode. This is a typical +-- application as it is often the case that the total width of the field block is larger than the +-- serial data width as shown in the example below. There are cases where the width of the +-- field-block is smaller than the serial data words. Therefore it is possible to force either sink +-- or source mode. +-- . g_mode = 0: auto select mode based on g_snk_data_w and g_src_data_w. +-- . g_mode = 1: use dp_field_blk in source mode regardless of g_*_data_w. +-- . g_mode = 2: use dp_field_blk in sink mode regardless of g_*_data_w. -- The diagrams below show dp_field_blk in source and sink configuration. For simplicity, the 5 -- fields are defined as follows (fields do not need to respect word boundaries): @@ -82,7 +91,8 @@ ENTITY dp_field_blk IS g_src_data_w : NATURAL; g_in_symbol_w : NATURAL := 1; g_out_symbol_w : NATURAL := 1; - g_pipeline_ready : BOOLEAN := FALSE + g_pipeline_ready : BOOLEAN := FALSE; + g_mode : NATURAL := 0 -- 0 = auto, 1 = source , 2 = sink ); PORT ( dp_rst : IN STD_LOGIC; @@ -123,7 +133,7 @@ ARCHITECTURE str OF dp_field_blk IS -- Mode: fields to data block (c_field_to_block=True) or data block to fields (c_field_to_block=False) -- a.k.a. wire to narrow or narrow to wide - CONSTANT c_field_to_block : BOOLEAN := g_snk_data_w>g_src_data_w; + CONSTANT c_field_to_block : BOOLEAN := sel_a_b(g_mode = 0, g_snk_data_w>g_src_data_w, sel_a_b(g_mode = 1, TRUE, FALSE)); -- Field to block: mm_fields only has SLV output, no input. Set input wirdt to zero. CONSTANT c_mm_fields_slv_in_w : NATURAL := sel_a_b(c_field_to_block, 0, g_src_data_w); diff --git a/libraries/base/dp/src/vhdl/dp_offload_rx.vhd b/libraries/base/dp/src/vhdl/dp_offload_rx.vhd index 6ce2e23d4cda4d15e7d7ad80eabee1b0a9729282..9ec0038dbd96b145dd56065d4d7c7e14e22611bc 100644 --- a/libraries/base/dp/src/vhdl/dp_offload_rx.vhd +++ b/libraries/base/dp/src/vhdl/dp_offload_rx.vhd @@ -149,7 +149,8 @@ BEGIN g_snk_data_w => c_dp_field_blk_snk_data_w, --g_data_w, g_src_data_w => c_dp_field_blk_src_data_w, --field_slv_in_len(field_arr_set_mode(g_hdr_field_arr , "RO")) g_in_symbol_w => c_symbol_w, - g_out_symbol_w => c_symbol_w + g_out_symbol_w => c_symbol_w, + g_mode => 2 -- sink mode ) PORT MAP ( dp_rst => dp_rst, diff --git a/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd b/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd index a7e72974601c0c47dd94097ae9cf90a7255a2f58..a27fc5a3e50be733febcd62b9de696f809ffb7a5 100644 --- a/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd +++ b/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd @@ -184,7 +184,8 @@ BEGIN g_src_data_w => c_dp_field_blk_src_data_w, g_in_symbol_w => g_symbol_w, g_out_symbol_w => g_symbol_w, - g_pipeline_ready => g_pipeline_ready + g_pipeline_ready => g_pipeline_ready, + g_mode => 1 -- source mode ) PORT MAP ( dp_clk => dp_clk, diff --git a/libraries/base/dp/src/vhdl/dp_repack_data.vhd b/libraries/base/dp/src/vhdl/dp_repack_data.vhd index d1c86bf258f14795eaa5ea49ddc9007a12fe1dc3..9469c48397784de9b3371c14caaf3505425b334e 100644 --- a/libraries/base/dp/src/vhdl/dp_repack_data.vhd +++ b/libraries/base/dp/src/vhdl/dp_repack_data.vhd @@ -139,6 +139,11 @@ -- The src_out.empty will be 2, because: -- (g_out_dat_w*g_out_nof_words-g_in_dat_w*g_in_nof_words)/g_out_symbol_w -- = (32*11 - 42*8*1)/ 8 = 2 octet symbols +-- . Instead of using dp_sosi.data for intermediate results in dp_repack_data, +-- a seperate std_logic_vector is used to carry the sosi data as the required +-- vector width can become larger than c_dp_stream_data_w. Note that for the +-- in/out sosi of dp_repack_data, the dp_sosi.data field is still used such +-- that there is no added complexity for the user of dp_repack_data. -- -- Design steps: -- * In total the development took 5 days. On day 3 I was in distress because @@ -189,7 +194,8 @@ ENTITY dp_repack_in IS snk_in : IN t_dp_sosi; src_in : IN t_dp_siso; - src_out : OUT t_dp_sosi + src_out : OUT t_dp_sosi; + src_out_data : OUT STD_LOGIC_VECTOR(g_in_dat_w * g_in_nof_words - 1 DOWNTO 0) ); END dp_repack_in; @@ -203,12 +209,13 @@ ARCHITECTURE rtl OF dp_repack_in IS TYPE t_dat_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); TYPE t_reg IS RECORD - dat_arr : t_dat_arr(g_in_nof_words-1 DOWNTO 0); -- internally use dat_arr[] to represent v.src_out.data - src_out : t_dp_sosi; -- sosi output - hold_out : t_dp_sosi; -- hold snk_in.sync/sop/eop until end of section and then hold valid src_out until src_in.ready - flush : STD_LOGIC; -- shift when snk_in.valid or flush in case the last subsection has < g_in_nof_words - dat_bit_cnt : NATURAL RANGE 0 TO c_bit_cnt_max; -- actual nof bits in subsection - pack_bit_cnt : NATURAL RANGE 0 TO c_bit_cnt_max; -- count nof bits in subsection + dat_arr : t_dat_arr(g_in_nof_words-1 DOWNTO 0); -- internally use dat_arr[] to represent v.src_out.data + src_out : t_dp_sosi; -- sosi output + src_out_data : STD_LOGIC_VECTOR(c_in_buf_dat_w-1 DOWNTO 0); -- Use seperate STD_LOGIC_VECTOR to carry the sosi data as c_in_buf_dat_w can be larger than c_dp_stream_data_w. + hold_out : t_dp_sosi; -- hold snk_in.sync/sop/eop until end of section and then hold valid src_out until src_in.ready + flush : STD_LOGIC; -- shift when snk_in.valid or flush in case the last subsection has < g_in_nof_words + dat_bit_cnt : NATURAL RANGE 0 TO c_bit_cnt_max; -- actual nof bits in subsection + pack_bit_cnt : NATURAL RANGE 0 TO c_bit_cnt_max; -- count nof bits in subsection END RECORD; SIGNAL data_vec : STD_LOGIC_VECTOR(c_in_buf_dat_w-1 DOWNTO 0); @@ -220,7 +227,6 @@ ARCHITECTURE rtl OF dp_repack_in IS -- Debug signals SIGNAL snk_in_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); SIGNAL i_src_out : t_dp_sosi; - SIGNAL src_out_data : STD_LOGIC_VECTOR(c_in_buf_dat_w-1 DOWNTO 0); SIGNAL dbg_g_in_dat_w : NATURAL := g_in_dat_w; SIGNAL dbg_in_nof_words : NATURAL := g_in_nof_words; @@ -232,7 +238,6 @@ BEGIN snk_in_data <= snk_in.data(g_in_dat_w-1 DOWNTO 0); src_out <= i_src_out; - src_out_data <= i_src_out.data(c_in_buf_dat_w-1 DOWNTO 0); gen_bypass : IF g_bypass=TRUE GENERATE snk_out <= src_in; @@ -306,8 +311,9 @@ BEGIN END IF; -- pass on the v.dat_arr as data vector + v.src_out_data := data_vec; v.src_out.data := RESIZE_DP_DATA(data_vec); - + -- pass on dat_bit_cnt via DP empty field v.src_out.empty := INCR_UVEC(v.hold_out.empty, c_in_buf_dat_w - v.dat_bit_cnt); @@ -361,7 +367,7 @@ BEGIN -------------------------------------------------------------------------- -- Wired output i_src_out <= r.src_out; - + src_out_data <= r.src_out_data; -------------------------------------------------------------------------- -- Flow control @@ -403,6 +409,7 @@ ENTITY dp_repack_out IS snk_out : OUT t_dp_siso; snk_in : IN t_dp_sosi; + snk_in_data : IN STD_LOGIC_VECTOR(g_in_buf_dat_w-1 DOWNTO 0); src_in : IN t_dp_siso; src_out : OUT t_dp_sosi @@ -437,7 +444,7 @@ ARCHITECTURE rtl OF dp_repack_out IS SIGNAL nxt_r : t_reg; -- Debug signals - SIGNAL snk_in_data : STD_LOGIC_VECTOR(g_in_buf_dat_w-1 DOWNTO 0); + SIGNAL i_src_out_data : STD_LOGIC_VECTOR(g_in_buf_dat_w-1 DOWNTO 0); SIGNAL i_src_out : t_dp_sosi; SIGNAL src_out_data : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); @@ -451,10 +458,8 @@ ARCHITECTURE rtl OF dp_repack_out IS BEGIN - snk_in_data <= snk_in.data(g_in_buf_dat_w-1 DOWNTO 0); - src_out <= i_src_out; - src_out_data <= i_src_out.data(g_out_dat_w-1 DOWNTO 0); + src_out_data <= i_src_out_data(g_out_dat_w-1 DOWNTO 0); gen_bypass : IF g_bypass=TRUE GENERATE snk_out <= src_in; @@ -463,11 +468,11 @@ BEGIN BEGIN i_src_out <= snk_in; IF c_snk_in_dat_lo>0 THEN - i_src_out.data <= SHIFT_UVEC(snk_in.data, c_snk_in_dat_lo); + i_src_out_data <= SHIFT_UVEC(snk_in_data, c_snk_in_dat_lo); i_src_out.empty <= INCR_UVEC( snk_in.empty, -c_snk_in_dat_lo); END IF; IF c_out_buf_dat_lo>0 THEN - i_src_out.data <= SHIFT_UVEC(snk_in.data, -c_out_buf_dat_lo); + i_src_out_data <= SHIFT_UVEC(snk_in_data, -c_out_buf_dat_lo); i_src_out.empty <= INCR_UVEC( snk_in.empty, c_out_buf_dat_lo); END IF; END PROCESS; @@ -605,7 +610,7 @@ BEGIN -------------------------------------------------------------------------- -- Wires - data_vec(c_out_buf_dat_w-1 DOWNTO c_out_buf_dat_lo) <= snk_in.data(g_in_buf_dat_w-1 DOWNTO c_snk_in_dat_lo); + data_vec(c_out_buf_dat_w-1 DOWNTO c_out_buf_dat_lo) <= snk_in_data(g_in_buf_dat_w-1 DOWNTO c_snk_in_dat_lo); -------------------------------------------------------------------------- -- Wired output @@ -707,12 +712,12 @@ BEGIN src_out <= i_src_out; snk_in_data <= i_snk_in.data(g_in_dat_w-1 DOWNTO 0); - pack_sosi_data <= pack_sosi.data(c_in_buf_dat_w-1 DOWNTO 0); src_out_data <= i_src_out.data(g_out_dat_w-1 DOWNTO 0); no_dp_repack_in : IF g_enable_repack_in=FALSE GENERATE i_snk_out <= pack_siso; pack_sosi <= i_snk_in; + pack_sosi_data <= RESIZE_UVEC(snk_in_data, c_in_buf_dat_w); END GENERATE; gen_dp_repack_in : IF g_enable_repack_in=TRUE GENERATE @@ -731,7 +736,8 @@ BEGIN snk_in => i_snk_in, src_in => pack_siso, - src_out => pack_sosi + src_out => pack_sosi, + src_out_data => pack_sosi_data ); END GENERATE; @@ -755,6 +761,7 @@ BEGIN snk_out => pack_siso, snk_in => pack_sosi, + snk_in_data => pack_sosi_data, src_in => src_in, src_out => i_src_out diff --git a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd index ecd2e6b6fea23856b16269dfba6fa2203f4f6eb3..b57aeab0eddc8f2df392ea50b10793b4db089a45 100644 --- a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd +++ b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd @@ -49,12 +49,12 @@ PACKAGE dp_stream_pkg Is -- This grouping is useful for functions that operate on a t_dp_sosi signal. -- * The info fields are valid at the sop or at the eop, but typically they hold their last active value to avoid unnessary -- toggling and to ease viewing in the wave window. - CONSTANT c_dp_stream_bsn_w : NATURAL := 64; -- 64 is sufficient to count blocks of data for years - CONSTANT c_dp_stream_data_w : NATURAL := 768; -- 72 is sufficient for max word 8 * 9-bit. 576 supports half rate DDR4 bus data width. The current 768 is enough for wide single clock SLVs (e.g. headers) - CONSTANT c_dp_stream_dsp_data_w : NATURAL := 64; -- 64 is sufficient for DSP data, including complex power accumulates - CONSTANT c_dp_stream_empty_w : NATURAL := 16; -- 8 is sufficient for max 256 symbols per data word, still use 16 bit to be able to count c_dp_stream_data_w in bits - CONSTANT c_dp_stream_channel_w : NATURAL := 32; -- 32 is sufficient for several levels of hierarchy in mapping types of streams on to channels - CONSTANT c_dp_stream_error_w : NATURAL := 32; -- 32 is sufficient for several levels of hierarchy in mapping error numbers, e.g. 32 different one-hot encoded errors, bit [0] = 0 = OK + CONSTANT c_dp_stream_bsn_w : NATURAL := 64; -- 64 is sufficient to count blocks of data for years + CONSTANT c_dp_stream_data_w : NATURAL := 1024; -- 72 is sufficient for max word 8 * 9-bit. 576 supports half rate DDR4 bus data width. The current 1024 is enough for wide single clock SLVs (e.g. headers) + CONSTANT c_dp_stream_dsp_data_w : NATURAL := 64; -- 64 is sufficient for DSP data, including complex power accumulates + CONSTANT c_dp_stream_empty_w : NATURAL := 16; -- 8 is sufficient for max 256 symbols per data word, still use 16 bit to be able to count c_dp_stream_data_w in bits + CONSTANT c_dp_stream_channel_w : NATURAL := 32; -- 32 is sufficient for several levels of hierarchy in mapping types of streams on to channels + CONSTANT c_dp_stream_error_w : NATURAL := 32; -- 32 is sufficient for several levels of hierarchy in mapping error numbers, e.g. 32 different one-hot encoded errors, bit [0] = 0 = OK CONSTANT c_dp_stream_ok : NATURAL := 0; -- SOSI err field OK value CONSTANT c_dp_stream_err : NATURAL := 1; -- SOSI err field error value /= OK diff --git a/libraries/base/dp/src/vhdl/mms_dp_split.vhd b/libraries/base/dp/src/vhdl/mms_dp_split.vhd index 8dc4c80b0595d99e0df1dd2873828901e743c4b6..08e4fe056c0ed205e5d0cee7dee1efb26bbb83dc 100644 --- a/libraries/base/dp/src/vhdl/mms_dp_split.vhd +++ b/libraries/base/dp/src/vhdl/mms_dp_split.vhd @@ -50,7 +50,9 @@ ENTITY mms_dp_split IS snk_in_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- ST source src_in_2arr : IN t_dp_siso_2arr_2(g_nof_streams-1 DOWNTO 0); - src_out_2arr : OUT t_dp_sosi_2arr_2(g_nof_streams-1 DOWNTO 0) + src_out_2arr : OUT t_dp_sosi_2arr_2(g_nof_streams-1 DOWNTO 0); + + out_nof_symbols : OUT t_natural_arr(g_nof_streams-1 DOWNTO 0) ); END mms_dp_split; @@ -82,6 +84,8 @@ BEGIN gen_stream : FOR i IN 0 TO g_nof_streams-1 GENERATE + out_nof_symbols(i) <= TO_UINT(nof_symbols(i)); + u_reg : ENTITY work.dp_split_reg GENERIC MAP ( g_nof_symbols => g_nof_symbols_max diff --git a/libraries/io/eth/hdllib.cfg b/libraries/io/eth/hdllib.cfg index 7553f16f0752b47e1202d15547d9f7d39635ad0a..909d905bed2e804092d562c2646aefd752c37d4b 100644 --- a/libraries/io/eth/hdllib.cfg +++ b/libraries/io/eth/hdllib.cfg @@ -1,6 +1,6 @@ hdl_lib_name = eth hdl_library_clause_name = eth_lib -hdl_lib_uses_synth = dp common diag tech_tse axi4 +hdl_lib_uses_synth = dp common diag tech_tse hdl_lib_uses_sim = hdl_lib_technology = @@ -28,7 +28,6 @@ synth_files = src/vhdl/eth_tester_tx.vhd src/vhdl/eth_tester_rx.vhd src/vhdl/eth_tester.vhd - src/vhdl/eth_tester_vivado_ip_wrapper.vhd test_bench_files = src/vhdl/eth_statistics.vhd @@ -38,9 +37,11 @@ test_bench_files = tb/vhdl/tb_eth.vhd tb/vhdl/tb_eth_tester_pkg.vhd tb/vhdl/tb_eth_tester.vhd + tb/vhdl/tb_eth_tester_high_bw.vhd tb/vhdl/tb_eth_stream_udp.vhd tb/vhdl/tb_tb_eth.vhd tb/vhdl/tb_tb_eth_tester.vhd + tb/vhdl/tb_tb_eth_tester_high_bw.vhd tb/vhdl/tb_tb_eth_stream_udp.vhd tb/vhdl/tb_eth_udp_offload.vhd tb/vhdl/tb_eth_ihl_to_20.vhd @@ -54,6 +55,7 @@ regression_test_vhdl = tb/vhdl/tb_eth_ihl_to_20.vhd tb/vhdl/tb_tb_eth.vhd tb/vhdl/tb_tb_eth_tester.vhd + tb/vhdl/tb_tb_eth_tester_high_bw.vhd tb/vhdl/tb_tb_eth_stream_udp.vhd diff --git a/libraries/io/eth/src/vhdl/eth_tester.vhd b/libraries/io/eth/src/vhdl/eth_tester.vhd index e6253bb87bd4c786fa8ed39d676775e9d17cb485..4b3b4ce3448975529ce77e04482f867e7cd01777 100644 --- a/libraries/io/eth/src/vhdl/eth_tester.vhd +++ b/libraries/io/eth/src/vhdl/eth_tester.vhd @@ -28,6 +28,7 @@ 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 dp_lib.dp_components_pkg.ALL; @@ -37,10 +38,16 @@ USE work.eth_tester_pkg.ALL; ENTITY eth_tester IS GENERIC ( - g_nof_streams : NATURAL := 1; - g_bg_sync_timeout : NATURAL := c_eth_tester_sync_timeout; - g_remove_crc : BOOLEAN := TRUE -- use TRUE when using sim_tse and tech_tse link interface, - -- use FALSE when streaming link interface + g_nof_streams : NATURAL := 1; + g_bg_sync_timeout : NATURAL := c_eth_tester_sync_timeout; + g_nof_octet_generate : NATURAL := 1; + g_nof_octet_output : NATURAL := 4; -- must be multiple of g_nof_octet_generate. + g_use_network_header : BOOLEAN := TRUE; + g_use_dp_header : BOOLEAN := TRUE; + g_hdr_field_arr : t_common_field_arr := c_eth_tester_hdr_field_arr; + g_hdr_field_sel : STD_LOGIC_VECTOR := c_eth_tester_hdr_field_sel; + g_remove_crc : BOOLEAN := TRUE -- use TRUE when using sim_tse and tech_tse link interface, + -- use FALSE when streaming link interface ); PORT ( -- Clocks and reset @@ -73,6 +80,8 @@ ENTITY eth_tester IS reg_bsn_monitor_v2_tx_cipo : OUT t_mem_cipo; reg_strobe_total_count_tx_copi : IN t_mem_copi := c_mem_copi_rst; reg_strobe_total_count_tx_cipo : OUT t_mem_cipo; + reg_dp_split_copi : IN t_mem_copi := c_mem_copi_rst; + reg_dp_split_cipo : OUT t_mem_cipo; -- . Rx reg_bsn_monitor_v2_rx_copi : IN t_mem_copi := c_mem_copi_rst; reg_bsn_monitor_v2_rx_cipo : OUT t_mem_cipo; @@ -84,6 +93,8 @@ END eth_tester; ARCHITECTURE str OF eth_tester IS + CONSTANT c_dp_split_reg_adr_w : NATURAL := 1; -- 1 for 1 stream in dp_split + 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 @@ -98,6 +109,8 @@ ARCHITECTURE str OF eth_tester IS 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); + SIGNAL reg_dp_split_copi_arr : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_mem_copi_rst); + SIGNAL reg_dp_split_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); @@ -109,7 +122,13 @@ BEGIN 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 + g_bg_sync_timeout => g_bg_sync_timeout, + g_nof_octet_generate => g_nof_octet_generate, + g_nof_octet_output => g_nof_octet_output, + g_use_network_header => g_use_network_header, + g_use_dp_header => g_use_dp_header, + g_hdr_field_arr => g_hdr_field_arr, + g_hdr_field_sel => g_hdr_field_sel ) PORT MAP ( -- Clocks and reset @@ -139,12 +158,18 @@ BEGIN 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) + reg_strobe_total_count_tx_cipo => reg_strobe_total_count_tx_cipo_arr(I), + reg_dp_split_copi => reg_dp_split_copi_arr(I), + reg_dp_split_cipo => reg_dp_split_cipo_arr(I) ); u_rx : ENTITY work.eth_tester_rx GENERIC MAP ( g_bg_sync_timeout => g_bg_sync_timeout, + g_nof_octet_unpack => g_nof_octet_generate, + g_nof_octet_input => g_nof_octet_output, + g_use_dp_header => g_use_dp_header, + g_hdr_field_arr => g_hdr_field_arr, g_remove_crc => g_remove_crc ) PORT MAP ( @@ -221,6 +246,18 @@ BEGIN miso_arr => reg_strobe_total_count_tx_cipo_arr ); + u_common_mem_mux_dp_split : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => c_dp_split_reg_adr_w + ) + PORT MAP ( + mosi => reg_dp_split_copi, + miso => reg_dp_split_cipo, + mosi_arr => reg_dp_split_copi_arr, + miso_arr => reg_dp_split_cipo_arr + ); + -- Rx u_common_mem_mux_bsn_monitor_v2_rx : ENTITY common_lib.common_mem_mux GENERIC MAP ( diff --git a/libraries/io/eth/src/vhdl/eth_tester_rx.vhd b/libraries/io/eth/src/vhdl/eth_tester_rx.vhd index 982054836a1dd884878c733548be96fc41ee054e..acaf31d8d3eec327626ddee2fedd3bdedd3c5fe3 100644 --- a/libraries/io/eth/src/vhdl/eth_tester_rx.vhd +++ b/libraries/io/eth/src/vhdl/eth_tester_rx.vhd @@ -38,6 +38,10 @@ USE work.eth_tester_pkg.ALL; ENTITY eth_tester_rx IS GENERIC ( g_bg_sync_timeout : NATURAL := 220*10**6; -- 10% margin for nominal 1 s with st_clk at 200MHz + g_nof_octet_unpack : NATURAL := 1; + g_nof_octet_input : NATURAL := 4; -- must be multiple of g_nof_octet_generate + g_use_dp_header : BOOLEAN := TRUE; + g_hdr_field_arr : t_common_field_arr := c_eth_tester_hdr_field_arr; g_remove_crc : BOOLEAN := TRUE -- use TRUE when using sim_tse and tech_tse link interface, -- use FALSE when streaming link interface ); @@ -67,14 +71,17 @@ ARCHITECTURE str OF eth_tester_rx IS CONSTANT c_nof_total_counts : NATURAL := 3; -- 0 = nof_sop, 1 = nof_valid, 2 = nof_crc_corrupt - CONSTANT c_empty_w : NATURAL := 2; -- for 0, 1, 2, 3 empty octets per word + CONSTANT c_empty_w : NATURAL := ceil_log2(g_nof_octet_input); CONSTANT c_error_w : NATURAL := 1; + CONSTANT c_in_data_w : NATURAL := g_nof_octet_input * c_octet_w; + CONSTANT c_repack_data_w : NATURAL := g_nof_octet_unpack * c_octet_w; + CONSTANT c_nof_repack_words : NATURAL := g_nof_octet_input / g_nof_octet_unpack; -- Rx FIFO size can be much less than rx_block_sz_max, because st_clk > -- eth_clk rate, but with st level tx-rx loopback the Rx FIFO does need -- rx_block_sz_max FIFO size. - CONSTANT rx_block_sz_max : NATURAL := c_eth_tester_rx_block_len_max / c_word_sz; -- = 9004 / 4 = 2251 - CONSTANT c_fifo_size : NATURAL := true_log_pow2(rx_block_sz_max); -- = 4096 words + CONSTANT rx_block_sz_max : NATURAL := ceil_div(c_eth_tester_rx_block_len_max, g_nof_octet_input); + CONSTANT c_fifo_size : NATURAL := true_log_pow2(rx_block_sz_max); SIGNAL rx_udp_data : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); SIGNAL rx_offload_sosi : t_dp_sosi; @@ -114,9 +121,9 @@ BEGIN u_dp_offload_rx : ENTITY dp_lib.dp_offload_rx GENERIC MAP ( g_nof_streams => 1, - g_data_w => c_word_w, + g_data_w => c_in_data_w, g_symbol_w => c_octet_w, - g_hdr_field_arr => c_eth_tester_hdr_field_arr, + g_hdr_field_arr => g_hdr_field_arr, g_remove_crc => g_remove_crc, g_crc_nof_words => 1 ) @@ -141,9 +148,11 @@ 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"))); + IF g_use_dp_header THEN + 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 IF; -- Map rx_offload_sosi.err c_tech_tse_error_w = 6 bit value on to c_error_w = 1 bit decoded_sosi.err value decoded_sosi.err <= TO_DP_ERROR(0); IF UNSIGNED(rx_offload_sosi.err(c_tech_tse_error_w-1 DOWNTO 0)) /= 0 THEN @@ -155,7 +164,7 @@ BEGIN p_verify_length : PROCESS(st_clk) BEGIN IF rising_edge(st_clk) THEN - IF decoded_sosi.sop = '1' THEN + IF g_use_dp_header AND 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; @@ -164,7 +173,7 @@ BEGIN u_rx_fifo : ENTITY dp_lib.dp_fifo_sc GENERIC MAP ( - g_data_w => c_word_w, + g_data_w => c_in_data_w, g_bsn_w => c_diag_bg_bsn_init_w, -- = 64 bit g_empty_w => c_empty_w, g_error_w => c_error_w, @@ -187,13 +196,13 @@ BEGIN src_out => rx_fifo_sosi ); - u_unpack : ENTITY dp_lib.dp_repack_data -- unpack 32b words into 8b octets + u_unpack : ENTITY dp_lib.dp_repack_data GENERIC MAP ( - g_in_dat_w => c_word_w, -- = 32 + g_in_dat_w => c_in_data_w, g_in_nof_words => 1, g_in_symbol_w => c_octet_w, - g_out_dat_w => c_octet_w, -- = 8 - g_out_nof_words => c_word_sz, -- = 4 + g_out_dat_w => c_repack_data_w, + g_out_nof_words => c_nof_repack_words, g_out_symbol_w => c_octet_w ) PORT MAP ( @@ -240,7 +249,7 @@ BEGIN END PROCESS; in_strobe_arr(0) <= unpacked_sosi.sop; -- count total nof Rx packets - in_strobe_arr(1) <= unpacked_sosi.valid; -- count total nof Rx valid octets + in_strobe_arr(1) <= unpacked_sosi.valid; -- count total nof Rx valid samples in_strobe_arr(2) <= crc_corrupt; -- count total nof corrupted Rx packets u_dp_strobe_total_count : ENTITY dp_lib.dp_strobe_total_count diff --git a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd index a110e63720b8dd841afff9b5af9d8c3fbd52d844..c63c25fccd12554350afdf08f252c76d6b436974 100644 --- a/libraries/io/eth/src/vhdl/eth_tester_tx.vhd +++ b/libraries/io/eth/src/vhdl/eth_tester_tx.vhd @@ -17,12 +17,21 @@ -- limitations under the License. -- ------------------------------------------------------------------------------- --- AUthor: E. Kooistra +-- AUthor: E. Kooistra, R. vd Walle -- Purpose: Test the 1GbE interface by sending and counting received packets. -- Description: Tx part of eth_tester, see detailed design in [1] -- -- References: -- [1] https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+ETH+tester+unit+for+1GbE +-- +-- Remarks: +-- . g_nof_octet_generate can be set to increase the amount of bytes generated +-- per clock cycle by the BG. This is done by duplicating the one byte +-- g_nof_octet_generate times using a generate statement. +-- . g_nof_octet_output determines the output data width, e.g. +-- when set to 4, the output sosi containis 4 * 8 = 32 bits of generated data. +-- This should be the same or a multiple of g_nof_octet_generate such that +-- it can be repacked. LIBRARY IEEE, common_lib, dp_lib, diag_lib; USE IEEE.std_logic_1164.ALL; @@ -36,7 +45,14 @@ USE work.eth_tester_pkg.ALL; ENTITY eth_tester_tx IS GENERIC ( - g_bg_sync_timeout : NATURAL := 220*10**6 -- 10% margin for nominal 1 s with st_clk at 200MHz + g_bg_sync_timeout : NATURAL := 220*10**6; -- 10% margin for nominal 1 s with st_clk at 200MHz + g_nof_octet_generate : NATURAL := 1; + g_nof_octet_output : NATURAL := 4; -- must be multiple of g_nof_octet_generate + g_use_network_header : BOOLEAN := TRUE; + g_use_dp_header : BOOLEAN := TRUE; + g_hdr_field_arr : t_common_field_arr := c_eth_tester_hdr_field_arr; + g_hdr_field_sel : STD_LOGIC_VECTOR := c_eth_tester_hdr_field_sel + ); PORT ( -- Clocks and reset @@ -66,36 +82,48 @@ ENTITY eth_tester_tx IS reg_bsn_monitor_v2_tx_copi : IN t_mem_copi := c_mem_copi_rst; reg_bsn_monitor_v2_tx_cipo : OUT t_mem_cipo; reg_strobe_total_count_tx_copi : IN t_mem_copi := c_mem_copi_rst; - reg_strobe_total_count_tx_cipo : OUT t_mem_cipo + reg_strobe_total_count_tx_cipo : OUT t_mem_cipo; + reg_dp_split_copi : IN t_mem_copi := c_mem_copi_rst; + reg_dp_split_cipo : OUT t_mem_cipo ); END eth_tester_tx; ARCHITECTURE str OF eth_tester_tx IS - CONSTANT c_empty_w : NATURAL := 2; -- for 0, 1, 2, 3 empty octets per word + CONSTANT c_empty_w : NATURAL := ceil_log2(g_nof_octet_output); -- 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_packet_sz_max : NATURAL := ceil_div(c_eth_tester_bg_block_len_max, c_word_sz); + CONSTANT c_packet_sz_max : NATURAL := ceil_div(c_eth_tester_bg_block_len_max, g_nof_octet_output); CONSTANT c_fifo_fill : NATURAL := c_packet_sz_max * 11 / 10; - CONSTANT c_fifo_size : NATURAL := true_log_pow2(c_fifo_fill + c_packet_sz_max); -- = 8192 + CONSTANT c_fifo_size : NATURAL := true_log_pow2(c_fifo_fill + c_packet_sz_max); CONSTANT c_fifo_size_w : NATURAL := ceil_log2(c_fifo_size); CONSTANT c_nof_total_counts : NATURAL := 1; -- one to count Tx packets + CONSTANT c_nof_repack_words : NATURAL := g_nof_octet_output / g_nof_octet_generate; -- yields integer as g_nof_octet_output is multiple of g_nof_octet_generate. + CONSTANT c_generate_data_w : NATURAL := g_nof_octet_generate * c_octet_w; + CONSTANT c_out_data_w : NATURAL := g_nof_octet_output * c_octet_w; + CONSTANT c_nof_symbols_max : NATURAL := c_network_eth_payload_jumbo_max; + CONSTANT c_use_split : BOOLEAN := sel_a_b(g_nof_octet_generate > 1, TRUE, FALSE); + SIGNAL ip_total_length : NATURAL; 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 in_split_sosi : t_dp_sosi; + SIGNAL in_split_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL out_split_sosi_arr : t_dp_sosi_arr(1 DOWNTO 0); + SIGNAL out_split_siso_arr : t_dp_siso_arr(1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + SIGNAL split_nof_symbols : NATURAL; SIGNAL bg_data : STD_LOGIC_VECTOR(c_octet_w-1 DOWNTO 0); SIGNAL bg_ctrl_hold : t_diag_block_gen; SIGNAL bg_block_len : NATURAL; - SIGNAL tx_packed_siso : t_dp_siso; SIGNAL tx_packed_sosi : t_dp_sosi; SIGNAL tx_packed_data : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); SIGNAL tx_fifo_sosi : t_dp_sosi; @@ -138,30 +166,40 @@ BEGIN GENERIC MAP ( g_nof_streams => 1, g_use_bg_buffer_ram => FALSE, - g_buf_addr_w => c_diag_bg_mem_adrs_w -- = 24, use full range 2**24 for BG addr --> data values + g_buf_addr_w => c_diag_bg_mem_adrs_w, -- = 24, use full range 2**24 for BG addr --> data values + g_buf_dat_w => c_octet_w ) 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_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, + 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_hold_arr(0) => bg_ctrl_hold, - out_sosi_arr(0) => bg_sosi, - out_siso_arr(0) => bg_siso + bg_ctrl_hold_arr(0) => bg_ctrl_hold, + out_sosi_arr(0) => bg_sosi, + out_siso_arr(0) => bg_siso ); + -- Duplicate bg_sosi.data g_nof_octets_generate times + p_duplicate : PROCESS(bg_sosi) + BEGIN + in_split_sosi <= bg_sosi; + FOR I IN 0 TO g_nof_octet_generate-1 LOOP + in_split_sosi.data((I+1) * c_octet_w-1 DOWNTO I * c_octet_w) <= bg_sosi.data(c_octet_w-1 DOWNTO 0); + END LOOP; + END PROCESS; + -- BG clock level flow control, needed when the dp_repack_data has to insert -- empty octets into the last packed word. - bg_siso.ready <= tx_packed_siso.ready; + bg_siso.ready <= in_split_siso.ready; -- BG block level flow control, needed in case BG settings result in eth bit - -- rate > 1 Gbps, to avoid u_tx_fifo overflow. + -- rate larger than the rated ethernet output speed, to avoid u_tx_fifo overflow. p_bg_siso_xon : PROCESS(st_rst, st_clk) BEGIN IF st_rst = '1' THEN @@ -174,26 +212,59 @@ BEGIN END IF; END PROCESS; - u_pack : ENTITY dp_lib.dp_repack_data -- pack 8b octets into 32b words + -- Use dp_split to make fine packet length adjustment on octet level. + -- dp_split sets the empty field to indicate the unused bytes in the last word. + gen_split : IF c_use_split GENERATE + u_mms_dp_split : ENTITY dp_lib.mms_dp_split + GENERIC MAP ( + g_data_w => c_generate_data_w, + g_symbol_w => c_octet_w, + g_nof_symbols_max => c_nof_symbols_max + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => st_rst, + dp_clk => st_clk, + + reg_mosi => reg_dp_split_copi, + reg_miso => reg_dp_split_cipo, + + snk_in_arr(0) => in_split_sosi, + snk_out_arr(0) => in_split_siso, + + src_in_2arr(0) => out_split_siso_arr, + src_out_2arr(0) => out_split_sosi_arr, + + out_nof_symbols(0) => split_nof_symbols + ); + END GENERATE; + + gen_no_split : IF NOT c_use_split GENERATE + out_split_sosi_arr(1) <= in_split_sosi; + in_split_siso <= out_split_siso_arr(1); + END GENERATE; + + u_pack : ENTITY dp_lib.dp_repack_data -- repack generated words to output width. GENERIC MAP ( - g_in_dat_w => c_octet_w, -- = 8 - g_in_nof_words => c_word_sz, -- = 4 + g_in_dat_w => c_generate_data_w, + g_in_nof_words => c_nof_repack_words, g_in_symbol_w => c_octet_w, - g_out_dat_w => c_word_w, -- = 32 + g_out_dat_w => c_out_data_w, g_out_nof_words => 1, g_out_symbol_w => c_octet_w ) PORT MAP ( rst => st_rst, clk => st_clk, - snk_out => tx_packed_siso, - snk_in => bg_sosi, + snk_out => out_split_siso_arr(1), -- connect dp_split head part, tail is discarded. + snk_in => out_split_sosi_arr(1), src_out => tx_packed_sosi ); u_tx_fifo : ENTITY dp_lib.dp_fifo_fill_eop GENERIC MAP ( - g_data_w => c_word_w, + g_data_w => c_out_data_w, g_bsn_w => c_diag_bg_bsn_init_w, -- = 64 bit g_empty_w => c_empty_w, g_use_bsn => TRUE, @@ -262,19 +333,24 @@ BEGIN -- The bg_block_len is still valid because bg_ctrl_hold holds the BG settings -- until it restarts, so no need to pass bg_block_len on via e.g. the channel -- field in u_fifo. - bg_block_len <= TO_UINT(bg_ctrl_hold.samples_per_packet(15 DOWNTO 0)); -- packet lenghts fit in 16b + bg_block_len <= split_nof_symbols WHEN c_use_split ELSE 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 <= 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); - 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; + gen_network_header : IF g_use_network_header GENERATE + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(g_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac; + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "ip_total_length" ) DOWNTO field_lo(g_hdr_field_arr, "ip_total_length" )) <= TO_UVEC(ip_total_length, 16); + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(g_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr; + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "udp_src_port" ) DOWNTO field_lo(g_hdr_field_arr, "udp_src_port" )) <= udp_src_port; + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "udp_total_length") DOWNTO field_lo(g_hdr_field_arr, "udp_total_length")) <= TO_UVEC(udp_total_length, 16); + END GENERATE; + + gen_dp_header : IF g_use_dp_header GENERATE + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "dp_length" ) DOWNTO field_lo(g_hdr_field_arr, "dp_length" )) <= TO_UVEC(app_total_length, 16); + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "dp_sync" ) DOWNTO field_lo(g_hdr_field_arr, "dp_sync" )) <= slv(tx_fifo_sosi.sync); + hdr_fields_slv_in(field_hi(g_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(g_hdr_field_arr, "dp_bsn" )) <= tx_fifo_sosi.bsn; + END GENERATE; ------------------------------------------------------------------------------- -- Tx ETH/UDP/IP packets with packed BG data @@ -282,10 +358,10 @@ BEGIN u_dp_offload_tx : ENTITY dp_lib.dp_offload_tx_v3 GENERIC MAP ( g_nof_streams => 1, - g_data_w => c_word_w, + g_data_w => c_out_data_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_hdr_field_arr => g_hdr_field_arr, + g_hdr_field_sel => g_hdr_field_sel, g_pipeline_ready => TRUE ) PORT MAP ( diff --git a/libraries/io/eth/tb/vhdl/tb_eth_tester_high_bw.vhd b/libraries/io/eth/tb/vhdl/tb_eth_tester_high_bw.vhd new file mode 100644 index 0000000000000000000000000000000000000000..0e0e07b7573188da65791687e9a4e6a567a1b270 --- /dev/null +++ b/libraries/io/eth/tb/vhdl/tb_eth_tester_high_bw.vhd @@ -0,0 +1,527 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2023 +-- 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: R. vd Walle +-- Purpose: Test bench for eth_tester using high bandwidth generic configuration +-- Description: Similar to the 1GbE testbench [1] for the eth tester but using generic +-- values for usage with high bandwidth, e.g. 10 / 100 GbE. +-- The g_nof_streams >= 1 are tested independently, using g_bg_ctrl_first for +-- BG in stream 0 and g_bg_ctrl_others for all other streams. +-- +-- Usage: +-- > as 8 +-- # * E.g. view sosi/data signals in dut/gen_streams/u_rx and u_tx +-- > 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, technology_lib, tech_tse_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 dp_lib.dp_components_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; +USE technology_lib.technology_select_pkg.ALL; +USE tech_tse_lib.tech_tse_pkg.ALL; +USE tech_tse_lib.tb_tech_tse_pkg.ALL; + +ENTITY tb_eth_tester_high_bw 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_nof_streams : NATURAL := 1; + g_nof_octet_output : NATURAL := 96; -- maximum = 96 bytes as max dp.data field = 768 bits. + g_nof_octet_generate : NATURAL := 96; + + -- 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_first : t_diag_block_gen_integer := ('1', '1', 500, 3, 200, 0, c_diag_bg_mem_max_adr, 0); -- for first stream + g_bg_ctrl_others : t_diag_block_gen_integer := ('1', '1', 300, 3, 10, 0, c_diag_bg_mem_max_adr, 0) -- for other streams + ); + PORT ( + tb_end : OUT STD_LOGIC + ); +END tb_eth_tester_high_bw; + + +ARCHITECTURE tb OF tb_eth_tester_high_bw 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_first : NATURAL := ceil_div(g_bg_ctrl_first.samples_per_packet, g_nof_octet_generate); + CONSTANT c_bg_block_len_others : NATURAL := ceil_div(g_bg_ctrl_others.samples_per_packet, g_nof_octet_generate); + CONSTANT c_bg_block_len_max : NATURAL := largest(c_bg_block_len_first, c_bg_block_len_others); + + CONSTANT c_bg_slot_len_first : NATURAL := c_bg_block_len_first + g_bg_ctrl_first.gapsize; + CONSTANT c_bg_slot_len_others : NATURAL := c_bg_block_len_others + g_bg_ctrl_others.gapsize; + CONSTANT c_bg_slot_len_max : NATURAL := largest(c_bg_slot_len_first, c_bg_slot_len_others); + + CONSTANT c_eth_packet_len_first : NATURAL := func_eth_tester_eth_packet_length(c_bg_block_len_first); + CONSTANT c_eth_packet_len_others : NATURAL := func_eth_tester_eth_packet_length(c_bg_block_len_others); + + -- Use REAL to avoid NATURAL overflow in bps calculation + CONSTANT c_bg_nof_bps_first : REAL := REAL(c_bg_block_len_first * c_octet_w) * REAL(c_nof_st_clk_per_s) / REAL(c_bg_slot_len_first); + CONSTANT c_bg_nof_bps_others : REAL := REAL(c_bg_block_len_others * c_octet_w) * REAL(c_nof_st_clk_per_s) / REAL(c_bg_slot_len_others); + CONSTANT c_bg_nof_bps_total : REAL := c_bg_nof_bps_first + REAL(g_nof_streams - 1) * c_bg_nof_bps_others; + + CONSTANT c_bg_sync_period_first : NATURAL := c_bg_slot_len_first * g_bg_ctrl_first.blocks_per_sync; + CONSTANT c_bg_sync_period_others : NATURAL := c_bg_slot_len_others * g_bg_ctrl_others.blocks_per_sync; + CONSTANT c_bg_sync_period_max : NATURAL := largest(c_bg_sync_period_first, c_bg_sync_period_others); + + CONSTANT c_run_time : NATURAL := g_nof_sync * c_bg_sync_period_max; + CONSTANT c_nof_sync_first : NATURAL := c_run_time / c_bg_sync_period_first; + CONSTANT c_nof_sync_others : NATURAL := c_run_time / c_bg_sync_period_others; + + -- 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_max >= 50; + CONSTANT c_rx_exp_latency_st : NATURAL := 19; + + -- CRC is added by Tx TSE IP and removed by dp_offload_rx when g_remove_crc = + -- g_loopback_eth = TRUE. Therefore internally only application payload + -- (= block_len) octets are counted. + CONSTANT c_nof_valid_per_packet_first : NATURAL := c_bg_block_len_first; + CONSTANT c_nof_valid_per_packet_others : NATURAL := c_bg_block_len_others; + + CONSTANT c_total_count_nof_valid_per_sync_first : NATURAL := g_bg_ctrl_first.blocks_per_sync * c_nof_valid_per_packet_first; + CONSTANT c_total_count_nof_valid_per_sync_others : NATURAL := g_bg_ctrl_others.blocks_per_sync * c_nof_valid_per_packet_others; + + CONSTANT c_mon_nof_sop_first : NATURAL := g_bg_ctrl_first.blocks_per_sync; + CONSTANT c_mon_nof_sop_others : NATURAL := g_bg_ctrl_others.blocks_per_sync; + CONSTANT c_mon_nof_valid_first_tx : NATURAL := c_mon_nof_sop_first * ceil_div(c_bg_block_len_first * g_nof_octet_generate, g_nof_octet_output); + CONSTANT c_mon_nof_valid_first_rx : NATURAL := c_mon_nof_sop_first * c_nof_valid_per_packet_first; + CONSTANT c_mon_nof_valid_others_tx : NATURAL := c_mon_nof_sop_others * ceil_div(c_bg_block_len_others * g_nof_octet_generate, g_nof_octet_output); + CONSTANT c_mon_nof_valid_others_rx : NATURAL := c_mon_nof_sop_others * c_nof_valid_per_packet_others; + + -- 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 i_tb_end : STD_LOGIC := '0'; + + -- Use same bg_ctrl for all others streams, this provides sufficient test coverage + SIGNAL bg_ctrl_arr : t_diag_block_gen_integer_arr(g_nof_streams-1 DOWNTO 0); + + SIGNAL tx_fifo_rd_emp_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + + -- ETH UDP data path interface + 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_dp_split_copi : t_mem_copi := c_mem_copi_rst; + SIGNAL reg_dp_split_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_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_total_count_nof_packet_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL exp_total_count_nof_packet_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); -- same for both tx and rx + + SIGNAL rx_total_count_nof_valid_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_exp_total_count_nof_valid_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + + SIGNAL rx_total_count_nof_corrupted_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_exp_total_count_nof_corrupted_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + + -- . reg_bsn_monitor_v2 + SIGNAL tx_mon_nof_sop_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL tx_mon_nof_valid_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL tx_mon_latency_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_mon_nof_sop_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_mon_nof_valid_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL rx_mon_latency_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + + -- View in Wave window + SIGNAL dbg_c_run_time : NATURAL := c_run_time; + SIGNAL dbg_c_mon_nof_sop_first : NATURAL := c_mon_nof_sop_first; + SIGNAL dbg_c_mon_nof_sop_others : NATURAL := c_mon_nof_sop_others; + SIGNAL dbg_c_mon_nof_valid_first_tx : NATURAL := c_mon_nof_valid_first_tx; + SIGNAL dbg_c_mon_nof_valid_first_rx : NATURAL := c_mon_nof_valid_first_rx; + SIGNAL dbg_c_mon_nof_valid_others_tx : NATURAL := c_mon_nof_valid_others_tx; + SIGNAL dbg_c_mon_nof_valid_others_rx : NATURAL := c_mon_nof_valid_others_rx; + +BEGIN + + tb_end <= i_tb_end; + + mm_clk <= (NOT mm_clk) OR i_tb_end AFTER mm_clk_period/2; + st_clk <= (NOT st_clk) OR i_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; + + -- Using + --SIGNAL exp_total_count_nof_packet_arr : t_natural_arr(g_nof_streams-1 DOWNTO 0); + -- (g_nof_streams-1 DOWNTO 1 => g_nof_sync * g_bg_ctrl_others.blocks_per_sync, + -- 0 => g_nof_sync * g_bg_ctrl_first.blocks_per_sync); + -- yields verror 1074, verror 1048, therefor use p_init instead, and + -- therefor use bg_ctrl_arr instead of c_bg_ctrl_arr. + p_init : PROCESS + BEGIN + bg_ctrl_arr <= (OTHERS => g_bg_ctrl_others); + bg_ctrl_arr(0) <= g_bg_ctrl_first; + + exp_total_count_nof_packet_arr <= (OTHERS => c_nof_sync_others * g_bg_ctrl_others.blocks_per_sync); + exp_total_count_nof_packet_arr(0) <= c_nof_sync_first * g_bg_ctrl_first.blocks_per_sync; + + rx_exp_total_count_nof_valid_arr <= (OTHERS => c_nof_sync_others * c_total_count_nof_valid_per_sync_others); + rx_exp_total_count_nof_valid_arr(0) <= c_nof_sync_first * c_total_count_nof_valid_per_sync_first; + + rx_exp_total_count_nof_corrupted_arr <= (OTHERS => 0); -- default no Rx errors + WAIT; + END PROCESS; + + ----------------------------------------------------------------------------- + -- MM control and monitoring + ----------------------------------------------------------------------------- + p_mm : PROCESS + VARIABLE v_value : NATURAL; + VARIABLE v_offset : NATURAL; + VARIABLE v_udp_dst_port : NATURAL; + BEGIN + i_tb_end <= '0'; + + proc_common_wait_until_low(mm_clk, mm_rst); + proc_common_wait_some_cycles(mm_clk, 10); + + --------------------------------------------------------------------------- + -- Rx UDP offload port + --------------------------------------------------------------------------- + v_udp_dst_port := TO_UINT(c_eth_tester_udp_dst_port); + + + + FOR I IN g_nof_streams-1 DOWNTO 0 LOOP + 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#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; + + --------------------------------------------------------------------------- + -- Stimuli + --------------------------------------------------------------------------- + FOR I IN g_nof_streams-1 DOWNTO 0 LOOP + v_offset := I * c_diag_bg_reg_adr_span; + -- Set number of octets per packet for dp_split + proc_mem_mm_bus_wr(I*2, bg_ctrl_arr(I).samples_per_packet, mm_clk, reg_dp_split_copi); + + -- Prepare the BG + proc_mem_mm_bus_wr(v_offset + 1, ceil_div(bg_ctrl_arr(I).samples_per_packet, g_nof_octet_generate) , mm_clk, reg_bg_ctrl_copi); + proc_mem_mm_bus_wr(v_offset + 2, bg_ctrl_arr(I).blocks_per_sync, mm_clk, reg_bg_ctrl_copi); + proc_mem_mm_bus_wr(v_offset + 3, bg_ctrl_arr(I).gapsize, mm_clk, reg_bg_ctrl_copi); + proc_mem_mm_bus_wr(v_offset + 4, bg_ctrl_arr(I).mem_low_adrs, mm_clk, reg_bg_ctrl_copi); + proc_mem_mm_bus_wr(v_offset + 5, bg_ctrl_arr(I).mem_high_adrs, mm_clk, reg_bg_ctrl_copi); + proc_mem_mm_bus_wr(v_offset + 6, bg_ctrl_arr(I).bsn_init, mm_clk, reg_bg_ctrl_copi); -- low part + proc_mem_mm_bus_wr(v_offset + 7, 0, mm_clk, reg_bg_ctrl_copi); -- high part + -- Enable the BG at st_pps pulse. + proc_mem_mm_bus_wr(v_offset + 0, 3, mm_clk, reg_bg_ctrl_copi); + + END LOOP; + 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 + FOR I IN g_nof_streams-1 DOWNTO 0 LOOP + v_offset := I * c_diag_bg_reg_adr_span; + -- Disable the other BG + proc_mem_mm_bus_wr(v_offset + 0, 0, mm_clk, reg_bg_ctrl_copi); + END LOOP; + + -- Wait until Tx FIFOs have emptied for all streams + WHILE UNSIGNED(tx_fifo_rd_emp_arr(g_nof_streams-1 DOWNTO 0)) /= 2**g_nof_streams - 1 LOOP + proc_common_wait_some_cycles(st_clk, 1); + END LOOP; + proc_common_wait_some_cycles(st_clk, c_bg_sync_period_max); + 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 + FOR I IN g_nof_streams-1 DOWNTO 0 LOOP + IF I = 0 THEN + print_str(c_tb_str & + "ETH bit rate (" & NATURAL'IMAGE(I) & ") :" & + " c_bg_nof_bps_first = " & REAL'IMAGE(c_bg_nof_bps_first) & " bps"); + ELSE + print_str(c_tb_str & + "ETH bit rate (" & NATURAL'IMAGE(I) & ") :" & + " c_bg_nof_bps_others = " & REAL'IMAGE(c_bg_nof_bps_others) & " bps"); + END IF; + END LOOP; + IF g_nof_streams > 1 THEN + print_str(c_tb_str & + "ETH bit rate total :" & + " c_bg_nof_bps_total = " & REAL'IMAGE(c_bg_nof_bps_total) & " bps"); + END IF; + + ------------------------------------------------------------------------- + -- Verification: Total counts + ------------------------------------------------------------------------- + FOR I IN g_nof_streams-1 DOWNTO 0 LOOP + -- . read low part, ignore high part (= 0) of two word total counts + v_offset := I * c_dp_strobe_total_count_reg_adr_span; + -- Tx total nof packets + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_strobe_total_count_tx_cipo.rddata(c_word_w-1 DOWNTO 0)); + -- Rx total nof packets + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_strobe_total_count_rx_cipo.rddata(c_word_w-1 DOWNTO 0)); + -- Rx total nof valids + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_strobe_total_count_rx_cipo.rddata(c_word_w-1 DOWNTO 0)); + -- Rx total nof corrupted + proc_mem_mm_bus_rd(v_offset + 4, 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_corrupted_arr(I) <= 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(" & NATURAL'IMAGE(I) & ") :" & + " nof_packet = " & NATURAL'IMAGE(tx_total_count_nof_packet_arr(I))); + + print_str(c_tb_str & + "Rx total counts monitor(" & NATURAL'IMAGE(I) & ") :" & + " nof_packet = " & NATURAL'IMAGE(rx_total_count_nof_packet_arr(I)) & + ", nof_valid = " & NATURAL'IMAGE(rx_total_count_nof_valid_arr(I)) & + ", nof_corrupted = " & NATURAL'IMAGE(rx_total_count_nof_corrupted_arr(I))); + + -- Verify, only log when wrong + IF c_bg_nof_bps_total < 10.0**9 THEN + ASSERT tx_total_count_nof_packet_arr(I) = exp_total_count_nof_packet_arr(I) REPORT c_tb_str & + "Wrong Tx total nof packets count(" & NATURAL'IMAGE(I) & + "), Tx count = " & NATURAL'IMAGE(tx_total_count_nof_packet_arr(I)) & + " /= " & NATURAL'IMAGE(exp_total_count_nof_packet_arr(I)) & + " = Expected count" SEVERITY ERROR; + + ASSERT rx_total_count_nof_packet_arr(I) = exp_total_count_nof_packet_arr(I) REPORT c_tb_str & + "Wrong Rx total nof packets count(" & NATURAL'IMAGE(I) & + "), Rx count = " & NATURAL'IMAGE(rx_total_count_nof_packet_arr(I)) & + " /= " & NATURAL'IMAGE(exp_total_count_nof_packet_arr(I)) & + " = Expected count" SEVERITY ERROR; + + ASSERT rx_total_count_nof_valid_arr(I) = rx_exp_total_count_nof_valid_arr(I) REPORT c_tb_str & + "Wrong Rx total nof valids count(" & NATURAL'IMAGE(I) & + "), Rx count = " & NATURAL'IMAGE(rx_total_count_nof_valid_arr(I)) & + " /= " & NATURAL'IMAGE(rx_exp_total_count_nof_valid_arr(I)) & + " = Expected count" SEVERITY ERROR; + + ASSERT rx_total_count_nof_corrupted_arr(I) = rx_exp_total_count_nof_corrupted_arr(I) REPORT c_tb_str & + "Wrong Rx total nof corrupted count(" & NATURAL'IMAGE(I) & + "), Rx count = " & NATURAL'IMAGE(rx_total_count_nof_corrupted_arr(I)) & + " /= " & NATURAL'IMAGE(rx_exp_total_count_nof_corrupted_arr(I)) & + " = Expected count" SEVERITY ERROR; + ELSE + -- Verify that Tx total nof packets = Rx total nof packets, also when + -- 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-Rx total nof packets count(" & NATURAL'IMAGE(I) & + "), Tx count = " & 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; + + ------------------------------------------------------------------------- + -- Verification: BSN monitors (yield same values in every sync interval) + ------------------------------------------------------------------------- + FOR I IN g_nof_streams-1 DOWNTO 0 LOOP + v_offset := I * c_dp_bsn_monitor_v2_reg_adr_span; + -- 3 = nof_sop + -- 4 = nof_valid + -- 6 = latency + -- . Tx + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_bsn_monitor_v2_tx_cipo.rddata(c_word_w-1 DOWNTO 0)); + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_bsn_monitor_v2_tx_cipo.rddata(c_word_w-1 DOWNTO 0)); + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_bsn_monitor_v2_tx_cipo.rddata(c_word_w-1 DOWNTO 0)); + -- . Rx + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_bsn_monitor_v2_rx_cipo.rddata(c_word_w-1 DOWNTO 0)); + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= TO_UINT(reg_bsn_monitor_v2_rx_cipo.rddata(c_word_w-1 DOWNTO 0)); + proc_mem_mm_bus_rd(v_offset + 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_arr(I) <= 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(" & NATURAL'IMAGE(I) & ") :" & + " nof_sop = " & NATURAL'IMAGE(tx_mon_nof_sop_arr(I)) & + ", nof_valid = " & NATURAL'IMAGE(tx_mon_nof_valid_arr(I)) & + ", latency = " & NATURAL'IMAGE(tx_mon_latency_arr(I))); + + print_str(c_tb_str & + "Rx BSN monitor(" & NATURAL'IMAGE(I) & ") :" & + " nof_sop = " & NATURAL'IMAGE(rx_mon_nof_sop_arr(I)) & + ", nof_valid = " & NATURAL'IMAGE(rx_mon_nof_valid_arr(I)) & + ", latency = " & NATURAL'IMAGE(rx_mon_latency_arr(I))); + + IF c_bg_nof_bps_total < 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 + IF I = 0 THEN + ASSERT tx_mon_nof_sop_arr(I) = c_mon_nof_sop_first REPORT c_tb_str & "Wrong tx nof_sop for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + ASSERT rx_mon_nof_sop_arr(I) = c_mon_nof_sop_first REPORT c_tb_str & "Wrong rx nof_sop for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + ASSERT tx_mon_nof_valid_arr(I) = c_mon_nof_valid_first_tx REPORT c_tb_str & "Wrong tx nof_valid for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + ASSERT rx_mon_nof_valid_arr(I) = c_mon_nof_valid_first_rx REPORT c_tb_str & "Wrong rx nof_valid for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + ELSE + ASSERT tx_mon_nof_sop_arr(I) = c_mon_nof_sop_others REPORT c_tb_str & "Wrong tx nof_sop for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + ASSERT rx_mon_nof_sop_arr(I) = c_mon_nof_sop_others REPORT c_tb_str & "Wrong rx nof_sop for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + ASSERT tx_mon_nof_valid_arr(I) = c_mon_nof_valid_others_tx REPORT c_tb_str & "Wrong tx nof_valid for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + ASSERT rx_mon_nof_valid_arr(I) = c_mon_nof_valid_others_rx REPORT c_tb_str & "Wrong rx nof_valid for stream (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + END IF; + ASSERT tx_mon_latency_arr(I) = c_tx_exp_latency REPORT c_tb_str & "Wrong tx latency for stream (" & NATURAL'IMAGE(I) & ")" 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_arr(I), c_rx_exp_latency_st, 10) REPORT + c_tb_str & "Wrong rx latency using st interface (" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + END IF; + END IF; + END LOOP; + + ------------------------------------------------------------------------- + -- End of test + ------------------------------------------------------------------------- + proc_common_wait_some_cycles(mm_clk, 100); + i_tb_end <= '1'; + WAIT; + END PROCESS; + + dut : ENTITY work.eth_tester + GENERIC MAP ( + g_nof_streams => g_nof_streams, + g_bg_sync_timeout => c_eth_tester_sync_timeout, + g_nof_octet_generate => g_nof_octet_generate, + g_nof_octet_output => g_nof_octet_output, + g_remove_crc => FALSE + ) + 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, + + tx_fifo_rd_emp_arr => tx_fifo_rd_emp_arr, + + tx_udp_sosi_arr => tx_udp_sosi_arr, + tx_udp_siso_arr => tx_udp_siso_arr, + + -- UDP receive interface + rx_udp_sosi_arr => rx_udp_sosi_arr, + + -- 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, + reg_dp_split_copi => reg_dp_split_copi, + reg_dp_split_cipo => reg_dp_split_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 + ); + + -- Loop back at streaming sosi level + rx_udp_sosi_arr <= tx_udp_sosi_arr; +END tb; diff --git a/libraries/io/eth/tb/vhdl/tb_tb_eth_tester_high_bw.vhd b/libraries/io/eth/tb/vhdl/tb_tb_eth_tester_high_bw.vhd new file mode 100644 index 0000000000000000000000000000000000000000..036d1641b590e1182adf53fa195aacffd90d5461 --- /dev/null +++ b/libraries/io/eth/tb/vhdl/tb_tb_eth_tester_high_bw.vhd @@ -0,0 +1,177 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2023 +-- 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: R. vd Walle +-- Purpose: Multi test bench for eth_tester for high bandwidths. +-- Description: Similar to the 1GbE TB as described in [1] but for 10 / 100 GbE. +-- +-- References: +-- [1] https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+ETH+tester+unit+for+1GbE +-- +-- Usage: +-- > as 8 +-- > run -all +-- Takes about 10 m + +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_tester_high_bw IS +END tb_tb_eth_tester_high_bw; + +ARCHITECTURE tb OF tb_tb_eth_tester_high_bw IS + + -- Multi tb + CONSTANT c_tb_w : NATURAL := 100; -- sufficiently long to fit all tb instances + CONSTANT c_tb_end_vec : STD_LOGIC_VECTOR(c_tb_w-1 DOWNTO 0) := (OTHERS=>'1'); + + SIGNAL tb_end_vec : STD_LOGIC_VECTOR(c_tb_w-1 DOWNTO 0) := c_tb_end_vec; -- best view as hex in Wave Window + SIGNAL tb_end : STD_LOGIC := '0'; + + -- Tb + CONSTANT c_eth_clk_MHz : NATURAL := 125; + CONSTANT c_st_clk_MHz : NATURAL := 200; + CONSTANT c_nof_sync : NATURAL := 2; + CONSTANT c_nof_sync_many : NATURAL := 50; -- sufficient to achieve Tx FIFO fill level + CONSTANT c_nof_streams : NATURAL := 3; + CONSTANT c_nof_blk : NATURAL := 3; -- nof_blk per sync + + -- Tx packet size and gap size in octets + CONSTANT c_block_len : NATURAL := 500; -- BG block length of first stream [0] + CONSTANT c_block_len_jumbo : NATURAL := 9000; + 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; + CONSTANT c_slot_len_min : NATURAL := c_block_len + c_gap_len_min; + + -- 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 + CONSTANT c_long_gap : NATURAL := c_gap_len_min * 10; + CONSTANT c_short_gap : NATURAL := 10; -- to cause BG xon/xoff flow control + CONSTANT c_zero_gap : NATURAL := 0; -- to verify BG ready flow control + + -- Choose c_others_len > c_block_len, so same c_gap_len is suitable to + -- keep Ethernet link rate < 1 Gbps + CONSTANT c_others_len : NATURAL := 65; -- BG block length of other streams [c_nof_streams-1 : 1] + + -- BG ctrl + CONSTANT c_high : NATURAL := c_diag_bg_mem_max_adr; -- = 2**24 + + CONSTANT c_bg_ctrl_rst : t_diag_block_gen_integer := ('0', '0', 1, c_nof_blk, c_gap_len, 0, c_high, 0); -- place holder for unused stream + + CONSTANT c_bg_ctrl_one : t_diag_block_gen_integer := ('1', '1', c_block_len, c_nof_blk, c_gap_len, 0, c_high, 0); -- for first stream + CONSTANT c_bg_ctrl_others : t_diag_block_gen_integer := ('1', '1', c_others_len, c_nof_blk, c_gap_len, 0, c_high, 0); -- for other streams + + -- . BG with different block lengths and other payload values + -- The payload values are only verified manually using the Wave Window + CONSTANT c_bg_ctrl_len_0 : t_diag_block_gen_integer := ('1', '1', c_block_len+0, c_nof_blk, c_gap_len, 0, 0, 0); -- nof octets + CONSTANT c_bg_ctrl_len_1 : t_diag_block_gen_integer := ('1', '1', c_block_len+1, c_nof_blk, c_gap_len, 1, 1, 0); -- nof octets + CONSTANT c_bg_ctrl_len_2 : t_diag_block_gen_integer := ('1', '1', c_block_len+2, c_nof_blk, c_gap_len, 1, 7, 0); -- nof octets + CONSTANT c_bg_ctrl_len_3 : t_diag_block_gen_integer := ('1', '1', c_block_len+3, c_nof_blk, c_gap_len, c_high-1, c_high-1, 0); -- nof octets + + CONSTANT c_bg_ctrl_multiple_first : t_diag_block_gen_integer := ('1', '1', c_block_len, c_nof_blk, c_nof_streams * c_gap_len, 0, c_high, 0); -- for first stream + CONSTANT c_bg_ctrl_multiple_others : t_diag_block_gen_integer := ('1', '1', c_others_len, c_nof_blk, c_nof_streams * c_gap_len, 0, c_high, 0); -- for other streams + +BEGIN + +-- g_tb_index : NATURAL := 0; -- use to incremental delay logging from tb instances in tb_tb +-- g_nof_sync : NATURAL := 3; -- number of BG sync intervals to set c_run_time +-- g_nof_streams : NATURAL := 2; +-- g_nof_octet_output : NATURAL := 96; -- maximum = 96 bytes as max dp.data field = 768 bits. +-- g_nof_octet_generate : NATURAL := 96; +-- +-- -- 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_first : t_diag_block_gen_integer := ('1', '1', 50, c_nof_blk, 100, 0, 30, 0); -- for first stream +-- g_bg_ctrl_others : t_diag_block_gen_integer := ('1', '1', 30, c_nof_blk, 10, 0, 30, 0) -- for other streams + + -- Tb instance prefix: + -- . u_st : uses streaming Tx-Rx interface + + + ----------------------------------------------------------------------------- + -- Single stream + ----------------------------------------------------------------------------- + -- Try different loopback interfaces + u_st_10g : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (0, c_nof_sync, 1, 8, 8, c_bg_ctrl_one, c_bg_ctrl_rst) PORT MAP (tb_end_vec(0)); -- 8 byte wide + u_st_100g : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (1, c_nof_sync, 1, 64, 64, c_bg_ctrl_one, c_bg_ctrl_rst) PORT MAP (tb_end_vec(1)); -- 64 byte wide + u_st_max : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (2, c_nof_sync, 1, 96, 96, c_bg_ctrl_one, c_bg_ctrl_rst) PORT MAP (tb_end_vec(2)); -- 96 byte wide as max dp.data width = 96*8=768 bits. + + -- Try large block size and nof blocks_per_sync = 1 + u_st_jumbo1 : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (10, c_nof_sync, 1, 96, 96, + ('1', '1', c_block_len_jumbo, 1, c_zero_gap, 0, c_high, 0), + c_bg_ctrl_rst) + PORT MAP (tb_end_vec(10)); + + -- Try large block sizes + u_st_jumbo2 : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (11, c_nof_sync, 1, 64, 64, + ('1', '1', c_block_len_jumbo, 2, c_zero_gap, 0, c_high, 0), + c_bg_ctrl_rst) + PORT MAP (tb_end_vec(11)); + + + + -- Try small block sizes at 64*8 = 512b bus size + -- . BG supports samples_per_packet >= 2, BG treats samples_per_packet = 1 as 2 + -- . ETH MAC pads samples_per_packet <= 6 to 6, to have minimum packet length of 64 octets, + -- because hdr = 14 + 20 + 8 + 12 and crc = 4 have 58 octets. + u_st_len2 : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (20, c_nof_sync, 1, 64, 64, + ('1', '1', 2, c_nof_blk, c_gap_len, 0, c_high, 0), + c_bg_ctrl_rst) + PORT MAP (tb_end_vec(20)); + + + -- Try different BG block lengths and data widths to verify sosi.empty nof octets in last word and repack. + u_st_bg_len_0 : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (30, c_nof_sync, 1, 64, 8, c_bg_ctrl_len_0, c_bg_ctrl_rst) PORT MAP (tb_end_vec(30)); + u_st_bg_len_1 : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (31, c_nof_sync, 1, 8, 1, c_bg_ctrl_len_1, c_bg_ctrl_rst) PORT MAP (tb_end_vec(31)); + u_st_bg_len_2 : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (32, c_nof_sync, 1, 8, 4, c_bg_ctrl_len_2, c_bg_ctrl_rst) PORT MAP (tb_end_vec(32)); + u_st_bg_len_3 : ENTITY work.tb_eth_tester_high_bw GENERIC MAP (33, c_nof_sync, 1, 64, 64, c_bg_ctrl_len_3, c_bg_ctrl_rst) PORT MAP (tb_end_vec(33)); + + ----------------------------------------------------------------------------- + -- Multiple streams + ----------------------------------------------------------------------------- + u_st_multiple_streams : ENTITY work.tb_eth_tester_high_bw + GENERIC MAP (80, c_nof_sync, c_nof_streams, 8, 8, + c_bg_ctrl_multiple_first, + c_bg_ctrl_multiple_others) + PORT MAP (tb_end_vec(80)); + + + tb_end <= '1' WHEN tb_end_vec = c_tb_end_vec ELSE '0'; + + p_tb_end : PROCESS + BEGIN + WAIT UNTIL tb_end='1'; + WAIT FOR 1 ns; + REPORT "Multi tb simulation finished." SEVERITY FAILURE; + WAIT; + END PROCESS; + +END tb;