diff --git a/applications/lofar2/designs/lofar2_unb2b_beamformer/src/vhdl/mmm_lofar2_unb2b_beamformer.vhd b/applications/lofar2/designs/lofar2_unb2b_beamformer/src/vhdl/mmm_lofar2_unb2b_beamformer.vhd index c116e37ee89765d76e53d2a79edbeae0ae33f75c..6071cc43dd969c7de9059ba46869e270a5284ce3 100644 --- a/applications/lofar2/designs/lofar2_unb2b_beamformer/src/vhdl/mmm_lofar2_unb2b_beamformer.vhd +++ b/applications/lofar2/designs/lofar2_unb2b_beamformer/src/vhdl/mmm_lofar2_unb2b_beamformer.vhd @@ -656,7 +656,7 @@ BEGIN reg_hdr_dat_clk_export => OPEN, reg_hdr_dat_reset_export => OPEN, - reg_hdr_dat_address_export => reg_hdr_dat_mosi.address(c_sdp_reg_hdr_dat_addr_w-1 DOWNTO 0), + reg_hdr_dat_address_export => reg_hdr_dat_mosi.address(c_sdp_reg_bf_hdr_dat_addr_w-1 DOWNTO 0), reg_hdr_dat_write_export => reg_hdr_dat_mosi.wr, reg_hdr_dat_writedata_export => reg_hdr_dat_mosi.wrdata(c_word_w-1 DOWNTO 0), reg_hdr_dat_read_export => reg_hdr_dat_mosi.rd, diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd index c97efa9fc2080f8c071a0f87e19ad6b4c7e53b70..8195f2a5cacd8e41671bfc167f51eedbcd8a549b 100644 --- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd +++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd @@ -719,7 +719,7 @@ BEGIN reg_hdr_dat_clk_export => OPEN, reg_hdr_dat_reset_export => OPEN, - reg_hdr_dat_address_export => reg_hdr_dat_mosi.address(c_sdp_reg_hdr_dat_addr_w-1 DOWNTO 0), + reg_hdr_dat_address_export => reg_hdr_dat_mosi.address(c_sdp_reg_bf_hdr_dat_addr_w-1 DOWNTO 0), reg_hdr_dat_write_export => reg_hdr_dat_mosi.wr, reg_hdr_dat_writedata_export => reg_hdr_dat_mosi.wrdata(c_word_w-1 DOWNTO 0), reg_hdr_dat_read_export => reg_hdr_dat_mosi.rd, @@ -815,7 +815,7 @@ BEGIN ram_st_xsq_clk_export => OPEN, ram_st_xsq_reset_export => OPEN, - ram_st_xsq_address_export => ram_st_xsq_mosi.address(c_sdp_ram_st_xsq_addr_w-1 DOWNTO 0), + ram_st_xsq_address_export => ram_st_xsq_mosi.address(c_sdp_ram_st_xsq_arr_addr_w-1 DOWNTO 0), ram_st_xsq_write_export => ram_st_xsq_mosi.wr, ram_st_xsq_writedata_export => ram_st_xsq_mosi.wrdata(c_word_w-1 DOWNTO 0), ram_st_xsq_read_export => ram_st_xsq_mosi.rd, diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/mmm_lofar2_unb2c_sdp_station.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/mmm_lofar2_unb2c_sdp_station.vhd index d35eb3c749dd6c451f79abb9fce02821fc1618d9..f1b1559012c486a7bdaf276bf0e11d7890f21558 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/mmm_lofar2_unb2c_sdp_station.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/mmm_lofar2_unb2c_sdp_station.vhd @@ -690,7 +690,7 @@ BEGIN reg_hdr_dat_clk_export => OPEN, reg_hdr_dat_reset_export => OPEN, - reg_hdr_dat_address_export => reg_hdr_dat_mosi.address(c_sdp_reg_hdr_dat_addr_w-1 DOWNTO 0), + reg_hdr_dat_address_export => reg_hdr_dat_mosi.address(c_sdp_reg_bf_hdr_dat_addr_w-1 DOWNTO 0), reg_hdr_dat_write_export => reg_hdr_dat_mosi.wr, reg_hdr_dat_writedata_export => reg_hdr_dat_mosi.wrdata(c_word_w-1 DOWNTO 0), reg_hdr_dat_read_export => reg_hdr_dat_mosi.rd, @@ -786,7 +786,7 @@ BEGIN ram_st_xsq_clk_export => OPEN, ram_st_xsq_reset_export => OPEN, - ram_st_xsq_address_export => ram_st_xsq_mosi.address(c_sdp_ram_st_xsq_addr_w-1 DOWNTO 0), + ram_st_xsq_address_export => ram_st_xsq_mosi.address(c_sdp_ram_st_xsq_arr_addr_w-1 DOWNTO 0), ram_st_xsq_write_export => ram_st_xsq_mosi.wr, ram_st_xsq_writedata_export => ram_st_xsq_mosi.wrdata(c_word_w-1 DOWNTO 0), ram_st_xsq_read_export => ram_st_xsq_mosi.rd, diff --git a/applications/lofar2/libraries/sdp/hdllib.cfg b/applications/lofar2/libraries/sdp/hdllib.cfg index 3ffb4a50f6bc0119df4d202cf2ebfe4c5fd688b4..20b9cf3d5a1a27bf384f3e33d35ee91ecd7e7705 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 reorder technology tech_pll mm dp diag aduh tech_jesd204b nw_10GbE eth +hdl_lib_uses_synth = common dp wpfb rTwoSDF filter si st reorder technology tech_pll mm dp diag aduh tech_jesd204b nw_10GbE eth ring hdl_lib_uses_sim = hdl_lib_technology = @@ -22,7 +22,8 @@ synth_files = src/vhdl/sdp_station.vhd test_bench_files = - tb/vhdl/tb_sdp_info.vhd + tb/vhdl/tb_sdp_pkg.vhd + tb/vhdl/tb_sdp_info.vhd tb/vhdl/tb_sdp_statistics_offload.vhd tb/vhdl/tb_tb_sdp_statistics_offload.vhd tb/vhdl/tb_sdp_crosslets_subband_select.vhd diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd index 2f74ef1528571469ec7352232ea0016c810e57a8..9d6215cc77615e82e00c636b1ca09be158d39060 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd @@ -40,9 +40,9 @@ USE work.sdp_pkg.ALL; ENTITY node_sdp_beamformer IS GENERIC ( g_sim : BOOLEAN := FALSE; + g_sim_sdp : t_sdp_sim := c_sdp_sim; g_beamset_id : NATURAL := 0; - g_scope_selected_beamlet : NATURAL := 0; - g_offload_time : NATURAL := c_sdp_offload_time + g_scope_selected_beamlet : NATURAL := 0 ); PORT ( dp_clk : IN STD_LOGIC; @@ -281,7 +281,7 @@ BEGIN u_sdp_bst_udp_offload: ENTITY work.sdp_statistics_offload GENERIC MAP ( g_statistics_type => "BST", - g_offload_time => g_offload_time, + g_offload_time => sel_a_b(g_sim, g_sim_sdp.offload_time, c_sdp_offload_time), g_beamset_id => g_beamset_id ) PORT MAP ( @@ -297,11 +297,8 @@ BEGIN reg_enable_mosi => reg_stat_enable_mosi, reg_enable_miso => reg_stat_enable_miso, - reg_hdr_dat_mosi => reg_stat_hdr_dat_mosi, - reg_hdr_dat_miso => reg_stat_hdr_dat_miso, - - sdp_info => sdp_info, - gn_index => TO_UINT(gn_id), + reg_hdr_dat_mosi => reg_stat_hdr_dat_mosi, + reg_hdr_dat_miso => reg_stat_hdr_dat_miso, in_sosi => bf_sum_sosi, out_sosi => bst_udp_sosi, @@ -309,7 +306,10 @@ BEGIN eth_src_mac => stat_eth_src_mac, udp_src_port => stat_udp_src_port, - ip_src_addr => stat_ip_src_addr + ip_src_addr => stat_ip_src_addr, + + sdp_info => sdp_info, + gn_index => TO_UINT(gn_id) ); --------------------------------------------------------------- diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd index 530ce569f6a5528af4e6b18a1cbc189deac959c5..ab0d594eb2cb7d75703e088bf7f2fa17a9b615a4 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd @@ -40,8 +40,8 @@ USE work.sdp_pkg.ALL; ENTITY node_sdp_correlator IS GENERIC ( g_sim : BOOLEAN := FALSE; - g_P_sq : NATURAL := c_sdp_P_sq; - g_offload_time : NATURAL := c_sdp_offload_time + g_sim_sdp : t_sdp_sim := c_sdp_sim; + g_P_sq : NATURAL := c_sdp_P_sq ); PORT ( dp_clk : IN STD_LOGIC; @@ -129,7 +129,8 @@ BEGIN --------------------------------------------------------------- u_crosslets_subband_select : ENTITY work.sdp_crosslets_subband_select GENERIC MAP ( - g_N_crosslets => c_sdp_N_crosslets_max + g_N_crosslets => c_sdp_N_crosslets_max, + g_ctrl_interval_size_min => sel_a_b(g_sim, g_sim_sdp.xst_nof_clk_per_sync_min, c_sdp_xst_nof_clk_per_sync_min) ) PORT MAP( dp_clk => dp_clk, @@ -271,9 +272,10 @@ BEGIN --------------------------------------------------------------- u_sdp_xst_udp_offload: ENTITY work.sdp_statistics_offload GENERIC MAP ( - g_statistics_type => "XST", - g_offload_time => g_offload_time, - g_P_sq => g_P_sq + g_statistics_type => "XST", + g_offload_time => sel_a_b(g_sim, g_sim_sdp.offload_time, c_sdp_offload_time), + g_P_sq => g_P_sq, + g_crosslets_direction => 1 -- = lane direction ) PORT MAP ( mm_clk => mm_clk, @@ -288,11 +290,8 @@ BEGIN reg_enable_mosi => reg_stat_enable_mosi, reg_enable_miso => reg_stat_enable_miso, - reg_hdr_dat_mosi => reg_stat_hdr_dat_mosi, - reg_hdr_dat_miso => reg_stat_hdr_dat_miso, - - sdp_info => sdp_info, - gn_index => TO_UINT(gn_id), + reg_hdr_dat_mosi => reg_stat_hdr_dat_mosi, + reg_hdr_dat_miso => reg_stat_hdr_dat_miso, in_sosi => crosslets_sosi_arr(0), out_sosi => xst_udp_sosi, @@ -301,6 +300,9 @@ BEGIN eth_src_mac => stat_eth_src_mac, udp_src_port => stat_udp_src_port, ip_src_addr => stat_ip_src_addr, + + gn_index => TO_UINT(gn_id), + sdp_info => sdp_info, nof_crosslets => nof_crosslets, crosslets_info => crosslets_info ); diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd index 1ecebdc0cb4714579b70843a8b0a4df13be7749b..aadbfee3b3af8fc6980d565c488d954dad0ec29c 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd @@ -49,9 +49,9 @@ USE work.sdp_pkg.ALL; ENTITY node_sdp_filterbank IS GENERIC ( g_sim : BOOLEAN := FALSE; + g_sim_sdp : t_sdp_sim := c_sdp_sim; g_wpfb : t_wpfb := c_sdp_wpfb_subbands; - g_scope_selected_subband : NATURAL := 0; - g_offload_time : NATURAL := c_sdp_offload_time + g_scope_selected_subband : NATURAL := 0 ); PORT ( dp_clk : IN STD_LOGIC; @@ -336,7 +336,7 @@ BEGIN u_sdp_sst_udp_offload: ENTITY work.sdp_statistics_offload GENERIC MAP ( g_statistics_type => "SST", - g_offload_time => g_offload_time + g_offload_time => sel_a_b(g_sim, g_sim_sdp.offload_time, c_sdp_offload_time) ) PORT MAP ( mm_clk => mm_clk, @@ -354,17 +354,17 @@ BEGIN reg_hdr_dat_mosi => reg_hdr_dat_mosi, reg_hdr_dat_miso => reg_hdr_dat_miso, - sdp_info => sdp_info, - gn_index => TO_UINT(gn_id), - subband_calibrated_flag => subband_calibrated_flag, - in_sosi => dp_selector_out_sosi_arr(0), out_sosi => sst_udp_sosi, out_siso => sst_udp_siso, eth_src_mac => eth_src_mac, udp_src_port => udp_src_port, - ip_src_addr => ip_src_addr + ip_src_addr => ip_src_addr, + + gn_index => TO_UINT(gn_id), + sdp_info => sdp_info, + subband_calibrated_flag => subband_calibrated_flag ); END str; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd index 4dbd3fd7db8170a70d4ce3779301d426b6bb5d34..0f8a3a8ef3292b6dc867f29ea8e3c4eb558b2bc3 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -20,7 +20,7 @@ ------------------------------------------------------------------------------- -- --- Author: R. van der Walle +-- Author: R. van der Walle, E. Kooistra -- Purpose: -- . This package contains sdp specific constants. -- Description: @@ -33,6 +33,7 @@ USE IEEE.std_logic_1164.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_field_pkg.ALL; +USE common_lib.common_network_layers_pkg.ALL; USE rTwoSDF_lib.rTwoSDFPkg.ALL; USE fft_lib.fft_pkg.ALL; USE filter_lib.fil_pkg.ALL; @@ -98,6 +99,7 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_W_beamlet : NATURAL := 8; CONSTANT c_sdp_W_gn_id : NATURAL := 5; CONSTANT c_sdp_W_statistic : NATURAL := 64; + CONSTANT c_sdp_W_statistic_sz : NATURAL := 2; -- = c_sdp_W_statistic / c_word_w CONSTANT c_sdp_W_sub_weight : NATURAL := 16; -- = w in s(w, p), s = signed CONSTANT c_sdp_W_sub_weight_fraction : NATURAL := 13; -- = p in s(w, p) CONSTANT c_sdp_W_sub_weight_magnitude : NATURAL := c_sdp_W_sub_weight - c_sdp_W_sub_weight_fraction - 1; -- = 2 @@ -117,17 +119,16 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_T_sub : TIME := c_sdp_N_fft * c_sdp_T_adc; CONSTANT c_sdp_W_bf_product : NATURAL := c_sdp_W_subband + c_sdp_W_bf_weight -1; CONSTANT c_sdp_X_sq : NATURAL := c_sdp_S_pn * c_sdp_S_pn; + CONSTANT c_sdp_block_period : NATURAL := c_sdp_N_fft * 1000 / c_sdp_f_adc_MHz; -- = 5120 [ns] - -- - CONSTANT c_sdp_marker_sst : NATURAL := 83; -- = 0x53 = 'S' - CONSTANT c_sdp_marker_bst : NATURAL := 66; -- = 0x42 = 'B' - CONSTANT c_sdp_marker_xst : NATURAL := 88; -- = 0x58 = 'X' + -- Default / tb values + CONSTANT c_sdp_beamlet_scale_default : NATURAL := 2**15; - --CONSTANT c_sdp_offload_time : NATURAL := 13000; -- from wave window 62855nS / 5nS = 12571 cycles. - CONSTANT c_sdp_offload_time : NATURAL := 600000; - + ----------------------------------------------------------------------------- + -- PFB + ----------------------------------------------------------------------------- - -- In SDP c_nof_channels = 2**nof_chan = 1 and wb_factor = 1, + -- In SDP c_nof_channels = 2**nof_chan = 1 and wb_factor = 1, -- therefore these parameters are not explicitly used in calculation of derived constants -- LTS 2020_11_23: --CONSTANT c_sdp_wpfb_subbands : t_wpfb := @@ -143,13 +144,16 @@ PACKAGE sdp_pkg is -- . g_fft_stage_dat_w = 22 (was 18) -- . g_fft_guard_w = 1 (was 2) CONSTANT c_sdp_wpfb_subbands : t_wpfb := - (1, c_sdp_N_fft, 0, c_sdp_P_pfb, - c_sdp_N_taps, 0, c_sdp_W_adc, 17, c_sdp_W_fir_coef, - true, false, true, 17, c_sdp_W_subband, 0, 22, 1, - true, 54, 2, 195313, c_fft_pipeline, c_fft_pipeline, - c_fil_ppf_pipeline); + (1, c_sdp_N_fft, 0, c_sdp_P_pfb, + c_sdp_N_taps, 0, c_sdp_W_adc, 17, c_sdp_W_fir_coef, + true, false, true, 17, c_sdp_W_subband, 0, 22, 1, + true, 54, c_sdp_W_statistic_sz, 195313, c_fft_pipeline, c_fft_pipeline, + c_fil_ppf_pipeline); + + ----------------------------------------------------------------------------- + -- Statistics offload + ----------------------------------------------------------------------------- - -- statistics offload -- The statistics offload uses the same 1GbE port as the NiosII for M&C. The 1GbE addresses defined in SW and here in FW. -- See NiosII code: -- https://git.astron.nl/desp/hdl/-/blob/master/libraries/unb_osy/unbos_eth.h @@ -157,22 +161,33 @@ PACKAGE sdp_pkg is -- and g_base_ip = x"0A63" in: -- https://git.astron.nl/desp/hdl/-/blob/master/boards/uniboard2b/libraries/unb2b_board/src/vhdl/ctrl_unb2b_board.vhd + -- Can use same offload time for all statistics, because 1GbE mux will combine them + --CONSTANT c_sdp_offload_time : NATURAL := 13000; -- from wave window 62855nS / 5nS = 12571 cycles. + CONSTANT c_sdp_offload_time : NATURAL := 600000; -- see L2SDP-452 + + -- packet lengths, see ICD SC-SDP + CONSTANT c_sdp_nof_bytes_per_statistic : NATURAL := 8; -- c_sdp_W_statistic_sz * c_word_sz = 2 * 4 = 8 + + CONSTANT c_sdp_stat_app_header_len : NATURAL := 32; + + CONSTANT c_sdp_stat_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := x"001B217176B9"; -- 001B217176B9 = DOP36-enp2s0 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_sst_udp_src_port_15_8 : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"D0"; -- TBC - 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 + CONSTANT c_sdp_stat_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(5001, 16); + 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 - CONSTANT c_sdp_cep_app_header_len : NATURAL := 32; - CONSTANT c_sdp_stat_app_header_len : NATURAL := 32; - - CONSTANT c_sdp_stat_nof_hdr_fields : NATURAL := 1+3+12+4+20+1; -- 608b; 19 32b words - CONSTANT c_sdp_stat_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "1"&"101"&"111011111001"&"0101"&"0100"&"000000000"&"0000100"&"0"; -- 0=data path, 1=MM controlled TODO ---CONSTANT c_sdp_stat_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "0"&"100"&"000000010001"&"0100"&"0100"&"000000010"&"1000000"&"0"; -- 0=data path, 1=MM controlled TODO + CONSTANT c_sdp_stat_version_id : NATURAL := 5; + CONSTANT c_sdp_stat_nof_hdr_fields : NATURAL := 1+3+12+4+20+1; -- 608b; 19 32b words + CONSTANT c_sdp_stat_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "1"&"101"&"111011111001"&"0100"&"0100"&"000000010"&"1000000"&"0"; -- 0=data path, 1=MM controlled +--CONSTANT c_sdp_stat_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "1"&"101"&"111011111001"&"0101"&"0100"&"000000000"&"0000100"&"0"; -- 0=data path, 1=MM controlled TODO (26 nov 2021) +--CONSTANT c_sdp_stat_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "0"&"100"&"000000010001"&"0100"&"0100"&"000000010"&"1000000"&"0"; -- 0=data path, 1=MM controlled TODO CONSTANT c_sdp_stat_hdr_field_arr : t_common_field_arr(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := ( - ( field_name_pad("word_align" ), "RW", 16, field_default(0) ), - ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"001B217176B9") ), -- 001B217176B9 = DOP36-enp2s0 + ( field_name_pad("word_align" ), "RW", 16, field_default(0) ), -- Tx TSE IP will strip these 2 padding bytes + ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(c_sdp_stat_eth_dst_mac) ), ( field_name_pad("eth_src_mac" ), "RW", 48, field_default(0) ), ( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ), @@ -187,15 +202,15 @@ PACKAGE sdp_pkg is ( field_name_pad("ip_protocol" ), "RW", 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"0A6300FE") ), -- 0A6300FE = DOP36-enp2s0 '10.99.0.254' + ( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(c_sdp_stat_ip_dst_addr) ), ( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ), - ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(5001) ), + ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(c_sdp_stat_udp_dst_port) ), ( field_name_pad("udp_total_length" ), "RW", 16, field_default(0) ), ( field_name_pad("udp_checksum" ), "RW", 16, field_default(0) ), ( field_name_pad("sdp_marker" ), "RW", 8, field_default(0) ), - ( field_name_pad("sdp_version_id" ), "RW", 8, field_default(5) ), + ( field_name_pad("sdp_version_id" ), "RW", 8, field_default(c_sdp_stat_version_id) ), ( field_name_pad("sdp_observation_id" ), "RW", 32, field_default(0) ), ( field_name_pad("sdp_station_id" ), "RW", 16, field_default(0) ), @@ -213,34 +228,94 @@ PACKAGE sdp_pkg is ( field_name_pad("sdp_integration_interval" ), "RW", 24, field_default(0) ), ( field_name_pad("sdp_data_id" ), "RW", 32, field_default(0) ), ( field_name_pad("sdp_nof_signal_inputs" ), "RW", 8, field_default(0) ), - ( field_name_pad("sdp_nof_bytes_per_statistics" ), "RW", 8, field_default(8) ), + ( field_name_pad("sdp_nof_bytes_per_statistic" ), "RW", 8, field_default(c_sdp_nof_bytes_per_statistic) ), ( field_name_pad("sdp_nof_statistics_per_packet" ), "RW", 16, field_default(0) ), - ( field_name_pad("sdp_block_period" ), "RW", 16, field_default(0) ), + ( field_name_pad("sdp_block_period" ), "RW", 16, field_default(c_sdp_block_period) ), ( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) ) ); - CONSTANT c_sdp_reg_stat_hdr_dat_addr_w : NATURAL := ceil_log2(field_nof_words(c_sdp_stat_hdr_field_arr, c_word_w)); - - -- 10GbE offload (cep = central processor) + CONSTANT c_sdp_reg_stat_hdr_dat_addr_w : NATURAL := ceil_log2(field_nof_words(c_sdp_stat_hdr_field_arr, c_word_w)); + + TYPE t_sdp_network_stat_header IS RECORD + sdp_marker : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_version_id : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_observation_id : STD_LOGIC_VECTOR(31 DOWNTO 0); + sdp_station_id : STD_LOGIC_VECTOR(15 DOWNTO 0); + + sdp_source_info_antenna_band_id : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_nyquist_zone_id : STD_LOGIC_VECTOR( 1 DOWNTO 0); + sdp_source_info_f_adc : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_fsub_type : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_payload_error : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_beam_repositioning_flag : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_subband_calibrated_flag : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_reserved : STD_LOGIC_VECTOR( 2 DOWNTO 0); + sdp_source_info_gn_id : STD_LOGIC_VECTOR( 4 DOWNTO 0); + + sdp_reserved : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_integration_interval : STD_LOGIC_VECTOR(23 DOWNTO 0); + sdp_data_id : STD_LOGIC_VECTOR(31 DOWNTO 0); + sdp_data_id_sst_signal_input_index : STD_LOGIC_VECTOR( 7 DOWNTO 0); -- sdp_data_id sub field + sdp_data_id_bst_beamlet_index : STD_LOGIC_VECTOR(15 DOWNTO 0); -- sdp_data_id sub field + sdp_data_id_xst_subband_index : STD_LOGIC_VECTOR(24 DOWNTO 16); -- sdp_data_id sub field + sdp_data_id_xst_signal_input_A_index : STD_LOGIC_VECTOR(15 DOWNTO 8); -- sdp_data_id sub field + sdp_data_id_xst_signal_input_B_index : STD_LOGIC_VECTOR( 7 DOWNTO 0); -- sdp_data_id sub field + sdp_nof_signal_inputs : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_nof_bytes_per_statistic : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_nof_statistics_per_packet : STD_LOGIC_VECTOR(15 DOWNTO 0); + sdp_block_period : STD_LOGIC_VECTOR(15 DOWNTO 0); + + dp_bsn : STD_LOGIC_VECTOR(63 DOWNTO 0); + END RECORD; + + TYPE t_sdp_stat_data_id IS RECORD + sst_signal_input_index : NATURAL RANGE 0 TO 2**8 - 1; -- < 192 = c_sdp_N_pn_max * c_sdp_S_pn + bst_beamlet_index : NATURAL RANGE 0 TO 2**16 - 1; -- < 976 = c_sdp_N_beamsets * c_sdp_S_sub_bf + xst_subband_index : NATURAL RANGE 0 TO 2**9 - 1; -- < 512 = c_sdp_N_sub + xst_signal_input_A_index : NATURAL RANGE 0 TO 2**8 - 1; -- < 192 = c_sdp_N_pn_max * c_sdp_S_pn + xst_signal_input_B_index : NATURAL RANGE 0 TO 2**8 - 1; -- < 192 = c_sdp_N_pn_max * c_sdp_S_pn + END RECORD; + + TYPE t_sdp_stat_header IS RECORD + eth : t_network_eth_header; + ip : t_network_ip_header; + udp : t_network_udp_header; + app : t_sdp_network_stat_header; + END RECORD; + + ----------------------------------------------------------------------------- + -- Beamlet output via 10GbE to CEP (= central processor) + ----------------------------------------------------------------------------- + CONSTANT c_sdp_marker_beamlets : NATURAL := 98; -- = x"62" = 'b' + + CONSTANT c_sdp_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := x"00074306C700"; -- 00074306C700 = DOP36-eth0 CONSTANT c_sdp_cep_eth_src_mac_47_16 : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00228608"; -- 47:16, 15:8 = backplane, 7:0 = node + CONSTANT c_sdp_cep_ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"C0A80001"; -- C0A80001 = '192.168.0.1' = DOP36-eth0 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_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_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_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; + CONSTANT c_sdp_cep_version_id : NATURAL := 5; CONSTANT c_sdp_cep_nof_blocks_per_packet : NATURAL := 4; - CONSTANT c_sdp_cep_nof_beamlets_per_block : NATURAL := c_sdp_S_sub_bf; -- number of dual pol beamlets (c_sdp_N_pol_bf = 2) + CONSTANT c_sdp_cep_nof_beamlets_per_block : NATURAL := c_sdp_S_sub_bf; -- number of dual pol beamlets (c_sdp_N_pol_bf = 2) + CONSTANT c_sdp_cep_nof_hdr_fields : NATURAL := 3+12+4+18+1; -- 592b; 9.25 64b words CONSTANT c_sdp_cep_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_cep_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"1100"&"00000010"&"000110"&"0"; -- 0=data path, 1=MM controlled TODO --CONSTANT c_sdp_cep_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_cep_nof_hdr_fields-1 DOWNTO 0) := "100"&"000000010001"&"0100"&"0100"&"00000000"&"101000"&"0"; -- 0=data path, 1=MM controlled TODO CONSTANT c_sdp_cep_hdr_field_arr : t_common_field_arr(c_sdp_cep_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_dst_mac" ), "RW", 48, field_default(c_sdp_cep_eth_dst_mac) ), ( field_name_pad("eth_src_mac" ), "RW", 48, field_default(0) ), ( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ), ( field_name_pad("ip_version" ), "RW", 4, field_default(4) ), ( field_name_pad("ip_header_length" ), "RW", 4, field_default(5) ), ( field_name_pad("ip_services" ), "RW", 8, field_default(0) ), - ( field_name_pad("ip_total_length" ), "RW", 16, field_default(7868) ), + ( field_name_pad("ip_total_length" ), "RW", 16, field_default(c_sdp_cep_ip_total_length) ), ( field_name_pad("ip_identification" ), "RW", 16, field_default(0) ), ( field_name_pad("ip_flags" ), "RW", 3, field_default(2) ), ( field_name_pad("ip_fragment_offset" ), "RW", 13, field_default(0) ), @@ -248,15 +323,15 @@ PACKAGE sdp_pkg is ( field_name_pad("ip_protocol" ), "RW", 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("ip_dst_addr" ), "RW", 32, field_default(c_sdp_cep_ip_dst_addr) ), ( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ), - ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(5000) ), - ( field_name_pad("udp_total_length" ), "RW", 16, field_default(7848) ), + ( field_name_pad("udp_dst_port" ), "RW", 16, field_default(c_sdp_cep_udp_dst_port) ), + ( field_name_pad("udp_total_length" ), "RW", 16, field_default(c_sdp_cep_udp_total_length) ), ( field_name_pad("udp_checksum" ), "RW", 16, field_default(0) ), - ( field_name_pad("sdp_marker" ), "RW", 8, field_default(x"62") ), - ( field_name_pad("sdp_version_id" ), "RW", 8, field_default(5) ), + ( field_name_pad("sdp_marker" ), "RW", 8, field_default(c_sdp_marker_beamlets) ), + ( field_name_pad("sdp_version_id" ), "RW", 8, field_default(c_sdp_cep_version_id) ), ( field_name_pad("sdp_observation_id" ), "RW", 32, field_default(0) ), ( field_name_pad("sdp_station_id" ), "RW", 16, field_default(0) ), @@ -270,19 +345,54 @@ PACKAGE sdp_pkg is ( 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_scale" ), "RW", 16, field_default(c_sdp_beamlet_scale_default) ), ( field_name_pad("sdp_beamlet_id" ), "RW", 16, field_default(0) ), ( field_name_pad("sdp_nof_blocks_per_packet" ), "RW", 8, field_default(c_sdp_cep_nof_blocks_per_packet) ), ( field_name_pad("sdp_nof_beamlets_per_block" ), "RW", 16, field_default(c_sdp_cep_nof_beamlets_per_block) ), - ( field_name_pad("sdp_block_period" ), "RW", 16, field_default(5120) ), + ( field_name_pad("sdp_block_period" ), "RW", 16, field_default(c_sdp_block_period) ), ( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) ) ); - -- ST UDP offload MM address widths - CONSTANT c_sdp_reg_stat_enable_addr_w : NATURAL := 1; + CONSTANT c_sdp_reg_cep_hdr_dat_addr_w : NATURAL := ceil_log2(field_nof_words(c_sdp_cep_hdr_field_arr, c_word_w)); + + TYPE t_sdp_network_cep_header IS RECORD + sdp_marker : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_version_id : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_observation_id : STD_LOGIC_VECTOR(31 DOWNTO 0); + sdp_station_id : STD_LOGIC_VECTOR(15 DOWNTO 0); + + sdp_source_info_antenna_band_id : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_nyquist_zone_id : STD_LOGIC_VECTOR( 1 DOWNTO 0); + sdp_source_info_f_adc : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_fsub_type : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_payload_error : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_repositioning_flag : STD_LOGIC_VECTOR( 0 DOWNTO 0); + sdp_source_info_beamlet_width : STD_LOGIC_VECTOR( 3 DOWNTO 0); + sdp_source_info_gn_id : STD_LOGIC_VECTOR( 4 DOWNTO 0); + + sdp_reserved : STD_LOGIC_VECTOR(39 DOWNTO 0); + sdp_beamlet_scale : STD_LOGIC_VECTOR(15 DOWNTO 0); + sdp_beamlet_id : STD_LOGIC_VECTOR(15 DOWNTO 0); + sdp_nof_blocks_per_packet : STD_LOGIC_VECTOR( 7 DOWNTO 0); + sdp_nof_beamlets_per_block : STD_LOGIC_VECTOR(15 DOWNTO 0); + sdp_block_period : STD_LOGIC_VECTOR(15 DOWNTO 0); + + dp_bsn : STD_LOGIC_VECTOR(63 DOWNTO 0); + END RECORD; + + TYPE t_sdp_cep_header IS RECORD + eth : t_network_eth_header; + ip : t_network_ip_header; + udp : t_network_udp_header; + app : t_sdp_network_cep_header; + END RECORD; + + ----------------------------------------------------------------------------- + -- MM + ----------------------------------------------------------------------------- -- 10GbE MM address widths - CONSTANT c_sdp_reg_hdr_dat_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + ceil_log2(field_nof_words(c_sdp_cep_hdr_field_arr, c_word_w)); + CONSTANT c_sdp_reg_bf_hdr_dat_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + c_sdp_reg_cep_hdr_dat_addr_w; CONSTANT c_sdp_reg_nw_10GbE_mac_addr_w : NATURAL := 13; CONSTANT c_sdp_reg_nw_10GbE_eth10g_addr_w : NATURAL := 1; @@ -294,7 +404,6 @@ PACKAGE sdp_pkg is nof_dat => 1, init_sl => '0'); - -- AIT MM address widths CONSTANT c_sdp_jesd204b_addr_w : NATURAL := ceil_log2(c_sdp_S_pn) + 8; CONSTANT c_sdp_jesd_ctrl_addr_w : NATURAL := 1; @@ -311,29 +420,38 @@ PACKAGE sdp_pkg is -- FSUB MM address widths CONSTANT c_sdp_ram_fil_coefs_addr_w : NATURAL := ceil_log2(c_sdp_N_fft * c_sdp_N_taps); - CONSTANT c_sdp_ram_st_sst_addr_w : NATURAL := ceil_log2(c_sdp_P_pfb*c_sdp_N_sub*c_sdp_Q_fft*c_sdp_wpfb_subbands.stat_data_sz); + CONSTANT c_sdp_ram_st_sst_addr_w : NATURAL := ceil_log2(c_sdp_P_pfb * c_sdp_N_sub * c_sdp_Q_fft * c_sdp_W_statistic_sz); CONSTANT c_sdp_reg_si_addr_w : NATURAL := 1; --enable/disable CONSTANT c_sdp_ram_equalizer_gains_addr_w : NATURAL := ceil_log2(c_sdp_P_pfb*c_sdp_N_sub*c_sdp_Q_fft); CONSTANT c_sdp_reg_dp_selector_addr_w : NATURAL := 1; --Select input 0 or 1. + -- STAT UDP offload MM address widths + CONSTANT c_sdp_reg_stat_enable_addr_w : NATURAL := 1; + -- BF MM address widths CONSTANT c_sdp_reg_sdp_info_addr_w : NATURAL := 4; CONSTANT c_sdp_ram_ss_ss_wide_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + ceil_log2(c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); CONSTANT c_sdp_ram_bf_weights_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + ceil_log2(c_sdp_N_pol_bf * c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); CONSTANT c_sdp_reg_bf_scale_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + 1; CONSTANT c_sdp_reg_dp_xonoff_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + 1; - CONSTANT c_sdp_ram_st_bst_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + ceil_log2(c_sdp_S_sub_bf*c_sdp_N_pol_bf*(c_longword_sz/c_word_sz)); + CONSTANT c_sdp_ram_st_bst_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + ceil_log2(c_sdp_S_sub_bf * c_sdp_N_pol_bf * c_sdp_W_statistic_sz); CONSTANT c_sdp_reg_stat_enable_bst_addr_w : NATURAL := ceil_log2(c_sdp_N_beamsets) + c_sdp_reg_stat_enable_addr_w; CONSTANT c_sdp_reg_stat_hdr_dat_bst_addr_w: NATURAL := ceil_log2(c_sdp_N_beamsets) + c_sdp_reg_stat_hdr_dat_addr_w; -- XSUB - CONSTANT c_sdp_crosslets_index_w : NATURAL := ceil_log2(c_sdp_N_sub); + CONSTANT c_sdp_crosslets_index_w : NATURAL := ceil_log2(c_sdp_N_sub); CONSTANT c_sdp_mm_reg_crosslets_info : t_c_mem := (latency => 1, adr_w => 4, dat_w => c_sdp_crosslets_index_w, nof_dat => 16, -- 15 offsets + 1 step init_sl => '0'); - CONSTANT c_sdp_crosslets_info_reg_w : NATURAL := c_sdp_mm_reg_crosslets_info.nof_dat*c_sdp_mm_reg_crosslets_info.dat_w; + CONSTANT c_sdp_crosslets_info_reg_w : NATURAL := c_sdp_mm_reg_crosslets_info.nof_dat*c_sdp_mm_reg_crosslets_info.dat_w; + CONSTANT c_sdp_crosslets_info_nof_offsets : NATURAL := c_sdp_mm_reg_crosslets_info.nof_dat - 1; + + TYPE t_sdp_crosslets_info IS RECORD + offset_arr : t_natural_arr(0 TO c_sdp_crosslets_info_nof_offsets-1); + step : NATURAL; + END RECORD; CONSTANT c_sdp_mm_reg_nof_crosslets : t_c_mem := (latency => 1, adr_w => 1, @@ -348,7 +466,8 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_reg_crosslets_info_addr_w : NATURAL := c_sdp_mm_reg_crosslets_info.adr_w; CONSTANT c_sdp_reg_nof_crosslets_addr_w : NATURAL := c_sdp_mm_reg_nof_crosslets.adr_w; CONSTANT c_sdp_reg_bsn_sync_scheduler_xsub_addr_w : NATURAL := 4; - CONSTANT c_sdp_ram_st_xsq_addr_w : NATURAL := ceil_log2(c_sdp_P_sq) + ceil_log2(c_sdp_N_crosslets_max * c_sdp_X_sq * c_nof_complex * (c_longword_sz/c_word_sz) ); + CONSTANT c_sdp_ram_st_xsq_addr_w : NATURAL := ceil_log2(c_sdp_N_crosslets_max * c_sdp_X_sq * c_nof_complex * c_sdp_W_statistic_sz); + CONSTANT c_sdp_ram_st_xsq_arr_addr_w : NATURAL := ceil_log2(c_sdp_P_sq) + c_sdp_ram_st_xsq_addr_w; -- RING MM address widths CONSTANT c_sdp_reg_bsn_monitor_v2_ring_rx_addr_w : NATURAL := ceil_log2(c_sdp_N_ring_lanes_max) + ceil_log2(c_sdp_N_pn_max) + ceil_Log2(7); @@ -364,11 +483,356 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_reg_diag_bg_addr_w : NATURAL := 3; CONSTANT c_sdp_ram_diag_bg_addr_w : NATURAL := 7; + ------------------------------------------------- + -- SDP simulation constants record, to use instead of HW default when g_sim = TRUE + ------------------------------------------------- + TYPE t_sdp_sim IS RECORD + xst_nof_clk_per_sync_min : NATURAL; + offload_time : NATURAL; -- select > 0 and gn_index > 0 to see effect of offload_time on statistics offload + END RECORD; + + CONSTANT c_sdp_sim : t_sdp_sim := (1, 10); + + ------------------------------------------------- + -- SDP functions + ------------------------------------------------- + + FUNCTION func_sdp_gn_index_to_pn_index(gn_index : NATURAL) RETURN NATURAL; + FUNCTION func_sdp_modulo_N_sub(sub_index : NATURAL) RETURN NATURAL; + + FUNCTION func_sdp_get_stat_marker(g_statistics_type : STRING) RETURN NATURAL; + FUNCTION func_sdp_get_stat_nof_signal_inputs(g_statistics_type : STRING) RETURN NATURAL; + FUNCTION func_sdp_get_stat_from_mm_data_size(g_statistics_type : STRING) RETURN NATURAL; + FUNCTION func_sdp_get_stat_from_mm_step_size(g_statistics_type : STRING) RETURN NATURAL; + FUNCTION func_sdp_get_stat_from_mm_nof_data(g_statistics_type : STRING) RETURN NATURAL; + FUNCTION func_sdp_get_stat_nof_statistics_per_packet(g_statistics_type : STRING) RETURN NATURAL; + 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_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 + + FUNCTION func_sdp_map_stat_header(hdr_fields_raw : STD_LOGIC_VECTOR) RETURN t_sdp_stat_header; + FUNCTION func_sdp_map_cep_header(hdr_fields_raw : STD_LOGIC_VECTOR) RETURN t_sdp_cep_header; + + FUNCTION func_sdp_map_stat_data_id(g_statistics_type : STRING; data_id_slv : STD_LOGIC_VECTOR) RETURN t_sdp_stat_data_id; + FUNCTION func_sdp_map_stat_data_id(g_statistics_type : STRING; data_id_rec : t_sdp_stat_data_id) RETURN STD_LOGIC_VECTOR; + + FUNCTION func_sdp_map_crosslets_info(info_slv : STD_LOGIC_VECTOR; nof_crosslets : NATURAL) RETURN t_sdp_crosslets_info; -- map only the used offsets + FUNCTION func_sdp_map_crosslets_info(info_slv : STD_LOGIC_VECTOR) RETURN t_sdp_crosslets_info; -- map all c_sdp_N_crosslets_max offsets + FUNCTION func_sdp_map_crosslets_info(info_rec : t_sdp_crosslets_info; nof_crosslets : NATURAL) RETURN STD_LOGIC_VECTOR; -- map only the used offsets + FUNCTION func_sdp_map_crosslets_info(info_rec : t_sdp_crosslets_info) RETURN STD_LOGIC_VECTOR; -- map all c_sdp_N_crosslets_max offsets + FUNCTION func_sdp_step_crosslets_info(info_rec : t_sdp_crosslets_info; nof_crosslets : NATURAL) RETURN t_sdp_crosslets_info; END PACKAGE sdp_pkg; PACKAGE BODY sdp_pkg IS - -END sdp_pkg; + FUNCTION func_sdp_gn_index_to_pn_index(gn_index : NATURAL) RETURN NATURAL IS + -- Determine PN index that starts at 0 per antenna band. + -- For LOFAR2 SDP there are two antenna bands: LB and HB. The LB starts at + -- GN index = 0 and has c_sdp_N_pn_lb = c_sdp_N_pn_max = 16 nodes. The HB + -- starts at c_sdp_N_pn_max. Assume every antenna_band starts at a GN: + -- + -- pn_index = gn_index MOD c_sdp_N_pn_max + -- + -- The fact that c_sdp_N_pn_max = 16 implies that instead of implementing + -- MOD it is possible to do: + -- + -- pn_index = gn_index[3:0], because log2(16) = 4 + CONSTANT c_pn_w : NATURAL := ceil_log2(c_sdp_N_pn_max); -- = 4 + -- use sufficient bits to fit both PN index and GN index in v_index + CONSTANT c_w : NATURAL := ceil_log2(c_sdp_N_pn_max + gn_index); + CONSTANT c_index : STD_LOGIC_VECTOR(c_w-1 DOWNTO 0) := TO_UVEC(gn_index, c_w); + BEGIN + RETURN TO_UINT(c_index(c_pn_w-1 DOWNTO 0)); + END func_sdp_gn_index_to_pn_index; + + FUNCTION func_sdp_modulo_N_sub(sub_index : NATURAL) RETURN NATURAL IS + BEGIN + ASSERT sub_index < 2 * c_sdp_N_sub REPORT "func_sdp_modulo_N_sub: sub_index too large" SEVERITY FAILURE; + IF sub_index < c_sdp_N_sub-1 THEN + RETURN sub_index; + ELSE + RETURN sub_index - c_sdp_N_sub; + END IF; + END func_sdp_modulo_N_sub; + + FUNCTION func_sdp_get_stat_marker(g_statistics_type : STRING) RETURN NATURAL IS + CONSTANT c_marker_sst : NATURAL := 83; -- = 0x53 = 'S' + CONSTANT c_marker_bst : NATURAL := 66; -- = 0x42 = 'B' + CONSTANT c_marker_xst : NATURAL := 88; -- = 0x58 = 'X' + BEGIN + RETURN sel_a_b(g_statistics_type="BST", c_marker_bst, + sel_a_b(g_statistics_type="XST", c_marker_xst, + c_marker_sst)); -- SST + END func_sdp_get_stat_marker; + + FUNCTION func_sdp_get_stat_nof_signal_inputs(g_statistics_type : STRING) RETURN NATURAL IS + BEGIN + RETURN sel_a_b(g_statistics_type="BST", 0, -- not applicable for BST, so use 0, + sel_a_b(g_statistics_type="XST", c_sdp_S_pn, + 1)); -- SST + END func_sdp_get_stat_nof_signal_inputs; + + FUNCTION func_sdp_get_stat_from_mm_data_size(g_statistics_type : STRING) RETURN NATURAL IS + BEGIN + RETURN sel_a_b(g_statistics_type="BST", c_sdp_N_pol_bf * c_sdp_W_statistic_sz, -- = 4 + sel_a_b(g_statistics_type="XST", c_nof_complex * c_sdp_W_statistic_sz, -- = 4 + c_sdp_W_statistic_sz)); -- = 2, SST + END func_sdp_get_stat_from_mm_data_size; + + FUNCTION func_sdp_get_stat_from_mm_step_size(g_statistics_type : STRING) RETURN NATURAL IS + CONSTANT c_data_size : NATURAL := func_sdp_get_stat_from_mm_data_size(g_statistics_type); + BEGIN + RETURN sel_a_b(g_statistics_type="BST", c_data_size, -- = 4 + sel_a_b(g_statistics_type="XST", c_data_size, -- = 4 + c_sdp_Q_fft * c_data_size)); -- = 4, SST + END func_sdp_get_stat_from_mm_step_size; + + FUNCTION func_sdp_get_stat_from_mm_nof_data(g_statistics_type : STRING) RETURN NATURAL IS + BEGIN + RETURN sel_a_b(g_statistics_type="BST", c_sdp_S_sub_bf, -- = 488 + sel_a_b(g_statistics_type="XST", c_sdp_X_sq, -- = 144 + c_sdp_N_sub)); -- = 512, SST + END func_sdp_get_stat_from_mm_nof_data; + + FUNCTION func_sdp_get_stat_nof_statistics_per_packet(g_statistics_type : STRING) RETURN NATURAL IS + BEGIN + RETURN sel_a_b(g_statistics_type="BST", c_sdp_S_sub_bf * c_sdp_N_pol_bf, -- = 976 + sel_a_b(g_statistics_type="XST", c_sdp_X_sq * c_nof_complex, -- = 288 + c_sdp_N_sub)); -- = 512, SST + END func_sdp_get_stat_nof_statistics_per_packet; + + FUNCTION func_sdp_get_stat_app_total_length(g_statistics_type : STRING) RETURN NATURAL IS + CONSTANT c_nof_statistics_per_packet : NATURAL := func_sdp_get_stat_nof_statistics_per_packet(g_statistics_type); + BEGIN + -- RETURN: + -- . SST : 4128 (= 4096 + 32) + -- . BST : 7840 (= 7808 + 32) + -- . XST : 2336 (= 2304 + 32) + RETURN c_nof_statistics_per_packet * c_sdp_nof_bytes_per_statistic + c_sdp_stat_app_header_len; + END func_sdp_get_stat_app_total_length; + + FUNCTION func_sdp_get_stat_udp_total_length(g_statistics_type : STRING) RETURN NATURAL IS + CONSTANT c_sdp_app_total_length : NATURAL := func_sdp_get_stat_app_total_length(g_statistics_type); + BEGIN + -- RETURN: + -- . SST : 4136 (= 4128 + 8) + -- . BST : 7848 (= 7840 + 8) + -- . XST : 2344 (= 2336 + 8) + RETURN c_sdp_app_total_length + c_network_udp_header_len; + END func_sdp_get_stat_udp_total_length; + + FUNCTION func_sdp_get_stat_ip_total_length(g_statistics_type : STRING) RETURN NATURAL IS + CONSTANT c_sdp_udp_total_length : NATURAL := func_sdp_get_stat_udp_total_length(g_statistics_type); + BEGIN + -- RETURN: + -- . SST : 4156 (= 4136 + 20) + -- . BST : 7868 (= 7848 + 20) + -- . XST : 2364 (= 2344 + 20) + RETURN c_sdp_udp_total_length + c_network_ip_header_len; + END func_sdp_get_stat_ip_total_length; + + 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, + sel_a_b(g_statistics_type="XST", P_sq * N_crosslets, + S_pn)); -- SST + END func_sdp_get_stat_nof_packets; + + FUNCTION func_sdp_get_stat_nof_packets(g_statistics_type : STRING) RETURN NATURAL IS + BEGIN + RETURN func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, c_sdp_P_sq, c_sdp_N_crosslets_max); + END func_sdp_get_stat_nof_packets; + + + FUNCTION func_sdp_map_stat_header(hdr_fields_raw : STD_LOGIC_VECTOR) RETURN t_sdp_stat_header IS + VARIABLE v : t_sdp_stat_header; + BEGIN + -- eth header + v.eth.dst_mac := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_dst_mac") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_dst_mac")); + v.eth.src_mac := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_src_mac")); + v.eth.eth_type := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_type") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_type")); + + -- ip header + v.ip.version := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_version") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_version")); + v.ip.header_length := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_header_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_header_length")); + v.ip.services := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_services") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_services")); + v.ip.total_length := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_total_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_total_length")); + v.ip.identification := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_identification") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_identification")); + v.ip.flags := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_flags") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_flags")); + v.ip.fragment_offset := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_fragment_offset") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_fragment_offset")); + v.ip.time_to_live := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_time_to_live") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_time_to_live")); + v.ip.protocol := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_protocol") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_protocol")); + v.ip.header_checksum := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_header_checksum") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_header_checksum")); + v.ip.src_ip_addr := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_src_addr") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_src_addr")); + v.ip.dst_ip_addr := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_dst_addr") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_dst_addr")); + + -- udp header + v.udp.src_port := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_src_port")); + v.udp.dst_port := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_dst_port") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_dst_port")); + v.udp.total_length := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_total_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_total_length")); + v.udp.checksum := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_checksum") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_checksum")); + + -- app header + v.app.sdp_marker := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_marker") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_marker")); + v.app.sdp_version_id := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_version_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_version_id")); + v.app.sdp_observation_id := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_observation_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_observation_id")); + v.app.sdp_station_id := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_station_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_station_id")); + + v.app.sdp_source_info_antenna_band_id := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id")); + v.app.sdp_source_info_nyquist_zone_id := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id")); + v.app.sdp_source_info_f_adc := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc")); + v.app.sdp_source_info_fsub_type := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type")); + v.app.sdp_source_info_payload_error := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_payload_error") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_payload_error")); + v.app.sdp_source_info_beam_repositioning_flag := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag")); + v.app.sdp_source_info_subband_calibrated_flag := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_subband_calibrated_flag") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_subband_calibrated_flag")); + v.app.sdp_source_info_reserved := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_reserved") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_reserved")); + v.app.sdp_source_info_gn_id := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id")); + + v.app.sdp_reserved := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_reserved") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_reserved")); + v.app.sdp_integration_interval := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_integration_interval") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_integration_interval")); + v.app.sdp_data_id := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_data_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_data_id")); + v.app.sdp_data_id_sst_signal_input_index := v.app.sdp_data_id( 7 DOWNTO 0); + v.app.sdp_data_id_bst_beamlet_index := v.app.sdp_data_id(15 DOWNTO 0); + v.app.sdp_data_id_xst_subband_index := v.app.sdp_data_id(24 DOWNTO 16); + v.app.sdp_data_id_xst_signal_input_A_index := v.app.sdp_data_id(15 DOWNTO 8); + v.app.sdp_data_id_xst_signal_input_B_index := v.app.sdp_data_id( 7 DOWNTO 0); + v.app.sdp_nof_signal_inputs := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs")); + v.app.sdp_nof_bytes_per_statistic := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_bytes_per_statistic") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_bytes_per_statistic")); + v.app.sdp_nof_statistics_per_packet := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet")); + v.app.sdp_block_period := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_block_period") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_block_period")); + + v.app.dp_bsn := hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "dp_bsn")); + RETURN v; + END func_sdp_map_stat_header; + + + FUNCTION func_sdp_map_cep_header(hdr_fields_raw : STD_LOGIC_VECTOR) RETURN t_sdp_cep_header IS + VARIABLE v : t_sdp_cep_header; + BEGIN + -- eth header + v.eth.dst_mac := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "eth_dst_mac") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "eth_dst_mac")); + v.eth.src_mac := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "eth_src_mac")); + v.eth.eth_type := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "eth_type") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "eth_type")); + + -- ip header + v.ip.version := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_version") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_version")); + v.ip.header_length := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_header_length") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_header_length")); + v.ip.services := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_services") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_services")); + v.ip.total_length := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_total_length") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_total_length")); + v.ip.identification := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_identification") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_identification")); + v.ip.flags := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_flags") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_flags")); + v.ip.fragment_offset := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_fragment_offset") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_fragment_offset")); + v.ip.time_to_live := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_time_to_live") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_time_to_live")); + v.ip.protocol := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_protocol") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_protocol")); + v.ip.header_checksum := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_header_checksum") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_header_checksum")); + v.ip.src_ip_addr := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_src_addr") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_src_addr")); + v.ip.dst_ip_addr := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "ip_dst_addr") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "ip_dst_addr")); + + -- udp header + v.udp.src_port := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "udp_src_port")); + v.udp.dst_port := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "udp_dst_port") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "udp_dst_port")); + v.udp.total_length := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "udp_total_length") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "udp_total_length")); + v.udp.checksum := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "udp_checksum") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "udp_checksum")); + + -- app header + v.app.sdp_marker := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_marker") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_marker")); + v.app.sdp_version_id := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_version_id") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_version_id")); + v.app.sdp_observation_id := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_observation_id") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_observation_id")); + v.app.sdp_station_id := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_station_id") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_station_id")); + + v.app.sdp_source_info_antenna_band_id := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_antenna_band_id") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_antenna_band_id")); + v.app.sdp_source_info_nyquist_zone_id := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_nyquist_zone_id") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_nyquist_zone_id")); + v.app.sdp_source_info_f_adc := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_f_adc") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_f_adc")); + v.app.sdp_source_info_fsub_type := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_fsub_type") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_fsub_type")); + v.app.sdp_source_info_payload_error := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_payload_error") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_payload_error")); + v.app.sdp_source_info_repositioning_flag := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_repositioning_flag") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_repositioning_flag")); + v.app.sdp_source_info_beamlet_width := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_beamlet_width") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_beamlet_width")); + v.app.sdp_source_info_gn_id := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_gn_id") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_gn_id")); + + v.app.sdp_reserved := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_reserved") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_reserved")); + v.app.sdp_beamlet_scale := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_beamlet_scale") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_beamlet_scale")); + v.app.sdp_beamlet_id := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_beamlet_id") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_beamlet_id")); + v.app.sdp_nof_blocks_per_packet := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_nof_blocks_per_packet") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_nof_blocks_per_packet")); + v.app.sdp_nof_beamlets_per_block := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_nof_beamlets_per_block") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_nof_beamlets_per_block")); + v.app.sdp_block_period := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "sdp_block_period") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "sdp_block_period")); + + v.app.dp_bsn := hdr_fields_raw(field_hi(c_sdp_cep_hdr_field_arr, "dp_bsn") DOWNTO field_lo(c_sdp_cep_hdr_field_arr, "dp_bsn")); + RETURN v; + END func_sdp_map_cep_header; + + + FUNCTION func_sdp_map_stat_data_id(g_statistics_type : STRING; data_id_slv : STD_LOGIC_VECTOR) RETURN t_sdp_stat_data_id IS + VARIABLE v_rec : t_sdp_stat_data_id; + BEGIN + IF g_statistics_type = "SST" THEN + v_rec.sst_signal_input_index := TO_UINT(data_id_slv(7 DOWNTO 0)); + ELSIF g_statistics_type = "BST" THEN + v_rec.bst_beamlet_index := TO_UINT(data_id_slv(15 DOWNTO 0)); + ELSIF g_statistics_type = "XST" THEN + v_rec.xst_subband_index := TO_UINT(data_id_slv(24 DOWNTO 16)); + v_rec.xst_signal_input_A_index := TO_UINT(data_id_slv(15 DOWNTO 8)); + v_rec.xst_signal_input_B_index := TO_UINT(data_id_slv(7 DOWNTO 0)); + END IF; + RETURN v_rec; + END func_sdp_map_stat_data_id; + + FUNCTION func_sdp_map_stat_data_id(g_statistics_type : STRING; data_id_rec : t_sdp_stat_data_id) RETURN STD_LOGIC_VECTOR IS + VARIABLE v_slv : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00000000"; + BEGIN + IF g_statistics_type = "SST" THEN + v_slv(7 DOWNTO 0) := TO_UVEC(data_id_rec.sst_signal_input_index, 8); + ELSIF g_statistics_type = "BST" THEN + v_slv(15 DOWNTO 0) := TO_UVEC(data_id_rec.bst_beamlet_index, 16); + ELSIF g_statistics_type = "XST" THEN + v_slv(24 DOWNTO 16) := TO_UVEC(data_id_rec.xst_subband_index, 9); + v_slv(15 DOWNTO 8) := TO_UVEC(data_id_rec.xst_signal_input_A_index, 8); + v_slv(7 DOWNTO 0) := TO_UVEC(data_id_rec.xst_signal_input_B_index, 8); + END IF; + RETURN v_slv; + END func_sdp_map_stat_data_id; + + + FUNCTION func_sdp_map_crosslets_info(info_slv : STD_LOGIC_VECTOR; nof_crosslets : NATURAL) RETURN t_sdp_crosslets_info IS + VARIABLE v_info : t_sdp_crosslets_info; + BEGIN + FOR I IN 0 TO nof_crosslets-1 LOOP -- map only used offsets + v_info.offset_arr(I) := TO_UINT(info_slv((I+1)*c_sdp_crosslets_index_w-1 DOWNTO I*c_sdp_crosslets_index_w)); + END LOOP; + v_info.step := TO_UINT(info_slv(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w)); + RETURN v_info; + END func_sdp_map_crosslets_info; + + FUNCTION func_sdp_map_crosslets_info(info_slv : STD_LOGIC_VECTOR) RETURN t_sdp_crosslets_info IS + BEGIN + RETURN func_sdp_map_crosslets_info(info_slv, c_sdp_crosslets_info_nof_offsets); -- map all offsets + END func_sdp_map_crosslets_info; + + FUNCTION func_sdp_map_crosslets_info(info_rec : t_sdp_crosslets_info; nof_crosslets : NATURAL) RETURN STD_LOGIC_VECTOR IS + VARIABLE v_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0); + BEGIN + FOR I IN 0 TO nof_crosslets-1 LOOP -- map only used offsets + v_info((I+1)*c_sdp_crosslets_index_w-1 DOWNTO I*c_sdp_crosslets_index_w) := TO_UVEC(info_rec.offset_arr(I), c_sdp_crosslets_index_w); + END LOOP; + v_info(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) := TO_UVEC(info_rec.step, c_sdp_crosslets_index_w); + RETURN v_info; + END func_sdp_map_crosslets_info; + + FUNCTION func_sdp_map_crosslets_info(info_rec : t_sdp_crosslets_info) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN func_sdp_map_crosslets_info(info_rec, c_sdp_crosslets_info_nof_offsets); -- map all offsets + END func_sdp_map_crosslets_info; + + + FUNCTION func_sdp_step_crosslets_info(info_rec : t_sdp_crosslets_info; nof_crosslets : NATURAL) RETURN t_sdp_crosslets_info IS + VARIABLE v_info : t_sdp_crosslets_info := info_rec; + BEGIN + FOR I IN 0 TO nof_crosslets-1 LOOP -- step only the used offsets + v_info.offset_arr(I) := v_info.offset_arr(I) + v_info.step; + END LOOP; + RETURN v_info; + END func_sdp_step_crosslets_info; +END sdp_pkg; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd index a0d6261300e81b140aa2db9bb9c2ccfd85094d2d..8ba6b29573f01fcdbd3f49fcd45c3cd514dd7e97 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd @@ -44,7 +44,8 @@ USE eth_lib.eth_pkg.ALL; ENTITY sdp_station IS GENERIC ( g_technology : NATURAL := c_tech_arria10_e1sg; - g_sim : BOOLEAN := FALSE; --Overridden by TB + g_sim : BOOLEAN := FALSE; -- Overridden by TB + g_sim_sdp : t_sdp_sim := c_sdp_sim; -- Used when g_sim = TRUE, otherwise use HW defaults g_wpfb : t_wpfb := c_sdp_wpfb_subbands; g_bsn_nof_clk_per_sync : NATURAL := c_sdp_N_clk_per_sync; -- Default 200M, overide for short simulation g_scope_selected_subband : NATURAL := 0; @@ -459,6 +460,7 @@ BEGIN u_fsub : ENTITY work.node_sdp_filterbank GENERIC MAP( g_sim => g_sim, + g_sim_sdp => g_sim_sdp, g_wpfb => g_wpfb, g_scope_selected_subband => g_scope_selected_subband ) @@ -508,8 +510,9 @@ BEGIN gen_use_xsub : IF g_use_xsub GENERATE u_xsub : ENTITY work.node_sdp_correlator GENERIC MAP( - g_sim => g_sim, - g_P_sq => g_P_sq + g_sim => g_sim, + g_sim_sdp => g_sim_sdp, + g_P_sq => g_P_sq ) PORT MAP( dp_clk => dp_clk, @@ -554,7 +557,8 @@ BEGIN u_bf : ENTITY work.node_sdp_beamformer GENERIC MAP( g_sim => g_sim, - g_beamset_id => beamset_id, + g_sim_sdp => g_sim_sdp, + g_beamset_id => beamset_id, g_scope_selected_beamlet => g_scope_selected_subband ) PORT MAP( 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 e756819c794fc0da75ecb178147bc40837302179..e3852bd36718fe5e2157207eedfae96682eaaf00 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd @@ -20,7 +20,7 @@ ------------------------------------------------------------------------------- -- --- Author: P. Donker, R van der Walle +-- Author: P. Donker, R van der Walle, E. Kooistra -- Purpose: -- . SDP statistics offload @@ -32,21 +32,23 @@ -- ------------------------------------------------------------------------------- -LIBRARY IEEE, common_lib, mm_lib, dp_lib; +LIBRARY IEEE, common_lib, mm_lib, dp_lib, ring_lib; USE IEEE.STD_LOGIC_1164.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_field_pkg.ALL; USE common_lib.common_network_layers_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; +USE ring_lib.ring_pkg.ALL; USE work.sdp_pkg.ALL; ENTITY sdp_statistics_offload IS GENERIC ( - g_statistics_type : STRING := "SST"; - g_offload_time : NATURAL := c_sdp_offload_time; - g_beamset_id : NATURAL := 0; - g_P_sq : NATURAL := c_sdp_P_sq -- use generic to support P_sq = 1 for one node and P_sq = c_sdp_P_sq for multiple nodes (with ring) + g_statistics_type : STRING := "SST"; + g_offload_time : NATURAL := c_sdp_offload_time; + g_beamset_id : NATURAL := 0; + g_P_sq : NATURAL := c_sdp_P_sq; -- use generic to support P_sq = 1 for one node and P_sq = c_sdp_P_sq for multiple nodes (with ring) + g_crosslets_direction : NATURAL := 1 -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction ); PORT ( -- Clocks and reset @@ -57,123 +59,141 @@ ENTITY sdp_statistics_offload IS dp_rst : IN STD_LOGIC; -- Memory access to statistics values - master_mosi : OUT t_mem_mosi; -- := c_mem_mosi_rst; - master_miso : IN t_mem_miso; + master_mosi : OUT t_mem_mosi; -- := c_mem_mosi_rst; + master_miso : IN t_mem_miso; -- Memory access to read/write settings - reg_enable_mosi : IN t_mem_mosi := c_mem_mosi_rst; - reg_enable_miso : OUT t_mem_miso; + reg_enable_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_enable_miso : OUT t_mem_miso; reg_hdr_dat_mosi : IN t_mem_mosi := c_mem_mosi_rst; reg_hdr_dat_miso : OUT t_mem_miso; -- Input timing regarding the integration interval of the statistics - in_sosi : IN t_dp_sosi; + in_sosi : IN t_dp_sosi; -- Streaming output of offloaded statistics packets - out_sosi : OUT t_dp_sosi; - out_siso : IN t_dp_siso; + out_sosi : OUT t_dp_sosi; + out_siso : IN t_dp_siso; -- inputs from other blocks eth_src_mac : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0); udp_src_port : IN STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0); ip_src_addr : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0); + + gn_index : IN NATURAL; sdp_info : IN t_sdp_info; subband_calibrated_flag : IN STD_LOGIC := '0'; nof_crosslets : IN STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - crosslets_info : IN STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - - gn_index : IN NATURAL + crosslets_info : IN STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0') ); END sdp_statistics_offload; ARCHITECTURE str OF sdp_statistics_offload IS - CONSTANT c_nof_streams : NATURAL := 1; - CONSTANT c_data_size : NATURAL := 2; - CONSTANT c_nof_data_per_step : NATURAL := 2; - - CONSTANT c_step_size : NATURAL := sel_a_b(g_statistics_type="BST", c_data_size, - sel_a_b(g_statistics_type="XST", c_data_size, - c_data_size * c_nof_data_per_step)); -- SST - - CONSTANT c_nof_data : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_N_pol_bf * c_sdp_S_sub_bf, - sel_a_b(g_statistics_type="XST", c_sdp_S_pn * c_sdp_S_pn * c_nof_complex, - c_sdp_N_sub)); -- SST - CONSTANT c_block_size : NATURAL := c_nof_data * c_step_size; - - CONSTANT c_nof_packets : NATURAL := sel_a_b(g_statistics_type="BST", 1, - sel_a_b(g_statistics_type="XST", g_P_sq * c_sdp_N_crosslets_max, - c_sdp_S_pn)); -- SST - - CONSTANT c_marker : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_marker_bst, - sel_a_b(g_statistics_type="XST", c_sdp_marker_xst, - c_sdp_marker_sst)); - - CONSTANT c_nof_signal_inputs : NATURAL := sel_a_b(g_statistics_type="BST", 0, - sel_a_b(g_statistics_type="XST", c_sdp_S_pn, - 1)); -- SST - - CONSTANT c_nof_statistics_per_packet : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_N_pol_bf * c_sdp_S_sub_bf, - sel_a_b(g_statistics_type="XST", (c_sdp_S_pn * c_sdp_S_pn * c_nof_complex), - c_sdp_N_sub)); -- SST + -- header fields + 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); + 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_nof_packets_max : NATURAL := func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, c_sdp_N_crosslets_max); + CONSTANT c_beamlet_id : NATURAL := g_beamset_id * c_sdp_S_sub_bf; - CONSTANT c_app_total_length : NATURAL := c_sdp_stat_app_header_len + c_nof_data * c_longword_sz; - CONSTANT c_udp_total_length : NATURAL := c_app_total_length + c_network_udp_header_len; - CONSTANT c_ip_total_length : NATURAL := c_app_total_length + c_network_udp_header_len + c_network_ip_header_len; + -- MM access settings per packet for u_dp_block_from_mm_dc + CONSTANT c_mm_data_size : NATURAL := func_sdp_get_stat_from_mm_data_size(g_statistics_type); + CONSTANT c_mm_step_size : NATURAL := func_sdp_get_stat_from_mm_step_size(g_statistics_type); + CONSTANT c_mm_nof_data : NATURAL := func_sdp_get_stat_from_mm_nof_data(g_statistics_type); + -- offload control TYPE t_reg IS RECORD - block_count : NATURAL; + packet_count : NATURAL; start_address : NATURAL; start_pulse : STD_LOGIC; dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0); - data_id : STD_LOGIC_VECTOR(31 DOWNTO 0); - nof_cycles_dly : NATURAL; payload_err : STD_LOGIC; - interval_cnt : NATURAL; - integration_interval : NATURAL; - crosslet_count : NATURAL; - nof_crosslets : NATURAL; + in_sop_cnt : NATURAL; + integration_interval : NATURAL; + interleave_count : NATURAL RANGE 0 TO c_sdp_Q_fft; + crosslet_count : NATURAL RANGE 0 TO c_sdp_N_crosslets_max; + instance_count : NATURAL RANGE 0 TO c_sdp_P_sq; + instance_address : NATURAL; + nof_crosslets : NATURAL RANGE 0 TO c_sdp_N_crosslets_max; + crosslets_info_rec : t_sdp_crosslets_info; END RECORD; - CONSTANT c_reg_rst : t_reg := (0, 0, '0', (OTHERS => '0'), (OTHERS => '0'), 0, '0', 0, 0, 0, 0); - - TYPE t_selected_crosslet_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_sdp_crosslets_index_w-1 DOWNTO 0); + CONSTANT c_crosslets_info_rst : t_sdp_crosslets_info := (offset_arr => (OTHERS => 0), step => 0); + CONSTANT c_reg_rst : t_reg := (0, 0, '0', (OTHERS => '0'), '0', 0, 0, 0, 0, 0, 0, 0, c_crosslets_info_rst); SIGNAL r : t_reg; SIGNAL nxt_r : t_reg; - SIGNAL trigger : STD_LOGIC := '0'; - SIGNAL done : STD_LOGIC := '0'; + SIGNAL gn_index_reg : NATURAL; -- index of this global node + SIGNAL pn_index : NATURAL; -- index of this node in antenna band + SIGNAL rn_index : NATURAL; -- index of this ring node + SIGNAL local_si_offset : NATURAL; -- index of first signal input on this node + SIGNAL remote_rn : NATURAL; -- index of remote ring node + SIGNAL remote_gn : NATURAL; -- index of remote global node + SIGNAL remote_pn : NATURAL; -- index of remote node in antenna band + SIGNAL remote_si_offset : NATURAL; -- index of first signal input on remote node + SIGNAL nof_cycles_dly : NATURAL; -- trigger_offload delay for this node + SIGNAL nof_packets : NATURAL; -- nof packets per integration interval + + SIGNAL data_id_rec : t_sdp_stat_data_id; + SIGNAL data_id_slv : STD_LOGIC_VECTOR(31 DOWNTO 0) := (OTHERS => '0'); + + SIGNAL trigger_en : STD_LOGIC := '0'; + SIGNAL trigger_offload : STD_LOGIC := '0'; + SIGNAL mm_done : STD_LOGIC := '0'; SIGNAL dp_block_from_mm_src_out : t_dp_sosi; SIGNAL dp_block_from_mm_src_in : t_dp_siso; SIGNAL dp_offload_snk_in : t_dp_sosi; SIGNAL dp_offload_snk_out : t_dp_siso; - SIGNAL dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0'); SIGNAL bsn_at_sync : STD_LOGIC_VECTOR(63 DOWNTO 0) := (OTHERS => '0'); + SIGNAL dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0'); - SIGNAL selected_crosslet_arr : t_selected_crosslet_arr(c_sdp_N_crosslets_max-1 DOWNTO 0); - BEGIN bsn_at_sync <= RESIZE_UVEC(in_sosi.bsn, 64) WHEN rising_edge(dp_clk) AND in_sosi.sync = '1'; - gen_sel_crosslets : FOR I IN 0 TO c_sdp_N_crosslets_max-1 GENERATE - selected_crosslet_arr(I) <= crosslets_info((I+1)*c_sdp_crosslets_index_w-1 DOWNTO I*c_sdp_crosslets_index_w); - END GENERATE; - + ------------------------------------------------------------------------------- - -- Assemble offload header info + -- Assemble offload header info, for data path fields that are selected by: + -- c_sdp_stat_hdr_field_sel = "1"&"101"&"111011111001"&"0100"&"0100"&"000000010"&"1000000"&"0" + -- eth ip udp app + -- where 0 = data path, 1 = MM controlled. The '0' fields are assigned here in dp_header_info + -- in order: + -- . eth: eth_src_mac + -- . ip: ip_total_length, + -- ip_header_checksum (not here, will be filled in by 1GbE eth component), + -- ip_src_addr + -- . udp: udp_src_port, + -- udp_total_length + -- udp_checksum, (not here, also not calculated in 1GbE eth component because would + -- require store and forward, send default 0) + -- . app: - sdp_marker, sdp_observation_id, sdp_station_id, + -- - sdp_source_info_antenna_band_id, + -- sdp_source_info_nyquist_zone_id, + -- sdp_source_info_f_adc, + -- sdp_source_info_fsub_type, + -- sdp_source_info_payload_error, + -- sdp_source_info_beam_repositioning_flag, + -- sdp_source_info_subband_calibrated_flag, + -- sdp_source_info_gn_id, + -- - sdp_integration_interval, sdp_data_id, sdp_nof_signal_inputs, + -- sdp_nof_bytes_per_statistic, + -- sdp_nof_statistics_per_packet, sdp_block_period + -- - dp_bsn ------------------------------------------------------------------------------- dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac; - dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "udp_src_port" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_src_port" )) <= udp_src_port; - dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr; dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "ip_total_length" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_total_length" )) <= TO_UVEC(c_ip_total_length, 16); + dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr; + dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "udp_src_port" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_src_port" )) <= udp_src_port; dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "udp_total_length" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_total_length" )) <= TO_UVEC(c_udp_total_length, 16); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_marker" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_marker" )) <= TO_UVEC(c_marker, 8); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_observation_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_observation_id" )) <= sdp_info.observation_id; @@ -185,15 +205,14 @@ BEGIN dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_payload_error" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_payload_error" )) <= SLV(r.payload_err); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" )) <= SLV(sdp_info.beam_repositioning_flag); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_subband_calibrated_flag" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_subband_calibrated_flag" )) <= SLV(subband_calibrated_flag); - dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_reserved" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_reserved" )) <= (OTHERS => '0'); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id" )) <= TO_UVEC(gn_index, 5); - dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_reserved" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_reserved" )) <= (OTHERS => '0'); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_integration_interval" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_integration_interval" )) <= TO_UVEC(r.integration_interval, 24); - dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_data_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_data_id" )) <= r.data_id; + dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_data_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_data_id" )) <= data_id_slv; dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs" )) <= TO_UVEC(c_nof_signal_inputs, 8); + dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_bytes_per_statistic" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_bytes_per_statistic" )) <= TO_UVEC(c_sdp_nof_bytes_per_statistic, 8); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet" )) <= TO_UVEC(c_nof_statistics_per_packet, 16); dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_block_period" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_block_period" )) <= sdp_info.block_period; - dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "dp_bsn" )) <= bsn_at_sync; + dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "dp_bsn" )) <= bsn_at_sync; p_reg : PROCESS(dp_rst, dp_clk) BEGIN @@ -204,77 +223,127 @@ BEGIN END IF; END PROCESS; - p_control_packet_offload : PROCESS(r, gn_index, in_sosi, trigger, done, dp_header_info, selected_crosslet_arr, nof_crosslets) - VARIABLE v: t_reg; + -- Derive and pipeline dynamic parameters + gn_index_reg <= gn_index WHEN rising_edge(dp_clk); + pn_index <= func_sdp_gn_index_to_pn_index(gn_index) WHEN rising_edge(dp_clk); + rn_index <= gn_index - TO_UINT(sdp_info.O_rn) WHEN rising_edge(dp_clk); + local_si_offset <= pn_index * c_sdp_S_pn WHEN rising_edge(dp_clk); + nof_cycles_dly <= gn_index * g_offload_time WHEN rising_edge(dp_clk); + nof_packets <= func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, r.nof_crosslets) WHEN rising_edge(dp_clk); + + remote_rn <= func_nof_hops_to_source_rn(r.instance_count, rn_index, TO_UINT(sdp_info.N_rn), g_crosslets_direction); + remote_gn <= TO_UINT(sdp_info.O_rn) + remote_rn; + remote_pn <= func_sdp_gn_index_to_pn_index(remote_gn) WHEN rising_edge(dp_clk); + remote_si_offset <= remote_pn * c_sdp_S_pn WHEN rising_edge(dp_clk); + + -- Assign application header data_id for different statistic types, use + -- GENERATE to keep unused fields at 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; + gen_data_id_bst : IF g_statistics_type = "BST" GENERATE + data_id_rec.bst_beamlet_index <= c_beamlet_id; + END GENERATE; + gen_data_id_xst : IF g_statistics_type = "XST" GENERATE + data_id_rec.xst_subband_index <= func_sdp_modulo_N_sub(r.crosslets_info_rec.offset_arr(r.crosslet_count)); + data_id_rec.xst_signal_input_A_index <= local_si_offset; + data_id_rec.xst_signal_input_B_index <= remote_si_offset; + END GENERATE; + + data_id_slv <= func_sdp_map_stat_data_id(g_statistics_type, data_id_rec); + + p_control_packet_offload : PROCESS(r, in_sosi, local_si_offset, trigger_offload, nof_crosslets, crosslets_info, nof_packets, mm_done, dp_header_info) + VARIABLE v : t_reg; + VARIABLE v_index : NATURAL; BEGIN v := r; - v.start_pulse := '0'; - v.nof_cycles_dly := gn_index * g_offload_time; + v.start_pulse := '0'; - -- Count number of sop's in a sync interval and get payload errors and keep them till next sync. + -- Count number of sop in a sync interval and get payload errors and keep them till next sync. IF in_sosi.sync = '1' THEN - v.integration_interval := r.interval_cnt + 1; -- count = index + 1 - v.interval_cnt := 0; - v.payload_err := '0'; + v.integration_interval := r.in_sop_cnt + 1; -- count = index + 1 + v.in_sop_cnt := 0; + v.payload_err := '0'; ELSE IF in_sosi.eop = '1' THEN v.payload_err := r.payload_err OR in_sosi.err(0); END IF; IF in_sosi.sop = '1' THEN - v.interval_cnt := r.interval_cnt + 1; + v.in_sop_cnt := r.in_sop_cnt + 1; END IF; END IF; - -- assign sdp_data_id for different statistic types - IF g_statistics_type = "SST" THEN - v.data_id := x"000000" & TO_UVEC(r.block_count + c_sdp_S_pn * gn_index, 8); - ELSIF g_statistics_type = "BST" THEN - v.data_id := x"0000" & TO_UVEC(c_beamlet_id, 16); - ELSIF g_statistics_type = "XST" THEN - v.data_id := x"0" & "000" & RESIZE_UVEC(selected_crosslet_arr(r.crosslet_count), 9) & TO_UVEC(r.block_count * c_sdp_S_pn, 8) & TO_UVEC(r.block_count * c_sdp_S_pn, 8); -- RW TODO: define for P_sq > 1 - ELSE - v.data_id := x"00000000"; + -- Capture nof_crosslets and crosslets_info at in_sosi.sync, to make sure + -- they do not change during packets offload. The trigger_offload occurs + -- after the nof_cycles_dly and the offload will have finished before the + -- next in_sosi.sync + IF in_sosi.sync = '1' THEN + v.nof_crosslets := TO_UINT(nof_crosslets); + v.crosslets_info_rec := func_sdp_map_crosslets_info(crosslets_info, TO_UINT(nof_crosslets)); END IF; -- Issue start_pulse per packet offload - IF trigger = '1' THEN - -- Use trigger to start first packet - v.start_pulse := '1'; - v.start_address := 0; - v.block_count := 0; - v.crosslet_count := 0; - v.nof_crosslets := TO_UINT(nof_crosslets); -- register nof_crosslets to make sure it does not change during packet output. - ELSIF done = '1' THEN - -- Use done to start next packets - IF r.block_count < c_nof_packets-1 THEN - IF g_statistics_type /= "XST" OR r.crosslet_count < r.nof_crosslets-1 THEN - -- For SST, BST and for XST nof_crosslets do: - IF r.block_count MOD c_nof_data_per_step = 0 THEN - v.start_address := r.block_count / c_nof_data_per_step * c_block_size; -- jump to first packet in next block - ELSE - v.start_address := r.start_address + c_data_size; -- step to next packet within block + IF trigger_offload = '1' THEN + -- Use trigger_offload to start first packet offload, all g_statistics_type start from start address 0 + v.start_pulse := '1'; + v.start_address := 0; + v.packet_count := 0; + v.interleave_count := 0; -- only used for SST + v.crosslet_count := 0; -- only used for XST + v.instance_count := 0; -- only used for XST + v.instance_address := 0; -- only used for XST + + ELSIF mm_done = '1' THEN + -- Use mm_done to start next packets offloads. + IF r.packet_count < nof_packets - 1 THEN + IF g_statistics_type = "SST" THEN + -- step step step step step step + -- start_address : 0, 2, 2048, 2050, 4096, 4098, 6144, 6146, 8192, 8194, 10240, 10242 + v.start_address := r.start_address + c_mm_data_size; -- default step to next packet in this step + v.interleave_count := r.interleave_count + 1; + IF r.interleave_count = c_sdp_Q_fft - 1 THEN + v.start_address := r.packet_count * c_sdp_N_sub * c_sdp_Q_fft * c_sdp_W_statistic_sz; -- jump to first packet for next step + v.interleave_count := 0; END IF; - v.start_pulse := '1'; - v.block_count := r.block_count + 1; + v.start_pulse := '1'; + v.packet_count := r.packet_count + 1; + + ELSIF g_statistics_type = "BST" THEN + NULL; -- there is only one BST packet, so no more packets to offload here. + + ELSIF g_statistics_type = "XST" THEN + -- start_address: + -- nof_crosslets: 0, 1, 2, 3, 4, 5, 6 + -- X_sq instance: + -- 0 0, 576, 1152, 1728, 2304, 2880, 3456 + -- 1 4096, 4672, 5248, 5824, 6400, 6976, 7552 + -- 2 8192, 8768, 9344, 9920, 10496, 11072, 11648 + -- 3 12288, 12864, 13440, 14016, 14592, 15168, 15744 + -- 4 16384, 16960, 17536, 18112, 18688, 19264, 19840 + -- 5 20480, 21056, 21632, 22208, 22784, 23360, 23936 + -- 6 24576, 25152, 25728, 26304, 26880, 27456, 28032 + -- 7 28672, 29248, 29824, 30400, 30976, 31552, 32128 + -- 8 32768, 33344, 33920, 34496, 35072, 35648, 36224 + v.start_address := r.start_address + c_sdp_X_sq * c_nof_complex * c_sdp_W_statistic_sz; -- continue with next packet in this instance v.crosslet_count := r.crosslet_count + 1; + IF r.crosslet_count = TO_UINT(nof_crosslets) - 1 THEN + v.start_address := r.instance_address + 2**c_sdp_ram_st_xsq_addr_w; -- jump to first packet in next instance + v.crosslet_count := 0; + v.instance_count := r.instance_count + 1; + v.instance_address := v.start_address; -- use v.start_address to avoid multipier needed in (r.instance_count + 1) * 2**c_sdp_ram_st_xsq_addr_w + END IF; + v.start_pulse := '1'; + v.packet_count := r.packet_count + 1; + ELSE - -- For XST after nof_crosslets do: - v.crosslet_count := 0; - -- skip block indices for unused XST blocks in this P_sq iteration by setting the block count to the next multiple of N_crosslets_max i.e. 7, 14, 21, etc. - v.block_count := r.block_count + 1 + (c_sdp_N_crosslets_max - r.nof_crosslets); + NULL; -- do nothing in case of unknown g_statistics_type END IF; - - ELSE - -- Prepare for next trigger interval. - v.start_address := 0; - v.block_count := 0; - v.crosslet_count := 0; END IF; END IF; - IF trigger = '1' OR done = '1' THEN - -- Release header info per packet offload + -- Release dp_header_info per packet offload + IF trigger_offload = '1' OR mm_done = '1' THEN v.dp_header_info := dp_header_info; END IF; nxt_r <= v; @@ -291,16 +360,17 @@ BEGIN reg_enable_mosi => reg_enable_mosi, reg_enable_miso => reg_enable_miso, - delay => r.nof_cycles_dly, + delay => nof_cycles_dly, trigger => in_sosi.sync, - trigger_dly => trigger + trigger_en => trigger_en, + trigger_dly => trigger_offload ); - u_dp_block_from_mm : ENTITY dp_lib.dp_block_from_mm_dc + u_dp_block_from_mm_dc : ENTITY dp_lib.dp_block_from_mm_dc GENERIC MAP ( - g_data_size => c_data_size, - g_step_size => c_step_size, - g_nof_data => c_nof_data, + g_data_size => c_mm_data_size, + g_step_size => c_mm_step_size, + g_nof_data => c_mm_nof_data, g_reverse_word_order => TRUE -- default word order is MSB after LSB, we need to stream LSB after MSB. ) PORT MAP( @@ -310,7 +380,7 @@ BEGIN mm_clk => mm_clk, start_pulse => r.start_pulse, start_address => r.start_address, - done => done, + done => mm_done, mm_mosi => master_mosi, mm_miso => master_miso, out_sosi => dp_block_from_mm_src_out, diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..cfdb39d35709b4e99f9ea643efc8c136819a15c9 --- /dev/null +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd @@ -0,0 +1,172 @@ +------------------------------------------------------------------------------- +-- +-- 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: E. Kooistra +-- Purpose: +-- . This package contains specific constants, functions for sdp test benches. +-- Description: +------------------------------------------------------------------------------- +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE common_lib.common_pkg.ALL; +USE work.sdp_pkg.ALL; + +PACKAGE tb_sdp_pkg is + ----------------------------------------------------------------------------- + -- Statistics offload + ----------------------------------------------------------------------------- + FUNCTION func_sdp_verify_stat_header(g_statistics_type : STRING; in_hdr, exp_hdr : t_sdp_stat_header; sdp_info : t_sdp_info) RETURN BOOLEAN; + + ----------------------------------------------------------------------------- + -- Beamlet output via 10GbE to CEP (= central processor) + ----------------------------------------------------------------------------- + FUNCTION func_sdp_verify_cep_header(in_hdr, exp_hdr : t_sdp_cep_header; sdp_info : t_sdp_info) RETURN BOOLEAN; + + +END PACKAGE tb_sdp_pkg; + +PACKAGE BODY tb_sdp_pkg IS + + FUNCTION func_sdp_verify_stat_header(g_statistics_type : STRING; in_hdr, exp_hdr : t_sdp_stat_header; sdp_info : t_sdp_info) RETURN BOOLEAN IS + BEGIN + -- eth header + ASSERT in_hdr.eth.dst_mac = exp_hdr.eth.dst_mac REPORT "Wrong " & g_statistics_type & " eth.dst_mac" SEVERITY ERROR; + ASSERT in_hdr.eth.src_mac = exp_hdr.eth.src_mac REPORT "Wrong " & g_statistics_type & " eth.src_mac" SEVERITY ERROR; + ASSERT in_hdr.eth.eth_type = exp_hdr.eth.eth_type REPORT "Wrong " & g_statistics_type & " eth.eth_type" SEVERITY ERROR; + + -- ip header + ASSERT in_hdr.ip.version = exp_hdr.ip.version REPORT "Wrong " & g_statistics_type & " ip.version" SEVERITY ERROR; + ASSERT in_hdr.ip.header_length = exp_hdr.ip.header_length REPORT "Wrong " & g_statistics_type & " ip.header_length" SEVERITY ERROR; + ASSERT in_hdr.ip.services = exp_hdr.ip.services REPORT "Wrong " & g_statistics_type & " ip.services" SEVERITY ERROR; + ASSERT in_hdr.ip.total_length = exp_hdr.ip.total_length REPORT "Wrong " & g_statistics_type & " ip.total_length" SEVERITY ERROR; + ASSERT in_hdr.ip.identification = exp_hdr.ip.identification REPORT "Wrong " & g_statistics_type & " ip.identification" SEVERITY ERROR; + ASSERT in_hdr.ip.flags = exp_hdr.ip.flags REPORT "Wrong " & g_statistics_type & " ip.flags" SEVERITY ERROR; + ASSERT in_hdr.ip.fragment_offset = exp_hdr.ip.fragment_offset REPORT "Wrong " & g_statistics_type & " ip.fragment_offset" SEVERITY ERROR; + ASSERT in_hdr.ip.time_to_live = exp_hdr.ip.time_to_live REPORT "Wrong " & g_statistics_type & " ip.time_to_live" SEVERITY ERROR; + ASSERT in_hdr.ip.protocol = exp_hdr.ip.protocol REPORT "Wrong " & g_statistics_type & " ip.protocol" SEVERITY ERROR; + ASSERT in_hdr.ip.header_checksum = exp_hdr.ip.header_checksum REPORT "Wrong " & g_statistics_type & " ip.header_checksum" SEVERITY ERROR; + ASSERT in_hdr.ip.src_ip_addr = exp_hdr.ip.src_ip_addr REPORT "Wrong " & g_statistics_type & " ip.src_ip_addr" SEVERITY ERROR; + ASSERT in_hdr.ip.dst_ip_addr = exp_hdr.ip.dst_ip_addr REPORT "Wrong " & g_statistics_type & " ip.dst_ip_addr" SEVERITY ERROR; + + -- udp header + ASSERT in_hdr.udp.src_port = exp_hdr.udp.src_port REPORT "Wrong " & g_statistics_type & " udp.src_port" SEVERITY ERROR; + ASSERT in_hdr.udp.dst_port = exp_hdr.udp.dst_port REPORT "Wrong " & g_statistics_type & " udp.dst_port" SEVERITY ERROR; + ASSERT in_hdr.udp.total_length = exp_hdr.udp.total_length REPORT "Wrong " & g_statistics_type & " udp.total_length" SEVERITY ERROR; + ASSERT in_hdr.udp.checksum = exp_hdr.udp.checksum REPORT "Wrong " & g_statistics_type & " udp.checksum" SEVERITY ERROR; + + -- app header + ASSERT in_hdr.app.sdp_marker = exp_hdr.app.sdp_marker REPORT "Wrong " & g_statistics_type & " app.sdp_marker" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_version_id = exp_hdr.app.sdp_version_id REPORT "Wrong " & g_statistics_type & " app.sdp_version_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_observation_id = sdp_info.observation_id REPORT "Wrong " & g_statistics_type & " app.sdp_observation_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_station_id = sdp_info.station_id REPORT "Wrong " & g_statistics_type & " app.sdp_station_id" SEVERITY ERROR; + + ASSERT in_hdr.app.sdp_source_info_antenna_band_id = slv(sdp_info.antenna_band_index) REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_antenna_band_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_nyquist_zone_id = sdp_info.nyquist_zone_index REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_nyquist_zone_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_f_adc = slv(sdp_info.f_adc) REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_f_adc" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_fsub_type = slv(sdp_info.fsub_type) REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_fsub_type" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_payload_error = exp_hdr.app.sdp_source_info_payload_error REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_payload_error" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_beam_repositioning_flag = slv(sdp_info.beam_repositioning_flag) REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_beam_repositioning_flag" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_subband_calibrated_flag = exp_hdr.app.sdp_source_info_subband_calibrated_flag REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_subband_calibrated_flag" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_reserved = exp_hdr.app.sdp_source_info_reserved REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_reserved" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_gn_id = exp_hdr.app.sdp_source_info_gn_id REPORT "Wrong " & g_statistics_type & " app.sdp_source_info_gn_id" SEVERITY ERROR; + + ASSERT in_hdr.app.sdp_reserved = exp_hdr.app.sdp_reserved REPORT "Wrong " & g_statistics_type & " app.sdp_reserved" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_integration_interval = exp_hdr.app.sdp_integration_interval REPORT "Wrong " & g_statistics_type & " app.sdp_integration_interval" SEVERITY ERROR; + + -- . sdp_data_id word and fields per g_statistics_type + ASSERT in_hdr.app.sdp_data_id = exp_hdr.app.sdp_data_id REPORT "Wrong " & g_statistics_type & " app.sdp_data_id" SEVERITY ERROR; + IF g_statistics_type = "SST" THEN + ASSERT in_hdr.app.sdp_data_id_sst_signal_input_index = exp_hdr.app.sdp_data_id_sst_signal_input_index REPORT "Wrong " & g_statistics_type & " app.sdp_data_id_sst_signal_input_index" SEVERITY ERROR; + ELSIF g_statistics_type = "BST" THEN + ASSERT in_hdr.app.sdp_data_id_bst_beamlet_index = exp_hdr.app.sdp_data_id_bst_beamlet_index REPORT "Wrong " & g_statistics_type & " app.sdp_data_id_bst_beamlet_index" SEVERITY ERROR; + ELSIF g_statistics_type = "XST" THEN + ASSERT in_hdr.app.sdp_data_id_xst_subband_index = exp_hdr.app.sdp_data_id_xst_subband_index REPORT "Wrong " & g_statistics_type & " app.sdp_data_id_xst_subband_index" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_data_id_xst_signal_input_A_index = exp_hdr.app.sdp_data_id_xst_signal_input_A_index REPORT "Wrong " & g_statistics_type & " app.sdp_data_id_xst_signal_input_A_index" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_data_id_xst_signal_input_B_index = exp_hdr.app.sdp_data_id_xst_signal_input_B_index REPORT "Wrong " & g_statistics_type & " app.sdp_data_id_xst_signal_input_B_index" SEVERITY ERROR; + ELSE + REPORT "Wrong " & g_statistics_type SEVERITY FAILURE; + END IF; + + ASSERT in_hdr.app.sdp_nof_signal_inputs = exp_hdr.app.sdp_nof_signal_inputs REPORT "Wrong " & g_statistics_type & " app.sdp_nof_signal_inputs" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_nof_bytes_per_statistic = exp_hdr.app.sdp_nof_bytes_per_statistic REPORT "Wrong " & g_statistics_type & " app.sdp_nof_bytes_per_statistic" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_nof_statistics_per_packet = exp_hdr.app.sdp_nof_statistics_per_packet REPORT "Wrong " & g_statistics_type & " app.sdp_nof_statistics_per_packet" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_block_period = sdp_info.block_period REPORT "Wrong " & g_statistics_type & " app.sdp_block_period" SEVERITY ERROR; + + ASSERT in_hdr.app.dp_bsn = exp_hdr.app.dp_bsn REPORT "Wrong " & g_statistics_type & " app.dp_bsn" SEVERITY ERROR; + RETURN TRUE; + END func_sdp_verify_stat_header; + + + FUNCTION func_sdp_verify_cep_header(in_hdr, exp_hdr : t_sdp_cep_header; sdp_info : t_sdp_info) RETURN BOOLEAN IS + BEGIN + -- eth header + ASSERT in_hdr.eth.dst_mac = exp_hdr.eth.dst_mac REPORT "Wrong beamlet eth.dst_mac" SEVERITY ERROR; + ASSERT in_hdr.eth.src_mac = exp_hdr.eth.src_mac REPORT "Wrong beamlet eth.src_mac" SEVERITY ERROR; + ASSERT in_hdr.eth.eth_type = exp_hdr.eth.eth_type REPORT "Wrong beamlet eth.eth_type" SEVERITY ERROR; + + -- ip header + ASSERT in_hdr.ip.version = exp_hdr.ip.version REPORT "Wrong beamlet ip.version" SEVERITY ERROR; + ASSERT in_hdr.ip.header_length = exp_hdr.ip.header_length REPORT "Wrong beamlet ip.header_length" SEVERITY ERROR; + ASSERT in_hdr.ip.services = exp_hdr.ip.services REPORT "Wrong beamlet ip.services" SEVERITY ERROR; + ASSERT in_hdr.ip.total_length = exp_hdr.ip.total_length REPORT "Wrong beamlet ip.total_length" SEVERITY ERROR; + ASSERT in_hdr.ip.identification = exp_hdr.ip.identification REPORT "Wrong beamlet ip.identification" SEVERITY ERROR; + ASSERT in_hdr.ip.flags = exp_hdr.ip.flags REPORT "Wrong beamlet ip.flags" SEVERITY ERROR; + ASSERT in_hdr.ip.fragment_offset = exp_hdr.ip.fragment_offset REPORT "Wrong beamlet ip.fragment_offset" SEVERITY ERROR; + ASSERT in_hdr.ip.time_to_live = exp_hdr.ip.time_to_live REPORT "Wrong beamlet ip.time_to_live" SEVERITY ERROR; + ASSERT in_hdr.ip.protocol = exp_hdr.ip.protocol REPORT "Wrong beamlet ip.protocol" SEVERITY ERROR; + ASSERT in_hdr.ip.header_checksum = exp_hdr.ip.header_checksum REPORT "Wrong beamlet ip.header_checksum" SEVERITY ERROR; + ASSERT in_hdr.ip.src_ip_addr = exp_hdr.ip.src_ip_addr REPORT "Wrong beamlet ip.src_ip_addr" SEVERITY ERROR; + ASSERT in_hdr.ip.dst_ip_addr = exp_hdr.ip.dst_ip_addr REPORT "Wrong beamlet ip.dst_ip_addr" SEVERITY ERROR; + + -- udp header + ASSERT in_hdr.udp.src_port = exp_hdr.udp.src_port REPORT "Wrong beamlet udp.src_port" SEVERITY ERROR; + ASSERT in_hdr.udp.dst_port = exp_hdr.udp.dst_port REPORT "Wrong beamlet udp.dst_port" SEVERITY ERROR; + ASSERT in_hdr.udp.total_length = exp_hdr.udp.total_length REPORT "Wrong beamlet udp.total_length" SEVERITY ERROR; + ASSERT in_hdr.udp.checksum = exp_hdr.udp.checksum REPORT "Wrong beamlet udp.checksum" SEVERITY ERROR; + + -- app header + ASSERT in_hdr.app.sdp_marker = exp_hdr.app.sdp_marker REPORT "Wrong beamlet app.sdp_marker" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_version_id = exp_hdr.app.sdp_version_id REPORT "Wrong beamlet app.sdp_version_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_observation_id = sdp_info.observation_id REPORT "Wrong beamlet app.sdp_observation_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_station_id = sdp_info.station_id REPORT "Wrong beamlet app.sdp_station_id" SEVERITY ERROR; + + ASSERT in_hdr.app.sdp_source_info_antenna_band_id = slv(sdp_info.antenna_band_index) REPORT "Wrong beamlet app.sdp_source_info_antenna_band_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_nyquist_zone_id = sdp_info.nyquist_zone_index REPORT "Wrong beamlet app.sdp_source_info_nyquist_zone_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_f_adc = slv(sdp_info.f_adc) REPORT "Wrong beamlet app.sdp_source_info_f_adc" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_fsub_type = slv(sdp_info.fsub_type) REPORT "Wrong beamlet app.sdp_source_info_fsub_type" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_payload_error = exp_hdr.app.sdp_source_info_payload_error REPORT "Wrong beamlet app.sdp_source_info_payload_error" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_repositioning_flag = slv(sdp_info.beam_repositioning_flag) REPORT "Wrong beamlet app.sdp_source_info_repositioning_flag" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_beamlet_width = exp_hdr.app.sdp_source_info_beamlet_width REPORT "Wrong beamlet app.sdp_source_info_beamlet_width" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_source_info_gn_id = exp_hdr.app.sdp_source_info_gn_id REPORT "Wrong beamlet app.sdp_source_info_gn_id" SEVERITY ERROR; + + ASSERT in_hdr.app.sdp_reserved = exp_hdr.app.sdp_reserved REPORT "Wrong beamlet app.sdp_reserved" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_beamlet_scale = exp_hdr.app.sdp_beamlet_scale REPORT "Wrong beamlet app.sdp_beamlet_scale" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_beamlet_id = exp_hdr.app.sdp_beamlet_id REPORT "Wrong beamlet app.sdp_beamlet_id" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_nof_blocks_per_packet = exp_hdr.app.sdp_nof_blocks_per_packet REPORT "Wrong beamlet app.sdp_nof_blocks_per_packet" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_nof_beamlets_per_block = exp_hdr.app.sdp_nof_beamlets_per_block REPORT "Wrong beamlet app.sdp_nof_beamlets_per_block" SEVERITY ERROR; + ASSERT in_hdr.app.sdp_block_period = sdp_info.block_period REPORT "Wrong beamlet app.sdp_block_period" SEVERITY ERROR; + + ASSERT in_hdr.app.dp_bsn = exp_hdr.app.dp_bsn REPORT "Wrong beamlet app.dp_bsn" SEVERITY ERROR; + RETURN TRUE; + END func_sdp_verify_cep_header; + +END tb_sdp_pkg; 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 dff32a18f324eb118a03045fbe521734ffbacdbf..46d605ba9674e5e51cc718884d35180bad76d1a4 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 @@ -20,7 +20,7 @@ ------------------------------------------------------------------------------- -- --- Author: P. Donker +-- Author: P. Donker, E. Kooistra -- Purpose: -- . test bench for sdp_statistics_offload.vhd @@ -29,11 +29,13 @@ -- https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Subband+filterbank -- . See figure 4.8 -- --- Remark: --- . +-- Usage: +-- > as 8 +-- > run -a +-- e.g. view test_offload_sosi and the rx_sdp_stat_header.app fields ------------------------------------------------------------------------------- -LIBRARY IEEE, common_lib, dp_lib; +LIBRARY IEEE, common_lib, dp_lib, ring_lib; USE IEEE.STD_LOGIC_1164.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; @@ -43,24 +45,38 @@ USE common_lib.common_network_layers_pkg.ALL; USE common_lib.common_field_pkg.ALL; USE common_lib.common_str_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; +USE ring_lib.ring_pkg.ALL; USE work.sdp_pkg.ALL; +USE work.tb_sdp_pkg.ALL; ENTITY tb_sdp_statistics_offload IS GENERIC ( - g_statistics_type : STRING := "XST"; - g_offload_time : NATURAL := 500; - g_beamset_id : NATURAL := 0; - g_P_sq : NATURAL := 1 --c_sdp_P_sq + -- All + g_statistics_type : STRING := "SST"; + g_offload_time : NATURAL := 50; + g_gn_index : NATURAL := 5; -- global node (GN) index, must be in range(O_rn, O_rn + N_rn), use > 0 to see effect of g_offload_time + -- BST + g_beamset_id : NATURAL := 1; -- < c_sdp_N_beamsets + -- XST + g_O_rn : NATURAL := 4; -- GN index of first ring node (RN) + g_N_rn : NATURAL := 8; -- <= c_sdp_N_rn_max = 16, number of nodes in ring + g_P_sq : NATURAL := 1; -- <= c_sdp_P_sq + g_nof_crosslets : NATURAL := 1; -- <= c_sdp_N_crosslets_max + g_crosslets_direction : NATURAL := 1 -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction ); END tb_sdp_statistics_offload; ARCHITECTURE tb OF tb_sdp_statistics_offload IS + CONSTANT c_dp_clk_period : TIME := 5 ns; -- 200 MHz - CONSTANT c_mm_clk_period : TIME := 20 ns; -- 50 MHz + CONSTANT c_mm_clk_period : TIME := 1 ns; -- 1 GHz to speed up simulation CONSTANT c_cross_clock_domain_latency : NATURAL := 20; + CONSTANT c_offload_time : NATURAL := g_offload_time * g_gn_index; + + -- 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"; @@ -68,58 +84,35 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS -- Used mm_adresses on mm bus "enable_mosi/miso". CONSTANT c_reg_enable_mm_addr_enable : NATURAL := 0; - -- Used mm_adresses on mm bus "hdr_dat_mosi/miso". - CONSTANT c_hdr_dat_mm_addr_eth_src_mac : NATURAL := 1; - CONSTANT c_hdr_dat_mm_addr_ip_src_addr : NATURAL := 13; - CONSTANT c_hdr_dat_mm_addr_udp_src_port : NATURAL := 15; - - -- Define SST RAM structure. - CONSTANT c_data_size : NATURAL := 2; - CONSTANT c_nof_data_per_step : NATURAL := 2; - CONSTANT c_step_size : NATURAL := sel_a_b(g_statistics_type="BST", c_data_size, - sel_a_b(g_statistics_type="XST", c_data_size, - c_data_size * c_nof_data_per_step)); -- SST + -- header fields + 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); + CONSTANT c_nof_packets_max : NATURAL := func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, c_sdp_N_crosslets_max); - CONSTANT c_nof_data : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_N_pol_bf * c_sdp_S_sub_bf, - sel_a_b(g_statistics_type="XST", c_sdp_S_pn * c_sdp_S_pn * c_nof_complex, - c_sdp_N_sub)); -- SST + CONSTANT c_beamlet_index : NATURAL := g_beamset_id * c_sdp_S_sub_bf; - CONSTANT c_nof_packets : NATURAL := sel_a_b(g_statistics_type="BST", 1, - sel_a_b(g_statistics_type="XST", g_P_sq, - c_sdp_S_pn)); -- SST + CONSTANT c_crosslets_info_rec : t_sdp_crosslets_info := (offset_arr => (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), step => 16); + CONSTANT c_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := func_sdp_map_crosslets_info(c_crosslets_info_rec); + -- payload data + CONSTANT c_data_size : NATURAL := c_sdp_W_statistic_sz; + CONSTANT c_nof_data : NATURAL := c_nof_statistics_per_packet; - -- Define SST RAM size for c_nof_packets. - CONSTANT c_ram_size : NATURAL := c_nof_data * c_data_size * c_nof_packets; + -- Define SST RAM size for c_nof_packets_max. + CONSTANT c_ram_size : NATURAL := c_nof_data * c_data_size * c_nof_packets_max; CONSTANT c_ram_w : NATURAL := ceil_log2(c_ram_size); --CONSTANT c_ram_buf : t_c_mem := (c_mem_ram_rd_latency, c_ram_w, 32, 2**c_ram_w, 'X'); CONSTANT c_ram_buf : t_c_mem := (1, c_ram_w, 32, 2**c_ram_w, 'X'); -- Define block timing. - CONSTANT c_nof_block_per_sync : NATURAL := 80; -- Sufficient to fit more than c_nof_packets offload packets per sync interval. - CONSTANT c_nof_clk_per_block : NATURAL := c_nof_data * c_data_size; - - -- Based on g_statistics_type: 'S'=0x53="SST", 'B'=0x42="BST", 'X'=0x58="XST". - CONSTANT c_marker : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_marker_bst, - sel_a_b(g_statistics_type="XST", c_sdp_marker_xst, - c_sdp_marker_sst)); -- SST - - CONSTANT c_nof_signal_inputs : NATURAL := sel_a_b(g_statistics_type="BST", 0, - sel_a_b(g_statistics_type="XST", c_sdp_S_pn, - 1)); -- SST - - CONSTANT c_nof_statistics_per_packet : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_N_pol_bf * c_sdp_S_sub_bf, - sel_a_b(g_statistics_type="XST", (c_sdp_S_pn * c_sdp_S_pn * c_nof_complex), - c_sdp_N_sub)); -- SST - - CONSTANT c_beamlet_id : NATURAL := g_beamset_id * c_sdp_S_sub_bf; - - CONSTANT c_app_total_length : NATURAL := c_sdp_stat_app_header_len + c_nof_data * c_longword_sz; - CONSTANT c_udp_total_length : NATURAL := c_app_total_length + c_network_udp_header_len; - CONSTANT c_ip_total_length : NATURAL := c_app_total_length + c_network_udp_header_len + c_network_ip_header_len; - + CONSTANT c_bsn_init : NATURAL := 0; + CONSTANT c_nof_block_per_sync : NATURAL := 3 + ceil_div(c_offload_time, c_nof_data) + c_nof_packets_max; -- Sufficient to fit more than c_nof_packets_max offload packets per sync interval. + CONSTANT c_nof_clk_per_block : NATURAL := c_nof_data * c_data_size; CONSTANT c_nof_valid_per_block : NATURAL := c_nof_data * c_data_size; - CONSTANT c_nof_sync : NATURAL := 5; + CONSTANT c_nof_sync : NATURAL := 3; CONSTANT c_nof_clk_per_sync : NATURAL := c_nof_block_per_sync * c_nof_clk_per_block; SIGNAL tb_end : STD_LOGIC := '0'; @@ -142,47 +135,87 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS SIGNAL offload_rx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL offload_rx_hdr_dat_miso : t_mem_miso; - SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_rst; - SIGNAL offload_sosi : t_dp_sosi; - SIGNAL offload_siso : t_dp_siso := c_dp_siso_rst; - - SIGNAL test_offload_sosi : t_dp_sosi := c_dp_sosi_rst; - SIGNAL test_offload_siso : t_dp_siso; - - 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 in_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL in_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL in_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0); + + SIGNAL offload_data : STD_LOGIC_VECTOR(31 DOWNTO 0); + SIGNAL offload_sosi : t_dp_sosi; + SIGNAL offload_siso : t_dp_siso := c_dp_siso_rst; + + SIGNAL test_offload_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL test_offload_en : STD_LOGIC := '0'; + SIGNAL test_offload_sop_cnt : NATURAL; + SIGNAL test_offload_eop_cnt : NATURAL; + + 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; + SIGNAL exp_sdp_stat_header : t_sdp_stat_header; + + SIGNAL exp_dp_bsn : STD_LOGIC_VECTOR(63 DOWNTO 0); + SIGNAL exp_sst_signal_input : NATURAL; + SIGNAL exp_bst_beamlet_index : NATURAL; + SIGNAL cur_X_sq_cell : NATURAL; + SIGNAL cur_crosslet : NATURAL; + SIGNAL exp_subband_index : NATURAL; + SIGNAL exp_xst_signal_input_A : NATURAL; + SIGNAL exp_xst_signal_input_B : NATURAL; -- Signals used to change settings of sdp_info. - SIGNAL gn_index : NATURAL := 1; -- select > 0 to see effect of g_offload_time - SIGNAL sdp_info : t_sdp_info := ( TO_UVEC(601, 16), -- station_id '0', -- antenna_band_index - x"00001111", -- observation_id - b"01", -- nyquist_zone_index - '0', -- f_adc - '1', -- fsub_type + x"FFFFFFFF", -- observation_id + b"01", -- nyquist_zone_index, 0 = first, 1 = second, 2 = third + '1', -- f_adc, 0 = 160 MHz, 1 = 200 MHz + '0', -- fsub_type, 0 = critically sampled, 1 = oversampled '0', -- beam_repositioning_flag - x"01", -- O_si - x"02", -- N_si - x"04", -- O_rn - x"08", -- N_rn + x"01", -- O_si, not used + x"02", -- N_si, not used + TO_UVEC(g_O_rn, 8), -- O_rn + TO_UVEC(g_N_rn, 8), -- N_rn x"1400" -- block_period = 5120 ); + SIGNAL gn_index : NATURAL := g_gn_index; -- this node GN + SIGNAL rn_index : NATURAL := g_gn_index - g_O_rn; -- this node RN + SIGNAL source_rn : NATURAL; -- source node RN + SIGNAL source_gn : NATURAL; -- source node GN + + SIGNAL subband_calibrated_flag : STD_LOGIC := '0'; + SIGNAL nof_crosslets : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL nof_packets : NATURAL; + -- Signals used for starting processes. - SIGNAL ram_wr_data : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0); - SIGNAL ram_wr_addr : STD_LOGIC_VECTOR(c_ram_buf.adr_w-1 DOWNTO 0); - SIGNAL ram_wr_en : STD_LOGIC; - SIGNAL init_ram_done : STD_LOGIC := '0'; + SIGNAL ram_wr_data : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0); + SIGNAL ram_wr_addr : STD_LOGIC_VECTOR(c_ram_buf.adr_w-1 DOWNTO 0); + SIGNAL ram_wr_en : STD_LOGIC; + SIGNAL init_ram_done : STD_LOGIC := '0'; SIGNAL in_sync_hold : STD_LOGIC := '0'; - SIGNAL rx_prev_bsn : NATURAL := 0; - SIGNAL rx_bsn : NATURAL := 0; - SIGNAL rx_block_cnt : NATURAL := 0; - SIGNAL rx_valid_clk_cnt : NATURAL := 0; + SIGNAL in_sync_cnt : NATURAL := 0; + SIGNAL test_sync_cnt : INTEGER; + + SIGNAL rx_packet_cnt : NATURAL := 0; + SIGNAL rx_valid_cnt : NATURAL := 0; + + -- Debug signals, to view in Wave window + SIGNAL dbg_c_nof_statistics_per_packet : NATURAL := c_nof_statistics_per_packet; + SIGNAL dbg_c_udp_total_length : NATURAL := c_udp_total_length; + SIGNAL dbg_c_ip_total_length : NATURAL := c_ip_total_length; + SIGNAL dbg_c_marker : NATURAL := c_marker; + SIGNAL dbg_c_nof_signal_inputs : NATURAL := c_nof_signal_inputs; + SIGNAL dbg_c_nof_packets_max : NATURAL := c_nof_packets_max; + SIGNAL dbg_c_beamlet_index : NATURAL := c_beamlet_index; + SIGNAL dbg_c_data_size : NATURAL := c_data_size; + SIGNAL dbg_c_nof_data : NATURAL := c_nof_data; + SIGNAL dbg_c_ram_size : NATURAL := c_ram_size; + SIGNAL dbg_c_crosslets_info_rec : t_sdp_crosslets_info := c_crosslets_info_rec; + SIGNAL dbg_c_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := c_crosslets_info_slv; BEGIN + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2; @@ -202,34 +235,21 @@ BEGIN ram_wr_data <= TO_UVEC(i, c_ram_buf.dat_w); ram_wr_en <= '1'; proc_common_wait_some_cycles(mm_clk, 1); - END LOOP; + END LOOP; ram_wr_en <= '0'; - proc_common_wait_until_high(dp_clk, in_sosi.sync); - init_ram_done <= '1'; + init_ram_done <= '1'; WAIT; END PROCESS; - p_enable_trigger : PROCESS - BEGIN - proc_common_wait_until_high(mm_clk, init_ram_done); - -- Enable common variabel delay. - proc_mem_mm_bus_wr(c_reg_enable_mm_addr_enable, 1, mm_clk, enable_miso, enable_mosi); - proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); - WAIT; - END PROCESS; - - -- Module dp_offload_tx_v3.vhd can handle 32 data that is not aligned, dp_offload_rx can not. - -- This is the reason the first 16bit of the header are always zero. - -- This process will start counting with bit16 high, the first bit that wil be received, - -- on each dp_clk the bsn is incremented with 0x10000, if you look at b63..b16 it looks like normal counting. - -- If dp_offload_rx.vhd is fixed this can be set normal again. + -- Start the input p_in_sosi : PROCESS BEGIN proc_common_wait_until_low(dp_clk, dp_rst); - proc_common_wait_some_cycles(dp_clk, 12); - in_sosi.bsn <= TO_DP_BSN(16#10000#); + proc_common_wait_some_cycles(dp_clk, 10); + in_sosi.bsn <= TO_DP_BSN(c_bsn_init); in_sosi.valid <= '1'; + in_crosslets_info_rec <= c_crosslets_info_rec; WHILE TRUE LOOP FOR i IN 0 TO c_nof_block_per_sync-1 LOOP FOR j IN 0 TO c_nof_clk_per_block-1 LOOP @@ -239,13 +259,17 @@ BEGIN IF i = 0 AND j = 0 THEN in_sosi.sync <= '1'; END IF; + IF i = 0 AND j = 1 THEN + -- Increment crosslets_info offsets for next sync interval + in_crosslets_info_rec <= func_sdp_step_crosslets_info(in_crosslets_info_rec, g_nof_crosslets); + END IF; IF j = 0 THEN in_sosi.sop <= '1'; - in_sosi.bsn <= INCR_UVEC(in_sosi.bsn, 16#10000#); -- = 2**16 = 65536 + in_sosi.bsn <= INCR_UVEC(in_sosi.bsn, 1); END IF; IF j = c_nof_clk_per_block-1 THEN in_sosi.eop <= '1'; - END IF; + END IF; proc_common_wait_some_cycles(dp_clk, 1); END LOOP; END LOOP; @@ -253,105 +277,167 @@ BEGIN WAIT; END PROCESS; + in_crosslets_info_slv <= func_sdp_map_crosslets_info(in_crosslets_info_rec, g_nof_crosslets); + + -- Enable the statistics offload when input is running + p_enable_trigger : PROCESS + BEGIN + proc_common_wait_until_high(mm_clk, init_ram_done); + -- Enable common variable delay. + proc_mem_mm_bus_wr(c_reg_enable_mm_addr_enable, 1, mm_clk, enable_miso, enable_mosi); + proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); + proc_common_wait_some_cycles(dp_clk, 1); + test_offload_en <= '1'; + WAIT; + END PROCESS; + + -- Crosslets settings + nof_crosslets <= TO_UVEC(g_nof_crosslets, c_sdp_nof_crosslets_reg_w); + nof_packets <= func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, g_nof_crosslets); + + -- Counters to time expected exp_sdp_stat_header fields per offload packet + p_exp_counters : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + -- Count sync intervals using in_sosi.sync, because there is no test_offload_sosi.sync + IF test_offload_en = '0' THEN + in_sync_cnt <= 0; + test_offload_sop_cnt <= 0; + test_offload_eop_cnt <= 0; + ELSE + -- Count test_offload_sosi sync integration intervals + IF in_sosi.sync = '1' THEN + in_sync_cnt <= in_sync_cnt + 1; + END IF; + + -- Count test_offload_sosi packets + IF test_offload_sosi.sop = '1' THEN + test_offload_sop_cnt <= test_offload_sop_cnt + 1; -- early count + END IF; + IF test_offload_sosi.eop = '1' THEN + test_offload_eop_cnt <= test_offload_eop_cnt + 1; -- after count + END IF; + END IF; + END IF; + END PROCESS; + test_sync_cnt <= in_sync_cnt + 0; -- optionally adjust to fit test_offload_sosi + + -- derive current X_sq correlator cell index + cur_X_sq_cell <= (test_offload_eop_cnt / g_nof_crosslets) MOD g_P_sq; + -- derive current N_crosslets index index + cur_crosslet <= test_offload_eop_cnt MOD g_nof_crosslets; + + -- derive source RN index + source_rn <= func_nof_hops_to_source_rn(cur_X_sq_cell, rn_index, g_N_rn, g_crosslets_direction); + source_gn <= g_O_rn + source_rn; + + -- Prepare exp_sdp_stat_header before test_offload_sosi.eop, so that p_exp_sdp_stat_header can + -- verify it at test_offload_sosi.eop. + + -- For all statistics + exp_dp_bsn <= TO_SVEC(c_bsn_init + 1 + test_sync_cnt * c_nof_block_per_sync, 64); + -- SST + exp_sst_signal_input <= rx_packet_cnt + c_sdp_S_pn * gn_index; + -- BST + exp_bst_beamlet_index <= c_beamlet_index; + -- XST + -- . prepare expected XST subband_index + exp_subband_index <= (c_crosslets_info_rec.offset_arr(cur_crosslet) + test_sync_cnt * c_crosslets_info_rec.step) MOD c_sdp_N_sub; + + -- . prepare expected XST signal_input_A index + exp_xst_signal_input_A <= (gn_index MOD c_sdp_N_pn_max) * c_sdp_S_pn; + + -- . 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(sdp_info, subband_calibrated_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 <= sdp_info.observation_id; + exp_sdp_stat_header.app.sdp_station_id <= sdp_info.station_id; + + exp_sdp_stat_header.app.sdp_source_info_antenna_band_id <= slv(sdp_info.antenna_band_index); + exp_sdp_stat_header.app.sdp_source_info_nyquist_zone_id <= sdp_info.nyquist_zone_index; + exp_sdp_stat_header.app.sdp_source_info_f_adc <= slv(sdp_info.f_adc); + exp_sdp_stat_header.app.sdp_source_info_fsub_type <= slv(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(sdp_info.beam_repositioning_flag); + exp_sdp_stat_header.app.sdp_source_info_subband_calibrated_flag <= slv(subband_calibrated_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 <= sdp_info.block_period; + + exp_sdp_stat_header.app.dp_bsn <= exp_dp_bsn; + END PROCESS; + + rx_sdp_stat_header <= func_sdp_map_stat_header(rx_hdr_fields_raw); + p_verify_header : PROCESS(test_offload_sosi) + VARIABLE v_bool : BOOLEAN; BEGIN + -- Prepare exp_sdp_stat_header before test_offload_sosi.eop, so that it can be verified at test_offload_sosi.eop IF test_offload_sosi.eop = '1' THEN - -- bsn is not fully received (bit 0-15 is missing) because 32 bit allignment not working in dp_offload_rx.vhd. - -- Check fixed settings. - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_dst_mac") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_dst_mac")) = x"001B217176B9" - REPORT "wrong eth_dst_mac" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_type") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_type")) = x"0800" - REPORT "wrong eth_type" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_version") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_version")) = TO_UVEC(4, 4) - REPORT "wrong ip_version" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_header_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_header_length")) = TO_UVEC(5, 4) - REPORT "wrong ip_header_length" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_services") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_services")) = TO_UVEC(0, 8) - REPORT "wrong ip_services" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_total_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_total_length")) = TO_UVEC(c_ip_total_length, 16) - REPORT "wrong ip_total_length" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_identification") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_identification")) = TO_UVEC(0, 16) - REPORT "wrong ip_identification" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_flags") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_flags")) = TO_UVEC(2, 3) - REPORT "wrong ip_flags" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_fragment_offset") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_fragment_offset")) = TO_UVEC(0, 13) - REPORT "wrong ip_fragment_offset" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_time_to_live") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_time_to_live")) = TO_UVEC(127, 8) - REPORT "wrong ip_time_to_live" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_protocol") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_protocol")) = TO_UVEC(17, 8) - REPORT "wrong ip_protocol" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_dst_addr") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_dst_addr")) = x"0A6300FE" - REPORT "wrong ip_dst_addr" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_dst_port") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_dst_port")) = TO_UVEC(5001, 16) - REPORT "wrong udp_dst_port" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_total_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_total_length")) = TO_UVEC(c_udp_total_length, 16) - REPORT "wrong udp_total_length" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_version_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_version_id")) = TO_UVEC(5, 8) - REPORT "wrong sdp_version_id" SEVERITY ERROR; - - -- Check settings set by mm interface in this test bench. - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_src_mac")) = c_eth_src_mac - REPORT "wrong eth_src_mac" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_src_addr") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_src_addr")) = c_ip_src_addr - REPORT "wrong ip_src_addr" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_src_port")) = c_udp_src_port - REPORT "wrong udp_src_port" SEVERITY ERROR; - - -- Check g_statistics_type settings set by sdp_statistics_offload.vhd. - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_marker") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_marker")) = TO_UVEC(c_marker, 8) - REPORT "wrong sdp_marker" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs")) = TO_UVEC(c_nof_signal_inputs, 8) - REPORT "wrong sdp_nof_signal_inputs" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet")) = TO_UVEC(c_nof_statistics_per_packet, 16) - REPORT "wrong sdp_nof_statistics_per_packet: " SEVERITY ERROR; - - -- Check some values from sdp_source_info. - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_observation_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_observation_id")) = sdp_info.observation_id - REPORT "wrong sdp_observation_id" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_station_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_station_id")) = sdp_info.station_id - REPORT "wrong sdp_station_id" SEVERITY ERROR; - ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id"))) = sdp_info.antenna_band_index - REPORT "wrong sdp_source_info_antenna_band_id" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id")) = sdp_info.nyquist_zone_index - REPORT "wrong sdp_source_info_nyquist_zone_id" SEVERITY ERROR; - ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc"))) = sdp_info.f_adc - REPORT "wrong sdp_source_info_f_adc" SEVERITY ERROR; - ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type"))) = sdp_info.fsub_type - REPORT "wrong sdp_source_info_fsub_type" SEVERITY ERROR; - ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag"))) = sdp_info.beam_repositioning_flag - REPORT "wrong sdp_source_info_beam_repositioning_flag" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id")) = TO_UVEC(gn_index, 5) - REPORT "wrong sdp_source_info_gn_id" SEVERITY ERROR; - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_block_period") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_block_period")) = sdp_info.block_period - REPORT "wrong sdp_block_period" SEVERITY ERROR; - - -- Check variable header info. - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_integration_interval") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_integration_interval")) = TO_UVEC(c_nof_block_per_sync, 24) - REPORT "wrong sdp_integration_interval" SEVERITY ERROR; - - IF g_statistics_type = "SST" THEN - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_data_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_data_id")) = TO_UVEC(rx_block_cnt + c_sdp_S_pn * gn_index, 32) - REPORT "wrong SST sdp_data_id" SEVERITY ERROR; - ELSIF g_statistics_type = "BST" THEN - ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_data_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_data_id")) = TO_UVEC(c_beamlet_id, 32) - REPORT "wrong BST sdp_data_id" SEVERITY ERROR; - --ELSIF g_statistics_type = "XST" THEN --TODO: RW define check - END IF; + v_bool := func_sdp_verify_stat_header(g_statistics_type, rx_sdp_stat_header, exp_sdp_stat_header, sdp_info); END IF; END PROCESS; - -- Count number of blocks in a sync interval. - -- There is no active test_offload_sosi.sync to restart the count. Therefore capture the in_sosi.sync in in_sync_hold, and - -- use in_sync_hold with test_offload_sosi.sop to start counting blocks (packets) from 0, at the start of every sync interval. - p_rx_block_cnt : PROCESS(dp_clk) + -- Count number of packets in a sync interval. + -- There is no active test_offload_sosi.sync to restart the count. Therefore capture the in_sosi.sync in in_sync_hold, and + -- use in_sync_hold with test_offload_sosi.sop to start counting packets from 0, at the start of every sync interval. + p_rx_packet_cnt : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN IF test_offload_sosi.sop = '1' THEN - IF in_sync_hold = '1' THEN - rx_block_cnt <= 0; + IF in_sync_hold = '1' THEN in_sync_hold <= '0'; + rx_packet_cnt <= 0; ELSE - rx_block_cnt <= rx_block_cnt + 1; + rx_packet_cnt <= rx_packet_cnt + 1; END IF; END IF; IF in_sosi.sync = '1' THEN @@ -360,58 +446,31 @@ BEGIN END IF; END PROCESS; - -- Capture rx_bsn from header. - rx_bsn <= TO_UINT(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "dp_bsn")+16)); - -- Keep rx_bsn from previous header. - rx_prev_bsn <= rx_bsn WHEN rising_edge(dp_clk); - - -- Verify number of blocks between 2 syncs and between 2 changed bsn numbers. - p_verify_nof_blocks : PROCESS(dp_clk) + -- Verify number of packets per sync interval + p_verify_nof_packets : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN IF init_ram_done = '1' THEN - - IF in_sosi.sync = '1' AND rx_block_cnt > 0 THEN - ASSERT rx_block_cnt = c_nof_packets-1 REPORT "wrong number of blocks between 2 sync" SEVERITY ERROR; - END IF; - - -- rx_prev_bsn > 0 is needed for the first time, when there is no previous BSN. - -- rx_bsn > rx_prev_bsn is needed to detect a new rx_bsn. - IF rx_prev_bsn > 0 AND rx_bsn > rx_prev_bsn THEN - ASSERT (rx_bsn - rx_prev_bsn) = c_nof_block_per_sync REPORT "wrong number of blocks between 2 bsn numbers" SEVERITY ERROR; + + IF in_sosi.sync = '1' AND rx_packet_cnt > 0 THEN + ASSERT rx_packet_cnt = nof_packets-1 REPORT "Wrong number of packets per sync interval" SEVERITY ERROR; END IF; + END IF; - test_offload_siso <= c_dp_siso_rdy; END IF; END PROCESS; - p_verify_nof_valid : PROCESS(dp_clk) + p_verify_nof_valid_per_packet : PROCESS(dp_clk) BEGIN IF rising_edge(dp_clk) THEN IF test_offload_sosi.sop = '1' THEN - rx_valid_clk_cnt <= 1; + rx_valid_cnt <= 1; ELSIF test_offload_sosi.eop = '1' THEN - ASSERT rx_valid_clk_cnt+1 = c_nof_valid_per_block REPORT "wrong number of clock counts while valid" SEVERITY ERROR; + ASSERT rx_valid_cnt+1 = c_nof_valid_per_block REPORT "Wrong number of valid per packet" SEVERITY ERROR; ELSE - rx_valid_clk_cnt <= rx_valid_clk_cnt + 1; + rx_valid_cnt <= rx_valid_cnt + 1; -- test_offload_sosi.valid has no gaps END IF; END IF; - END PROCESS; - - p_mm_offload : PROCESS - BEGIN - proc_common_wait_until_low(mm_clk, mm_rst); - proc_common_wait_some_cycles(mm_clk, 10); - -- Write ethernet destinations via reg_hdr_dat_mosi. - proc_mem_mm_bus_wr(c_hdr_dat_mm_addr_udp_src_port, TO_UINT(c_udp_src_port), mm_clk, hdr_dat_miso, hdr_dat_mosi); - proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); - - proc_mem_mm_bus_wr(c_hdr_dat_mm_addr_ip_src_addr, TO_UINT(c_ip_src_addr), mm_clk, hdr_dat_miso, hdr_dat_mosi); - proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); - - proc_mem_mm_bus_wr(c_hdr_dat_mm_addr_eth_src_mac, TO_UINT(c_eth_src_mac), mm_clk, hdr_dat_miso, hdr_dat_mosi); - proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency); - WAIT; END PROCESS; p_dp_end : PROCESS @@ -441,7 +500,7 @@ BEGIN rd_en_b => master_mosi.rd, rd_dat_b => master_miso.rddata(c_ram_buf.dat_w-1 DOWNTO 0), rd_val_b => master_miso.rdval - ); + ); u_rx : ENTITY dp_lib.dp_offload_rx GENERIC MAP ( @@ -449,24 +508,23 @@ BEGIN 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 + g_crc_nof_words => 0 ) PORT MAP ( mm_rst => mm_rst, mm_clk => mm_clk, - + dp_rst => dp_rst, dp_clk => dp_clk, - + reg_hdr_dat_mosi => offload_rx_hdr_dat_mosi, reg_hdr_dat_miso => offload_rx_hdr_dat_miso, - + snk_in_arr(0) => offload_sosi, snk_out_arr(0) => offload_siso, - + src_out_arr(0) => test_offload_sosi, - src_in_arr(0) => test_offload_siso, - + hdr_fields_out_arr(0) => rx_hdr_fields_out, hdr_fields_raw_arr(0) => rx_hdr_fields_raw ); @@ -474,37 +532,51 @@ BEGIN -- SDP info u_dut: ENTITY work.sdp_statistics_offload GENERIC MAP ( - g_statistics_type => g_statistics_type, - g_offload_time => g_offload_time, - g_beamset_id => g_beamset_id, - g_P_sq => g_P_sq + g_statistics_type => g_statistics_type, + g_offload_time => g_offload_time, + g_beamset_id => g_beamset_id, + g_P_sq => g_P_sq, + g_crosslets_direction => g_crosslets_direction ) PORT MAP ( - mm_clk => mm_clk, - mm_rst => mm_rst, + mm_clk => mm_clk, + mm_rst => mm_rst, - dp_clk => dp_clk, - dp_rst => dp_rst, + dp_clk => dp_clk, + dp_rst => dp_rst, - master_mosi => master_mosi, - master_miso => master_miso, + -- MM + master_mosi => master_mosi, + master_miso => master_miso, reg_enable_mosi => enable_mosi, reg_enable_miso => enable_miso, - reg_hdr_dat_mosi => hdr_dat_mosi, - reg_hdr_dat_miso => hdr_dat_miso, + reg_hdr_dat_mosi => hdr_dat_mosi, + reg_hdr_dat_miso => hdr_dat_miso, + + -- ST + in_sosi => in_sosi, + out_sosi => offload_sosi, + out_siso => offload_siso, - sdp_info => sdp_info, - gn_index => gn_index, + -- Inputs from other blocks + eth_src_mac => c_eth_src_mac, + udp_src_port => c_udp_src_port, + ip_src_addr => c_ip_src_addr, - in_sosi => in_sosi, - out_sosi => offload_sosi, - out_siso => offload_siso, + gn_index => gn_index, - eth_src_mac => c_eth_src_mac, - udp_src_port => c_udp_src_port, - ip_src_addr => c_ip_src_addr + sdp_info => sdp_info, + subband_calibrated_flag => subband_calibrated_flag, + nof_crosslets => nof_crosslets, + crosslets_info => in_crosslets_info_slv ); + -- Check crosslet_info functions + ASSERT c_crosslets_info_rec = func_sdp_map_crosslets_info(c_crosslets_info_slv) REPORT "Error in func_sdp_map_crosslets_info()" SEVERITY FAILURE; + + -- To view the 32 bit 1GbE offload data more easily in the Wave window + offload_data <= offload_sosi.data(31 DOWNTO 0); + END tb; diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd index e0506591d517a9df01f03904a3c1bec1c98a1c28..db3baf5a19b8352c9da6e203b68ddc8cdb0ad2e4 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd @@ -19,7 +19,7 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- Author : R vd Walle +-- Author : R vd Walle, E. Kooistra -- Purpose: Verify multiple variations of tb_sdp_statistics_offload -- Description: -- Usage: @@ -37,15 +37,27 @@ ARCHITECTURE tb OF tb_tb_sdp_statistics_offload IS SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' BEGIN +-- -- All -- g_statistics_type : STRING := "SST"; -- g_offload_time : NATURAL := 500; +-- g_gn_index : NATURAL := 1; -- global node (GN) index, use > 0 to see effect of g_offload_time +-- -- BST -- g_beamset_id : NATURAL := 0; +-- -- XST +-- g_O_rn : NATURAL := 0; -- GN index of first ring node (RN) +-- g_N_rn : NATURAL := 16; -- <= c_sdp_N_rn_max = 16, number of nodes in ring -- g_P_sq : NATURAL := c_sdp_P_sq +-- g_nof_crosslets : NATURAL := 1; +-- g_crosslets_direction : INTEGER := 1; -- +1 or -1 + + u_sst : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("SST", 50, 3, 0, 0); + u_bst_0 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 50, 1, 0, 0); + u_bst_1 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 50, 1, 1, 0); + u_xst_P1 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16, 1, 1, 1); + u_xst_P1_N3 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16, 1, 3, 1); + u_xst_P9 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16, 9, 1, 1); + u_xst_P9_N3 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16, 9, 3, 1); + u_xst_P9_N3_neg : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16, 9, 3, 0); + u_xst_P8_N7_RN1_15 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 1, 15, 8, 7, 0); - u_sst : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("SST"); - u_bst_0 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST"); - u_bst_1 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 500, 1); - u_xst_1 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 500, 0, 1); - u_xst_P_sq : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST"); - END tb; diff --git a/libraries/base/common/src/vhdl/common_variable_delay.vhd b/libraries/base/common/src/vhdl/common_variable_delay.vhd index 847bb54e531d2bc300783c1f2431f25fcef1b97f..510f22ac51fe8c3841a3f65578495c143aa938a1 100644 --- a/libraries/base/common/src/vhdl/common_variable_delay.vhd +++ b/libraries/base/common/src/vhdl/common_variable_delay.vhd @@ -18,13 +18,12 @@ -- -------------------------------------------------------------------------- -- Author: --- . Pieter Donker +-- . Pieter Donker, Eric Kooistra -- Purpose: --- . Delay input pulse by number of given delay cycles +-- . Delay input pulse by delay number of cycles -- Description: --- . delay input pulse by delay number of cycles --- . output pulse is derived from low-high transition of input pulse. --- . the actual pulse delay will be delay + 1, due to implementation latency of 1 clk cycle +-- . The actual pulse delay will be delay + 1, due to implementation latency +-- of 1 clk cycle -- -------------------------------------------------------------------------- LIBRARY IEEE, technology_lib; @@ -36,41 +35,51 @@ ENTITY common_variable_delay IS g_max_delay : NATURAL := 200 * 10**6 ); PORT ( - rst : IN STD_LOGIC; - clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; - delay : IN NATURAL RANGE 0 TO g_max_delay := 0; - enable : IN STD_LOGIC := '0'; - in_val : IN STD_LOGIC; - out_val : OUT STD_LOGIC + delay : IN NATURAL RANGE 0 TO g_max_delay := 0; + enable : IN STD_LOGIC := '0'; + in_pulse : IN STD_LOGIC; + out_pulse : OUT STD_LOGIC ); END common_variable_delay; ARCHITECTURE rtl OF common_variable_delay IS - SIGNAL i_out_val : STD_LOGIC; - SIGNAL nxt_out_val : STD_LOGIC; - SIGNAL delay_cnt : NATURAL; - SIGNAL nxt_delay_cnt : NATURAL; - SIGNAL prev_in_val : STD_LOGIC; + SIGNAL i_out_pulse : STD_LOGIC; + SIGNAL nxt_out_pulse : STD_LOGIC; + SIGNAL cnt_en : STD_LOGIC; + SIGNAL nxt_cnt_en : STD_LOGIC; + SIGNAL delay_cnt : NATURAL; + SIGNAL nxt_delay_cnt : NATURAL; BEGIN - out_val <= i_out_val; + out_pulse <= i_out_pulse; - p_delay: PROCESS(enable, in_val, prev_in_val, delay, delay_cnt) + p_delay: PROCESS(enable, in_pulse, delay, cnt_en, delay_cnt) BEGIN - nxt_out_val <= '0'; - nxt_delay_cnt <= 0; + nxt_out_pulse <= '0'; + nxt_cnt_en <= '0'; + nxt_delay_cnt <= 0; IF enable = '1' THEN - IF in_val = '1' AND prev_in_val = '0' THEN -- detect rising edge of in_val - IF delay = 0 THEN - nxt_out_val <= '1'; + -- Use cnt_en to avoid that toggling enable causes an out_pulse + nxt_cnt_en <= cnt_en; + IF cnt_en = '1' THEN + nxt_delay_cnt <= delay_cnt + 1; + IF delay_cnt + 1 = delay THEN + nxt_out_pulse <= '1'; + nxt_cnt_en <= '0'; END IF; ELSE - nxt_delay_cnt <= delay_cnt + 1; - IF delay_cnt+1 = delay THEN - nxt_out_val <= '1'; + -- Accept new in_pulse when idle, ignore new in_pulse when busy + IF in_pulse = '1' THEN + IF delay = 0 THEN + nxt_out_pulse <= '1'; -- out_pulse immediately + ELSE + nxt_cnt_en <= '1'; -- apply out_pulse after delay + END IF; END IF; END IF; END IF; @@ -79,13 +88,13 @@ BEGIN p_clk : PROCESS(rst, clk) BEGIN IF rst = '1' THEN - i_out_val <= '0'; + i_out_pulse <= '0'; + cnt_en <= '0'; delay_cnt <= 0; - prev_in_val <= '0'; ELSIF rising_edge(clk) THEN - i_out_val <= nxt_out_val; + i_out_pulse <= nxt_out_pulse; + cnt_en <= nxt_cnt_en; delay_cnt <= nxt_delay_cnt; - prev_in_val <= in_val; END IF; END PROCESS; diff --git a/libraries/base/common/src/vhdl/mms_common_variable_delay.vhd b/libraries/base/common/src/vhdl/mms_common_variable_delay.vhd index 50a10a41eb102ef7be497679191e7676cd9989bb..5b43f4acddc2c50351dac660916b9dc560601d1f 100644 --- a/libraries/base/common/src/vhdl/mms_common_variable_delay.vhd +++ b/libraries/base/common/src/vhdl/mms_common_variable_delay.vhd @@ -44,12 +44,13 @@ ENTITY mms_common_variable_delay IS delay : IN NATURAL := 0; trigger : IN STD_LOGIC := '0'; + trigger_en : OUT STD_LOGIC; trigger_dly : OUT STD_LOGIC ); END mms_common_variable_delay; -ARCHITECTURE rtl OF mms_common_variable_delay IS +ARCHITECTURE str OF mms_common_variable_delay IS CONSTANT c_enable_mem_reg : t_c_mem := (c_mem_reg_rd_latency, 1, 1, 1, '0'); @@ -58,18 +59,20 @@ ARCHITECTURE rtl OF mms_common_variable_delay IS SIGNAL enable : STD_LOGIC := '0'; BEGIN - enable <= sl(enable_reg); + + trigger_en <= sl(enable_reg); -- also provide enable as OUT + enable <= sl(enable_reg); -- device under test - u_dut : ENTITY work.common_variable_delay + u_common_variable_delay : ENTITY work.common_variable_delay PORT MAP ( - rst => dp_rst, - clk => dp_clk, + rst => dp_rst, + clk => dp_clk, - delay => delay, - enable => enable, - in_val => trigger, - out_val => trigger_dly + delay => delay, + enable => enable, + in_pulse => trigger, + out_pulse => trigger_dly ); u_mms_common_reg : ENTITY work.mms_common_reg @@ -89,4 +92,4 @@ BEGIN out_reg => enable_reg ); -END; \ No newline at end of file +END; diff --git a/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd b/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd index 8e91b07b721c6b83b4b9ecf236eb27fa77624b20..0227f26201ab4c4b1aff7a8b9989ea7469407e46 100644 --- a/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd +++ b/libraries/base/common/tb/vhdl/tb_common_variable_delay.vhd @@ -41,8 +41,13 @@ ARCHITECTURE tb OF tb_common_variable_delay IS CONSTANT c_clk_period : TIME := 10 ns; CONSTANT c_trigger_interval : NATURAL := 40; -- in clk's CONSTANT c_trigger_latency : NATURAL := 1; -- in clk's - CONSTANT c_delay_arr : t_natural_arr(0 TO 3) := (0, 1, 3, 12); + + -- Use a delay > c_trigger_interval to check wiht exp_triggers_cnt that new + -- triggers are ignored when a delay is already busy + CONSTANT c_delay_arr : t_natural_arr(0 TO 5) := (0, 1, 3, 12, c_trigger_interval * 3, 10); + SIGNAL stimuli_done : STD_LOGIC := '0'; + SIGNAL tb_end : STD_LOGIC := '0'; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '0'; @@ -51,13 +56,19 @@ ARCHITECTURE tb OF tb_common_variable_delay IS SIGNAL enable : STD_LOGIC := '0'; SIGNAL trigger : STD_LOGIC := '0'; SIGNAL trigger_dly : STD_LOGIC := '0'; + + -- Use triggers_cnt to verify that triggers only occur when enable = '1' + -- and when the delay is not busy + SIGNAL triggers_cnt : NATURAL := 0; + SIGNAL exp_triggers_cnt : NATURAL := c_delay_arr'LENGTH; + BEGIN clk <= (NOT clk) OR tb_end AFTER c_clk_period/2; rst <= '1', '0' AFTER c_clk_period*4; - -- generate trigger signal - proc_common_gen_pulse(c_trigger_interval/2, c_trigger_interval, '1', rst, clk, trigger); + -- generate trigger pulse signal + proc_common_gen_pulse(1, c_trigger_interval, '1', rst, clk, trigger); p_in_stimuli : PROCESS VARIABLE clk_cnt : NATURAL := 0; @@ -66,15 +77,12 @@ BEGIN enable <= '0'; WAIT UNTIL rst = '0'; - WAIT UNTIL rising_edge(clk); - -- If enable = 0, no trigger_dly is expected, see wave-window - proc_common_wait_some_cycles(clk, 50); + -- If enable = 0, no trigger_dly is expected + proc_common_wait_some_cycles(clk, c_trigger_interval * 3); - + -- Enable trigger output and count clk's between trigger and trigger_dly enable <= '1'; - -- enable trigger output and count clk's between trigger lo-hi and trigger_dly lo-hi - -- check if counted clk's = c_trigger_latency + delay FOR i IN c_delay_arr'RANGE LOOP delay <= c_delay_arr(i); clk_cnt := 0; @@ -83,28 +91,32 @@ BEGIN clk_cnt := clk_cnt + 1; proc_common_wait_some_cycles(clk, 1); END LOOP; - ASSERT clk_cnt = c_trigger_latency + delay REPORT "delay failure, got " & int_to_str(clk_cnt) & ", expect " & int_to_str(c_trigger_latency+delay) SEVERITY ERROR; + -- Verify that expected delay was applied + ASSERT clk_cnt = c_trigger_latency + delay REPORT "delay failure, got " & int_to_str(clk_cnt) & ", expect " & int_to_str(c_trigger_latency+delay) SEVERITY ERROR; proc_common_wait_some_cycles(clk, 10); END LOOP; - enable <= '0'; - proc_common_wait_some_cycles(clk, 10); + proc_common_wait_some_cycles(clk, c_trigger_interval * 3); + ASSERT triggers_cnt = exp_triggers_cnt REPORT "wrong number of trigger_dly." SEVERITY ERROR; - tb_end <= '1'; + proc_common_wait_some_cycles(clk, 10); + tb_end <= '1'; WAIT; END PROCESS; + triggers_cnt <= triggers_cnt + 1 WHEN rising_edge(clk) AND trigger_dly = '1'; + -- device under test u_dut : ENTITY work.common_variable_delay PORT MAP ( - rst => rst, - clk => clk, + rst => rst, + clk => clk, - delay => delay, - enable => enable, - in_val => trigger, - out_val => trigger_dly + delay => delay, + enable => enable, + in_pulse => trigger, + out_pulse => trigger_dly ); END tb; diff --git a/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd b/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd index 39d08e87c644510a4d667ccc4a25de279487df3a..4727523f9249a25f53bbfb1b44cc53fc0652b191 100644 --- a/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd +++ b/libraries/base/common/tb/vhdl/tb_mms_common_variable_delay.vhd @@ -88,8 +88,8 @@ BEGIN WAIT; END PROCESS; - -- generate trigger signal - proc_common_gen_pulse(c_trigger_interval/2, c_trigger_interval, '1', rst, clk, trigger); + -- generate trigger pulse signal + proc_common_gen_pulse(1, c_trigger_interval, '1', rst, clk, trigger); -- device under test u_dut : ENTITY work.mms_common_variable_delay diff --git a/libraries/io/eth/src/vhdl/eth_statistics.vhd b/libraries/io/eth/src/vhdl/eth_statistics.vhd index 0fb1ce71315a0b2a1b3ce41625f52e8b7f964ce4..9f3bd8c9bac21e811bebdcfd467b0653c5fb4f02 100644 --- a/libraries/io/eth/src/vhdl/eth_statistics.vhd +++ b/libraries/io/eth/src/vhdl/eth_statistics.vhd @@ -60,6 +60,7 @@ ENTITY eth_statistics IS ); PORT ( eth_serial_in : IN STD_LOGIC; + eth_src_out : OUT t_dp_sosi; -- Output received sosi tb_end : OUT STD_LOGIC -- To be used to stop test-bench generated clocks ); END eth_statistics; @@ -148,4 +149,7 @@ BEGIN tb_end => i_tb_end ); + -- Output the received decoded data, to support further external analysis + eth_src_out <= tech_tse_rx_src_out; + END str;