diff --git a/applications/lofar2/libraries/sdp/hdllib.cfg b/applications/lofar2/libraries/sdp/hdllib.cfg index 465219f6cdac4a4a43b46ff3a3f6c42d16b82ed2..cdabca45cfaf7e7098d52eeb503da66aab334798 100644 --- a/applications/lofar2/libraries/sdp/hdllib.cfg +++ b/applications/lofar2/libraries/sdp/hdllib.cfg @@ -1,6 +1,6 @@ hdl_lib_name = lofar2_sdp hdl_library_clause_name = lofar2_sdp_lib -hdl_lib_uses_synth = common dp wpfb rTwoSDF filter si st technology mm dp diag aduh tech_jesd204b +hdl_lib_uses_synth = common dp wpfb rTwoSDF filter si st technology mm dp diag aduh tech_jesd204b tr_10GbE hdl_lib_uses_sim = hdl_lib_technology = @@ -10,6 +10,7 @@ synth_files = src/vhdl/sdp_subband_equalizer.vhd src/vhdl/sdp_bf_weights.vhd src/vhdl/sdp_beamformer_local.vhd + src/vhdl/sdp_beamformer_output.vhd src/vhdl/node_sdp_adc_input_and_timing.vhd src/vhdl/node_sdp_filterbank.vhd test_bench_files = diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c94d2fc0473fa4bc0d20651897c0f35851eca65e --- /dev/null +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd @@ -0,0 +1,338 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- +-- Author: R. van der Walle +-- Purpose: +-- The beamformer output (BDO) packetizes the beamlet data into UDP/IP packets. +-- Description: +-- Remark: +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, dp_lib, tr_10GbE_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_field_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE work.sdp_pkg.ALL; + +ENTITY sdp_beamformer_output IS + GENERIC ( + g_beamset_id : NATURAL := 0 + + ); + PORT ( + dp_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + + mm_clk : IN STD_LOGIC; + mm_rst : IN STD_LOGIC; + + reg_hdr_dat_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_hdr_dat_miso : OUT t_mem_miso; + + reg_dp_xonoff_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_dp_xonoff_miso : OUT t_mem_miso; + + in_sosi : IN t_dp_sosi; + out_sosi : OUT t_dp_sosi; + src_in : IN t_dp_siso; + + sdp_info : IN t_sdp_info; + gn_id : IN STD_LOGIC_VECTOR(4 DOWNTO 0); + + eth_src_mac : IN STD_LOGIC_VECTOR(47 DOWNTO 0); + ip_src_addr : IN STD_LOGIC_VECTOR(31 DOWNTO 0); + udp_src_port : IN STD_LOGIC_VECTOR(15 DOWNTO 0); + + hdr_fields_out : OUT STD_LOGIC_VECTOR(1023 DOWNTO 0) + ); +END sdp_beamformer_output; + + +ARCHITECTURE str OF sdp_beamformer_output IS + + CONSTANT c_data_w : NATURAL := c_nof_complex*c_sdp_W_beamlet; --16b + CONSTANT c_marker : STD_LOGIC_VECTOR := x"62"; + CONSTANT c_version : NATURAL := 5; + CONSTANT c_nof_blocks_per_packet : NATURAL := 4; + CONSTANT c_nof_beamlets_per_block : NATURAL := c_sdp_N_pol * c_sdp_S_sub_bf; + CONSTANT c_beamlet_id : NATURAL := g_beamset_id * c_sdp_S_sub_bf; + CONSTANT c_fifo_fill : NATURAL := c_nof_blocks_per_packet * c_nof_beamlets_per_block / 4; -- 4 beamlets fit in 1 64bit longword + CONSTANT c_fifo_size : NATURAL := c_fifo_fill + 11; -- Make fifo size large enough for adding header. + + SIGNAL snk_in_concat : t_dp_sosi; + SIGNAL dp_packet_merge_src_out : t_dp_sosi; + SIGNAL dp_repack_data_src_out : t_dp_sosi; + SIGNAL dp_fifo_sc_src_out : t_dp_sosi; + SIGNAL dp_fifo_sc_src_in : t_dp_siso; + SIGNAL dp_offload_tx_src_out : t_dp_sosi; + SIGNAL dp_offload_tx_src_in : t_dp_siso; + SIGNAL ip_checksum_src_out : t_dp_sosi; + SIGNAL ip_checksum_src_in : t_dp_siso; + + SIGNAL common_fifo_rd_req : STD_LOGIC; + SIGNAL payload_err : STD_LOGIC_VECTOR(0 DOWNTO 0); + + SIGNAL dp_offload_tx_hdr_fields : STD_LOGIC_VECTOR(1023 DOWNTO 0); + + ------------------------------------------------------------------------------- + -- dp_offload_tx + ------------------------------------------------------------------------------- + CONSTANT c_nof_hdr_fields : NATURAL := 3+12+4+18+1; -- 592b; 9.25 64b words + CONSTANT c_hdr_field_sel : STD_LOGIC_VECTOR(c_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"110000000010001110"&"0"; + + CONSTANT c_hdr_field_arr : t_common_field_arr(c_nof_hdr_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"00074306C700") ), -- 00074306C700=DOP36-eth0 + ( field_name_pad("eth_src_mac" ), "RW", 48, field_default(0) ), + ( field_name_pad("eth_type" ), "RO", 16, field_default(x"0800") ), + ( field_name_pad("ip_version" ), "RO", 4, field_default(4) ), + ( field_name_pad("ip_header_length" ), "RO", 4, field_default(5) ), + ( field_name_pad("ip_services" ), "RO", 8, field_default(0) ), + ( field_name_pad("ip_total_length" ), "RO", 16, field_default(7868) ), + ( field_name_pad("ip_identification" ), "RO", 16, field_default(0) ), + ( field_name_pad("ip_flags" ), "RO", 3, field_default(2) ), + ( field_name_pad("ip_fragment_offset" ), "RO", 13, field_default(0) ), + ( field_name_pad("ip_time_to_live" ), "RO", 8, field_default(127) ), + ( field_name_pad("ip_protocol" ), "RO", 8, field_default(17) ), + ( field_name_pad("ip_header_checksum" ), "RW", 16, field_default(0) ), + ( field_name_pad("ip_src_addr" ), "RW", 32, field_default(0) ), + ( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"C0A80001") ), -- C0A80001=DOP36-eth0 '192.168.0.1' + ( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ), + ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(0) ), + ( field_name_pad("udp_total_length" ), "RO", 16, field_default(7848) ), + ( field_name_pad("udp_checksum" ), "RO", 16, field_default(0) ), + ( field_name_pad("sdp_marker" ), "RO", 8, field_default(c_marker) ), + ( field_name_pad("sdp_version_id" ), "RO", 8, field_default(c_version) ), + ( field_name_pad("sdp_observation_id" ), "RW", 32, field_default(0) ), + ( field_name_pad("sdp_station_id" ), "RW", 16, field_default(0) ), + ( field_name_pad("sdp_source_info_antenna_band_id" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_nyquist_zone_id" ), "RW", 2, field_default(0) ), + ( field_name_pad("sdp_source_info_f_adc" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_fsub_type" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_payload_error" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_repositioning_flag" ), "RW", 1, field_default(0) ), + ( field_name_pad("sdp_source_info_beamlet_width" ), "RO", 4, field_default(c_sdp_W_beamlet) ), + ( field_name_pad("sdp_source_info_gn_id" ), "RW", 5, field_default(0) ), + ( field_name_pad("sdp_reserved" ), "RW", 40, field_default(0) ), + ( field_name_pad("sdp_beamlet_scale" ), "RW", 16, field_default(2**15) ), + ( field_name_pad("sdp_beamlet_id" ), "RO", 16, field_default(c_beamlet_id) ), + ( field_name_pad("sdp_nof_blocks_per_packet" ), "RO", 8, field_default(c_nof_blocks_per_packet) ), + ( field_name_pad("sdp_nof_beamlets_per_block" ), "RO", 16, field_default(c_nof_beamlets_per_block) ), + ( field_name_pad("sdp_block_period" ), "RW", 16, field_default(5120) ), + ( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) ) ); + +BEGIN + + ------------------------------------------------------------------------------- + -- Input rewiring: concatenate input complex fields to data field + -- . dp_repack_data works with data fields only + ------------------------------------------------------------------------------- + p_snk_in_arr : PROCESS(in_sosi) + BEGIN + snk_in_concat <= in_sosi; + snk_in_concat.data(c_data_w-1 DOWNTO 0) <= in_sosi.im(c_sdp_W_beamlet-1 DOWNTO 0) & in_sosi.re(c_sdp_W_beamlet-1 DOWNTO 0); + END PROCESS; + + ------------------------------------------------------------------------------- + -- dp_repack_data + -- . 16b -> 64b + -- . We don't need to flow control the source beacause we're going from 16b->64b + ------------------------------------------------------------------------------- + u_dp_repack_data : ENTITY dp_lib.dp_repack_data + GENERIC MAP ( + g_in_dat_w => c_data_w, + g_in_nof_words => 4, + g_out_dat_w => c_longword_w, + g_out_nof_words => 1 + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + + snk_in => snk_in_concat, + snk_out => OPEN, + + src_out => dp_repack_data_src_out, + src_in => c_dp_siso_rdy + ); + + ------------------------------------------------------------------------------- + -- dp_packet_merge + ------------------------------------------------------------------------------- + u_dp_packet_merge : ENTITY dp_lib.dp_packet_merge + GENERIC MAP( + g_nof_pkt => c_nof_blocks_per_packet + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + + snk_out => OPEN, + snk_in => dp_repack_data_src_out, + + src_in => c_dp_siso_rdy, + src_out => dp_packet_merge_src_out + ); + + ------------------------------------------------------------------------------- + -- FIFO + -- . We're inserting headers, so dp_offload_tx needs a flow controllable + -- source. + -- . Also, we need a fill FIFO here because 16b->64b will introduce gaps in our + -- TX stream (not allowed by 10G TX MAC). + ------------------------------------------------------------------------------- + u_dp_fifo_fill_sc : ENTITY dp_lib.dp_fifo_fill_sc + GENERIC MAP ( + g_data_w => c_longword_w, + g_empty_w => c_byte_w, + g_use_empty => TRUE, + g_use_bsn => TRUE, + g_bsn_w => 64, + g_use_sync => TRUE, + g_fifo_size => c_fifo_size, + g_fifo_fill => c_fifo_fill + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + + snk_in => dp_packet_merge_src_out, + + src_out => dp_fifo_sc_src_out, + src_in => dp_fifo_sc_src_in + ); + + -- Simple fifo to store the payload error at eop. + common_fifo_rd_req <= dp_fifo_sc_src_out.sop AND dp_fifo_sc_src_out.valid; + u_common_fifo_sc : ENTITY common_lib.common_fifo_sc + GENERIC MAP ( + g_dat_w => 1, + g_nof_words => 2 + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + wr_dat => dp_packet_merge_src_out.err(0 DOWNTO 0), + wr_req => dp_packet_merge_src_out.eop, + rd_dat => payload_err, + rd_req => common_fifo_rd_req + ); + + ------------------------------------------------------------------------------- + -- Assemble offload info + ------------------------------------------------------------------------------- + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(c_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_hdr_field_arr, "udp_src_port")) <= udp_src_port; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr; + + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_observation_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_observation_id" )) <= sdp_info.observation_id; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_station_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_station_id" )) <= sdp_info.station_id; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_source_info_antenna_band_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_antenna_band_id" )) <= SLV(sdp_info.antenna_band_index); + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_source_info_nyquist_zone_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_nyquist_zone_id" )) <= sdp_info.nyquist_zone_index; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_source_info_f_adc" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_f_adc" )) <= SLV(sdp_info.f_adc); + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_source_info_fsub_type" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_fsub_type" )) <= SLV(sdp_info.fsub_type); + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_source_info_payload_error" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_payload_error" )) <= payload_err; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_source_info_repositioning_flag" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_repositioning_flag" )) <= SLV(sdp_info.beam_repositioning_flag); + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_source_info_gn_id" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_source_info_gn_id" )) <= gn_id; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_reserved" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_reserved" )) <= (OTHERS => '0'); + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_beamlet_scale" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_beamlet_scale" )) <= sdp_info.beamlet_scale; + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "sdp_block_period" ) DOWNTO field_lo(c_hdr_field_arr, "sdp_block_period" )) <= sdp_info.block_period; + + dp_offload_tx_hdr_fields(field_hi(c_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_hdr_field_arr, "dp_bsn" )) <= dp_fifo_sc_src_out.bsn(63 DOWNTO 0); + + + ------------------------------------------------------------------------------- + -- dp_offload_tx_v3 + ------------------------------------------------------------------------------- + u_dp_offload_tx_v3 : ENTITY dp_lib.dp_offload_tx_v3 + GENERIC MAP ( + g_nof_streams => 1, + g_data_w => c_longword_w, + g_symbol_w => c_byte_w, + g_hdr_field_arr => c_hdr_field_arr, + g_hdr_field_sel => c_hdr_field_sel + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + + dp_rst => dp_rst, + dp_clk => dp_clk, + + reg_hdr_dat_mosi => reg_hdr_dat_mosi, + reg_hdr_dat_miso => reg_hdr_dat_miso, + + snk_in_arr(0) => dp_fifo_sc_src_out, + snk_out_arr(0) => dp_fifo_sc_src_in, + + src_out_arr(0) => dp_offload_tx_src_out, + src_in_arr(0) => dp_offload_tx_src_in, + + hdr_fields_in_arr(0) => dp_offload_tx_hdr_fields, + hdr_fields_out_arr(0) => hdr_fields_out + ); + + ------------------------------------------------------------------------------- + -- tr_10GbE_ip_checksum + ------------------------------------------------------------------------------- + u_tr_10GbE_ip_checksum : ENTITY tr_10GbE_lib.tr_10GbE_ip_checksum + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + snk_in => dp_offload_tx_src_out, + snk_out => dp_offload_tx_src_in, + + src_out => ip_checksum_src_out, + src_in => ip_checksum_src_in + ); + + ------------------------------------------------------------------------------- + -- mms_dp_xonoff + ------------------------------------------------------------------------------- + u_mms_dp_xonoff : ENTITY dp_lib.mms_dp_xonoff + GENERIC MAP( + g_default_value => '0' + ) + PORT MAP( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + + reg_mosi => reg_dp_xonoff_mosi, + reg_miso => reg_dp_xonoff_miso, + + -- Streaming clock domain + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- ST sinks + snk_out_arr(0) => ip_checksum_src_in, + snk_in_arr(0) => ip_checksum_src_out, + -- ST source + src_in_arr(0) => src_in, + src_out_arr(0) => out_sosi + ); + +END str; diff --git a/libraries/base/dp/src/vhdl/dp_packet_merge.vhd b/libraries/base/dp/src/vhdl/dp_packet_merge.vhd index dea61acafacd9e2ce20ec0ea4c94ee819e882ec2..77a3a2dd6b0e5c090398d6099a6c720ca92a97e1 100644 --- a/libraries/base/dp/src/vhdl/dp_packet_merge.vhd +++ b/libraries/base/dp/src/vhdl/dp_packet_merge.vhd @@ -35,8 +35,6 @@ -- . with g_align_at_sync=true the merge can be forced to restart at a snk_in.sync. -- -- Issues: --- . merged err should preferrably be the bit wise or of the merged input packet err field instead --- of only the err field of the last. -- -- Design steps: -- A) No flow control @@ -333,10 +331,15 @@ BEGIN END IF; IF snk_in.eop = '1' THEN + IF r.pkt_cnt = 0 THEN + v.src_out.err := snk_in.err; + ELSE + v.src_out.err := r.src_out.err OR snk_in.err; -- OR the err fields of the packets to reflect combined error status. + END IF; + IF r.pkt_cnt = r.nof_pkt-1 THEN v.src_out.eop := '1'; v.src_out.empty := snk_in.empty; - v.src_out.err := snk_in.err; -- use err of last packet for merged packet END IF; END IF; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_packet_merge.vhd b/libraries/base/dp/tb/vhdl/tb_dp_packet_merge.vhd index afbb9d176adaee077b5943b41c95784ffedb21f8..f37dab7d34f6a13a485ea7a1fd91c31110fd13ed 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_packet_merge.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_packet_merge.vhd @@ -198,6 +198,7 @@ BEGIN v_sosi.bsn := STD_LOGIC_VECTOR( UNSIGNED(c_bsn_init) + c_verify_at_least*g_nof_pkt); v_sosi.channel := TO_DP_CHANNEL(c_channel_init + c_verify_at_least*g_nof_pkt); v_sosi.err := TO_DP_ERROR(c_err_init + c_verify_at_least*g_nof_pkt); + -- . account for g_pkt_len v_sosi.data := INCR_UVEC(v_sosi.data, g_pkt_len-1); v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w-1 DOWNTO 0)); -- wrap when >= 2**g_data_w @@ -236,7 +237,6 @@ BEGIN proc_dp_verify_data("verify_snk_in.data", c_rl, c_data_max, c_unsigned_1, clk, verify_en_valid, verify_snk_out.ready, verify_snk_in.valid, verify_snk_in.data, prev_verify_snk_in.data); proc_dp_verify_data("verify_snk_in.bsn", c_rl, c_unsigned_0, TO_UNSIGNED(c_verify_data_gap,32), clk, verify_en_sop, verify_snk_out.ready, verify_snk_in.sop, verify_snk_in.bsn, prev_verify_snk_in.bsn); proc_dp_verify_data("verify_snk_in.channel", c_rl, c_unsigned_0, TO_UNSIGNED(c_verify_data_gap,32), clk, verify_en_sop, verify_snk_out.ready, verify_snk_in.sop, verify_snk_in.channel, prev_verify_snk_in.channel); - proc_dp_verify_data("verify_snk_in.err", c_rl, c_unsigned_0, TO_UNSIGNED(c_verify_data_gap,32), clk, verify_en_eop, verify_snk_out.ready, verify_snk_in.eop, verify_snk_in.err, prev_verify_snk_in.err); -- Verify that the output sync occurs when expected proc_dp_verify_sync(c_sync_period, c_sync_offset, clk, verify_en_sop, verify_snk_in.sync, verify_snk_in.sop, verify_snk_in.bsn);