diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd index 699432520d6dd52630da4eba11077828468f1e42..accf8edef90703a6ed9c6fe3668b04de0875c022 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd @@ -42,7 +42,7 @@ use work.tb_sdp_pkg.all; entity tb_sdp_beamformer_output is generic ( - g_nof_repeat : natural := 10; + g_nof_repeat : natural := 50; g_beamset_id : natural := 0; g_use_transpose : boolean := false; g_use_multiple_destinations : boolean := false @@ -53,17 +53,25 @@ architecture tb of tb_sdp_beamformer_output is constant c_dp_clk_period : time := 5 ns; -- 200 MHz constant c_mm_clk_period : time := 1 ns; -- fast MM clk to speed up simulation - constant c_cross_clock_domain_latency : natural := 20; - - constant c_bf_block_len : natural := c_sdp_N_pol_bf * c_sdp_S_sub_bf; -- = 2 * 488 = 976 - constant c_bf_gap_size : natural := c_sdp_N_fft - c_bf_block_len; -- = 1024 - 976 = 48 - - constant c_exp_beamlet_scale : natural := natural(1.0 / 2.0**9 * real(c_sdp_unit_beamlet_scale)); - constant c_exp_beamlet_scale_slv : std_logic_vector(c_sdp_W_beamlet_scale-1 downto 0) := - to_uvec(c_exp_beamlet_scale, c_sdp_W_beamlet_scale); - constant c_exp_gn_id : natural := 3; - constant c_exp_gn_id_slv : std_logic_vector(c_sdp_W_gn_id - 1 downto 0) := - to_uvec(c_exp_gn_id, c_sdp_W_gn_id); + constant c_init_bsn : natural := 0; + constant c_bf_block_len : natural := c_sdp_N_pol_bf * c_sdp_S_sub_bf; -- = 2 * 488 = 976 + constant c_bf_gap_size : natural := c_sdp_N_fft - c_bf_block_len; -- = 1024 - 976 = 48 + + constant c_exp_beamlet_scale : natural := natural(1.0 / 2.0**9 * real(c_sdp_unit_beamlet_scale)); + constant c_exp_beamlet_scale_slv : std_logic_vector(c_sdp_W_beamlet_scale-1 downto 0) := + to_uvec(c_exp_beamlet_scale, c_sdp_W_beamlet_scale); + constant c_gn_id : natural := 3; + constant c_gn_id_slv : std_logic_vector(c_sdp_W_gn_id - 1 downto 0) := + to_uvec(c_gn_id, c_sdp_W_gn_id); + constant c_id : std_logic_vector(7 downto 0) := to_uvec(c_gn_id, 8); + constant c_cep_eth_src_mac : std_logic_vector(47 downto 0) := c_sdp_cep_eth_src_mac_47_16 & func_sdp_gn_index_to_mac_15_0(c_gn_id); + constant c_cep_ip_src_addr : std_logic_vector(31 downto 0) := c_sdp_cep_ip_src_addr_31_16 & func_sdp_gn_index_to_ip_15_0(c_gn_id); + constant c_cep_udp_src_port : std_logic_vector(15 downto 0) := c_sdp_cep_udp_src_port_15_8 & c_id; + + -- Checksum value obtained from rx_sdp_cep_header.ip.header_checksum in wave window + constant c_exp_ip_header_checksum : natural := 16#5BDB#; + constant c_exp_payload_error : std_logic := '0'; + constant c_exp_beamlet_index : natural := g_beamset_id * c_sdp_S_sub_bf; constant c_exp_sdp_info : t_sdp_info := (to_uvec(7, 6), -- antenna_field_index to_uvec(601, 10), -- station_id @@ -76,8 +84,6 @@ architecture tb of tb_sdp_beamformer_output is x"1400" -- block_period = 5120 ); - constant c_beamlet_index : natural := g_beamset_id * c_sdp_S_sub_bf; - signal tb_end : std_logic := '0'; signal dp_clk : std_logic := '1'; signal dp_rst : std_logic; @@ -105,8 +111,25 @@ architecture tb of tb_sdp_beamformer_output is signal rx_hdr_dat_cipo : t_mem_cipo; signal rx_hdr_fields_out : std_logic_vector(1023 downto 0); signal rx_hdr_fields_raw : std_logic_vector(1023 downto 0) := (others => '0'); - signal rx_sdp_cep_header : t_sdp_cep_header; - signal rx_beamlet_sosi : t_dp_sosi; + signal rx_beamlet_header : t_sdp_cep_header; + signal exp_beamlet_header : t_sdp_cep_header; + signal exp_dp_bsn : natural; + + -- Beamlets packets data + signal rx_beamlet_data : std_logic_vector(c_longword_w - 1 downto 0); -- 64 bit + signal rx_beamlet_sosi : t_dp_sosi := c_dp_sosi_rst; + signal rx_beamlet_sop_cnt : natural := 0; + signal rx_beamlet_eop_cnt : natural := 0; + + -- [0 : 3] = X, Y, X, Y + signal rx_beamlet_arr_re : t_sdp_beamlet_part_arr; + signal rx_beamlet_arr_im : t_sdp_beamlet_part_arr; + signal rx_beamlet_cnt : natural; + signal rx_beamlet_valid : std_logic; + + -- [0 : 4 * 488 * 2 - 1] = [0 : 3903] + signal rx_packet_list_re : t_sdp_beamlet_packet_list; + signal rx_packet_list_im : t_sdp_beamlet_packet_list; begin dp_rst <= '1', '0' after c_dp_clk_period * 7; dp_clk <= (not dp_clk) or tb_end after c_dp_clk_period / 2; @@ -115,11 +138,25 @@ begin mm_clk <= (not mm_clk) or tb_end after c_mm_clk_period / 2; p_mm : process - variable v_offset : natural; begin proc_common_wait_until_low(dp_clk, mm_rst); proc_common_wait_some_cycles(mm_clk, 10); + ---------------------------------------------------------------------------- + -- Header fields + ---------------------------------------------------------------------------- + -- . Use sim default dst and src MAC, IP, UDP port from sdp_pkg.vhd and + -- based on c_gn_id + -- . use signed to fit 32 b in integer + proc_mem_mm_bus_wr(39, to_uint(c_cep_eth_src_mac(47 downto 32)), mm_clk, hdr_dat_cipo, hdr_dat_copi); + proc_mem_mm_bus_wr(38, to_sint(c_cep_eth_src_mac(31 downto 0)), mm_clk, hdr_dat_cipo, hdr_dat_copi); + proc_mem_mm_bus_wr(26, to_sint(c_cep_ip_src_addr), mm_clk, hdr_dat_cipo, hdr_dat_copi); + proc_mem_mm_bus_wr(24, to_uint(c_cep_udp_src_port), mm_clk, hdr_dat_cipo, hdr_dat_copi); + proc_mem_mm_bus_wr(41, to_uint(c_sdp_cep_eth_dst_mac(47 downto 32)), mm_clk, hdr_dat_cipo, hdr_dat_copi); + proc_mem_mm_bus_wr(40, to_sint(c_sdp_cep_eth_dst_mac(31 downto 0)), mm_clk, hdr_dat_cipo, hdr_dat_copi); + proc_mem_mm_bus_wr(25, to_sint(c_sdp_cep_ip_dst_addr), mm_clk, hdr_dat_cipo, hdr_dat_copi); + proc_mem_mm_bus_wr(23, to_uint(c_sdp_cep_udp_dst_port), mm_clk, hdr_dat_cipo, hdr_dat_copi); + ---------------------------------------------------------------------------- -- Enable beamlet output (dp_xonoff) ---------------------------------------------------------------------------- @@ -135,7 +172,7 @@ begin g_use_complex => true, g_re_init => 0, g_im_init => 1, - g_bsn_init => TO_DP_BSN(0), + g_bsn_init => TO_DP_BSN(c_init_bsn), g_err_init => 0, -- not used g_err_incr => 0, -- not used g_channel_init => 0, -- not used @@ -165,7 +202,8 @@ begin generic map ( g_beamset_id => g_beamset_id, g_use_transpose => g_use_transpose, - g_use_multiple_destinations => g_use_multiple_destinations + g_use_multiple_destinations => g_use_multiple_destinations, + g_sim_force_bsn_error => false ) port map ( mm_clk => mm_clk, @@ -189,7 +227,7 @@ begin sdp_info => c_exp_sdp_info, beamlet_scale => c_exp_beamlet_scale_slv, - gn_id => c_exp_gn_id_slv, + gn_id => c_gn_id_slv, -- Source MAC/IP/UDP are not used, c_sdp_cep_hdr_field_sel selects MM programmable instead eth_src_mac => bdo_eth_src_mac, @@ -227,5 +265,66 @@ begin hdr_fields_raw_arr(0) => rx_hdr_fields_raw ); - rx_sdp_cep_header <= func_sdp_map_cep_header(rx_hdr_fields_raw); + ----------------------------------------------------------------------------- + -- Beamlet offload packet header + ----------------------------------------------------------------------------- + + -- Counters to time expected cep_header fields per offload packet + p_test_counters : process(dp_clk) + begin + if rising_edge(dp_clk) then + -- Count rx_beamlet_sosi packets + if rx_beamlet_sosi.sop = '1' then + rx_beamlet_sop_cnt <= rx_beamlet_sop_cnt + 1; -- early count + end if; + if rx_beamlet_sosi.eop = '1' then + rx_beamlet_eop_cnt <= rx_beamlet_eop_cnt + 1; -- after count + end if; + end if; + end process; + + -- Prepare exp_beamlet_header before rx_beamlet_sosi.eop, so that + -- p_verify_beamlet_header can verify it at rx_beamlet_sosi.eop. + exp_beamlet_header <= func_sdp_compose_cep_header(c_exp_ip_header_checksum, + c_exp_sdp_info, + c_gn_id, + c_exp_payload_error, + c_exp_beamlet_scale, + c_exp_beamlet_index, + exp_dp_bsn); + + rx_beamlet_header <= func_sdp_map_cep_header(rx_hdr_fields_raw); + + p_verify_beamlet_header : process + variable v_bool : boolean; + begin + wait until rising_edge(dp_clk); + -- Prepare exp_sdp_cep_header at sop, so that it can be verified at eop + if rx_beamlet_sosi.sop = '1' then + -- Expected BSN increments by c_sdp_cep_nof_blocks_per_packet = 4 blocks + -- per packet + exp_dp_bsn <= c_init_bsn + rx_beamlet_sop_cnt * c_sdp_cep_nof_blocks_per_packet; + end if; + + -- Verify header at eop + if rx_beamlet_sosi.eop = '1' then + v_bool := func_sdp_verify_cep_header(rx_beamlet_header, exp_beamlet_header); + end if; + end process; + + ----------------------------------------------------------------------------- + -- Beamlet offload packet data + ----------------------------------------------------------------------------- + -- To view the 64 bit 10GbE offload data more easily in the Wave window + rx_beamlet_data <= rx_beamlet_sosi.data(c_longword_w - 1 downto 0); + + proc_sdp_cep_rx_beamlets(dp_clk, + rx_beamlet_sosi, + rx_beamlet_cnt, + rx_beamlet_valid, + rx_beamlet_arr_re, + rx_beamlet_arr_im, + rx_packet_list_re, + rx_packet_list_im); + end tb;