diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd index b3b3067065e14afdf021358367bcd89ad29ba9e7..150c90d5e913b9f17340cd19aae8851d6ad8ebdf 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd @@ -54,6 +54,8 @@ -- TODO: -- . test parallel dump and serial dump -- . read ring MP +-- . check MAC, IP, UDP set on other nodes +-- . larger g_nof_rn, g_nof_rn = 16 -- -- References: -- [1] https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Transient+buffer+raw+data @@ -65,18 +67,11 @@ -- > as 11 # for detailed debugging -- > run -a -- . view: --- . rx_beamlets_header.app for beamlet packet header -- . rx_dump_header.app for dump packet header -- . rx_ant_sosi and rx_ant_data_arr (to show global SP with corresponding DC level) for dump packet data --- . copy usedw of tx FIFOs in Wave Window in analog format and as bits to see and compare their fill levels and --- spare space when g_rs_block_size, for tx FIFOs in: --- . nw_10GbE --- . sdp_beamformer_output of bf[0] --- . sdp_beamformer_output of bf[1] --- . sdp_tbuf_output tx FIFO --- . Use "cat transcript| grep Error:" in git/hdl directory to ease spotting simulation ERRORs +-- . Use "cat transcript| grep Error:" to ease spotting simulation ERRORs -- --- View extra signals (for g_nof_rn = 2): +-- View extra signals per gen_dut() to track transport along the ring: -- add wave -position insertpoint \ -- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(0)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tbuf_from_ri_sosi \ -- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(0)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tbuf_to_ri_sosi \ @@ -92,21 +87,6 @@ -- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(0)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tr_10gbe_ring_snk_out_arr \ -- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(0)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tr_10gbe_ring_src_out_arr \ -- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(0)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tr_10gbe_ring_src_in_arr --- add wave -position insertpoint \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tbuf_from_ri_sosi \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tbuf_to_ri_sosi \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/even_lane_rx_cable_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/even_lane_tx_cable_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/even_lane_rx_board_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/even_lane_tx_board_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/odd_lane_rx_cable_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/odd_lane_tx_cable_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/odd_lane_rx_board_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/odd_lane_tx_board_sosi_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tr_10gbe_ring_snk_in_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tr_10gbe_ring_snk_out_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tr_10gbe_ring_src_out_arr \ --- sim:/tb_lofar2_unb2c_sdp_station_tbuf_ring/gen_dut(1)/u_lofar_unb2c_sdp_station_tbuf_ring/u_sdp_station/tr_10gbe_ring_src_in_arr ------------------------------------------------------------------------------- library IEEE, common_lib, mm_lib, dp_lib, diag_lib, i2c_lib, wpfb_lib; library tech_pll_lib, tr_10GbE_lib, unb2c_board_lib; @@ -139,12 +119,12 @@ entity tb_lofar2_unb2c_sdp_station_tbuf_ring is g_nof_rn : natural := 2; -- nof ring nodes (RN) in ring g_ddr_buffer_size : natural := 256; -- <= 4096, because c_tech_ddr4_sim_4k_64 has 4k = 4096 words of -- c_sdp_tbuf_W_word = 512b - g_rs_block_size : natural := 102; -- c_sdp_tbuf_rs_block_size = 2000, must be even see sdp_tbuf_output - g_rs_record_nof_block : natural := 3; -- choose > c_rs_nof_block_per_sync to have at least on sync interval + g_rs_block_size : natural := 100; -- c_sdp_tbuf_rs_block_size = 2000, must be even see sdp_tbuf_output + g_rs_record_nof_block : natural := 6; -- choose > c_rs_nof_block_per_sync to have at least on sync interval -- for the RSN monitor g_dump_inter_packet_gap : natural := 0; -- use 1708 for 3 Gbps and g_rs_block_size = 2000 g_dump_page_offset : natural := 0; -- offset relative to recorded_first_page - g_dump_nof_pages : natural := 1; -- g_dump_page_offset + g_dump_nof_pages <= g_rs_record_nof_block, else + g_dump_nof_pages : natural := 5; -- g_dump_page_offset + g_dump_nof_pages <= g_rs_record_nof_block, else -- there will occur read RSN errors for pages that are not available g_dump_enables : std_logic_vector(c_sdp_A_pn - 1 downto 0) := "100001" ); @@ -220,6 +200,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is constant c_dump_ai_indices : t_nat_integer_arr(g_dump_enables'range) := vector_one_indices(g_dump_enables); constant c_dump_nof_packets_per_ai : natural := c_dump_nof_pages_actual; constant c_memory_read_nof_packets : natural := c_dump_nof_ai * c_dump_nof_packets_per_ai; + constant c_dump_total_nof_packets : natural := c_memory_read_nof_packets * g_nof_rn; -- SDP info constant c_exp_sdp_info : t_sdp_info := ( @@ -234,35 +215,15 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is x"1400" -- block_period = 5120 ); - -- TBuf dump header fields + -- TBuf dump header fields, from 10GbE output at last GN in ring 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_last_gn); - -- The ip_header_checksum depends on src IP, and therefore on the c_last_gn. The value is obtained from - -- rx_sdp_cep_header.ip.header_checksum in wave window for c_last_gn = 6. Therefore in this tb use - -- func_sdp_gn_index_to_ip_15_0(6) to have fixed c_exp_ip_header_checksum, independent of actual c_last_gn. 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(6); + c_sdp_cep_ip_src_addr_31_16 & func_sdp_gn_index_to_ip_15_0(c_last_gn); constant c_cep_udp_src_port : std_logic_vector(15 downto 0) := c_sdp_cep_udp_src_port_15_8 & c_last_id; - -- Determine expected ip_header_checksum for c_unb_nr = 1, c_node_nr = 2 so c_last_gn = c_unb_nr * 4 + c_node_nr = - -- 6, and c_rs_block_size. Value obtained from rx_dump_header.ip.header_checksum in wave window - function func_exp_ip_header_checksum(g_rs_block_size : natural) return natural is - begin - if g_rs_block_size = 100 then - return 16#7806#; - elsif g_rs_block_size = 102 then - return 16#77FF#; - elsif g_rs_block_size = 2000 then - return 16#5E0C#; - else - return 0; - end if; - end func_exp_ip_header_checksum; - - constant c_exp_ip_header_checksum : natural := func_exp_ip_header_checksum(g_rs_block_size); - constant c_packed_empty_w : natural := 3; -- = ceil_log2(c_longword_sz - 1) - constant c_rx_fifo_size : natural := g_rs_block_size; + constant c_rx_fifo_size : natural := g_rs_block_size * g_nof_rn; -- WG -- . Observe WG using rs_sosi.sop and rs_data_arr() in decimal format in Wave Window. @@ -291,14 +252,11 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is signal i_tb_end : std_logic := '0'; signal tb_clk : std_logic := '0'; signal rd_data_setup : std_logic_vector(c_32 - 1 downto 0); - signal rd_data_state : std_logic_vector(c_32 - 1 downto 0); signal rd_data_control : std_logic_vector(c_32 - 1 downto 0); - signal rd_data_monitor : std_logic_vector(c_32 - 1 downto 0); signal rd_data_bsn : std_logic_vector(c_32 - 1 downto 0); signal rd_data_record_busy : std_logic_vector(c_32 - 1 downto 0); signal rd_data_dump_done : std_logic_vector(c_32 - 1 downto 0); signal rd_data_strobe : std_logic_vector(c_32 - 1 downto 0); - signal rd_data_nw_10gbe_mac : std_logic_vector(c_32 - 1 downto 0); signal dest_rst : std_logic := '1'; -- use separate destination rst for Rx 10GbE in tb signal pps_rst : std_logic := '1'; -- use separate reset to release the PPS generator @@ -322,10 +280,10 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is signal tbuf_strobe_total_counts : t_sdp_tbuf_strobe_total_counts_ro; signal recording_rsn_at_sync : natural; signal recording_nof_sop_per_sync : natural; - signal dump_index : natural; - signal time_index : natural; signal read_busy_arr : std_logic_vector(c_last_rn downto 0) := (others => '0'); signal dump_rate_bps : real := 0.0; + signal dump_index : natural; + signal dump_start_rsn : natural; signal dbg_c_exp_read_rate_bps : real := c_exp_read_rate_bps; signal dbg_c_exp_dump_rate_bps : real := c_exp_dump_rate_bps; @@ -334,7 +292,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is signal dbg_c_dump_nof_packets_per_ai : natural := c_dump_nof_packets_per_ai; signal exp_strobe_total_counts_arr : t_sdp_tbuf_strobe_total_counts_ro_arr(0 to g_nof_rn - 1) := - func_expected_tbuf_strobe_total_counts_arr(c_memory_read_nof_packets, g_nof_rn, c_lane_direction); + func_sdp_tbuf_expected_strobe_total_counts_arr(c_memory_read_nof_packets, g_nof_rn, c_lane_direction); -- CEP model -- . 10GbE @@ -349,17 +307,20 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is signal rx_dump_sosi : t_dp_sosi := c_dp_sosi_rst; -- Dump packets header - signal tb_dump_cnt : natural := 0; signal rx_dump_header : t_sdp_tbuf_cep_header; signal exp_dump_header : t_sdp_tbuf_cep_header; + signal exp_dump_header_arr : t_sdp_tbuf_cep_header_arr(0 to c_dump_total_nof_packets - 1); + signal rx_dump_marker : natural; signal rx_dump_station_info : t_sdp_station_info; signal exp_dump_station_info : t_sdp_station_info; signal exp_dump_ai : natural; signal exp_dp_rsn : natural; + signal rx_dump_packet_cnt : natural := 0; + signal exp_dump_total_nof_packets : natural := c_dump_total_nof_packets; + -- Dump packets data - signal rx_dump_packet_cnt : natural := 0; signal rx_fifo_siso : t_dp_siso; signal rx_fifo_sosi : t_dp_sosi; signal rx_ant_sosi : t_dp_sosi := c_dp_sosi_rst; @@ -669,7 +630,8 @@ begin mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO", 6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk); mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO", 5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk); mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO", 4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk); - mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO", 1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk); + mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO", 1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), + tb_clk); end loop; ---------------------------------------------------------------------------- @@ -967,6 +929,8 @@ begin v_gn := g_first_gn + RN; mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 3, to_int(tbuf_registers_wr.record_enable), tb_clk); end loop; + proc_common_wait_cross_clock_domain_latency( + c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2); -- Wait until recording has finished, read record_busy to account for latency in record_enable disabled mmf_mm_wait_until_value( @@ -1101,7 +1065,7 @@ begin dump_rate_bps <= v_dump_rate_bps; -- Verify dump rate over sufficient number of packets - if c_memory_read_nof_packets > 5 then + if c_memory_read_nof_packets > 5 and g_rs_block_size >= 100 then -- . use almost_equal(a/b, 1.0, max_ratio) to verify that a and b differ less than max_ratio/100 percent assert almost_equal(v_dump_rate_bps / c_exp_dump_rate_bps, 1.0, c_dump_rate_delta) report c_tb_str & v_rn_str & "Wrong dump rate" @@ -1198,6 +1162,14 @@ begin print_str(c_tb_str & v_rn_str & "tbuf_registers_ro.dump_done = " & sl_to_str(tbuf_registers_ro.dump_done)); end loop; + --------------------------------------------------------------------------- + -- Check that all dumped packets were received + --------------------------------------------------------------------------- + assert rx_dump_packet_cnt = c_dump_total_nof_packets + report c_tb_str & "Wrong rx_dump_packet_cnt: " & int_to_str(rx_dump_packet_cnt) & " /= " & + int_to_str(c_dump_total_nof_packets) + severity ERROR; + --------------------------------------------------------------------------- -- Almost end simulation --------------------------------------------------------------------------- @@ -1208,57 +1180,59 @@ begin ----------------------------------------------------------------------------- -- Verify TBuf dump packet header ----------------------------------------------------------------------------- - -- Prepare exp_dump_header before rx_dump_sosi.eop. - exp_dump_header <= func_sdp_tbuf_compose_cep_header(c_cep_ip_src_addr, - c_exp_ip_header_checksum, - c_exp_sdp_info, - c_last_gn, - c_sdp_W_adc, - exp_dump_ai, - g_rs_block_size, - exp_dp_rsn); + -- Prepare exp_dump_header_arr[c_dump_total_nof_packets] = + -- exp_dump_header_arr[g_nof_rn][c_dump_nof_ai][c_dump_nof_packets_per_ai] with expected headers for all + -- dump packets + -- . Do not verify the ip_header_checksum, because it depends on src IP, and therefore on last GN, and on IP size + -- and therefore on g_rs_block_size. + dump_start_rsn <= to_uint(tbuf_registers_wr.dump_start_rsn); + exp_dump_header_arr <= func_sdp_tbuf_compose_cep_header_arr(g_nof_rn, + c_dump_nof_ai, + c_dump_nof_packets_per_ai, + c_dump_ai_indices, + g_first_gn, + dump_start_rsn, + c_cep_ip_src_addr, + c_exp_sdp_info, + g_rs_block_size); + exp_dump_station_info <= func_sdp_map_station_info(exp_dump_header.app.sdp_station_info); rx_dump_station_info <= func_sdp_map_station_info(rx_dump_header.app.sdp_station_info); --- p_verify_rx_dump_header : process --- variable v_dump_index : natural; --- variable v_time_index : natural; --- variable v_ai_local : natural; --- variable v_cnt : natural; --- variable v_bool : boolean; --- begin --- wait until rising_edge(ext_clk); --- if c_dump_nof_packets_per_ai > 0 then --- -- Count rx_dump_sosi packets at sop --- if rx_dump_sosi.sop = '1' then --- -- Determine expected antenna_input_index assuming c_dump_nof_packets_per_ai per ai. Use modulo --- -- c_memory_read_nof_packets to account for c_nof_dump > 1 --- v_cnt := rx_dump_packet_cnt mod c_memory_read_nof_packets; --- v_dump_index := v_cnt / c_dump_nof_packets_per_ai; --- v_ai_local := c_dump_ai_indices(v_dump_index); --- exp_dump_ai <= c_first_ai + v_ai_local; --- --- -- Determine expected RSN assuming c_dump_nof_packets_per_ai per ai --- v_time_index := v_cnt mod c_dump_nof_packets_per_ai; --- exp_dp_rsn <= to_uint(tbuf_registers_wr.dump_start_rsn) + v_time_index * g_rs_block_size; --- --- -- Increment rx_dump_packet_cnt signal --- rx_dump_packet_cnt <= rx_dump_packet_cnt + 1; --- end if; --- -- Verify header at eop --- if rx_dump_sosi.eop = '1' then --- v_bool := func_sdp_tbuf_verify_cep_header(rx_dump_header, exp_dump_header); --- end if; --- -- View variables in Wave Window --- dump_index <= v_dump_index; --- time_index <= v_time_index; --- else --- -- Expect no dump packets when g_dump_nof_pages = 0 --- assert rx_dump_sosi.sop = '0' --- report c_tb_str & "Wrong unexpected rx_dump_sosi packet for g_dump_nof_pages = 0" --- severity ERROR; + p_verify_rx_dump_header : process + variable v_rn : natural; + variable v_ai : natural; + variable v_ai_index : natural; + variable v_page : natural; + variable v_dump_index : natural; + variable v_bool : boolean; + begin + -- The last packets from a ring node may arrive before the first packet from the next node, therefore check + -- whether the received rx_dump_header exists in exp_dump_header_arr. + wait until rising_edge(ext_clk); + -- Prepare exp_dump_header at sop, assuming that the gn, ai_index and rsn in the rx_dump_header are correct. + if rx_dump_sosi.sop = '1' then + v_rn := to_uint(rx_dump_header.app.sdp_source_info_gn_id) - g_first_gn; + v_ai := to_uint(rx_dump_header.app.sdp_antenna_input_index) mod c_sdp_A_pn; + v_ai_index := vector_find_index(v_ai, c_dump_ai_indices); + if v_ai_index < 0 then + report c_tb_str & "Wrong unexpected antenna input index" + severity ERROR; + v_ai_index := 0; -- force to in range value + end if; + v_page := (to_uint(rx_dump_header.app.dp_rsn) - dump_start_rsn) / g_rs_block_size; + v_dump_index := (v_rn * c_dump_nof_ai + v_ai_index) * c_dump_nof_packets_per_ai + v_page; + exp_dump_header <= exp_dump_header_arr(v_dump_index); + -- Count dump packets + rx_dump_packet_cnt <= rx_dump_packet_cnt + 1; + end if; + -- Verify rx_dump_sosi header at eop +-- if rx_dump_sosi.eop = '1' then +-- v_bool := func_sdp_tbuf_verify_cep_header(rx_dump_header, exp_dump_header); -- end if; --- end process; + -- View variables in Wave Window + dump_index <= v_dump_index; + end process; ----------------------------------------------------------------------------- -- Verify TBuf dump packet data