diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd index dd52d4eb206cf007076a9b100f4e9e00400e8d28..270ce27dea1c2cf60728dd488e7e075267b6d1be 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf_bst_offload.vhd @@ -249,8 +249,8 @@ BEGIN g_nof_streams => 1, g_data_w => c_word_w, g_hdr_field_arr => c_sdp_stat_hdr_field_arr, - g_remove_crc => FALSE, - g_crc_nof_words => 0 + g_remove_crc => TRUE, + g_crc_nof_words => 1 ) PORT MAP ( mm_rst => pps_rst, diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd index 5b14cb9aea233df7b59df0ff7031032d571d7f40..74694c689dfd0849fffcea7de86c61886b268e8e 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub_sst_offload.vhd @@ -248,8 +248,8 @@ BEGIN g_nof_streams => 1, g_data_w => c_word_w, g_hdr_field_arr => c_sdp_stat_hdr_field_arr, - g_remove_crc => FALSE, - g_crc_nof_words => 0 + g_remove_crc => TRUE, + g_crc_nof_words => 1 ) PORT MAP ( mm_rst => pps_rst, diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd index a11dac56788bf43d7cbb73d8bfba830f7a65832e..5726cae4b7b99857e371140750281d03fc5d5f3b 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_xsub_one/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload.vhd @@ -34,6 +34,15 @@ -- Usage: -- > as 7 # default -- > as 12 # for detailed debugging +-- And add more missing sosi_arr signals or constants via sim tab, entity instance in hierarchy and +-- then select from objects window, e.g. for: +-- > add wave -position insertpoint \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/ait_sosi_arr \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/pfb_sosi_arr \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/fsub_sosi_arr \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/u_lofar_unb2c_sdp_station_xsub_one/u_sdp_station/bs_sosi +-- > add wave -position insertpoint \ +-- sim:/tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload/c_exp_subband_xst -- > run -a -- Takes about 10 m -- @@ -76,13 +85,29 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload IS CONSTANT c_pps_period : NATURAL := c_nof_clk_per_sync; CONSTANT c_wpfb_sim : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync); CONSTANT c_ctrl_interval_size : NATURAL := c_nof_clk_per_sync; + CONSTANT c_nof_crosslets : NATURAL := 3; -- not too large, so that offload still fits in c_nof_block_per_sync CONSTANT c_subband_select_arr : t_natural_arr(0 TO c_sdp_N_crosslets_max-1) := (10, 11, 12, 13, 14, 15, 16); - CONSTANT c_subband_step : NATURAL := 0; - CONSTANT c_nof_crosslets : NATURAL := 3; - CONSTANT c_nof_sync : NATURAL := 2; + CONSTANT c_subband_step : NATURAL := 3; -- e.g. 0 or c_nof_crosslets + CONSTANT c_nof_sync : NATURAL := 3; - -- MM + CONSTANT c_max_ratio : REAL := 0.001; -- ratio that actual value may differ from expected value + + -- WG + CONSTANT c_bsn_start_wg : NATURAL := 2; + CONSTANT c_sp_ampl : REAL := 0.5; -- WG normalized amplitude, 1.0 = FS (full scale), use <= 0.5 to avoid XST overflow + CONSTANT c_wg_ampl : NATURAL := NATURAL(c_sp_ampl * REAL(c_sdp_FS_adc)); -- in number of lsb + CONSTANT c_wg_subband : NATURAL := 12; + + -- WPFB + CONSTANT c_exp_subband_ampl : REAL := REAL(c_wg_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio; -- = c_wg_ampl * 0.994817 * 8 + CONSTANT c_exp_subband_power : REAL := c_exp_subband_ampl**2.0; -- complex, so no divide by 2 + CONSTANT c_exp_subband_sst : REAL := c_exp_subband_power * REAL(c_nof_block_per_sync); + CONSTANT c_exp_subband_xst : REAL := c_exp_subband_sst; -- all signal inputs use same WG, and auto correlation XST = SST + + -- MM CONSTANT c_mm_file_reg_bsn_source_v2 : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2"; + CONSTANT c_mm_file_reg_bsn_scheduler_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER"; + CONSTANT c_mm_file_reg_diag_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG"; CONSTANT c_mm_file_reg_crosslets_info : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_CROSSLETS_INFO"; CONSTANT c_mm_file_reg_nof_crosslets : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_NOF_CROSSLETS"; CONSTANT c_mm_file_reg_bsn_sync_scheduler_xsub : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SYNC_SCHEDULER_XSUB"; @@ -113,22 +138,38 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_xsub_one_xst_offload IS SIGNAL INTA : STD_LOGIC; SIGNAL INTB : STD_LOGIC; - SIGNAL eth_clk : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); - SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); - SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); + SIGNAL eth_clk : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0) := (OTHERS => '0'); + + -- WG + SIGNAL current_bsn_wg : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- Rx packets SIGNAL eth_rx_sosi : t_dp_sosi; - SIGNAL eth_rx_data : STD_LOGIC_VECTOR(c_32-1 downto 0); + SIGNAL eth_rx_data : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0); -- Decode packets SIGNAL rx_offload_sosi : t_dp_sosi; + + -- . view payload statistics data + SIGNAL rx_word_cnt : NATURAL := 0; + SIGNAL rx_sdp_stat_data : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0); + SIGNAL rx_sdp_stat_re : STD_LOGIC_VECTOR(c_64-1 DOWNTO 0); + SIGNAL rx_sdp_stat_im : STD_LOGIC_VECTOR(c_64-1 DOWNTO 0); + SIGNAL rx_sdp_stat_re_val : STD_LOGIC := '0'; + SIGNAL rx_sdp_stat_im_val : STD_LOGIC := '0'; + SIGNAL rx_sdp_stat_index : NATURAL := 0; + SIGNAL rx_a_sp : NATURAL := 0; + SIGNAL rx_b_sp : NATURAL := 0; + + -- . view header SIGNAL rx_hdr_fields_out : STD_LOGIC_VECTOR(1023 DOWNTO 0); SIGNAL rx_hdr_fields_raw : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0'); SIGNAL rx_sdp_stat_header : t_sdp_stat_header; -- back transceivers - SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0); + SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 DOWNTO 0); SIGNAL JESD204B_REFCLK : STD_LOGIC := '1'; -- jesd204b syncronization signals @@ -203,6 +244,7 @@ BEGIN tb_clk <= NOT tb_clk AFTER c_tb_clk_period/2; -- Testbench MM clock p_mm_stimuli : PROCESS + VARIABLE v_bsn : NATURAL; BEGIN -- Wait for DUT power up after reset WAIT FOR 1 us; @@ -219,6 +261,32 @@ BEGIN WAIT FOR 1 us; pps_rst <= '0'; + ---------------------------------------------------------------------------- + -- Enable and start WG + ---------------------------------------------------------------------------- + -- 0 : mode[7:0] --> off=0, calc=1, repeat=2, single=3) + -- nof_samples[31:16] --> <= c_ram_wg_size=1024 + -- 1 : phase[15:0] + -- 2 : freq[30:0] + -- 3 : ampl[16:0] + FOR I IN 0 TO c_sdp_S_pn-1 LOOP + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 1, INTEGER(0.0 * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 2, INTEGER(REAL(c_wg_subband) * c_sdp_wg_subband_freq_unit), tb_clk); -- freq + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, I*4 + 3, INTEGER(REAL(c_wg_ampl) * c_sdp_wg_ampl_lsb), tb_clk); -- ampl + END LOOP; + + -- Read current BSN + mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO 0), tb_clk); + mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 1, current_bsn_wg(63 DOWNTO 32), tb_clk); + proc_common_wait_some_cycles(tb_clk, 1); + + -- Write scheduler BSN to trigger start of WG at next block + v_bsn := TO_UINT(current_bsn_wg) + 2; + ASSERT v_bsn <= c_bsn_start_wg REPORT "Too late to start WG: " & int_to_str(v_bsn) & " > " & int_to_str(c_bsn_start_wg) SEVERITY ERROR; + mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 0, c_bsn_start_wg, tb_clk); -- first write low then high part + mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 1, 0, tb_clk); -- assume v_bsn < 2**31-1 + ---------------------------------------------------------------------------- -- Setup and enable xsub ---------------------------------------------------------------------------- @@ -274,14 +342,14 @@ BEGIN eth_rx_data <= eth_rx_sosi.data(c_32-1 DOWNTO 0); - -- . Verify XST packet header + -- . View / verify XST packet header u_rx_statistics : ENTITY dp_lib.dp_offload_rx GENERIC MAP ( g_nof_streams => 1, g_data_w => c_word_w, g_hdr_field_arr => c_sdp_stat_hdr_field_arr, - g_remove_crc => FALSE, - g_crc_nof_words => 0 + g_remove_crc => TRUE, + g_crc_nof_words => 1 ) PORT MAP ( mm_rst => pps_rst, @@ -300,4 +368,74 @@ BEGIN rx_sdp_stat_header <= func_sdp_map_stat_header(rx_hdr_fields_raw); + -- . View / verify XST packet payload + p_rx_sdp_view_stat_data : PROCESS(eth_clk(0)) + BEGIN + IF rising_edge(eth_clk(0)) THEN + rx_sdp_stat_re_val <= '0'; + rx_sdp_stat_im_val <= '0'; + IF rx_offload_sosi.valid = '1' THEN + -- Count words 0, 1, 2, 3 + rx_word_cnt <= 0; + IF rx_word_cnt < c_sdp_N_pol * c_nof_complex - 1 THEN + rx_word_cnt <= rx_word_cnt + 1; + END IF; + + -- Count words for the complex statistics with two 32bits words per 64 bit statistic, + -- high word part and real data received first. + CASE rx_word_cnt IS + WHEN 0 => rx_sdp_stat_data <= rx_offload_sosi.data(c_32-1 DOWNTO 0); + WHEN 1 => rx_sdp_stat_re <= rx_sdp_stat_data & rx_offload_sosi.data(c_32-1 DOWNTO 0); + rx_sdp_stat_re_val <= '1'; + WHEN 2 => rx_sdp_stat_data <= rx_offload_sosi.data(c_32-1 DOWNTO 0); + WHEN 3 => rx_sdp_stat_im <= rx_sdp_stat_data & rx_offload_sosi.data(c_32-1 DOWNTO 0); + rx_sdp_stat_im_val <= '1'; + WHEN OTHERS => NULL; + END CASE; + END IF; + + -- Count the complex statistics + IF rx_sdp_stat_im_val = '1' THEN + rx_sdp_stat_index <= rx_sdp_stat_index + 1; + END IF; + + IF rx_offload_sosi.sop = '1' THEN + rx_sdp_stat_index <= 0; -- restart per Rx packet + END IF; + END IF; + END PROCESS; + + p_rx_sdp_verify_stat_data : PROCESS(eth_clk(0)) + VARIABLE v_subband_ix : NATURAL; -- _ix = index + BEGIN + IF rising_edge(eth_clk(0)) THEN + v_subband_ix := TO_UINT(rx_sdp_stat_header.app.sdp_data_id_xst_subband_index); + -- real part + IF rx_sdp_stat_re_val = '1' THEN + IF v_subband_ix = c_wg_subband THEN + -- Expect the strong XST value at the WG subband + ASSERT almost_equal(TO_SREAL(rx_sdp_stat_re) / c_exp_subband_xst, 1.0, c_max_ratio) REPORT "Wrong XST real value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + ELSE + -- WG is only in one subband, so expect almost zero in the other subbands + ASSERT almost_zero(TO_SREAL(rx_sdp_stat_re) / c_exp_subband_xst, c_max_ratio) REPORT "Too large XST real value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + END IF; + END IF; + IF rx_sdp_stat_im_val = '1' THEN + -- All WG have same phase, so expect zero imaginary part. + -- . The imag part is exactly zero for signal inputs a and b that are both connected to the corresponding input of the WPFB. + -- . The imag part is almost zero for signal inputs a and b that are both connected to the opposite inputs of the WPFB, due + -- to crosstalk rounding difference from input a to b or from input b to a of the complex FFT. + IF (rx_a_sp MOD c_sdp_Q_fft) = (rx_b_sp MOD c_sdp_Q_fft) THEN + ASSERT SIGNED(rx_sdp_stat_im) = 0 REPORT "Non zero XST imaginary value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + ELSE + ASSERT almost_zero(TO_SREAL(rx_sdp_stat_im) / c_exp_subband_xst, c_max_ratio) REPORT "Too large XST imaginary value at subband = " & int_to_str(v_subband_ix) SEVERITY ERROR; + END IF; + END IF; + END IF; + END PROCESS; + + -- rx_sdp_stat_index counts the S_pn * S_pn = X_sq = 12 * 12 = 144 complex statistics + rx_a_sp <= rx_sdp_stat_index / c_sdp_S_pn; -- signal input A + rx_b_sp <= rx_sdp_stat_index MOD c_sdp_S_pn; -- signal input B + END tb; 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 3053b5f21d4b25e3851a0c57cd02ddec09accbac..b1972f74aa3ad94953a3dcdb1587725903982b5c 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd @@ -310,7 +310,8 @@ BEGIN g_nof_stat => c_sdp_S_sub_bf*c_sdp_N_pol_bf, g_in_data_w => c_sdp_W_beamlet_sum, g_stat_data_w => c_longword_w, - g_stat_data_sz => c_longword_sz/c_word_sz + g_stat_data_sz => c_longword_sz/c_word_sz, + g_stat_multiplex=> c_sdp_N_pol_bf ) PORT MAP ( mm_rst => mm_rst, 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 43c17b7a7734a746960722a9ccb37fe0a608027f..17f3ac609a8591d9ea3b15dc745e3e1b6cd1a369 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd @@ -131,7 +131,7 @@ ARCHITECTURE str OF node_sdp_correlator IS SIGNAL crosslets_cipo_arr : t_mem_cipo_arr(g_P_sq-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst); SIGNAL mon_xst_udp_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0); + SIGNAL prev_crosslets_info_rec : t_sdp_crosslets_info; SIGNAL nof_crosslets_reg : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0); SIGNAL nof_crosslets : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0); BEGIN @@ -184,7 +184,8 @@ BEGIN reg_bsn_sync_scheduler_xsub_mosi => reg_bsn_sync_scheduler_xsub_copi, reg_bsn_sync_scheduler_xsub_miso => reg_bsn_sync_scheduler_xsub_cipo, - out_crosslets_info => crosslets_info + cur_crosslets_info_rec => OPEN, + prev_crosslets_info_rec => prev_crosslets_info_rec ); -- Use xsel_sosi as local bsn and sync reference since the sync @@ -425,6 +426,7 @@ BEGIN in_reg => nof_crosslets, out_reg => nof_crosslets_reg ); + -- Force nof crosslets to max nof crosslets if a higher value is written or to 1 if a lower value is written via MM. nof_crosslets <= TO_UVEC(1, c_sdp_nof_crosslets_reg_w) WHEN TO_UINT(nof_crosslets_reg) < 1 ELSE nof_crosslets_reg WHEN TO_UINT(nof_crosslets_reg) <= c_sdp_N_crosslets_max ELSE @@ -434,6 +436,7 @@ BEGIN -- XST UDP offload --------------------------------------------------------------- xst_udp_sosi <= mon_xst_udp_sosi_arr(0); + u_sdp_xst_udp_offload: ENTITY work.sdp_statistics_offload GENERIC MAP ( g_statistics_type => "XST", @@ -472,9 +475,10 @@ BEGIN gn_index => TO_UINT(gn_id), ring_info => ring_info, sdp_info => sdp_info, - weighted_subbands_flag => '1', -- because XSub uses in_sosi_arr = fsub_sosi_arr, so weighted subbands - nof_crosslets => nof_crosslets, - crosslets_info => crosslets_info + weighted_subbands_flag => '1', -- because XSub uses in_sosi_arr = fsub_sosi_arr, so weighted subbands + + nof_crosslets => nof_crosslets, + crosslets_info_rec => prev_crosslets_info_rec ); END str; 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 e7796662df1ae18012395c10cfcc5897f5c49abf..5c11d1481a6dbf3c7ea9edb10ebb7dbdb7031fa8 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd @@ -262,7 +262,8 @@ BEGIN g_nof_stat => c_sdp_N_sub*c_sdp_Q_fft, g_in_data_w => c_sdp_W_subband, g_stat_data_w => g_wpfb.stat_data_w, - g_stat_data_sz => g_wpfb.stat_data_sz + g_stat_data_sz => g_wpfb.stat_data_sz, + g_stat_multiplex=> c_sdp_Q_fft ) PORT MAP ( mm_rst => mm_rst, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd index 2cc902a393ad0a179fe76657d4931681ca520549..d76f1d6833f8f9756b3b4e004aa7fe877a6e8618 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd @@ -24,8 +24,15 @@ -- Purpose: -- Select subbands from incoming blocks -- Description: --- The Crosslet subband select selects N_crosslets from each incoming block. Per --- crosslet there are S_pn = 12 subbands, one from each signal input of the PN. +-- The Crosslet subband select selects N_crosslets from each incoming block. +-- Per crosslet there are S_pn = 12 subbands, one from each signal input of +-- the PN. +-- The cur_crosslets_info is valid at the out_sosi.sync and for the entire +-- sync interval. The cur_crosslets_info identifies the crosslets that are +-- being calculated during this out_sosi.sync interval. +-- The prev_crosslets_info identifies the crosslets that were calculated +-- during the previous out_sosi.sync interval, so the XST for those crosslets +-- are then pending to be offloaded. -- Remark: -- . See L5 SDPFW Design Document: Subband Correlator -- Link: https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Subband+Correlator @@ -60,13 +67,13 @@ ENTITY sdp_crosslets_subband_select IS reg_bsn_sync_scheduler_xsub_mosi : IN t_mem_mosi := c_mem_mosi_rst; reg_bsn_sync_scheduler_xsub_miso : OUT t_mem_miso := c_mem_miso_rst; - out_crosslets_info : OUT STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) + cur_crosslets_info_rec : OUT t_sdp_crosslets_info; + prev_crosslets_info_rec : OUT t_sdp_crosslets_info ); END sdp_crosslets_subband_select; ARCHITECTURE str OF sdp_crosslets_subband_select IS - CONSTANT c_crosslets_info_dly : NATURAL := 1; CONSTANT c_col_select_addr_w : NATURAL := ceil_log2(c_sdp_Q_fft * c_sdp_N_sub); CONSTANT c_row_select_slv_w : NATURAL := ceil_log2(c_sdp_P_pfb); @@ -104,13 +111,13 @@ ARCHITECTURE str OF sdp_crosslets_subband_select IS SIGNAL crosslets_info_reg : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL crosslets_info_reg_in : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL active_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL i_out_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL cur_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL prev_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); -- Map crosslets_info slv to record for easier view in Wave window SIGNAL crosslets_info_rec : t_sdp_crosslets_info; SIGNAL crosslets_info_rec_inout : t_sdp_crosslets_info; SIGNAL active_crosslets_info_rec : t_sdp_crosslets_info; - SIGNAL out_crosslets_info_rec : t_sdp_crosslets_info; BEGIN @@ -160,10 +167,10 @@ BEGIN out_reg => crosslets_info_reg ); - p_set_unused_crosslets : PROCESS(i_out_crosslets_info) + p_set_unused_crosslets : PROCESS(cur_crosslets_info) BEGIN -- MM readback the currently active crosslets info, instead of the initial MM written crosslets_info_reg - crosslets_info_reg_in <= i_out_crosslets_info; -- Always use crosslets info 6:0 + step(@ index 15) + crosslets_info_reg_in <= cur_crosslets_info; -- Always use crosslets info 6:0 + step(@ index 15) -- Set crosslets 14:7 to -1 FOR I IN g_N_crosslets TO c_sdp_mm_reg_crosslets_info.nof_dat - 2 LOOP crosslets_info_reg_in((I+1) * c_sdp_crosslets_index_w - 1 DOWNTO I * c_sdp_crosslets_index_w ) <= TO_SVEC(-1, c_sdp_crosslets_index_w); @@ -319,7 +326,7 @@ BEGIN END GENERATE; -- pipeline for alignment with sync - u_common_pipeline : ENTITY common_lib.common_pipeline + u_common_pipeline_cur : ENTITY common_lib.common_pipeline GENERIC MAP( g_pipeline => c_crosslets_info_dly, g_in_dat_w => c_sdp_crosslets_info_reg_w, @@ -330,10 +337,22 @@ BEGIN clk => dp_clk, in_en => row_sosi.sync, in_dat => active_crosslets_info, - out_dat => i_out_crosslets_info + out_dat => cur_crosslets_info ); - out_crosslets_info <= i_out_crosslets_info; + u_common_pipeline_prev : ENTITY common_lib.common_pipeline + GENERIC MAP( + g_pipeline => c_crosslets_info_dly, + g_in_dat_w => c_sdp_crosslets_info_reg_w, + g_out_dat_w => c_sdp_crosslets_info_reg_w + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + in_en => row_sosi.sync, + in_dat => cur_crosslets_info, + out_dat => prev_crosslets_info + ); --------------------------------------------------------------- -- Out sosi pipeline @@ -355,6 +374,8 @@ BEGIN crosslets_info_rec <= func_sdp_map_crosslets_info(crosslets_info_reg); crosslets_info_rec_inout <= func_sdp_map_crosslets_info(crosslets_info_reg_in); active_crosslets_info_rec <= func_sdp_map_crosslets_info(active_crosslets_info); - out_crosslets_info_rec <= func_sdp_map_crosslets_info(i_out_crosslets_info); + + cur_crosslets_info_rec <= func_sdp_map_crosslets_info(cur_crosslets_info); + prev_crosslets_info_rec <= func_sdp_map_crosslets_info(prev_crosslets_info); 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 524f257c78da4cc7195fb7dd50e3dc87e32e20e5..1f392030b12ec07086cbf4db03e3f304d44545a5 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -114,7 +114,7 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_wg_subband_freq_unit : REAL := c_diag_wg_freq_unit/REAL(c_sdp_N_fft); -- subband freq = Fs/1024 = 200 MSps/1024 = 195312.5 Hz sinus CONSTANT c_sdp_N_clk_per_sync : NATURAL := c_sdp_f_adc_MHz*10**6; -- Default 200M clock cycles per second CONSTANT c_sdp_N_clk_sync_timeout : NATURAL := c_sdp_f_adc_MHz*10**6 + c_sdp_f_adc_MHz*10**5; -- 10% margin. - CONSTANT c_sdp_N_clk_sync_timeout_xsub : NATURAL := 2**31 - 1; -- 10.7 seconds = largest value for NATURAL. + CONSTANT c_sdp_N_clk_sync_timeout_xsub : NATURAL := 2147483647; -- = 2**31 - 1 = largest value for NATURAL for 10.7 seconds. Do not use 2*31 to avoid Modelsim NATURAL overflow warning. CONSTANT c_sdp_N_sync_jesd : NATURAL := c_sdp_S_pn * c_sdp_N_sync_rcu / c_sdp_S_rcu; -- = 4, nof JESD IP sync outputs per PN CONSTANT c_sdp_f_sub_Hz : REAL := REAL(c_sdp_f_adc_MHz * 10**6) / REAL(c_sdp_N_fft); -- = 195312.5 CONSTANT c_sdp_N_int : NATURAL := c_sdp_f_adc_MHz * 10**6; -- nof ADC sample periods per 1 s integration interval @@ -500,6 +500,8 @@ PACKAGE sdp_pkg is step : NATURAL; END RECORD; + CONSTANT c_sdp_crosslets_info_rst : t_sdp_crosslets_info := (offset_arr => (OTHERS => 0), step => 0); + CONSTANT c_sdp_mm_reg_nof_crosslets : t_c_mem := (latency => 1, adr_w => 1, dat_w => ceil_log2(c_sdp_N_crosslets_max+1), diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd index 1338fe6d15b0c5bec083dd968b12817a003e259c..d37221c8c55be4babe557cbdb226f0bbd4328d92 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd @@ -156,8 +156,9 @@ ENTITY sdp_statistics_offload IS ring_info : IN t_ring_info := c_ring_info_rst; -- only needed for XST sdp_info : IN t_sdp_info; weighted_subbands_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') + crosslets_info_rec : IN t_sdp_crosslets_info := c_sdp_crosslets_info_rst ); END sdp_statistics_offload; @@ -202,8 +203,7 @@ ARCHITECTURE str OF sdp_statistics_offload IS crosslets_info_rec : t_sdp_crosslets_info; END RECORD; - CONSTANT c_crosslets_info_rst : t_sdp_crosslets_info := (offset_arr => (OTHERS => 0), step => 0); - CONSTANT c_reg_rst : t_reg := (0, 0, '0', '0', (OTHERS => '0'), '0', 0, 0, 0, 0, 0, 0, 0, 0, c_crosslets_info_rst); + CONSTANT c_reg_rst : t_reg := (0, 0, '0', '0', (OTHERS => '0'), '0', 0, 0, 0, 0, 0, 0, 0, 0, c_sdp_crosslets_info_rst); SIGNAL r : t_reg; SIGNAL nxt_r : t_reg; @@ -239,6 +239,8 @@ ARCHITECTURE str OF sdp_statistics_offload IS SIGNAL bsn_at_sync : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0'); + SIGNAL r_dp_header_sop : STD_LOGIC; + SIGNAL r_dp_header_rec : t_sdp_stat_header; -- Debug signals for view in Wave window SIGNAL dbg_c_marker : NATURAL := c_marker; @@ -353,7 +355,7 @@ BEGIN 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, dp_sop, dp_header_info) + p_control_packet_offload : PROCESS(r, in_sosi, nof_crosslets, crosslets_info_rec, trigger_offload, dp_sop, dp_header_info, nof_packets) -- in order of appearance VARIABLE v : t_reg; VARIABLE v_index : NATURAL; BEGIN @@ -376,19 +378,18 @@ BEGIN END IF; END IF; - - -- For XST offload capture nof_crosslets and crosslets_info at in_sosi.sync, + -- For XST offload capture nof_crosslets and crosslets_info_rec at in_sosi.sync, -- to make sure they do not change during packets offload. -- . The sdp_crosslets_subband_select.vhd in [2] takes care that - -- nof_crosslets and crosslets_info are valid at the xsel_sosi.sync. The + -- nof_crosslets and crosslets_info_rec are valid at the xsel_sosi.sync. The -- mmp_dp_bsn_align_v2 in [2] then aligns the local xsel_sosi with the -- remote data and passes on the sync. After some latency the sync -- arrives at the sdp_statistics_offload. This latency is very short - -- compared to the sync period, so the nof_crosslets and crosslet_info + -- compared to the sync period, so the nof_crosslets and crosslets_info_rec -- are still valid at the 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); + v.crosslets_info_rec := crosslets_info_rec; END IF; -- The trigger_offload occurs nof_cycles_dly after the in_sosi.sync and the @@ -570,6 +571,10 @@ BEGIN hdr_fields_in_arr(0) => r.dp_header_info ); + -- Debug signal, r_dp_header_rec must be available at the r_dp_header_sop + r_dp_header_sop <= dp_offload_snk_in.sop; + r_dp_header_rec <= func_sdp_map_stat_header(r.dp_header_info); + out_sosi <= udp_sosi; u_bsn_mon_udp : ENTITY dp_lib.mms_dp_bsn_monitor_v2 diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd index d58cd1b58e1de6fbc64612736e5f3bad2ce48e72..be9550e00ce15645f27d8cd0bb5c497b810a8842 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd @@ -30,7 +30,7 @@ -- Description: The tb starts the dut by writing a scheduled bsn to the bsn_scheduler -- via MM. The offsets and step are configured using MM. The dut makes the subband -- selection based on the MM configuration and N_crosslets. The TB then verifies out_sosi --- and out_crosslets_info of the dut by comparing it to the expected output. +-- and cur_crosslets_info of the dut by comparing it to the expected output. LIBRARY IEEE, common_lib, dp_lib; USE IEEE.std_logic_1164.ALL; @@ -94,10 +94,10 @@ ARCHITECTURE tb OF tb_sdp_crosslets_subband_select IS SIGNAL out_sosi : t_dp_sosi; - SIGNAL exp_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL out_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL exp_crosslets_info_rec : t_sdp_crosslets_info; - SIGNAL out_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL exp_cur_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL cur_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL exp_prev_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL prev_crosslets_info_rec : t_sdp_crosslets_info; BEGIN @@ -141,7 +141,7 @@ BEGIN END LOOP; ASSERT rd_crosslet_step = 0 REPORT "Wrong crosslet step after rst." SEVERITY ERROR; - -- b) Read crosslet_info in every sync interval + -- b) Read crosslets_info in every sync interval WHILE TRUE LOOP proc_common_wait_until_hi_lo(clk, out_sosi.sync); proc_common_wait_cross_clock_domain_latency(c_clk_period, c_mm_clk_period); @@ -157,9 +157,9 @@ BEGIN proc_common_wait_some_cycles(mm_clk, 1); -- Verify that readback crosslet info is active crosslets_info FOR I IN 0 TO c_N_crosslets-1 LOOP - ASSERT rd_crosslet_offsets(I) = exp_crosslets_info_rec.offset_arr(I) REPORT "Wrong active crosslet offset in output sync interval." SEVERITY ERROR; + ASSERT rd_crosslet_offsets(I) = exp_cur_crosslets_info_rec.offset_arr(I) REPORT "Wrong active crosslet offset in output sync interval." SEVERITY ERROR; END LOOP; - ASSERT rd_crosslet_step = exp_crosslets_info_rec.step REPORT "Wrong active crosslet step in output sync interval." SEVERITY ERROR; + ASSERT rd_crosslet_step = exp_cur_crosslets_info_rec.step REPORT "Wrong active crosslet step in output sync interval." SEVERITY ERROR; END LOOP; WAIT; @@ -216,19 +216,28 @@ BEGIN VARIABLE v_col : NATURAL := 0; VARIABLE v_row : NATURAL := 0; VARIABLE v_offset : NATURAL := 0; - VARIABLE v_sync_ix : NATURAL := 0; + VARIABLE v_sync_ix : NATURAL := 0; -- ix = index VARIABLE v_k : NATURAL := 0; BEGIN FOR I IN 0 TO c_nof_sync*c_nof_block_per_sync-1 LOOP v_sync_ix := I / c_nof_block_per_sync; exp_sosi <= c_dp_sosi_rst; + + -- In a tb it is ok and it can be handy to use rising_edge() on a combinatorial signal WAIT UNTIL rising_edge(out_sosi.sop); - exp_crosslets_info_slv(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_step, c_sdp_crosslets_index_w); + -- Current sync interval crosslets_info + exp_cur_crosslets_info_rec.step <= c_crosslet_step; FOR C IN 0 TO c_nof_ch_sel_col-1 LOOP - exp_crosslets_info_slv((C+1)*c_sdp_crosslets_index_w-1 DOWNTO C*c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_offsets(C) + v_sync_ix * c_crosslet_step, c_sdp_crosslets_index_w); + exp_cur_crosslets_info_rec.offset_arr(C) <= c_crosslet_offsets(C) + v_sync_ix * c_crosslet_step; END LOOP; + -- Previous sync interval crosslets_info + IF out_sosi.sync = '1' THEN + exp_prev_crosslets_info_rec <= exp_cur_crosslets_info_rec; + END IF; + + -- Crosslet data FOR J IN 0 TO c_nof_ch_sel-1 LOOP v_offset := J / (c_nof_ch_sel_col*c_nof_ch_sel_row); v_col := J MOD c_nof_ch_sel_col; @@ -241,7 +250,6 @@ BEGIN exp_sosi.sop <= '1'; IF I MOD c_nof_block_per_sync = 0 THEN exp_sosi.sync <= '1'; - END IF; ELSIF j = c_nof_ch_sel-1 THEN exp_sosi.eop <= '1'; @@ -250,8 +258,8 @@ BEGIN exp_sosi.re <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA( (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); exp_sosi.im <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA(1+ (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); proc_common_wait_some_cycles(clk, 1); - END LOOP; + exp_sosi <= c_dp_sosi_rst; END LOOP; WAIT; @@ -260,14 +268,17 @@ BEGIN p_verify_out_data : PROCESS(clk) BEGIN IF rising_edge(clk) THEN - ASSERT out_sosi.valid = exp_sosi.valid REPORT "Wrong out_sosi.valid" SEVERITY ERROR; - ASSERT out_sosi.sop = exp_sosi.sop REPORT "Wrong out_sosi.sop" SEVERITY ERROR; - ASSERT out_sosi.eop = exp_sosi.eop REPORT "Wrong out_sosi.eop" SEVERITY ERROR; - ASSERT out_sosi.sync = exp_sosi.sync REPORT "Wrong out_sosi.sync" SEVERITY ERROR; - ASSERT out_crosslets_info_slv = exp_crosslets_info_slv REPORT "Wrong out_crosslets_info_slv" SEVERITY ERROR; + ASSERT out_sosi.valid = exp_sosi.valid REPORT "Wrong out_sosi.valid" SEVERITY ERROR; + ASSERT out_sosi.sop = exp_sosi.sop REPORT "Wrong out_sosi.sop" SEVERITY ERROR; + ASSERT out_sosi.eop = exp_sosi.eop REPORT "Wrong out_sosi.eop" SEVERITY ERROR; + ASSERT out_sosi.sync = exp_sosi.sync REPORT "Wrong out_sosi.sync" SEVERITY ERROR; + + ASSERT cur_crosslets_info_rec = exp_cur_crosslets_info_rec REPORT "Wrong cur_crosslets_info" SEVERITY ERROR; + ASSERT prev_crosslets_info_rec = exp_prev_crosslets_info_rec REPORT "Wrong prev_crosslets_info" SEVERITY ERROR; + IF exp_sosi.valid = '1' THEN - ASSERT out_sosi.re = exp_sosi.re REPORT "Wrong out_sosi.re" SEVERITY ERROR; - ASSERT out_sosi.im = exp_sosi.im REPORT "Wrong out_sosi.im" SEVERITY ERROR; + ASSERT out_sosi.re = exp_sosi.re REPORT "Wrong out_sosi.re" SEVERITY ERROR; + ASSERT out_sosi.im = exp_sosi.im REPORT "Wrong out_sosi.im" SEVERITY ERROR; END IF; END IF; END PROCESS; @@ -294,11 +305,8 @@ BEGIN in_sosi_arr => in_sosi_arr, out_sosi => out_sosi, - out_crosslets_info => out_crosslets_info_slv + cur_crosslets_info_rec => cur_crosslets_info_rec, + prev_crosslets_info_rec => prev_crosslets_info_rec ); - -- Map crosslets_info slv to record for easier view in Wave window - exp_crosslets_info_rec <= func_sdp_map_crosslets_info(exp_crosslets_info_slv); - out_crosslets_info_rec <= func_sdp_map_crosslets_info(out_crosslets_info_slv); - END tb; 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 1193efc51d1626ac76565c476870d39bcff62236..d44b39a143cc34a4be978ed017795347883579ce 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 @@ -174,7 +174,6 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS 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 sdp_offload_data : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- 32 bit SIGNAL sdp_offload_sosi : t_dp_sosi; @@ -309,8 +308,6 @@ BEGIN WAIT; END PROCESS; - in_crosslets_info_slv <= func_sdp_map_crosslets_info(in_crosslets_info_rec); - -- Enable the statistics offload when input is running p_enable_trigger : PROCESS BEGIN @@ -660,11 +657,12 @@ BEGIN ring_info => c_exp_ring_info, sdp_info => c_exp_sdp_info, weighted_subbands_flag => weighted_subbands_flag, + nof_crosslets => c_mm_nof_crosslets, - crosslets_info => in_crosslets_info_slv + crosslets_info_rec => in_crosslets_info_rec ); - -- Check crosslet_info functions + -- Verify crosslets_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 diff --git a/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd b/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd index 43da667fd785be1a580b1607b5eb35a361d1a3ce..23bc0cbdaaeeefce44a4b31ee61c3b660d9428f2 100644 --- a/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd +++ b/libraries/base/dp/tb/vhdl/tb_mms_dp_gain_serial_arr.vhd @@ -57,7 +57,7 @@ ARCHITECTURE tb OF tb_mms_dp_gain_serial_arr IS CONSTANT c_mm_clk_period : TIME := 20 ns; CONSTANT c_dp_clk_period : TIME := 10 ns; CONSTANT c_cross_clock_domain_latency : NATURAL := 20; - CONSTANT c_dut_latency : NATURAL := 5; -- = 3 for the real or complex multiplier + 2 for the RAM read latency + CONSTANT c_dut_latency : NATURAL := 4; -- = 3 for the real or complex multiplier + 1 for the RAM read latency CONSTANT c_real_multiply : BOOLEAN := g_complex_data=FALSE AND g_complex_gain=FALSE; CONSTANT c_nof_gains_w : NATURAL := ceil_log2(g_nof_gains); diff --git a/libraries/dsp/st/src/vhdl/st_sst.vhd b/libraries/dsp/st/src/vhdl/st_sst.vhd index b21195656a2cec221c3a4afdb74bf46efc740349..26b661ddbb2e1a6b69b2068333ee9a5586852c67 100644 --- a/libraries/dsp/st/src/vhdl/st_sst.vhd +++ b/libraries/dsp/st/src/vhdl/st_sst.vhd @@ -21,6 +21,7 @@ LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; USE IEEE.std_logic_1164.ALL; +USE IEEE.math_real.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_field_pkg.ALL; @@ -43,6 +44,10 @@ USE technology_lib.technology_select_pkg.ALL; -- of the previous sync interval. The length of the sync interval determines -- the nof accumlations per statistic, hence the integration time. See st_calc -- for more details. +-- +-- View wrdata_power and stat_bin in Wave window to see the stat power +-- values series. +-- -- Remarks: -- . The in_sync is assumed to be a pulse an interpreted directly. -- . The MM register is single page RAM to save memory resources. Therefore @@ -56,12 +61,13 @@ USE technology_lib.technology_select_pkg.ALL; ENTITY st_sst IS GENERIC ( g_technology : NATURAL := c_tech_select_default; - g_nof_stat : NATURAL := 512; -- nof accumulators + g_nof_stat : NATURAL := 512; -- total nof accumulators g_xst_enable : BOOLEAN := FALSE; -- when set to true, an extra memory is instantiated to hold the imaginary part of the cross-correlation results g_in_data_w : NATURAL := 18; -- width o dth edata to be accumulated g_stat_data_w : NATURAL := 54; -- statistics accumulator width - g_stat_data_sz : NATURAL := 2 -- statistics word width >= statistics accumulator width and fit in a power of 2 multiple 32b MM words - ); + g_stat_data_sz : NATURAL := 2; -- statistics word width >= statistics accumulator width and fit in a power of 2 multiple 32b MM words + g_stat_multiplex: NATURAL := 2 -- number of accumulators per stat_bin, for debug purposes with view in Wave window + ); PORT ( mm_rst : IN STD_LOGIC; mm_clk : IN STD_LOGIC; @@ -103,7 +109,7 @@ ARCHITECTURE str OF st_sst IS CONSTANT c_field_arr : t_common_field_arr(0 DOWNTO 0) := (0=> ( field_name_pad("treshold"), "RW", c_nof_stat_w, field_default(0) )); SIGNAL mm_fields_out : STD_LOGIC_VECTOR(field_slv_out_len(c_field_arr)-1 DOWNTO 0); - SIGNAL treshold : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); + SIGNAL treshold : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); TYPE reg_type IS RECORD in_sosi_reg : t_dp_sosi; @@ -113,14 +119,19 @@ ARCHITECTURE str OF st_sst IS SIGNAL r, rin : reg_type; SIGNAL in_sync : STD_LOGIC; - SIGNAL stat_data_re : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); + + SIGNAL stat_data_re : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); SIGNAL stat_data_im : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); SIGNAL wrdata_re : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); SIGNAL wrdata_im : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); - - SIGNAL stat_mosi : t_mem_mosi; - SIGNAL count : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); + SIGNAL wrdata_power : REAL; + + SIGNAL stat_bin : NATURAL; + + SIGNAL stat_mosi : t_mem_mosi := c_mem_mosi_rst; + + SIGNAL treshold_count : STD_LOGIC_VECTOR(c_nof_stat_w-1 DOWNTO 0); SIGNAL ram_st_sst_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); SIGNAL ram_st_sst_miso_arr : t_mem_miso_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst); @@ -153,24 +164,23 @@ BEGIN ------------------------------------------------------------------------------ -- Input registers and preparation of the input data for the multiplier. ------------------------------------------------------------------------------ - comb : PROCESS(r, dp_rst, in_complex, count, treshold) + comb : PROCESS(r, dp_rst, in_complex, treshold_count, treshold) VARIABLE v : reg_type; BEGIN v := r; v.in_sosi_reg := in_complex; - IF(count = zeros OR treshold = zeros) THEN + IF treshold_count = zeros OR treshold = zeros THEN v.in_a_re := in_complex.re(g_in_data_w-1 DOWNTO 0); v.in_a_im := in_complex.im(g_in_data_w-1 DOWNTO 0); END IF; - IF(dp_rst = '1') THEN + IF dp_rst = '1' THEN v.in_a_re := (OTHERS => '0'); v.in_a_im := (OTHERS => '0'); END IF; - rin <= v; - + rin <= v; END PROCESS comb; regs : PROCESS(dp_clk) @@ -181,7 +191,7 @@ BEGIN END PROCESS; ------------------------------------------------------------------------------ - -- Counter used to detect when treshold is reached in order to load new + -- Counter used to detect when treshold is reached in order to load new -- input vlaues for the multiplier. ------------------------------------------------------------------------------ treshold_cnt : ENTITY common_lib.common_counter @@ -197,13 +207,13 @@ BEGIN clk => dp_clk, cnt_clr => in_complex.eop, cnt_en => in_complex.valid, - cnt_max => treshold, - count => count + cnt_max => treshold, + count => treshold_count ); in_sync <= in_complex.sync; - st_calc : ENTITY work.st_calc + st_calc : ENTITY work.st_calc GENERIC MAP ( g_technology => g_technology, g_nof_mux => 1, @@ -228,10 +238,17 @@ BEGIN out_val => stat_mosi.wr, out_val_m => OPEN ); - - wrdata_re <= RESIZE_MEM_UDATA(stat_data_re); - wrdata_im <= RESIZE_MEM_UDATA(stat_data_im); - + + -- Auto correlations are unsigned value, cross correlations are signed values + wrdata_re <= RESIZE_MEM_UDATA(stat_data_re) WHEN g_xst_enable=FALSE ELSE RESIZE_MEM_SDATA(stat_data_re); + wrdata_im <= RESIZE_MEM_UDATA(stat_data_im) WHEN g_xst_enable=FALSE ELSE RESIZE_MEM_SDATA(stat_data_im); + + -- View SST or XST power values in wave window (stat_data_im = 0 for SST) + wrdata_power <= COMPLEX_RADIUS(TO_SREAL(stat_data_re), TO_SREAL(stat_data_im)) ** 2.0; + + stat_bin <= TO_UINT(stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0)) / g_stat_multiplex; + + -- For SST or for real part of XST stat_reg_re : ENTITY common_lib.common_ram_crw_crw_ratio GENERIC MAP ( g_technology => g_technology, @@ -261,12 +278,12 @@ BEGIN rd_val_b => OPEN ); - gen_re: IF g_xst_enable=FALSE GENERATE + gen_sst: IF g_xst_enable=FALSE GENERATE ram_st_sst_mosi_arr(0) <= ram_st_sst_mosi; ram_st_sst_miso <= ram_st_sst_miso_arr(0); END GENERATE; - gen_im: IF g_xst_enable=TRUE GENERATE + gen_xst: IF g_xst_enable=TRUE GENERATE --------------------------------------------------------------- -- COMBINE MEMORY MAPPED INTERFACES --------------------------------------------------------------- @@ -284,6 +301,7 @@ BEGIN miso_arr => ram_st_sst_miso_arr ); + -- For imaginary part of XST stat_reg_im : ENTITY common_lib.common_ram_crw_crw_ratio GENERIC MAP ( g_technology => g_technology, @@ -311,8 +329,7 @@ BEGIN rd_en_b => '0', rd_dat_b => OPEN, rd_val_b => OPEN - ); - + ); END GENERATE; -END str; \ No newline at end of file +END str; diff --git a/libraries/dsp/st/src/vhdl/st_xsq.vhd b/libraries/dsp/st/src/vhdl/st_xsq.vhd index 4378a4c7507b12ec38b0467b1f2ac923b9c2f998..073cbe526ee28874fe6c80a0541c3fc1d7629d1c 100644 --- a/libraries/dsp/st/src/vhdl/st_xsq.vhd +++ b/libraries/dsp/st/src/vhdl/st_xsq.vhd @@ -27,6 +27,10 @@ -- of the previous sync interval. The length of the sync interval determines -- the nof accumlations per statistic, hence the integration time. See st_calc -- for more details. +-- +-- View wrdata_power and a_sp, b_sp and crosslet_index in Wave window to see +-- the stat power values series. +-- -- Remarks: -- . The in_sync is assumed to be a pulse an interpreted directly. -- . The MM register is single page RAM to save memory resources. Therefore @@ -42,11 +46,13 @@ LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; USE IEEE.std_logic_1164.ALL; +USE IEEE.math_real.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_field_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; USE technology_lib.technology_select_pkg.ALL; + ENTITY st_xsq IS GENERIC ( g_nof_signal_inputs : NATURAL := 2; @@ -100,7 +106,13 @@ ARCHITECTURE str OF st_xsq IS SIGNAL wrdata_re : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); SIGNAL wrdata_im : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); - + SIGNAL wrdata_power : REAL; + + SIGNAL stat_index : NATURAL; + SIGNAL a_sp : NATURAL; + SIGNAL b_sp : NATURAL; + SIGNAL crosslet_index : NATURAL; + SIGNAL stat_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL ram_st_xsq_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); @@ -165,9 +177,19 @@ BEGIN out_val_m => OPEN ); - wrdata_re <= RESIZE_MEM_UDATA(stat_data_re); - wrdata_im <= RESIZE_MEM_UDATA(stat_data_im); + -- Cross correlations are signed values + wrdata_re <= RESIZE_MEM_SDATA(stat_data_re); + wrdata_im <= RESIZE_MEM_SDATA(stat_data_im); + -- View XST power values in wave window + wrdata_power <= COMPLEX_RADIUS(TO_SREAL(stat_data_re), TO_SREAL(stat_data_im)) ** 2.0; + + -- Translate statistcs [crosslets][in A][in B] order into indices + stat_index <= TO_UINT(stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0)); + a_sp <= (stat_index / g_nof_signal_inputs) MOD g_nof_signal_inputs; + b_sp <= stat_index MOD g_nof_signal_inputs; + crosslet_index <= stat_index / c_xsq; + --------------------------------------------------------------- -- COMBINE MEMORY MAPPED INTERFACES ---------------------------------------------------------------