diff --git a/libraries/base/common/src/vhdl/common_str_pkg.vhd b/libraries/base/common/src/vhdl/common_str_pkg.vhd index cda0f3672e1b164d7156a455166ae428c340b609..c6adcaad935043c1eabd4dc0a0b674ab3a0c524a 100644 --- a/libraries/base/common/src/vhdl/common_str_pkg.vhd +++ b/libraries/base/common/src/vhdl/common_str_pkg.vhd @@ -57,6 +57,7 @@ PACKAGE common_str_pkg IS FUNCTION real_to_str(re: REAL; width : INTEGER; digits : INTEGER) RETURN STRING; PROCEDURE print_str(str : STRING); + PROCEDURE print_str(str: STRING; enable: BOOLEAN); FUNCTION str_to_ascii_integer_arr(s: STRING) RETURN t_integer_arr; FUNCTION str_to_ascii_slv_8_arr( s: STRING) RETURN t_slv_8_arr; @@ -262,13 +263,21 @@ PACKAGE BODY common_str_pkg IS END; PROCEDURE print_str(str: STRING) IS - VARIABLE v_line: LINE; + VARIABLE v_line: LINE; BEGIN write(v_line, str); writeline(output, v_line); deallocate(v_line); END; + PROCEDURE print_str(str: STRING; enable: BOOLEAN) IS + VARIABLE v_line: LINE; + BEGIN + IF enable THEN + print_str(str); + END IF; + END; + FUNCTION str_to_ascii_integer_arr(s: STRING) RETURN t_integer_arr IS VARIABLE r: t_integer_arr(0 TO s'RIGHT-1); BEGIN diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 3b1bff1f02a4186cb170dc23e7f7e42b99c69aea..34a2c49f89a64e30918443ee012c44e85d40f1d5 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -347,6 +347,7 @@ test_bench_files = tb/vhdl/tb_tb_tb_dp_backpressure.vhd tb/vhdl/tb_dp_offload_tx_v3.vhd + tb/vhdl/tb_tb_dp_offload_tx_v3.vhd tb/vhdl/tb_dp_offload_rx_filter.vhd tb/vhdl/tb_dp_selector_arr.vhd tb/vhdl/tb_mms_dp_scale.vhd @@ -416,6 +417,7 @@ regression_test_vhdl = tb/vhdl/tb_tb_dp_xonoff.vhd tb/vhdl/tb_dp_selector_arr.vhd tb/vhdl/tb_mms_dp_scale.vhd + tb/vhdl/tb_tb_dp_offload_tx_v3.vhd [modelsim_project_file] diff --git a/libraries/base/dp/src/vhdl/dp_offload_rx.vhd b/libraries/base/dp/src/vhdl/dp_offload_rx.vhd index 9effa4c7f350bc97dcadd99b59682feabad782f9..3cb3907f1f9d858e6f140c819628fa5305ffff8f 100644 --- a/libraries/base/dp/src/vhdl/dp_offload_rx.vhd +++ b/libraries/base/dp/src/vhdl/dp_offload_rx.vhd @@ -19,6 +19,27 @@ -- ------------------------------------------------------------------------------- +-- Author: D. van der Schuur, E. Kooistra +-- Purpose: +-- . Split a user-defined header from a data block e.g. to from an Eth frame +-- Description: +-- . The dp_offload_tx_v3 --> dp_offload_rx form a pair. +-- . The header and data block can be split at symbol level, to support a header +-- that does not have an integer number of g_data_w. The header length is +-- defined by c_nof_header_symbols. +-- . The header contents can be monitored and is defined by g_hdr_field_arr. +-- . The data block is output via src_out_arr. If the data block contains an +-- integer number of g_data_w words, then src_out_arr.empty = 0. +-- . Default the g_symbol_w = 0 which implies g_symbol_w = g_data_w. +-- - If the header length is not an integer number of g_data_w, then +-- g_symbol_w has to be set such that c_nof_symbols_per_data and +-- c_nof_header_symbols are both integers. The g_symbol_w is then used +-- to control the split. +-- - If the data block length is not an integer number of g_data_w, then +-- g_symbol_w defines the symbol width of the data and is used to +-- control the snk_out_arr empty field. + + LIBRARY IEEE, common_lib, dp_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; @@ -31,6 +52,7 @@ ENTITY dp_offload_rx IS GENERIC ( g_nof_streams : NATURAL; g_data_w : NATURAL; + g_symbol_w : NATURAL := 0; -- default 0 yields g_symbol_w = g_data_w g_hdr_field_arr : t_common_field_arr; g_remove_crc : BOOLEAN := FALSE; g_crc_nof_words : NATURAL := 0 @@ -59,7 +81,9 @@ END dp_offload_rx; ARCHITECTURE str OF dp_offload_rx IS - CONSTANT c_nof_header_words : NATURAL := field_slv_len(g_hdr_field_arr) / g_data_w; + CONSTANT c_symbol_w : NATURAL := sel_a_b(g_symbol_w = 0, g_data_w, g_symbol_w); + CONSTANT c_nof_symbols_per_data : NATURAL := g_data_w / g_symbol_w; + CONSTANT c_nof_header_symbols : NATURAL := field_slv_len(g_hdr_field_arr) / c_symbol_w; CONSTANT c_field_sel : STD_LOGIC_VECTOR(g_hdr_field_arr'RANGE) := (OTHERS=>'0');-- Not used in sink mode but requires set range @@ -92,8 +116,8 @@ BEGIN u_dp_split : ENTITY work.dp_split GENERIC MAP ( g_data_w => g_data_w, - g_symbol_w => g_data_w, - g_nof_symbols => c_nof_header_words + g_symbol_w => c_symbol_w, + g_nof_symbols => c_nof_header_symbols ) PORT MAP ( rst => dp_rst, @@ -117,10 +141,12 @@ BEGIN gen_dp_field_blk : FOR i IN 0 TO g_nof_streams-1 GENERATE u_dp_field_blk : ENTITY work.dp_field_blk GENERIC MAP ( - g_field_arr => field_arr_set_mode(g_hdr_field_arr , "RO"), - g_field_sel => c_field_sel, - 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_field_arr => field_arr_set_mode(g_hdr_field_arr , "RO"), + g_field_sel => c_field_sel, + 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 ) PORT MAP ( dp_rst => dp_rst, @@ -152,7 +178,7 @@ BEGIN u_dp_tail_remove : ENTITY work.dp_tail_remove GENERIC MAP ( g_data_w => g_data_w, - g_symbol_w => g_data_w, + g_symbol_w => c_symbol_w, g_nof_symbols => sel_a_b(g_remove_crc, g_crc_nof_words, 0) ) PORT MAP ( 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 e841015d5418e980fad3d84ca0c347f4df7170f8..f72352cd6925c80356551b0c2fa3b6761b1f9877 100644 --- a/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd +++ b/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd @@ -19,21 +19,25 @@ -- ------------------------------------------------------------------------------- +-- Author: D. van der Schuur, E. Kooistra -- Purpose: --- . Concatenate a user-defined header to a DP frame e.g. to create an Ethernet frame +-- . Concatenate a user-defined header to a data block e.g. to create an Eth +-- frame -- Description: --- . The header contents can be controlled dynamically by data path or MM control (selected by g_hdr_field_sel) --- . The header and data can be concatened at symbol level. The g_symbol_w defines the --- resolution of the empty field. The g_data_w must be an integer multiple of the --- g_symbol_w. If the empty field is not used or if the empty field is always 0 then --- set g_symbol_w = g_data_w. --- . For example to concat header and data for an Ethernet frame use: +-- . The dp_offload_tx_v3 --> dp_offload_rx form a pair. +-- . The header contents can be controlled dynamically by data path or MM +-- control (selected by g_hdr_field_sel) +-- . The header and data can be concatened at symbol level. The g_symbol_w +-- defines the resolution of the empty field. The g_data_w must be an +-- integer multiple of the g_symbol_w. If the empty field is not used or +-- if the empty field is always 0 then set g_symbol_w = g_data_w. +-- . For example to concat header and data block for an Ethernet frame use: -- - g_data_w = 32 (1GbE) or 64 (10GbE) --- - g_symbol_w = c_byte_w = 8 if either the header or the data can have an --- non-zero empty field, so when they are not a multiple of 4 bytes --- (= 32b) or 8 bytes (= 64b). --- g_symbol_w = g_data_w if the empty field is always 0, so the number of bits in --- the header and data are an integer number of g_data_w. +-- - g_symbol_w = c_byte_w = 8 if either the header or the data block can +-- have an non-zero empty field, so when they are not a multiple of +-- 4 bytes (= 32b) or 8 bytes (= 64b). +-- g_symbol_w = g_data_w if the empty field is always 0, so the number of +-- bits in the header and data are an integer number of g_data_w. LIBRARY IEEE, common_lib, technology_lib, mm_lib; @@ -50,7 +54,7 @@ ENTITY dp_offload_tx_v3 IS g_nof_streams : NATURAL; g_data_w : NATURAL; g_symbol_w : NATURAL; - g_hdr_field_arr : t_common_field_arr; -- User defined header fields + g_hdr_field_arr : t_common_field_arr; -- User defined header fields g_hdr_field_sel : STD_LOGIC_VECTOR; -- For each header field, select the source: 0=data path, 1=MM controlled g_pipeline_ready : BOOLEAN := FALSE ); diff --git a/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd b/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd index 0481f2ff99f2ea88456c65a93dc800f136537c9b..70d6538309705161c9cd4870c762f448b08d57a2 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd @@ -24,12 +24,29 @@ -- Description: -- u_tx u_rx -- ___________________ ___________________ --- |dp_offload_tx_v3| |dp_offload_rx | +-- |dp_offload_tx_v3 | |dp_offload_rx | -- stimuli_src -->| |--->| |--> verify_snk -- | in out | | | in out | -- |___________________| | |___________________| -- | -- link_offload_sosi +-- +-- The verification of the header - data block boundary is controlled via +-- g_symbol_w: +-- . g_symbol_w = g_data_w : boundary at g_data_w +-- . g_symbol_w < g_data_w : boundary at g_symbol_w, by reducing the number +-- of the header dp_bsn field by 1 symbol. If the c_bsn_w <= 32 then the +-- header MM interface only needs one MM word to read the header, so +-- therefore there are two sizes of c_expected_tx_hdr_word_arr_* and +-- c_expected_rx_hdr_word_arr_*. +-- +-- Remarks: +-- . The g_flow_control_verify has to be e_active, otherwise the tb fails, +-- probably due to limitation in dp_offload_rx.vhd. +-- . It appears that the tx_hdr_word read values are the MM write values, so +-- read of value from logic fields (with MM override '0', e.g. dp_bsn, +-- eth_src_mac) is not supported. +-- -- Usage: -- > as 10 -- > run -all @@ -54,9 +71,10 @@ ENTITY tb_dp_offload_tx_v3 IS -- general g_flow_control_stimuli : t_dp_flow_control_enum := e_pulse; -- always e_active, e_random or e_pulse flow control g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control + g_print_en : BOOLEAN := TRUE; -- specific g_data_w : NATURAL := 64; - g_nof_repeat : NATURAL := 100; + g_symbol_w : NATURAL := 32; g_pkt_len : NATURAL := 240; g_pkt_gap : NATURAL := 16 ); @@ -68,6 +86,18 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS CONSTANT c_mm_clk_period : TIME := 1 ns; CONSTANT c_dp_clk_period : TIME := 5 ns; + -- Simulate header / payload boundary at g_data_w boundary or at g_symbol_w + -- boundary with one empty symbol, by adapting the size of the header dp_bsn + -- field: + -- . If g_symbol_w = g_data_w then boundary is at g_data_w, so empty is 0. + -- . If g_symbol_w < g_data_w then boundary is at last symbol, so empty is 1. + CONSTANT c_nof_symbols_per_data : NATURAL := g_data_w / g_symbol_w; + CONSTANT c_nof_symbols_per_bsn : NATURAL := c_dp_stream_bsn_w / g_symbol_w; -- = 64 / g_symbol_w + CONSTANT c_bsn_w : NATURAL := sel_a_b(c_nof_symbols_per_data = 1, + g_symbol_w * c_nof_symbols_per_bsn, + g_symbol_w * (c_nof_symbols_per_bsn - 1)); + CONSTANT c_use_shortened_header : BOOLEAN := c_bsn_w <= c_word_w; + -- dp_stream_stimuli CONSTANT c_stimuli_pulse_active : NATURAL := 3; CONSTANT c_stimuli_pulse_period : NATURAL := 4; @@ -87,48 +117,53 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS CONSTANT c_sync_period : NATURAL := 5; CONSTANT c_sync_offset : NATURAL := 2; CONSTANT c_bsn_init : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := TO_DP_BSN(0); + CONSTANT c_nof_sync : NATURAL := 3; + CONSTANT c_nof_packets : NATURAL := c_sync_period * c_nof_sync; CONSTANT c_hdr_len : NATURAL := 7; - CONSTANT c_wait_last_evt : NATURAL := 100 + g_nof_repeat * c_hdr_len; + CONSTANT c_wait_last_evt : NATURAL := 100 + c_nof_packets * c_hdr_len; ----------------------------------------------------------------------------- -- Tx offload ----------------------------------------------------------------------------- -- From apertif_udp_offload_pkg.vhd: - CONSTANT c_udp_offload_nof_hdr_fields : NATURAL := 3+12+4+3; -- 22, 448b; 7 64b words - CONSTANT c_udp_offload_nof_hdr_words : NATURAL := 26; -- 23 single word + 3 double word = 26 32b words + CONSTANT c_udp_offload_nof_hdr_fields : NATURAL := 3+12+4+3; -- 22, 448b; 7 64b words + CONSTANT c_udp_offload_nof_hdr_words_default : NATURAL := 26; -- 23 single word + 3 double word = 26 32b words + CONSTANT c_udp_offload_nof_hdr_words_shortened : NATURAL := c_udp_offload_nof_hdr_words_default - 1; + CONSTANT c_udp_offload_nof_hdr_words : NATURAL := sel_a_b(c_use_shortened_header, c_udp_offload_nof_hdr_words_shortened, c_udp_offload_nof_hdr_words_default); + -- Notes: -- . pre-calculated ip_header_checksum is valid only for UNB0, FN0 targeting IP 10.10.10.10 -- . udp_total_length = 176 beamlets * 64b / 8b = 1408B + 14 DP bytes + 8 UDP bytes = 1430B CONSTANT c_udp_offload_hdr_field_arr : t_common_field_arr(c_udp_offload_nof_hdr_fields-1 DOWNTO 0) := ( -- index - ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"001B214368AC") ), -- 21 - ( field_name_pad("eth_src_mac" ), "RW", 48, field_default(x"0123456789AB") ), -- 20 - ( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ), -- 19 - ( field_name_pad("ip_version" ), "RW", 4, field_default(4) ), -- 18 - ( field_name_pad("ip_header_length" ), "RW", 4, field_default(5) ), -- 17 - ( field_name_pad("ip_services" ), "RW", 8, field_default(0) ), -- 16 - ( field_name_pad("ip_total_length" ), "RW", 16, field_default(1450) ), -- 15 - ( field_name_pad("ip_identification" ), "RW", 16, field_default(0) ), -- 14 - ( field_name_pad("ip_flags" ), "RW", 3, field_default(2) ), -- 13 - ( field_name_pad("ip_fragment_offset" ), "RW", 13, field_default(0) ), -- 12 - ( field_name_pad("ip_time_to_live" ), "RW", 8, field_default(127) ), -- 11 - ( field_name_pad("ip_protocol" ), "RW", 8, field_default(17) ), -- 10 - ( field_name_pad("ip_header_checksum" ), "RW", 16, field_default(29928) ), -- 9 - ( field_name_pad("ip_src_addr" ), "RW", 32, field_default(x"C0A80009") ), -- 8 - ( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"C0A80001") ), -- 7 - ( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ), -- 6 - ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(0) ), -- 5 - ( field_name_pad("udp_total_length" ), "RW", 16, field_default(1430) ), -- 4 - ( field_name_pad("udp_checksum" ), "RW", 16, field_default(0) ), -- 3 - ( field_name_pad("dp_reserved" ), "RW", 47, field_default(x"010203040506") ), -- 2 - ( field_name_pad("dp_sync" ), "RW", 1, field_default(0) ), -- 1 - ( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) ) ); -- 0 + ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"001B214368AC") ), -- 21 + ( field_name_pad("eth_src_mac" ), "RW", 48, field_default(x"0123456789AB") ), -- 20 + ( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ), -- 19 + ( field_name_pad("ip_version" ), "RW", 4, field_default(4) ), -- 18 + ( field_name_pad("ip_header_length" ), "RW", 4, field_default(5) ), -- 17 + ( field_name_pad("ip_services" ), "RW", 8, field_default(0) ), -- 16 + ( field_name_pad("ip_total_length" ), "RW", 16, field_default(1450) ), -- 15 + ( field_name_pad("ip_identification" ), "RW", 16, field_default(0) ), -- 14 + ( field_name_pad("ip_flags" ), "RW", 3, field_default(2) ), -- 13 + ( field_name_pad("ip_fragment_offset" ), "RW", 13, field_default(0) ), -- 12 + ( field_name_pad("ip_time_to_live" ), "RW", 8, field_default(127) ), -- 11 + ( field_name_pad("ip_protocol" ), "RW", 8, field_default(17) ), -- 10 + ( field_name_pad("ip_header_checksum" ), "RW", 16, field_default(29928) ), -- 9 + ( field_name_pad("ip_src_addr" ), "RW", 32, field_default(x"C0A80009") ), -- 8 + ( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"C0A80001") ), -- 7 + ( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ), -- 6 + ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(0) ), -- 5 + ( field_name_pad("udp_total_length" ), "RW", 16, field_default(1430) ), -- 4 + ( field_name_pad("udp_checksum" ), "RW", 16, field_default(0) ), -- 3 + ( field_name_pad("dp_reserved" ), "RW", 47, field_default(x"010203040506") ), -- 2 + ( field_name_pad("dp_sync" ), "RW", 1, field_default(0) ), -- 1 + ( field_name_pad("dp_bsn" ), "RW", c_bsn_w, field_default(0) ) ); -- 0 -- TX: Corresponding storage of c_udp_offload_hdr_field_arr in MM register words -- . Note: It appears that the tx_hdr_word read values are the MM write values, so read of value from logic fields (with MM override '0', e.g. dp_bsn, eth_src_mac) is not supported. - CONSTANT c_expected_tx_hdr_word_arr : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words-1) := ( -- word address + CONSTANT c_expected_tx_hdr_word_arr_default : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words_default-1) := ( -- word address X"00000000", -- 0 = dp_bsn[31:0] -- readback is MM value, not the logic value - X"00000000", -- 1 = dp_bsn[63:32] + X"00000000", -- 1 = dp_bsn[c_bsn_w-1:32] X"00000000", -- 2 = dp_sync X"03040506", -- 3 = dp_reserved[31:0] X"00000102", -- 4 = dp_reserved[47:32] @@ -154,11 +189,38 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS X"214368AC", -- 24 = eth_dst_mac[31:0] X"0000001B"); -- 25 = eth_dst_mac[47:32] + CONSTANT c_expected_tx_hdr_word_arr_shortened : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words_shortened-1) := ( -- word address + X"00000000", -- 0 = dp_bsn[31:0] -- readback is MM value, not the logic value + X"00000000", -- 1 = dp_sync + X"03040506", -- 2 = dp_reserved[31:0] + X"00000102", -- 3 = dp_reserved[47:32] + X"00000000", -- 4 = udp_checksum + X"00000596", -- 5 = udp_total_length + X"00000000", -- 6 = udp_dst_port + X"00000000", -- 7 = udp_src_port -- readback is MM value, not the logic value + X"C0A80001", -- 8 = ip_dst_addr + X"C0A80009", -- 9 = ip_src_addr + X"000074E8", -- 10 = ip_header_checksum + X"00000011", -- 11 = ip_protocol + X"0000007F", -- 12 = ip_time_to_live + X"00000000", -- 13 = ip_fragment_offset + X"00000002", -- 14 = ip_flags + X"00000000", -- 15 = ip_identification + X"000005AA", -- 16 = ip_total_length + X"00000000", -- 17 = ip_services + X"00000005", -- 18 = ip_header_length + X"00000004", -- 19 = ip_version + X"00000800", -- 20 = eth_type[15:0] + X"456789AB", -- 21 = eth_src_mac[31:0] -- readback is MM value, not the logic value + X"00000123", -- 22 = eth_src_mac[47:32] + X"214368AC", -- 23 = eth_dst_mac[31:0] + X"0000001B"); -- 24 = eth_dst_mac[47:32] + -- RX: Corresponding storage of c_udp_offload_hdr_field_arr in MM register words - CONSTANT c_expected_rx_hdr_word_arr : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words-1) := ( -- word address - X"0000000B", -- 0 = dp_bsn[31:0] -- dynamic value obtained from simulation - X"00000000", -- 1 = dp_bsn[63:32] - X"00000000", -- 2 = dp_sync -- dynamic value obtained from simulation + CONSTANT c_expected_rx_hdr_word_arr_default : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words_default-1) := ( -- word address + X"00000002", -- 0 = dp_bsn[31:0] -- dynamic value obtained from simulation + X"00000000", -- 1 = dp_bsn[c_bsn_w-1:32] + X"00000001", -- 2 = dp_sync -- dynamic value obtained from simulation X"03040506", -- 3 = dp_reserved[31:0] X"00000102", -- 4 = dp_reserved[47:32] X"00000000", -- 5 = udp_checksum @@ -183,6 +245,33 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS X"214368AC", -- 24 = eth_dst_mac[31:0] X"0000001B"); -- 25 = eth_dst_mac[47:32] + CONSTANT c_expected_rx_hdr_word_arr_shortened : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words_shortened-1) := ( -- word address + X"00000002", -- 0 = dp_bsn[31:0] -- dynamic value obtained from simulation + X"00000001", -- 1 = dp_sync -- dynamic value obtained from simulation + X"03040506", -- 2 = dp_reserved[31:0] + X"00000102", -- 3 = dp_reserved[47:32] + X"00000000", -- 4 = udp_checksum + X"00000596", -- 5 = udp_total_length + X"00000000", -- 6 = udp_dst_port + X"00000000", -- 7 = udp_src_port + X"C0A80001", -- 8 = ip_dst_addr + X"C0A80009", -- 9 = ip_src_addr + X"000074E8", -- 10 = ip_header_checksum + X"00000011", -- 11 = ip_protocol + X"0000007F", -- 12 = ip_time_to_live + X"00000000", -- 13 = ip_fragment_offset + X"00000002", -- 14 = ip_flags + X"00000000", -- 15 = ip_identification + X"000005AA", -- 16 = ip_total_length + X"00000000", -- 17 = ip_services + X"00000005", -- 18 = ip_header_length + X"00000004", -- 19 = ip_version + X"00000800", -- 20 = eth_type[15:0] + X"86080000", -- 21 = eth_src_mac[31:0] -- readback is the logic value x"00228608" & id_backplane = 0 & id_chip = 0 (c_NODE_ID = 0) + X"00000022", -- 22 = eth_src_mac[47:32] + X"214368AC", -- 23 = eth_dst_mac[31:0] + X"0000001B"); -- 24 = eth_dst_mac[47:32] + -- From apertif_unb1_fn_beamformer_udp_offload.vhd: 221 111111111000 0000 000 -- Override ('1') only the Ethernet fields so we can use MM defaults there. 109 876543210987 6543 210 CONSTANT c_hdr_field_ovr_init : STD_LOGIC_VECTOR(c_udp_offload_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111111"&"1111"&"100"; @@ -250,6 +339,7 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS SIGNAL verify_snk_out : t_dp_siso := c_dp_siso_rdy; SIGNAL verify_snk_in : t_dp_sosi; SIGNAL verify_snk_in_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + SIGNAL prev_verify_snk_in_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); BEGIN @@ -279,7 +369,7 @@ BEGIN g_bsn_init => c_bsn_init, -- specific g_in_dat_w => g_data_w, - g_nof_repeat => g_nof_repeat, + g_nof_repeat => c_nof_packets, g_pkt_len => g_pkt_len, g_pkt_gap => g_pkt_gap, g_wait_last_evt => c_wait_last_evt @@ -403,13 +493,13 @@ BEGIN tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "ip_src_addr" )) <= x"0A63" & id_backplane & INCR_UVEC(id_chip, 1); tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "dp_sync" ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "dp_sync" )) <= slv(dp_offload_tx_snk_in_arr(0).sync); - tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "dp_bsn" )) <= dp_offload_tx_snk_in_arr(0).bsn(63 DOWNTO 0); + tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "dp_bsn" )) <= dp_offload_tx_snk_in_arr(0).bsn(c_bsn_w-1 DOWNTO 0); u_tx : ENTITY work.dp_offload_tx_v3 GENERIC MAP ( g_nof_streams => 1, g_data_w => g_data_w, - g_symbol_w => g_data_w, + g_symbol_w => g_symbol_w, g_hdr_field_arr => c_udp_offload_hdr_field_arr, g_hdr_field_sel => c_hdr_field_ovr_init ) @@ -438,20 +528,23 @@ BEGIN VARIABLE v_word : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); BEGIN proc_common_wait_until_hi_lo(dp_clk, tx_offload_sosi_arr(0).sync); - proc_common_wait_until_hi_lo(dp_clk, tx_offload_sosi_arr(0).sync); - print_str(""); + print_str("", g_print_en); FOR I IN 0 TO c_udp_offload_nof_hdr_words-1 LOOP proc_mem_mm_bus_rd(I, mm_clk, reg_dp_offload_tx_hdr_dat_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); v_word := reg_dp_offload_tx_hdr_dat_miso.rddata(31 DOWNTO 0); -- Log word in transcript window - print_str("tx_hdr_word(" & int_to_str(I) & ") = " & slv_to_hex(v_word)); + print_str("tx_hdr_word(" & int_to_str(I) & ") = " & slv_to_hex(v_word), g_print_en); -- View word in wave window tx_hdr_word <= v_word; -- Verify expected word - ASSERT c_expected_tx_hdr_word_arr(I) = v_word REPORT "Unexpected tx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_tx_hdr_word_arr(I)) SEVERITY ERROR; + IF c_use_shortened_header THEN + ASSERT c_expected_tx_hdr_word_arr_shortened(I) = v_word REPORT "Unexpected tx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_tx_hdr_word_arr_shortened(I)) SEVERITY ERROR; + ELSE + ASSERT c_expected_tx_hdr_word_arr_default(I) = v_word REPORT "Unexpected tx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_tx_hdr_word_arr_default(I)) SEVERITY ERROR; + END IF; END LOOP; - print_str(""); + print_str("", g_print_en); WAIT; END PROCESS; @@ -481,6 +574,7 @@ BEGIN GENERIC MAP ( g_nof_streams => 1, g_data_w => g_data_w, + g_symbol_w => g_symbol_w, g_hdr_field_arr => c_udp_offload_hdr_field_arr, g_remove_crc => FALSE, g_crc_nof_words => 0 @@ -520,24 +614,69 @@ BEGIN VARIABLE v_word : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); BEGIN proc_common_wait_until_hi_lo(dp_clk, verify_snk_in.sync); - proc_common_wait_until_hi_lo(dp_clk, verify_snk_in.sync); - proc_common_wait_until_hi_lo(dp_clk, verify_snk_in.sync); - print_str(""); + -- Check first packet after sync with dp_sync = 1 + -- wait some latency until header fields of this sync packet are available via MM + proc_common_wait_some_cycles(dp_clk, 10); + print_str("", g_print_en); FOR I IN 0 TO c_udp_offload_nof_hdr_words-1 LOOP proc_mem_mm_bus_rd(I, mm_clk, reg_dp_offload_rx_hdr_dat_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); v_word := reg_dp_offload_rx_hdr_dat_miso.rddata(31 DOWNTO 0); -- Log word in transcript window - print_str("rx_hdr_word(" & int_to_str(I) & ") : " & slv_to_hex(v_word)); + print_str("rx_hdr_word(" & int_to_str(I) & ") : " & slv_to_hex(v_word), g_print_en); -- View word in wave window rx_hdr_word <= v_word; -- Verify expected word - ASSERT c_expected_rx_hdr_word_arr(I) = v_word REPORT "Unexpected rx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_rx_hdr_word_arr(I)) SEVERITY ERROR; + IF c_use_shortened_header THEN + ASSERT v_word = c_expected_rx_hdr_word_arr_shortened(I) REPORT "Unexpected rx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_rx_hdr_word_arr_shortened(I)) SEVERITY ERROR; + ELSE + ASSERT v_word = c_expected_rx_hdr_word_arr_default(I) REPORT "Unexpected rx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_rx_hdr_word_arr_default(I)) SEVERITY ERROR; + END IF; END LOOP; - print_str(""); + print_str("", g_print_en); + + -- Check dp_bsn and dp_sync of second packet after sync with dp_sync = 0 + proc_common_wait_until_hi_lo(dp_clk, verify_snk_in.sop); + -- wait some latency until header fields of this sync packet are available via MM + proc_common_wait_some_cycles(dp_clk, 10); + -- dp_bsn lo + proc_mem_mm_bus_rd(0, mm_clk, reg_dp_offload_rx_hdr_dat_mosi); + proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); + v_word := reg_dp_offload_rx_hdr_dat_miso.rddata(31 DOWNTO 0); + rx_hdr_word <= v_word; -- View word in wave window + IF c_use_shortened_header THEN + ASSERT v_word = INCR_UVEC(c_expected_rx_hdr_word_arr_shortened(0), 1) REPORT "Unexpected dp_bsn from MM" SEVERITY ERROR; + ELSE + ASSERT v_word = INCR_UVEC(c_expected_rx_hdr_word_arr_default(0), 1) REPORT "Unexpected dp_bsn from MM" SEVERITY ERROR; + END IF; + -- dp_sync + IF c_use_shortened_header THEN + proc_mem_mm_bus_rd(1, mm_clk, reg_dp_offload_rx_hdr_dat_mosi); + ELSE + proc_mem_mm_bus_rd(2, mm_clk, reg_dp_offload_rx_hdr_dat_mosi); + END IF; + proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); + v_word := reg_dp_offload_rx_hdr_dat_miso.rddata(31 DOWNTO 0); + rx_hdr_word <= v_word; -- View word in wave window + ASSERT v_word = TO_UVEC(0, 32) REPORT "Unexpected dp_sync from MM" SEVERITY ERROR; + WAIT; END PROCESS; + p_verify_snk_in_data : PROCESS + BEGIN + -- Note: This verification overlaps with u_dp_stream_verify because that also verifies incrementing valid data. + WAIT UNTIL rising_edge(dp_clk); + prev_verify_snk_in_data <= verify_snk_in.data(g_data_w-1 DOWNTO 0); + IF verify_snk_in.sop = '1' THEN + ASSERT TO_UINT(verify_snk_in.data) MOD g_pkt_len = 0 REPORT "Wrong decoded data at sop." SEVERITY ERROR; + ELSIF verify_snk_in.eop = '1' THEN + ASSERT TO_UINT(verify_snk_in.data) MOD g_pkt_len = g_pkt_len - 1 REPORT "Wrong decoded data at eop." SEVERITY ERROR; + ELSIF verify_snk_in.valid = '1' THEN + ASSERT TO_UINT(verify_snk_in.data) = TO_UINT(prev_verify_snk_in_data) + 1 REPORT "Wrong decoded data at valid." SEVERITY ERROR; + END IF; + END PROCESS; + ------------------------------------------------------------------------------ -- Auxiliary diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_offload_tx_v3.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_offload_tx_v3.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f55d74d6584f394a5bbe5326a81c6eafd0abb84e --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_offload_tx_v3.vhd @@ -0,0 +1,60 @@ +-- -------------------------------------------------------------------------- +-- Copyright 2021 +-- 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: E. Kooistra, Jan 2022 +-- Purpose: Regression multi tb for dp_offload_tx_v3 and dp_offload_rx +-- Description: +-- Usage: +-- > as 5 +-- > run -all + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE work.tb_dp_pkg.ALL; -- for t_dp_flow_control_enum + +ENTITY tb_tb_dp_offload_tx_v3 IS +END tb_tb_dp_offload_tx_v3; + + +ARCHITECTURE tb OF tb_tb_dp_offload_tx_v3 IS + + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' + +BEGIN + + -- -- general + -- g_flow_control_stimuli : t_dp_flow_control_enum := e_pulse; -- always e_active, e_random or e_pulse flow control + -- g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control + -- g_print_en : BOOLEAN := TRUE; + -- -- specific + -- g_data_w : NATURAL := 64; + -- g_symbol_w : NATURAL := 16; + -- g_pkt_len : NATURAL := 240; + -- g_pkt_gap : NATURAL := 16 + + u_pls_act_data_w_64 : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_pulse, e_active, FALSE, 64, 64, 240, 16); + u_pls_act_data_w_64_no_gap : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_pulse, e_active, FALSE, 64, 64, 240, 0); + u_rnd_act_data_w_64 : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_random, e_active, FALSE, 64, 64, 240, 16); + u_rnd_act_data_w_32 : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_random, e_active, FALSE, 32, 32, 240, 16); + --u_act_rnd_data_w : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_active, e_random, FALSE, 64, 64, 240, 16); + u_rnd_act_data_64_symbol_16 : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_random, e_active, FALSE, 64, 16, 240, 16); + u_rnd_act_data_64_symbol_32 : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_random, e_active, FALSE, 64, 32, 240, 16); + u_rnd_act_data_32_symbol_8 : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_random, e_active, FALSE, 32, 8, 240, 16); + u_rnd_act_data_32_symbol_16 : ENTITY work.tb_dp_offload_tx_v3 GENERIC MAP (e_random, e_active, FALSE, 32, 16, 240, 16); + +END tb;