diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd index d7f13a3d36a8bbe8dbb0ba7d4c6d5b86f60a3229..c249bdfbf36cd3bfb72c435d906390f3187bf112 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd @@ -211,6 +211,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDE#; -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window CONSTANT c_exp_beamlet_scale : NATURAL := NATURAL(g_beamlet_scale * REAL(c_sdp_unit_beamlet_scale)); -- c_sdp_unit_beamlet_scale = 2**15; + CONSTANT c_exp_beamlet_index : NATURAL := 0; -- depends on beamset bset * c_sdp_S_sub_bf CONSTANT c_exp_sdp_info : t_sdp_info := ( TO_UVEC(601, 16), -- station_id @@ -1213,57 +1214,68 @@ BEGIN -- Prepare exp_sdp_cep_header before rx_beamlet_sosi.eop, so that -- p_exp_sdp_cep_header can verify it at rx_beamlet_sosi.eop. - p_exp_sdp_cep_header : PROCESS(exp_dp_bsn) - BEGIN - -- eth header - exp_sdp_cep_header.eth.dst_mac <= c_cep_eth_dst_mac; - exp_sdp_cep_header.eth.src_mac <= c_cep_eth_src_mac; - exp_sdp_cep_header.eth.eth_type <= x"0800"; - - -- ip header - exp_sdp_cep_header.ip.version <= TO_UVEC( 4, c_network_ip_version_w); - exp_sdp_cep_header.ip.header_length <= TO_UVEC( 5, c_network_ip_header_length_w); - exp_sdp_cep_header.ip.services <= TO_UVEC( 0, c_network_ip_services_w); - exp_sdp_cep_header.ip.total_length <= c_sdp_cep_ip_total_length; -- 7868, see ICD STAT-CEP - exp_sdp_cep_header.ip.identification <= TO_UVEC( 0, c_network_ip_identification_w); - exp_sdp_cep_header.ip.flags <= TO_UVEC( 2, c_network_ip_flags_w); - exp_sdp_cep_header.ip.fragment_offset <= TO_UVEC( 0, c_network_ip_fragment_offset_w); - exp_sdp_cep_header.ip.time_to_live <= TO_UVEC( 127, c_network_ip_time_to_live_w); - exp_sdp_cep_header.ip.protocol <= TO_UVEC( 17, c_network_ip_protocol_w); - exp_sdp_cep_header.ip.header_checksum <= TO_UVEC( c_exp_ip_header_checksum, c_network_ip_header_checksum_w); - exp_sdp_cep_header.ip.src_ip_addr <= c_cep_ip_src_addr; -- c_network_ip_addr_w - exp_sdp_cep_header.ip.dst_ip_addr <= c_cep_ip_dst_addr; -- c_network_ip_addr_w - - -- udp header - exp_sdp_cep_header.udp.src_port <= c_cep_udp_src_port; - exp_sdp_cep_header.udp.dst_port <= c_cep_udp_dst_port; - exp_sdp_cep_header.udp.total_length <= c_sdp_cep_udp_total_length; -- 7848, see ICD STAT-CEP - exp_sdp_cep_header.udp.checksum <= TO_UVEC( 0, c_network_udp_checksum_w); - - -- app header - exp_sdp_cep_header.app.sdp_marker <= TO_UVEC(c_sdp_marker_beamlets, 8); -- 98 = x"62" = 'b' - exp_sdp_cep_header.app.sdp_version_id <= TO_UVEC(c_sdp_cep_version_id, 8); -- 5 - exp_sdp_cep_header.app.sdp_observation_id <= c_exp_sdp_info.observation_id; - exp_sdp_cep_header.app.sdp_station_id <= c_exp_sdp_info.station_id; - - exp_sdp_cep_header.app.sdp_source_info_antenna_band_id <= slv(c_exp_sdp_info.antenna_band_index); - exp_sdp_cep_header.app.sdp_source_info_nyquist_zone_id <= c_exp_sdp_info.nyquist_zone_index; - exp_sdp_cep_header.app.sdp_source_info_f_adc <= slv(c_exp_sdp_info.f_adc); - exp_sdp_cep_header.app.sdp_source_info_fsub_type <= slv(c_exp_sdp_info.fsub_type); - exp_sdp_cep_header.app.sdp_source_info_payload_error <= TO_UVEC(0, 1); - exp_sdp_cep_header.app.sdp_source_info_repositioning_flag <= slv(c_exp_sdp_info.beam_repositioning_flag); - exp_sdp_cep_header.app.sdp_source_info_beamlet_width <= TO_UVEC(c_sdp_W_beamlet, 4); - exp_sdp_cep_header.app.sdp_source_info_gn_id <= TO_UVEC(c_gn_index, 5); - - exp_sdp_cep_header.app.sdp_reserved <= TO_UVEC( 0, 40); - exp_sdp_cep_header.app.sdp_beamlet_scale <= TO_UVEC( c_exp_beamlet_scale, 16); - exp_sdp_cep_header.app.sdp_beamlet_index <= TO_UVEC( 0, 16); -- depends on bset - exp_sdp_cep_header.app.sdp_nof_blocks_per_packet <= TO_UVEC( c_sdp_cep_nof_blocks_per_packet, 8); - exp_sdp_cep_header.app.sdp_nof_beamlets_per_block <= TO_UVEC(c_sdp_cep_nof_beamlets_per_block, 16); - exp_sdp_cep_header.app.sdp_block_period <= c_exp_sdp_info.block_period; - - exp_sdp_cep_header.app.dp_bsn <= TO_UVEC(exp_dp_bsn, 64); -- depends on bset and time - END PROCESS; + exp_sdp_cep_header <= func_sdp_compose_cep_header(c_cep_eth_dst_mac, + c_cep_eth_src_mac, + c_cep_ip_src_addr, + c_cep_ip_dst_addr, + c_exp_ip_header_checksum, + c_exp_sdp_info, + c_gn_index, + c_exp_beamlet_scale, + c_exp_beamlet_index, + exp_dp_bsn); + + --p_exp_sdp_cep_header : PROCESS(exp_dp_bsn) + --BEGIN + -- -- eth header + -- exp_sdp_cep_header.eth.dst_mac <= c_cep_eth_dst_mac; + -- exp_sdp_cep_header.eth.src_mac <= c_cep_eth_src_mac; + -- exp_sdp_cep_header.eth.eth_type <= x"0800"; + -- + -- -- ip header + -- exp_sdp_cep_header.ip.version <= TO_UVEC( 4, c_network_ip_version_w); + -- exp_sdp_cep_header.ip.header_length <= TO_UVEC( 5, c_network_ip_header_length_w); + -- exp_sdp_cep_header.ip.services <= TO_UVEC( 0, c_network_ip_services_w); + -- exp_sdp_cep_header.ip.total_length <= c_sdp_cep_ip_total_length; -- 7868, see ICD STAT-CEP + -- exp_sdp_cep_header.ip.identification <= TO_UVEC( 0, c_network_ip_identification_w); + -- exp_sdp_cep_header.ip.flags <= TO_UVEC( 2, c_network_ip_flags_w); + -- exp_sdp_cep_header.ip.fragment_offset <= TO_UVEC( 0, c_network_ip_fragment_offset_w); + -- exp_sdp_cep_header.ip.time_to_live <= TO_UVEC( 127, c_network_ip_time_to_live_w); + -- exp_sdp_cep_header.ip.protocol <= TO_UVEC( 17, c_network_ip_protocol_w); + -- exp_sdp_cep_header.ip.header_checksum <= TO_UVEC( c_exp_ip_header_checksum, c_network_ip_header_checksum_w); + -- exp_sdp_cep_header.ip.src_ip_addr <= c_cep_ip_src_addr; -- c_network_ip_addr_w + -- exp_sdp_cep_header.ip.dst_ip_addr <= c_cep_ip_dst_addr; -- c_network_ip_addr_w + -- + -- -- udp header + -- exp_sdp_cep_header.udp.src_port <= c_cep_udp_src_port; + -- exp_sdp_cep_header.udp.dst_port <= c_cep_udp_dst_port; + -- exp_sdp_cep_header.udp.total_length <= c_sdp_cep_udp_total_length; -- 7848, see ICD STAT-CEP + -- exp_sdp_cep_header.udp.checksum <= TO_UVEC( 0, c_network_udp_checksum_w); + -- + -- -- app header + -- exp_sdp_cep_header.app.sdp_marker <= TO_UVEC(c_sdp_marker_beamlets, 8); -- 98 = x"62" = 'b' + -- exp_sdp_cep_header.app.sdp_version_id <= TO_UVEC(c_sdp_cep_version_id, 8); -- 5 + -- exp_sdp_cep_header.app.sdp_observation_id <= c_exp_sdp_info.observation_id; + -- exp_sdp_cep_header.app.sdp_station_id <= c_exp_sdp_info.station_id; + -- + -- exp_sdp_cep_header.app.sdp_source_info_antenna_band_id <= slv(c_exp_sdp_info.antenna_band_index); + -- exp_sdp_cep_header.app.sdp_source_info_nyquist_zone_id <= c_exp_sdp_info.nyquist_zone_index; + -- exp_sdp_cep_header.app.sdp_source_info_f_adc <= slv(c_exp_sdp_info.f_adc); + -- exp_sdp_cep_header.app.sdp_source_info_fsub_type <= slv(c_exp_sdp_info.fsub_type); + -- exp_sdp_cep_header.app.sdp_source_info_payload_error <= TO_UVEC(0, 1); + -- exp_sdp_cep_header.app.sdp_source_info_repositioning_flag <= slv(c_exp_sdp_info.beam_repositioning_flag); + -- exp_sdp_cep_header.app.sdp_source_info_beamlet_width <= TO_UVEC(c_sdp_W_beamlet, 4); + -- exp_sdp_cep_header.app.sdp_source_info_gn_id <= TO_UVEC(c_gn_index, 5); + -- + -- exp_sdp_cep_header.app.sdp_reserved <= TO_UVEC( 0, 40); + -- exp_sdp_cep_header.app.sdp_beamlet_scale <= TO_UVEC( c_exp_beamlet_scale, 16); + -- exp_sdp_cep_header.app.sdp_beamlet_index <= TO_UVEC( 0, 16); -- depends on bset + -- exp_sdp_cep_header.app.sdp_nof_blocks_per_packet <= TO_UVEC( c_sdp_cep_nof_blocks_per_packet, 8); + -- exp_sdp_cep_header.app.sdp_nof_beamlets_per_block <= TO_UVEC(c_sdp_cep_nof_beamlets_per_block, 16); + -- exp_sdp_cep_header.app.sdp_block_period <= c_exp_sdp_info.block_period; + -- + -- exp_sdp_cep_header.app.dp_bsn <= TO_UVEC(exp_dp_bsn, 64); -- depends on bset and time + --END PROCESS; rx_sdp_cep_header <= func_sdp_map_cep_header(rx_hdr_fields_raw); diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd index 5930355ea60378745c482fe374b8f529f4f51448..dd52d4eb206cf007076a9b100f4e9e00400e8d28 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd @@ -75,6 +75,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_bst_offload IS CONSTANT c_nof_clk_per_sync : NATURAL := c_nof_block_per_sync*c_sdp_N_fft; CONSTANT c_pps_period : NATURAL := c_nof_clk_per_sync; CONSTANT c_wpfb_sim : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync); + CONSTANT c_nof_sync : NATURAL := 1; -- MM CONSTANT c_mm_file_reg_bsn_source_v2 : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2"; @@ -88,12 +89,12 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_bst_offload IS SIGNAL eth_done : STD_LOGIC := '0'; -- . 1GbE output - CONSTANT c_eth_check_nof_packets : NATURAL := 1; -- received packets in 1 sync period + CONSTANT c_eth_check_nof_packets : NATURAL := c_nof_sync * 1; CONSTANT c_eth_header_size : NATURAL := 19; -- words CONSTANT c_eth_crc_size : NATURAL := 1; -- word CONSTANT c_eth_packet_size : NATURAL := c_eth_header_size + c_eth_crc_size + (c_sdp_W_statistic / c_word_w) * c_sdp_S_sub_bf * c_sdp_N_pol; -- 20 + 2 * 488 * 2 = 1972 CONSTANT c_eth_check_nof_valid : NATURAL := c_eth_check_nof_packets * c_eth_packet_size; - CONSTANT c_eth_runtime_timeout : TIME := 2 * c_nof_clk_per_sync * c_ext_clk_period; -- eth statistics should be done at the second sync interval + CONSTANT c_eth_runtime_timeout : TIME := (c_nof_sync + 1) * c_nof_clk_per_sync * c_ext_clk_period; -- eth statistics should be done after c_nof_sync intervals -- DUT SIGNAL ext_clk : STD_LOGIC := '0'; @@ -109,6 +110,16 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_bst_offload IS SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); + -- Rx packets + SIGNAL eth_rx_sosi : t_dp_sosi; + SIGNAL eth_rx_data : STD_LOGIC_VECTOR(c_32-1 downto 0); + + -- Decode packets + SIGNAL rx_offload_sosi : t_dp_sosi; + 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_stat_header : t_sdp_stat_header; + -- back transceivers SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0); SIGNAL JESD204B_REFCLK : STD_LOGIC := '1'; @@ -200,7 +211,7 @@ BEGIN ---------------------------------------------------------------------------- -- Offload enable ---------------------------------------------------------------------------- - mmf_mm_bus_wr(c_mm_file_reg_stat_enable_bst, 0, 1, tb_clk); + mmf_mm_bus_wr(c_mm_file_reg_stat_enable_bst, 0, 1, tb_clk); -- only beamset 0 -- wait for udp offload is done proc_common_wait_until_high(ext_clk, eth_done); @@ -224,9 +235,38 @@ BEGIN g_check_nof_valid => TRUE, g_check_nof_valid_ref => c_eth_check_nof_valid ) - PORT MAP ( + PORT MAP ( eth_serial_in => eth_txp(0), + eth_src_out => eth_rx_sosi, tb_end => eth_done ); + eth_rx_data <= eth_rx_sosi.data(c_32-1 DOWNTO 0); + + -- . Verify XST packet header + u_rx_statistics : ENTITY dp_lib.dp_offload_rx + GENERIC MAP ( + g_nof_streams => 1, + g_data_w => c_word_w, + g_hdr_field_arr => c_sdp_stat_hdr_field_arr, + g_remove_crc => FALSE, + g_crc_nof_words => 0 + ) + PORT MAP ( + mm_rst => pps_rst, + mm_clk => tb_clk, + + dp_rst => pps_rst, + dp_clk => eth_clk(0), + + snk_in_arr(0) => eth_rx_sosi, + + src_out_arr(0) => rx_offload_sosi, + + hdr_fields_out_arr(0) => rx_hdr_fields_out, + hdr_fields_raw_arr(0) => rx_hdr_fields_raw + ); + + rx_sdp_stat_header <= func_sdp_map_stat_header(rx_hdr_fields_raw); + END tb; diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd index 80a3fbf828e332298152bccadb5b6ee33fe80641..5b14cb9aea233df7b59df0ff7031032d571d7f40 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd @@ -74,6 +74,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_fsub_sst_offload IS CONSTANT c_nof_clk_per_sync : NATURAL := c_nof_block_per_sync*c_sdp_N_fft; CONSTANT c_pps_period : NATURAL := c_nof_clk_per_sync; CONSTANT c_wpfb_sim : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync); + CONSTANT c_nof_sync : NATURAL := 2; -- MM CONSTANT c_mm_file_reg_bsn_source_v2 : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2"; @@ -87,12 +88,12 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_fsub_sst_offload IS SIGNAL eth_done : STD_LOGIC := '0'; -- . 1GbE output - CONSTANT c_eth_check_nof_packets : NATURAL := c_sdp_S_pn; -- received packets in 1 sync period + CONSTANT c_eth_check_nof_packets : NATURAL := c_nof_sync * c_sdp_S_pn; CONSTANT c_eth_header_size : NATURAL := 19; -- words CONSTANT c_eth_crc_size : NATURAL := 1; -- word CONSTANT c_eth_packet_size : NATURAL := c_eth_header_size + c_eth_crc_size + c_sdp_N_sub * (c_sdp_W_statistic / c_word_w); -- 20 + 512 * 2 = 1044 CONSTANT c_eth_check_nof_valid : NATURAL := c_eth_check_nof_packets * c_eth_packet_size; - CONSTANT c_eth_runtime_timeout : TIME := 2 * c_nof_clk_per_sync * c_ext_clk_period; -- eth statistics should be done at the second sync interval + CONSTANT c_eth_runtime_timeout : TIME := (c_nof_sync + 1) * c_nof_clk_per_sync * c_ext_clk_period; -- eth statistics should be done after c_nof_sync intervals -- DUT SIGNAL ext_clk : STD_LOGIC := '0'; @@ -108,6 +109,16 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_fsub_sst_offload IS SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); + -- Rx packets + SIGNAL eth_rx_sosi : t_dp_sosi; + SIGNAL eth_rx_data : STD_LOGIC_VECTOR(c_32-1 downto 0); + + -- Decode packets + SIGNAL rx_offload_sosi : t_dp_sosi; + 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_stat_header : t_sdp_stat_header; + -- back transceivers SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0); SIGNAL JESD204B_REFCLK : STD_LOGIC := '1'; @@ -225,7 +236,36 @@ BEGIN ) PORT MAP ( eth_serial_in => eth_txp(0), + eth_src_out => eth_rx_sosi, tb_end => eth_done ); + eth_rx_data <= eth_rx_sosi.data(c_32-1 DOWNTO 0); + + -- . Verify XST packet header + u_rx_statistics : ENTITY dp_lib.dp_offload_rx + GENERIC MAP ( + g_nof_streams => 1, + g_data_w => c_word_w, + g_hdr_field_arr => c_sdp_stat_hdr_field_arr, + g_remove_crc => FALSE, + g_crc_nof_words => 0 + ) + PORT MAP ( + mm_rst => pps_rst, + mm_clk => tb_clk, + + dp_rst => pps_rst, + dp_clk => eth_clk(0), + + snk_in_arr(0) => eth_rx_sosi, + + src_out_arr(0) => rx_offload_sosi, + + hdr_fields_out_arr(0) => rx_hdr_fields_out, + hdr_fields_raw_arr(0) => rx_hdr_fields_raw + ); + + rx_sdp_stat_header <= func_sdp_map_stat_header(rx_hdr_fields_raw); + END tb; diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd index 8219a71f3fe2fbf6a0159224c884afb7a95321b9..a11dac56788bf43d7cbb73d8bfba830f7a65832e 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd @@ -76,11 +76,17 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload IS CONSTANT c_pps_period : NATURAL := c_nof_clk_per_sync; CONSTANT c_wpfb_sim : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync); CONSTANT c_ctrl_interval_size : NATURAL := c_nof_clk_per_sync; + CONSTANT c_subband_select_arr : t_natural_arr(0 TO c_sdp_N_crosslets_max-1) := (10, 11, 12, 13, 14, 15, 16); + CONSTANT c_subband_step : NATURAL := 0; + CONSTANT c_nof_crosslets : NATURAL := 3; + CONSTANT c_nof_sync : NATURAL := 2; -- MM CONSTANT c_mm_file_reg_bsn_source_v2 : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2"; - CONSTANT c_mm_file_reg_stat_enable_xst : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_STAT_ENABLE_XST"; + CONSTANT c_mm_file_reg_crosslets_info : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_CROSSLETS_INFO"; + CONSTANT c_mm_file_reg_nof_crosslets : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_NOF_CROSSLETS"; CONSTANT c_mm_file_reg_bsn_sync_scheduler_xsub : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SYNC_SCHEDULER_XSUB"; + CONSTANT c_mm_file_reg_stat_enable_xst : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_STAT_ENABLE_XST"; -- Tb SIGNAL tb_end : STD_LOGIC := '0'; @@ -90,12 +96,12 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload IS SIGNAL eth_done : STD_LOGIC := '0'; -- . 1GbE output - CONSTANT c_eth_check_nof_packets : NATURAL := 1; -- received packets in 1 sync period + CONSTANT c_eth_check_nof_packets : NATURAL := c_nof_sync * c_nof_crosslets; CONSTANT c_eth_header_size : NATURAL := 19; -- words CONSTANT c_eth_crc_size : NATURAL := 1; -- word - CONSTANT c_eth_packet_size : NATURAL := c_eth_header_size + c_eth_crc_size + (c_sdp_W_statistic / c_word_w) * c_sdp_S_pn * c_sdp_S_pn * c_nof_complex; -- 20 + 2 * 12 * 12 * 2 = 596 + CONSTANT c_eth_packet_size : NATURAL := c_eth_header_size + c_eth_crc_size + (c_sdp_W_statistic / c_word_w) * c_sdp_S_pn * c_sdp_S_pn * c_nof_complex; -- 20 + 2 * 12 * 12 * 2 = 596 CONSTANT c_eth_check_nof_valid : NATURAL := c_eth_check_nof_packets * c_eth_packet_size; - CONSTANT c_eth_runtime_timeout : TIME := 3 * c_nof_clk_per_sync * c_ext_clk_period; -- eth statistics should be done at the third sync interval + CONSTANT c_eth_runtime_timeout : TIME := (c_nof_sync + 2) * c_nof_clk_per_sync * c_ext_clk_period; -- eth statistics should be done after c_nof_sync -- DUT SIGNAL ext_clk : STD_LOGIC := '0'; @@ -111,6 +117,16 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload IS SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); + -- Rx packets + SIGNAL eth_rx_sosi : t_dp_sosi; + SIGNAL eth_rx_data : STD_LOGIC_VECTOR(c_32-1 downto 0); + + -- Decode packets + SIGNAL rx_offload_sosi : t_dp_sosi; + 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_stat_header : t_sdp_stat_header; + -- back transceivers SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0); SIGNAL JESD204B_REFCLK : STD_LOGIC := '1'; @@ -204,15 +220,26 @@ BEGIN pps_rst <= '0'; ---------------------------------------------------------------------------- - -- Enable xsub + -- Setup and enable xsub ---------------------------------------------------------------------------- + + -- Crosslets info + FOR I IN 0 TO c_sdp_N_crosslets_max-1 LOOP + mmf_mm_bus_wr(c_mm_file_reg_crosslets_info, I, c_subband_select_arr(I), tb_clk); -- offsets + END LOOP; + mmf_mm_bus_wr(c_mm_file_reg_crosslets_info, 15, c_subband_step, tb_clk); -- step size + + -- Number of crosslets + mmf_mm_bus_wr(c_mm_file_reg_nof_crosslets, 0, c_nof_crosslets, tb_clk); + + -- Integration interval and enable mmf_mm_bus_wr(c_mm_file_reg_bsn_sync_scheduler_xsub, 1, c_ctrl_interval_size, tb_clk); -- Interval size mmf_mm_bus_wr(c_mm_file_reg_bsn_sync_scheduler_xsub, 2, c_nof_block_per_sync, tb_clk); -- first write bsn low then bsn high part mmf_mm_bus_wr(c_mm_file_reg_bsn_sync_scheduler_xsub, 3, 0, tb_clk); -- bsn high, assume v_bsn < 2**31-1 mmf_mm_bus_wr(c_mm_file_reg_bsn_sync_scheduler_xsub, 0, 1, tb_clk); -- enable ---------------------------------------------------------------------------- - -- Offload enable + -- XST offload enable ---------------------------------------------------------------------------- mmf_mm_bus_wr(c_mm_file_reg_stat_enable_xst, 0, 1, tb_clk); @@ -229,8 +256,9 @@ BEGIN END PROCESS; ------------------------------------------------------------------------- - -- Verify proper DUT 1GbE offload output using Ethernet packet statistics + -- Verify proper DUT 1GbE offload output ------------------------------------------------------------------------- + -- . Verify Ethernet packet statistics u_eth_statistics : ENTITY eth_lib.eth_statistics GENERIC MAP ( g_runtime_nof_packets => c_eth_check_nof_packets, @@ -240,7 +268,36 @@ BEGIN ) PORT MAP ( eth_serial_in => eth_txp(0), + eth_src_out => eth_rx_sosi, tb_end => eth_done ); + eth_rx_data <= eth_rx_sosi.data(c_32-1 DOWNTO 0); + + -- . Verify XST packet header + u_rx_statistics : ENTITY dp_lib.dp_offload_rx + GENERIC MAP ( + g_nof_streams => 1, + g_data_w => c_word_w, + g_hdr_field_arr => c_sdp_stat_hdr_field_arr, + g_remove_crc => FALSE, + g_crc_nof_words => 0 + ) + PORT MAP ( + mm_rst => pps_rst, + mm_clk => tb_clk, + + dp_rst => pps_rst, + dp_clk => eth_clk(0), + + snk_in_arr(0) => eth_rx_sosi, + + src_out_arr(0) => rx_offload_sosi, + + hdr_fields_out_arr(0) => rx_hdr_fields_out, + hdr_fields_raw_arr(0) => rx_hdr_fields_raw + ); + + rx_sdp_stat_header <= func_sdp_map_stat_header(rx_hdr_fields_raw); + END tb; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd index 376b64247fa6e8bef2e5f4d903a4b97d95a2b225..30bec41ee81f0b7e11370b8723aa3e9a65d7b190 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -198,7 +198,7 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_stat_eth_src_mac_47_16 : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00228608"; -- 00:22:86:08:pp:qq CONSTANT c_sdp_stat_ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"0A6300FE"; -- 0A6300FE = '10.99.0.254' = DOP36-enp2s0 CONSTANT c_sdp_stat_ip_src_addr_31_16 : STD_LOGIC_VECTOR(15 DOWNTO 0) := x"0A63"; -- 10.99.xx.yy - CONSTANT c_sdp_stat_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(5001, 16); + CONSTANT c_sdp_stat_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(5001, 16); -- 0x1389 = 5001 CONSTANT c_sdp_sst_udp_src_port_15_8 : STD_LOGIC_VECTOR( 7 DOWNTO 0) := x"D0"; -- TBC, 7:0 = gn_id (= ID[7:0] = backplane[5:0] & node[1:0]) CONSTANT c_sdp_bst_udp_src_port_15_8 : STD_LOGIC_VECTOR( 7 DOWNTO 0) := x"D1"; -- TBC CONSTANT c_sdp_xst_udp_src_port_15_8 : STD_LOGIC_VECTOR( 7 DOWNTO 0) := x"D2"; -- TBC @@ -318,7 +318,7 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_cep_ip_src_addr_31_16 : STD_LOGIC_VECTOR(15 DOWNTO 0) := x"C0A8"; -- 31:16, 15:8 = backplane, 7:0 = node + 1 = 192.168.xx.yy CONSTANT c_sdp_cep_ip_total_length : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(7868, 16); -- see ICD STAT-CEP CONSTANT c_sdp_cep_udp_total_length : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(7848, 16); -- see ICD STAT-CEP - CONSTANT c_sdp_cep_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(5000, 16); + CONSTANT c_sdp_cep_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(5000, 16); -- 0x1380 = 5000 CONSTANT c_sdp_cep_udp_src_port_15_8 : STD_LOGIC_VECTOR( 7 DOWNTO 0) := x"D0"; -- 15:8, 7:0 = gn_id (= ID[7:0] = backplane[5:0] & node[1:0]) CONSTANT c_sdp_cep_app_header_len : NATURAL := 32; @@ -566,6 +566,7 @@ PACKAGE sdp_pkg is FUNCTION func_sdp_get_stat_app_total_length(g_statistics_type : STRING) RETURN NATURAL; FUNCTION func_sdp_get_stat_udp_total_length(g_statistics_type : STRING) RETURN NATURAL; FUNCTION func_sdp_get_stat_ip_total_length(g_statistics_type : STRING) RETURN NATURAL; + FUNCTION func_sdp_get_stat_udp_src_port(g_statistics_type : STRING; gn_index : NATURAL) RETURN STD_LOGIC_VECTOR; FUNCTION func_sdp_get_stat_nof_packets(g_statistics_type : STRING; S_pn, P_sq, N_crosslets : NATURAL) RETURN NATURAL; FUNCTION func_sdp_get_stat_nof_packets(g_statistics_type : STRING) RETURN NATURAL; -- use c_sdp_S_pn, c_sdp_P_sq, c_sdp_N_crosslets_max @@ -701,6 +702,14 @@ PACKAGE BODY sdp_pkg IS RETURN c_sdp_udp_total_length + c_network_ip_header_len; END func_sdp_get_stat_ip_total_length; + FUNCTION func_sdp_get_stat_udp_src_port(g_statistics_type : STRING; gn_index : NATURAL) RETURN STD_LOGIC_VECTOR IS + CONSTANT c_gn_index : STD_LOGIC_VECTOR(7 DOWNTO 0) := TO_UVEC(gn_index, 8); + BEGIN + RETURN sel_a_b(g_statistics_type="BST", c_sdp_bst_udp_src_port_15_8 & c_gn_index, -- BST = 0xD0 & gn_index + sel_a_b(g_statistics_type="XST", c_sdp_xst_udp_src_port_15_8 & c_gn_index, -- XST = 0xD1 & gn_index + c_sdp_sst_udp_src_port_15_8 & c_gn_index)); -- SST = 0xD2 & gn_index + END func_sdp_get_stat_udp_src_port; + FUNCTION func_sdp_get_stat_nof_packets(g_statistics_type : STRING; S_pn, P_sq, N_crosslets : NATURAL) RETURN NATURAL IS BEGIN RETURN sel_a_b(g_statistics_type="BST", 1, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd index 934dbb94caddf710fb87cdda18238fa359dc3b2b..efb23c8a92d1e738b96ed7cbdbb2263ed7ed2b92 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd @@ -187,7 +187,7 @@ ARCHITECTURE str OF sdp_statistics_offload IS packet_count : NATURAL RANGE 0 TO c_nof_packets_max; start_address : NATURAL RANGE 0 TO c_mm_ram_size; start_pulse : STD_LOGIC; - sync : STD_LOGIC; + start_sync : STD_LOGIC; dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0); payload_err : STD_LOGIC; in_sop_cnt : NATURAL; @@ -337,7 +337,7 @@ BEGIN END PROCESS; -- Assign application header data_id for different statistic types, use - -- GENERATE to keep unused fields at 0. + -- GENERATE to keep unused fields at 0 (all fields are NATURAL, so default to 0). gen_data_id_sst : IF g_statistics_type = "SST" GENERATE data_id_rec.sst_signal_input_index <= r.packet_count + local_si_offset; END GENERATE; @@ -358,7 +358,7 @@ BEGIN BEGIN v := r; v.start_pulse := '0'; - v.sync := '0'; + v.start_sync := '0'; -- Count number of sop in a sync interval and get payload errors and keep them till next sync. IF in_sosi.sync = '1' THEN @@ -378,7 +378,7 @@ BEGIN -- For XST offload capture nof_crosslets and crosslets_info at in_sosi.sync, -- to make sure they do not change during packets offload. - -- . The sdp_crosslets_subband_select.vhd takes in [2] takes care that + -- . The sdp_crosslets_subband_select.vhd in [2] takes care that -- nof_crosslets and crosslets_info are valid at the xsel_sosi.sync. The -- mmp_dp_bsn_align_v2 in [2] then aligns the local xsel_sosi with the -- remote data and passes on the sync. After some latency the sync @@ -403,7 +403,7 @@ BEGIN -- Use trigger_offload to start first packet offload, all -- g_statistics_type start from start address 0 v.start_pulse := '1'; - v.sync := '1'; + v.start_sync := '1'; v.start_address := 0; v.packet_count := 0; v.interleave_count := 0; -- only used for SST @@ -414,9 +414,7 @@ BEGIN -- The dp_sop = '1' when the packet has been read from statistics memory -- and is about to get out of the dp_fifo_fill_eop in - -- u_dp_block_from_mm_dc. The difference between dp_sop and the mm_done - -- output of u_dp_block_from_mm_dc, is that dp_sop also includes any - -- dp_fifo_fill_eop latency. This ensures that the dp_sop identifies the + -- u_dp_block_from_mm_dc. This ensures that the dp_sop identifies the -- sop of the offload packet. At the dp_sop: -- . the dp_header_info per packet offload can be released -- . the next packet offload can be prepared @@ -446,7 +444,7 @@ BEGIN ELSIF g_statistics_type = "XST" THEN -- start_address: - -- nof_crosslets: 0, 1, 2, 3, 4, 5, 6 + -- nof_crosslets: 1, 2, 3, 4, 5, 6, 7 -- X_sq instance: -- 0 0, 576, 1152, 1728, 2304, 2880, 3456 -- 1 4096, 4672, 5248, 5824, 6400, 6976, 7552 @@ -502,7 +500,8 @@ BEGIN g_nof_data => c_mm_nof_data, g_word_w => c_word_w, g_reverse_word_order => g_reverse_word_order, - g_bsn_w => c_dp_stream_bsn_w + g_bsn_w => c_dp_stream_bsn_w, + g_bsn_incr_enable => FALSE -- all offload block have same bsn_at_sync ) PORT MAP( dp_rst => dp_rst, @@ -510,26 +509,23 @@ BEGIN mm_rst => mm_rst, mm_clk => mm_clk, start_pulse => r.start_pulse, - sync_in => r.sync, - bsn_at_sync => bsn_at_sync, + sync_in => r.start_sync, + bsn_at_sync => bsn_at_sync, start_address => r.start_address, - done => mm_done, -- not used, use dp_sop instead mm_mosi => master_mosi, mm_miso => master_miso, + out_sop => dp_sop, -- = dp_block_from_mm_src_out.sop out_sosi => dp_block_from_mm_src_out, out_siso => dp_block_from_mm_src_in ); - -- Use dp_block_from_mm_src_out.sop as dp_sop, to include the - -- dp_fifo_fill_eop that is in dp_block_from_mm_dc. The dp_sop thus is the - -- sop of the packet that is about to be offloaded by u_dp_offload_tx_v3. - -- The r.dp_header_info must be available at the dp_offload_snk_in.sop. - -- This is guaranteed because: + -- The dp_sop is the sop of the packet that is about to be offloaded by + -- u_dp_offload_tx_v3. The r.dp_header_info must be available at the + -- dp_offload_snk_in.sop. This is guaranteed because: -- . r.dp_header_info is available one clock cycle after dp_sop in -- p_control_packet_offload. -- . The dp_offload_snk_in is delayed also by at least one clock cycle by -- u_dp_pipeline_ready. - dp_sop <= dp_block_from_mm_src_out.sop; u_dp_pipeline_ready : ENTITY dp_lib.dp_pipeline_ready PORT MAP( @@ -543,6 +539,13 @@ BEGIN src_out => dp_offload_snk_in ); + -- The bsn_at_sync is passed on via r.dp_header_info so that + -- u_dp_offload_tx_v3 can put it in the udp_sosi header. + -- The dp_offload_snk_in.bsn that is passed on by u_dp_block_from_mm_dc is + -- in fact not used, but useful to see in udp_sosi.bsn in the Wave Window. + -- Similar dp_offload_snk_in.sync that is passed on by u_dp_block_from_mm_dc + -- is in fact not used, but useful to have in udp_sosi.sync (e.g. for the + -- tb). u_dp_offload_tx_v3: ENTITY dp_lib.dp_offload_tx_v3 GENERIC MAP ( g_nof_streams => c_nof_streams, @@ -594,7 +597,4 @@ BEGIN in_sosi_arr(0) => udp_sosi ); - - - END str; diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd index 7c2e39c5f1af617d757ee4fe815428bedac881ce..529ca373069abab0a5067ea4975abb1fab15ab13 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd @@ -28,17 +28,45 @@ LIBRARY IEEE, common_lib; USE IEEE.std_logic_1164.ALL; USE common_lib.common_pkg.ALL; +USE common_lib.common_network_layers_pkg.ALL; USE work.sdp_pkg.ALL; PACKAGE tb_sdp_pkg is ----------------------------------------------------------------------------- -- Statistics offload ----------------------------------------------------------------------------- + FUNCTION func_sdp_compose_stat_header(eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); -- eth header + eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); + ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); -- ip header + ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); + sdp_info : t_sdp_info; -- app header + g_statistics_type : STRING; + weighted_subbands_flag : STD_LOGIC; + gn_index : NATURAL; + nof_block_per_sync : NATURAL; + sst_signal_input : NATURAL; + beamlet_index : NATURAL; + subband_index : NATURAL; + xst_signal_input_A : NATURAL; + xst_signal_input_B : NATURAL; + dp_bsn : NATURAL) RETURN t_sdp_stat_header; + FUNCTION func_sdp_verify_stat_header(g_statistics_type : STRING; in_hdr, exp_hdr : t_sdp_stat_header) RETURN BOOLEAN; ----------------------------------------------------------------------------- -- Beamlet output via 10GbE to CEP (= central processor) ----------------------------------------------------------------------------- + FUNCTION func_sdp_compose_cep_header(eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); -- eth header + eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); + ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); -- ip header + ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); + ip_header_checksum : NATURAL; + sdp_info : t_sdp_info; -- app header + gn_index : NATURAL; + beamlet_scale : NATURAL; + beamlet_index : NATURAL; + dp_bsn : NATURAL) RETURN t_sdp_cep_header; + FUNCTION func_sdp_verify_cep_header(in_hdr, exp_hdr : t_sdp_cep_header) RETURN BOOLEAN; @@ -46,6 +74,99 @@ END PACKAGE tb_sdp_pkg; PACKAGE BODY tb_sdp_pkg IS + FUNCTION func_sdp_compose_stat_header(eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); -- eth header + eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); + ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); -- ip header + ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); + sdp_info : t_sdp_info; -- app header + g_statistics_type : STRING; + weighted_subbands_flag : STD_LOGIC; + gn_index : NATURAL; + nof_block_per_sync : NATURAL; + sst_signal_input : NATURAL; + beamlet_index : NATURAL; + subband_index : NATURAL; + xst_signal_input_A : NATURAL; + xst_signal_input_B : NATURAL; + dp_bsn : NATURAL) RETURN t_sdp_stat_header IS + CONSTANT c_nof_statistics_per_packet : NATURAL := func_sdp_get_stat_nof_statistics_per_packet(g_statistics_type); + CONSTANT c_udp_total_length : NATURAL := func_sdp_get_stat_udp_total_length(g_statistics_type); + CONSTANT c_ip_total_length : NATURAL := func_sdp_get_stat_ip_total_length(g_statistics_type); + CONSTANT c_marker : NATURAL := func_sdp_get_stat_marker(g_statistics_type); + CONSTANT c_nof_signal_inputs : NATURAL := func_sdp_get_stat_nof_signal_inputs(g_statistics_type); + + VARIABLE v_hdr : t_sdp_stat_header; + BEGIN + -- eth header + v_hdr.eth.dst_mac := eth_dst_mac; + v_hdr.eth.src_mac := eth_src_mac; + v_hdr.eth.eth_type := x"0800"; + + -- ip header + v_hdr.ip.version := TO_UVEC( 4, c_network_ip_version_w); + v_hdr.ip.header_length := TO_UVEC( 5, c_network_ip_header_length_w); + v_hdr.ip.services := TO_UVEC( 0, c_network_ip_services_w); + v_hdr.ip.total_length := TO_UVEC(c_ip_total_length, c_network_ip_total_length_w); + v_hdr.ip.identification := TO_UVEC( 0, c_network_ip_identification_w); + v_hdr.ip.flags := TO_UVEC( 2, c_network_ip_flags_w); + v_hdr.ip.fragment_offset := TO_UVEC( 0, c_network_ip_fragment_offset_w); + v_hdr.ip.time_to_live := TO_UVEC( 127, c_network_ip_time_to_live_w); + v_hdr.ip.protocol := TO_UVEC( 17, c_network_ip_protocol_w); + v_hdr.ip.header_checksum := TO_UVEC( 0, c_network_ip_header_checksum_w); + v_hdr.ip.src_ip_addr := ip_src_addr; -- c_network_ip_addr_w + v_hdr.ip.dst_ip_addr := ip_dst_addr; -- c_network_ip_addr_w + + -- udp header + IF g_statistics_type = "SST" THEN + v_hdr.udp.src_port := c_sdp_sst_udp_src_port_15_8 & TO_UVEC(gn_index, 8); + ELSIF g_statistics_type = "BST" THEN + v_hdr.udp.src_port := c_sdp_bst_udp_src_port_15_8 & TO_UVEC(gn_index, 8); + ELSIF g_statistics_type = "XST" THEN + v_hdr.udp.src_port := c_sdp_xst_udp_src_port_15_8 & TO_UVEC(gn_index, 8); + END IF; + v_hdr.udp.dst_port := c_sdp_stat_udp_dst_port; + v_hdr.udp.total_length := TO_UVEC(c_udp_total_length, c_network_udp_port_w); + v_hdr.udp.checksum := TO_UVEC( 0, c_network_udp_checksum_w); + + -- app header + v_hdr.app.sdp_marker := TO_UVEC(c_marker, 8); + v_hdr.app.sdp_version_id := TO_UVEC(c_sdp_stat_version_id, 8); + v_hdr.app.sdp_observation_id := sdp_info.observation_id; + v_hdr.app.sdp_station_id := sdp_info.station_id; + + v_hdr.app.sdp_source_info_antenna_band_id := slv(sdp_info.antenna_band_index); + v_hdr.app.sdp_source_info_nyquist_zone_id := sdp_info.nyquist_zone_index; + v_hdr.app.sdp_source_info_f_adc := slv(sdp_info.f_adc); + v_hdr.app.sdp_source_info_fsub_type := slv(sdp_info.fsub_type); + v_hdr.app.sdp_source_info_payload_error := TO_UVEC(0, 1); + v_hdr.app.sdp_source_info_beam_repositioning_flag := slv(sdp_info.beam_repositioning_flag); + v_hdr.app.sdp_source_info_weighted_subbands_flag := slv(weighted_subbands_flag); + v_hdr.app.sdp_source_info_reserved := TO_UVEC(0, 3); + v_hdr.app.sdp_source_info_gn_id := TO_UVEC(gn_index, 5); + + v_hdr.app.sdp_reserved := TO_UVEC( 0, 8); + v_hdr.app.sdp_integration_interval := TO_UVEC(nof_block_per_sync, 24); + IF g_statistics_type = "SST" THEN + v_hdr.app.sdp_data_id := TO_UVEC(sst_signal_input, 32); + v_hdr.app.sdp_data_id_sst_signal_input_index := TO_UVEC(sst_signal_input, 8); + ELSIF g_statistics_type = "BST" THEN + v_hdr.app.sdp_data_id := TO_UVEC(beamlet_index, 32); + v_hdr.app.sdp_data_id_bst_beamlet_index := TO_UVEC(beamlet_index, 16); + ELSIF g_statistics_type = "XST" THEN + v_hdr.app.sdp_data_id := TO_UVEC(0, 7) & TO_UVEC(subband_index, 9) & TO_UVEC(xst_signal_input_A, 8) & TO_UVEC(xst_signal_input_B, 8); + v_hdr.app.sdp_data_id_xst_subband_index := TO_UVEC(subband_index, 9); + v_hdr.app.sdp_data_id_xst_signal_input_A_index := TO_UVEC(xst_signal_input_A, 8); + v_hdr.app.sdp_data_id_xst_signal_input_B_index := TO_UVEC(xst_signal_input_B, 8); + END IF; + v_hdr.app.sdp_nof_signal_inputs := TO_UVEC( c_nof_signal_inputs, 8); + v_hdr.app.sdp_nof_bytes_per_statistic := TO_UVEC(c_sdp_nof_bytes_per_statistic, 8); + v_hdr.app.sdp_nof_statistics_per_packet := TO_UVEC( c_nof_statistics_per_packet, 16); + v_hdr.app.sdp_block_period := sdp_info.block_period; + + v_hdr.app.dp_bsn := TO_UVEC(dp_bsn, 64); + RETURN v_hdr; + END func_sdp_compose_stat_header; + FUNCTION func_sdp_verify_stat_header(g_statistics_type : STRING; in_hdr, exp_hdr : t_sdp_stat_header) RETURN BOOLEAN IS BEGIN -- eth header @@ -116,6 +237,69 @@ PACKAGE BODY tb_sdp_pkg IS END func_sdp_verify_stat_header; + FUNCTION func_sdp_compose_cep_header(eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); -- eth header + eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); + ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); -- ip header + ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); + ip_header_checksum : NATURAL; + sdp_info : t_sdp_info; -- app header + gn_index : NATURAL; + beamlet_scale : NATURAL; + beamlet_index : NATURAL; + dp_bsn : NATURAL) RETURN t_sdp_cep_header IS + VARIABLE v_hdr : t_sdp_cep_header; + BEGIN + -- eth header + v_hdr.eth.dst_mac := eth_dst_mac; + v_hdr.eth.src_mac := eth_src_mac; + v_hdr.eth.eth_type := x"0800"; + + -- ip header + v_hdr.ip.version := TO_UVEC( 4, c_network_ip_version_w); + v_hdr.ip.header_length := TO_UVEC( 5, c_network_ip_header_length_w); + v_hdr.ip.services := TO_UVEC( 0, c_network_ip_services_w); + v_hdr.ip.total_length := c_sdp_cep_ip_total_length; + v_hdr.ip.identification := TO_UVEC( 0, c_network_ip_identification_w); + v_hdr.ip.flags := TO_UVEC( 2, c_network_ip_flags_w); + v_hdr.ip.fragment_offset := TO_UVEC( 0, c_network_ip_fragment_offset_w); + v_hdr.ip.time_to_live := TO_UVEC( 127, c_network_ip_time_to_live_w); + v_hdr.ip.protocol := TO_UVEC( 17, c_network_ip_protocol_w); + v_hdr.ip.header_checksum := TO_UVEC( ip_header_checksum, c_network_ip_header_checksum_w); + v_hdr.ip.src_ip_addr := ip_src_addr; -- c_network_ip_addr_w + v_hdr.ip.dst_ip_addr := ip_dst_addr; -- c_network_ip_addr_w + + -- udp header + v_hdr.udp.src_port := c_sdp_cep_udp_src_port_15_8 & TO_UVEC(gn_index, 8); + v_hdr.udp.dst_port := c_sdp_cep_udp_dst_port; + v_hdr.udp.total_length := c_sdp_cep_udp_total_length; + v_hdr.udp.checksum := TO_UVEC(0, c_network_udp_checksum_w); + + -- app header + v_hdr.app.sdp_marker := TO_UVEC(c_sdp_marker_beamlets, 8); + v_hdr.app.sdp_version_id := TO_UVEC(c_sdp_cep_version_id, 8); + v_hdr.app.sdp_observation_id := sdp_info.observation_id; + v_hdr.app.sdp_station_id := sdp_info.station_id; + + v_hdr.app.sdp_source_info_antenna_band_id := slv(sdp_info.antenna_band_index); + v_hdr.app.sdp_source_info_nyquist_zone_id := sdp_info.nyquist_zone_index; + v_hdr.app.sdp_source_info_f_adc := slv(sdp_info.f_adc); + v_hdr.app.sdp_source_info_fsub_type := slv(sdp_info.fsub_type); + v_hdr.app.sdp_source_info_payload_error := TO_UVEC(0, 1); + v_hdr.app.sdp_source_info_repositioning_flag := slv(sdp_info.beam_repositioning_flag); + v_hdr.app.sdp_source_info_beamlet_width := TO_UVEC(c_sdp_W_beamlet, 4); + v_hdr.app.sdp_source_info_gn_id := TO_UVEC(gn_index, 5); + + v_hdr.app.sdp_reserved := TO_UVEC(0, 40); + v_hdr.app.sdp_beamlet_scale := TO_UVEC(beamlet_scale, 16); + v_hdr.app.sdp_beamlet_index := TO_UVEC(beamlet_index, 16); + v_hdr.app.sdp_nof_blocks_per_packet := TO_UVEC(c_sdp_cep_nof_blocks_per_packet, 8); + v_hdr.app.sdp_nof_beamlets_per_block := TO_UVEC(c_sdp_cep_nof_beamlets_per_block, 16); + v_hdr.app.sdp_block_period := sdp_info.block_period; + + v_hdr.app.dp_bsn := TO_UVEC(dp_bsn, 64); + RETURN v_hdr; + END func_sdp_compose_cep_header; + FUNCTION func_sdp_verify_cep_header(in_hdr, exp_hdr : t_sdp_cep_header) RETURN BOOLEAN IS VARIABLE v_beamlet_index : NATURAL; BEGIN diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd index 99ebd6f839aef1583d421cee33c40dfcca70927a..1193efc51d1626ac76565c476870d39bcff62236 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd @@ -85,7 +85,7 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS -- In this tb simply use fixed network src addresses CONSTANT c_eth_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"123456789ABC"; CONSTANT c_ip_src_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := x"0A090807"; - CONSTANT c_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0) := x"D001"; + CONSTANT c_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0) := func_sdp_get_stat_udp_src_port(g_statistics_type, g_gn_index); -- Used mm_adresses on mm bus "enable_mosi/miso". CONSTANT c_reg_enable_mm_addr_enable : NATURAL := 0; @@ -191,7 +191,7 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL rx_sdp_stat_header : t_sdp_stat_header; SIGNAL exp_sdp_stat_header : t_sdp_stat_header; - SIGNAL exp_dp_bsn : STD_LOGIC_VECTOR(63 DOWNTO 0); + SIGNAL exp_dp_bsn : NATURAL; SIGNAL exp_sst_signal_input : NATURAL; SIGNAL exp_bst_beamlet_index : NATURAL; SIGNAL cur_X_sq_cell : NATURAL; @@ -354,7 +354,7 @@ BEGIN -- verify it at rx_offload_sosi.eop. -- For all statistics - exp_dp_bsn <= TO_SVEC(c_bsn_init + 1 + rx_sync_cnt * c_nof_block_per_sync, 64); + exp_dp_bsn <= c_bsn_init + 1 + rx_sync_cnt * c_nof_block_per_sync; -- SST exp_sst_signal_input <= rx_packet_cnt + c_sdp_S_pn * gn_index; -- BST @@ -369,70 +369,21 @@ BEGIN -- . prepare expected XST signal_input_B index, assume crosslet transport in positive direction exp_xst_signal_input_B <= (source_gn MOD c_sdp_N_pn_max) * c_sdp_S_pn; - p_exp_sdp_stat_header : PROCESS(weighted_subbands_flag, gn_index, exp_dp_bsn, exp_sst_signal_input, exp_subband_index, exp_xst_signal_input_A, exp_xst_signal_input_B) - BEGIN - -- eth header - exp_sdp_stat_header.eth.dst_mac <= c_sdp_stat_eth_dst_mac; - exp_sdp_stat_header.eth.src_mac <= c_eth_src_mac; - exp_sdp_stat_header.eth.eth_type <= x"0800"; - - -- ip header - exp_sdp_stat_header.ip.version <= TO_UVEC( 4, c_network_ip_version_w); - exp_sdp_stat_header.ip.header_length <= TO_UVEC( 5, c_network_ip_header_length_w); - exp_sdp_stat_header.ip.services <= TO_UVEC( 0, c_network_ip_services_w); - exp_sdp_stat_header.ip.total_length <= TO_UVEC(c_ip_total_length, c_network_ip_total_length_w); - exp_sdp_stat_header.ip.identification <= TO_UVEC( 0, c_network_ip_identification_w); - exp_sdp_stat_header.ip.flags <= TO_UVEC( 2, c_network_ip_flags_w); - exp_sdp_stat_header.ip.fragment_offset <= TO_UVEC( 0, c_network_ip_fragment_offset_w); - exp_sdp_stat_header.ip.time_to_live <= TO_UVEC( 127, c_network_ip_time_to_live_w); - exp_sdp_stat_header.ip.protocol <= TO_UVEC( 17, c_network_ip_protocol_w); - exp_sdp_stat_header.ip.header_checksum <= TO_UVEC( 0, c_network_ip_header_checksum_w); - exp_sdp_stat_header.ip.src_ip_addr <= c_ip_src_addr; -- c_network_ip_addr_w - exp_sdp_stat_header.ip.dst_ip_addr <= c_sdp_stat_ip_dst_addr; -- c_network_ip_addr_w - - -- udp header - exp_sdp_stat_header.udp.src_port <= c_udp_src_port; - exp_sdp_stat_header.udp.dst_port <= TO_UVEC( 5001, c_network_udp_port_w); - exp_sdp_stat_header.udp.total_length <= TO_UVEC(c_udp_total_length, c_network_udp_port_w); - exp_sdp_stat_header.udp.checksum <= TO_UVEC( 0, c_network_udp_checksum_w); - - -- app header - exp_sdp_stat_header.app.sdp_marker <= TO_UVEC(c_marker, 8); - exp_sdp_stat_header.app.sdp_version_id <= TO_UVEC(c_sdp_stat_version_id, 8); - exp_sdp_stat_header.app.sdp_observation_id <= c_exp_sdp_info.observation_id; - exp_sdp_stat_header.app.sdp_station_id <= c_exp_sdp_info.station_id; - - exp_sdp_stat_header.app.sdp_source_info_antenna_band_id <= slv(c_exp_sdp_info.antenna_band_index); - exp_sdp_stat_header.app.sdp_source_info_nyquist_zone_id <= c_exp_sdp_info.nyquist_zone_index; - exp_sdp_stat_header.app.sdp_source_info_f_adc <= slv(c_exp_sdp_info.f_adc); - exp_sdp_stat_header.app.sdp_source_info_fsub_type <= slv(c_exp_sdp_info.fsub_type); - exp_sdp_stat_header.app.sdp_source_info_payload_error <= TO_UVEC(0, 1); - exp_sdp_stat_header.app.sdp_source_info_beam_repositioning_flag <= slv(c_exp_sdp_info.beam_repositioning_flag); - exp_sdp_stat_header.app.sdp_source_info_weighted_subbands_flag <= slv(weighted_subbands_flag); - exp_sdp_stat_header.app.sdp_source_info_reserved <= TO_UVEC(0, 3); - exp_sdp_stat_header.app.sdp_source_info_gn_id <= TO_UVEC(gn_index, 5); - - exp_sdp_stat_header.app.sdp_reserved <= TO_UVEC( 0, 8); - exp_sdp_stat_header.app.sdp_integration_interval <= TO_UVEC(c_nof_block_per_sync, 24); - IF g_statistics_type = "SST" THEN - exp_sdp_stat_header.app.sdp_data_id <= TO_UVEC(exp_sst_signal_input, 32); - exp_sdp_stat_header.app.sdp_data_id_sst_signal_input_index <= TO_UVEC(exp_sst_signal_input, 8); - ELSIF g_statistics_type = "BST" THEN - exp_sdp_stat_header.app.sdp_data_id <= TO_UVEC(c_beamlet_index, 32); - exp_sdp_stat_header.app.sdp_data_id_bst_beamlet_index <= TO_UVEC(c_beamlet_index, 16); - ELSIF g_statistics_type = "XST" THEN - exp_sdp_stat_header.app.sdp_data_id <= TO_UVEC(0, 7) & TO_UVEC(exp_subband_index, 9) & TO_UVEC(exp_xst_signal_input_A, 8) & TO_UVEC(exp_xst_signal_input_B, 8); - exp_sdp_stat_header.app.sdp_data_id_xst_subband_index <= TO_UVEC(exp_subband_index, 9); - exp_sdp_stat_header.app.sdp_data_id_xst_signal_input_A_index <= TO_UVEC(exp_xst_signal_input_A, 8); - exp_sdp_stat_header.app.sdp_data_id_xst_signal_input_B_index <= TO_UVEC(exp_xst_signal_input_B, 8); - END IF; - exp_sdp_stat_header.app.sdp_nof_signal_inputs <= TO_UVEC( c_nof_signal_inputs, 8); - exp_sdp_stat_header.app.sdp_nof_bytes_per_statistic <= TO_UVEC(c_sdp_nof_bytes_per_statistic, 8); - exp_sdp_stat_header.app.sdp_nof_statistics_per_packet <= TO_UVEC( c_nof_statistics_per_packet, 16); - exp_sdp_stat_header.app.sdp_block_period <= c_exp_sdp_info.block_period; - - exp_sdp_stat_header.app.dp_bsn <= exp_dp_bsn; - END PROCESS; + exp_sdp_stat_header <= func_sdp_compose_stat_header(c_sdp_stat_eth_dst_mac, + c_eth_src_mac, + c_ip_src_addr, + c_sdp_stat_ip_dst_addr, + c_exp_sdp_info, + g_statistics_type, + weighted_subbands_flag, + gn_index, + c_nof_block_per_sync, + exp_sst_signal_input, + c_beamlet_index, + exp_subband_index, + exp_xst_signal_input_A, + exp_xst_signal_input_B, + exp_dp_bsn); rx_sdp_stat_header <= func_sdp_map_stat_header(rx_hdr_fields_raw); diff --git a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd index 839b6eee681665af5afb5b3a144169868fc309c5..fb32a58e02b98a023a4ddce8a75dfae4068bf0d0 100644 --- a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd +++ b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd @@ -58,8 +58,9 @@ -- sync_in is not equal to start_pulse as start pulse indicates the start -- of a packet and not the start of a sync period. -- . For generating a bsn at out_sosi, the bsn_at_sync should contain the --- desired bsn at sync_in pulse. The bsn is increased in this component at --- every start_pulse. +-- desired bsn at sync_in pulse. If g_bsn_incr_enable then out_sosi.bsn is +-- incremented in this component at every start_pulse, else out_sosi.bsn +-- is kept at bsn_at_sync. -- -------------------------------------------------------------------------- LIBRARY IEEE,common_lib; @@ -78,16 +79,17 @@ ENTITY dp_block_from_mm IS g_word_w : NATURAL := c_word_w; g_mm_rd_latency : NATURAL := 1; -- default 1 from rd_en to rd_val, use 2 to ease timing closure g_reverse_word_order : BOOLEAN := FALSE; - g_bsn_w : NATURAL := 1 - ); + g_bsn_w : NATURAL := 1; + g_bsn_incr_enable : BOOLEAN := TRUE + ); PORT ( rst : IN STD_LOGIC; clk : IN STD_LOGIC; start_pulse : IN STD_LOGIC; - sync_in : IN STD_LOGIC := '0'; -- Must be syncronous with start_pulse. + sync_in : IN STD_LOGIC := '0'; -- Must be syncronous with start_pulse. bsn_at_sync : IN STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); start_address : IN NATURAL; - mm_done : OUT STD_LOGIC; + mm_done : OUT STD_LOGIC; -- = out_sosi.eop mm_mosi : OUT t_mem_mosi; mm_miso : IN t_mem_miso; out_sosi : OUT t_dp_sosi; @@ -158,7 +160,7 @@ BEGIN out_sosi.bsn <= RESIZE_DP_BSN(out_bsn); -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so r.bsn can be used for output bsn END PROCESS; - mm_done <= r.eop; + mm_done <= out_eop; p_reg : PROCESS(rst, clk) BEGIN @@ -219,7 +221,7 @@ BEGIN IF v.sync_in_detected = '1' THEN v.sync := '1'; v.sync_in_detected := '0'; - ELSE + ELSIF g_bsn_incr_enable = TRUE THEN v.bsn := INCR_UVEC(r.bsn, 1); END IF; END IF; diff --git a/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd b/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd index 86189e162cc1f7c9ccc80c94795eac7f32d9a7f4..b355ca2e1d552d078a634042fabe958c1372826c 100644 --- a/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd +++ b/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd @@ -21,10 +21,22 @@ -- . Pieter Donker -- Purpose: -- . Read a block of data from memory mapped (MM) location and stream it as a block of data, --- this is a dual-clock wrapper around dp_block_from_mm.vhd +-- this is a dual-clock wrapper around dp_block_from_mm.vhd. -- Description: -- . https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Subband+filterbank -- . see dp_block_from_mm.vhd +-- . read block - output block synchronisation: +-- The start_pulse causes dp_block_from_mm to read a block from memory. The +-- mm_done = mm_fifo_sosi.eop signals that the last word was read from +-- memory and is about to enter the u_dp_fifo_fill_eop. The +-- u_dp_fifo_fill_eop can only output a new packet when it has got the eop, +-- so then the out_sop = dp_out_sosi.sop will appear some cycles later at the +-- u_dp_fifo_fill_eop output, due to the mm_clk - dp_clk domain crossing. +-- The out_sop thus indicates that the complete block available in the +-- u_dp_fifo_fill_eop and is being output. Now a new start_pulse can be +-- accepted by dp_block_from_mm_dc to read a next block. Thanks to this +-- handshake the start_pulse and out_sop always follow in pairs. +-- -- -------------------------------------------------------------------------- LIBRARY IEEE,common_lib; @@ -42,8 +54,9 @@ ENTITY dp_block_from_mm_dc IS g_nof_data : NATURAL; g_word_w : NATURAL := c_word_w; g_reverse_word_order : BOOLEAN := FALSE; - g_bsn_w : NATURAL := 1 - ); + g_bsn_w : NATURAL := 1; + g_bsn_incr_enable : BOOLEAN := TRUE + ); PORT ( -- mm_clk domain mm_rst : IN STD_LOGIC; @@ -54,10 +67,10 @@ ENTITY dp_block_from_mm_dc IS dp_rst : IN STD_LOGIC; dp_clk : IN STD_LOGIC; start_pulse : IN STD_LOGIC; - sync_in : IN STD_LOGIC := '0'; -- Must be syncronous with start_pulse. + sync_in : IN STD_LOGIC := '0'; -- Must be syncronous with start_pulse. bsn_at_sync : IN STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); start_address : IN NATURAL; - done : OUT STD_LOGIC; + out_sop : OUT STD_LOGIC; -- = out_sosi.sop out_sosi : OUT t_dp_sosi; out_siso : IN t_dp_siso ); @@ -69,61 +82,80 @@ ARCHITECTURE str OF dp_block_from_mm_dc IS -- Fit one packet in FIFO, and less than two, to avoid filling the FIFO with -- multiple packets in case writing FIFO (mm_clk) is faster than reading - -- FIFO (dp_clk). + -- FIFO (dp_clk). It also works if the FIFO can fit multiple packets, + -- because the handshake between out_sop and start_pulse takes care that a + -- new packet will only be input when the previous packet is being output. CONSTANT c_fifo_fill : NATURAL := c_packet_size; CONSTANT c_fifo_size : NATURAL := c_packet_size + c_packet_size/2; CONSTANT c_start_addr_w : NATURAL := c_natural_w; CONSTANT c_delay_len : NATURAL := c_meta_delay_len; + SIGNAL dp_out_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL dp_out_siso : t_dp_siso; SIGNAL mm_fifo_sosi : t_dp_sosi := c_dp_sosi_rst; SIGNAL mm_fifo_siso : t_dp_siso; - SIGNAL start_pulse_dly : STD_LOGIC_VECTOR(0 TO c_delay_len) := (OTHERS => '0'); - SIGNAL sync_dly : STD_LOGIC_VECTOR(0 TO c_delay_len) := (OTHERS => '0'); SIGNAL mm_start_pulse : STD_LOGIC := '0'; + SIGNAL mm_sync_hi : STD_LOGIC := '0'; + SIGNAL mm_sync_level : STD_LOGIC := '0'; SIGNAL mm_sync : STD_LOGIC := '0'; - SIGNAL mm_done : STD_LOGIC := '0'; + SIGNAL mm_done : STD_LOGIC := '0'; -- not used, instead use out_sop SIGNAL mm_bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL start_address_slv : STD_LOGIC_VECTOR(c_start_addr_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL mm_start_address_slv : STD_LOGIC_VECTOR(c_start_addr_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL mm_start_address : NATURAL := 0; BEGIN - -- Use sync/start_pulse_dly to make sure mm_start_address_slv is stable before - -- mm_start_pulse, also when mm_clk is faster than dp_clk (e.g. in sim). - start_pulse_dly(0) <= start_pulse; - start_pulse_dly(1 TO c_delay_len) <= start_pulse_dly(0 TO c_delay_len-1) WHEN rising_edge(dp_clk); - sync_dly(0) <= sync_in; - sync_dly(1 TO c_delay_len) <= sync_dly(0 TO c_delay_len-1) WHEN rising_edge(dp_clk); + -- Use g_delay_len = c_meta_delay_len + 4 for start_pulse and g_delay_len = + -- c_meta_delay_len for the other signals. The + 4 ensures that the other + -- signals are already stable in the mm_clk domain, when the mm_start_pulse + -- occurs in the mm_clk domain. Use + 4 to still have 2 clock cycles margin + -- if mm_start_pulse arrive one clock cycle early and mm_sync_hi arrives one + -- clock cycle late. u_common_spulse_start_pulse : ENTITY common_lib.common_spulse + GENERIC MAP ( + g_delay_len => c_meta_delay_len + 4 + ) PORT MAP ( in_rst => dp_rst, in_clk => dp_clk, - in_pulse => start_pulse_dly(c_delay_len), + in_pulse => start_pulse, out_rst => mm_rst, out_clk => mm_clk, out_pulse => mm_start_pulse ); + -- The synchronous start_pulse and sync_in in the dp_clk domain cannot be + -- passed on via two separate common_spulse instances, because then they may + -- appear at different clock cycles in the mm_clk domain, due to that the + -- dp_clk and mm_clk are asynchronous on HW. Therefore use mm_sync_level to + -- pass on sync_in. u_common_spulse_sync : ENTITY common_lib.common_spulse + GENERIC MAP ( + g_delay_len => c_meta_delay_len + ) PORT MAP ( in_rst => dp_rst, in_clk => dp_clk, - in_pulse => sync_dly(c_delay_len), + in_pulse => sync_in, out_rst => mm_rst, out_clk => mm_clk, - out_pulse => mm_sync + out_pulse => mm_sync_hi ); - u_common_spulse_mm_done : ENTITY common_lib.common_spulse - PORT MAP ( - in_rst => mm_rst, - in_clk => mm_clk, - in_pulse => mm_done, - out_rst => dp_rst, - out_clk => dp_clk, - out_pulse => done - ); + p_mm_sync : PROCESS(mm_clk) + BEGIN + IF rising_edge(mm_clk) THEN + IF mm_sync_hi = '1' THEN + mm_sync_level <= '1'; + END IF; + IF mm_start_pulse = '1' THEN + mm_sync_level <= '0'; + END IF; + END IF; + END PROCESS; + + mm_sync <= mm_sync_level AND mm_start_pulse; -- synchronous with mm_start_pulse start_address_slv <= TO_UVEC(start_address, c_start_addr_w); mm_start_address <= TO_UINT(mm_start_address_slv); @@ -169,8 +201,8 @@ BEGIN snk_in => mm_fifo_sosi, snk_out => mm_fifo_siso, -- ST source - src_out => out_sosi, - src_in => out_siso + src_out => dp_out_sosi, + src_in => dp_out_siso ); u_dp_block_from_mm : ENTITY work.dp_block_from_mm @@ -181,7 +213,8 @@ BEGIN g_nof_data => g_nof_data, g_word_w => g_word_w, g_reverse_word_order => g_reverse_word_order, - g_bsn_w => g_bsn_w + g_bsn_w => g_bsn_w, + g_bsn_incr_enable => g_bsn_incr_enable ) PORT MAP ( clk => mm_clk, @@ -191,11 +224,18 @@ BEGIN sync_in => mm_sync, bsn_at_sync => mm_bsn_at_sync, start_address => mm_start_address, - mm_done => mm_done, + mm_done => mm_done, -- = mm_fifo_sosi.eop mm_mosi => mm_mosi, mm_miso => mm_miso, out_sosi => mm_fifo_sosi, out_siso => mm_fifo_siso ); + + -- Wire output + out_sop <= dp_out_sosi.sop; + + out_sosi <= dp_out_sosi; + dp_out_siso <= out_siso; + END str;