diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd index b55c9c6142bbc652752d52a54177d8f6a93960b1..9ee13577f479ac34dd2143451473be70948d41a5 100644 --- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd +++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd @@ -33,7 +33,7 @@ -- 2) Read current BSN from reg_bsn_scheduler_wg and write reg_bsn_scheduler_wg -- to trigger start of WG at BSN. -- --- 3) Read subband statistics (SST) via MM and verify with c_exp_subband_power at g_subband. +-- 3) Read subband statistics (SST) via MM and verify with exp_subband_power at g_subband. -- . use weighted subbands (default selected by MM) -- -- 4) View in wave window @@ -127,7 +127,12 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_fsub IS CONSTANT c_pol_index : NATURAL := g_sp MOD c_sdp_Q_fft; CONSTANT c_pfb_index : NATURAL := g_sp / c_sdp_Q_fft; -- only read used WPFB unit out of range(c_sdp_P_pfb = 6) CONSTANT c_exp_subband_sp_power_ratio : REAL := 1.0/8.0; -- subband power / SP power, depends on internal WPFB quantization and FIR coefficients - CONSTANT c_exp_subband_power : REAL := c_exp_wg_power_sp * c_exp_subband_sp_power_ratio; + CONSTANT c_exp_subband_power_raw : REAL := c_exp_wg_power_sp * c_exp_subband_sp_power_ratio; + CONSTANT c_exp_subband_power_weighted : REAL := c_exp_subband_power_raw * g_subband_gain**2.0; + + -- . expected limit values, obtained with print_str() for g_subband = 102 + CONSTANT c_exp_subband_power_leakage_snr_dB : REAL := 75.0; -- < 76.372 + CONSTANT c_exp_subband_power_crosstalk_snr_dB : REAL := 95.0; -- < 96.284 TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL; TyPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub-1); @@ -136,12 +141,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_fsub IS CONSTANT c_subband_weight_re : INTEGER := INTEGER(g_subband_gain * REAL(c_sdp_unit_sub_weight) * COS(g_subband_phase * MATH_2_PI / 360.0)); CONSTANT c_subband_weight_im : INTEGER := INTEGER(g_subband_gain * REAL(c_sdp_unit_sub_weight) * SIN(g_subband_phase * MATH_2_PI / 360.0)); - SIGNAL sp_subband_weight_re : INTEGER := 0; - SIGNAL sp_subband_weight_im : INTEGER := 0; - SIGNAL sp_subband_weight_gain : REAL := 0.0; - SIGNAL sp_subband_weight_phase : REAL := 0.0; - - -- MM + -- MM -- . Address widths of a single MM instance CONSTANT c_addr_w_reg_diag_wg : NATURAL := 2; -- . Address spans of a single MM instance @@ -176,13 +176,17 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_fsub IS SIGNAL sp_subband_power_crosstalk : REAL := 0.0; SIGNAL sp_subband_power_crosstalk_snr_dB : REAL := 0.0; -- signal to noise (crosstalk) ration - -- . expected limit values, obtained with print_str() for g_subband = 102 - CONSTANT c_exp_subband_power_leakage_snr_dB : REAL := 75.0; -- < 76.372 - CONSTANT c_exp_subband_power_crosstalk_snr_dB : REAL := 95.0; -- < 96.284 + SIGNAL exp_subband_power : REAL := 0.0; -- . Selector SIGNAL sst_offload_weighted_subbands : STD_LOGIC; + -- . Subband equalizer + SIGNAL sp_subband_weight_re : INTEGER := 0; + SIGNAL sp_subband_weight_im : INTEGER := 0; + SIGNAL sp_subband_weight_gain : REAL := 0.0; + SIGNAL sp_subband_weight_phase : REAL := 0.0; + -- DUT SIGNAL ext_clk : STD_LOGIC := '0'; SIGNAL ext_pps : STD_LOGIC := '0'; @@ -283,19 +287,21 @@ BEGIN JESD204B_SYNC_N => jesd204b_sync_n ); + exp_subband_power <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_subband_power_raw, c_exp_subband_power_weighted); + ------------------------------------------------------------------------------ -- MM slave accesses via file IO ------------------------------------------------------------------------------ - tb_clk <= NOT tb_clk AFTER c_tb_clk_period/2; -- Testbench MM clock + tb_clk <= NOT tb_clk AFTER c_tb_clk_period/2; -- Testbench MM clock p_mm_stimuli : PROCESS - VARIABLE v_bsn : NATURAL; - VARIABLE v_data_lo, v_data_hi : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); - VARIABLE v_stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); - VARIABLE v_len, v_span, v_offset, v_A : NATURAL; -- address ranges, indices - VARIABLE v_W, v_P, v_U, v_S, v_B : NATURAL; -- array indicies - VARIABLE v_re, v_im, v_int : INTEGER; - VARIABLE v_power : REAL; + VARIABLE v_bsn : NATURAL; + VARIABLE v_data_lo, v_data_hi : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + VARIABLE v_stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); + VARIABLE v_len, v_span, v_offset, v_addr : NATURAL; -- address ranges, indices + VARIABLE v_W, v_P, v_U, v_S, v_B : NATURAL; -- array indicies + VARIABLE v_re, v_im, v_weight : INTEGER; + VARIABLE v_power : REAL; BEGIN -- Wait for DUT power up after reset WAIT FOR 1 us; @@ -312,6 +318,9 @@ BEGIN WAIT FOR 1 us; pps_rst <= '0'; + ---------------------------------------------------------------------------- + -- Read weighted subband selector + ---------------------------------------------------------------------------- mmf_mm_bus_rd(c_mm_file_reg_dp_selector, 0, rd_data, tb_clk); proc_common_wait_some_cycles(tb_clk, 1); sst_offload_weighted_subbands <= NOT rd_data(0); @@ -344,29 +353,27 @@ BEGIN ---------------------------------------------------------------------------- -- Write subband weight for selected g_sp and g_subband ---------------------------------------------------------------------------- - -- . MM format: (cint16)subband_weights[S_pn/Q_fft]_[Q_fft][N_sub] = [S_pn][N_sub] - v_A := g_sp * c_sdp_N_sub + g_subband; + -- . MM format: (cint16)RAM_EQUALIZER_GAINS[S_pn/Q_fft]_[Q_fft][N_sub] = [S_pn][N_sub] + v_addr := g_sp * c_sdp_N_sub + g_subband; -- . read - mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains, v_A, rd_data, tb_clk); - proc_common_wait_some_cycles(tb_clk, 1); - v_re := unpack_complex_re(rd_data, c_sdp_W_bf_weight); - v_im := unpack_complex_im(rd_data, c_sdp_W_bf_weight); + mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains, v_addr, rd_data, tb_clk); + v_re := unpack_complex_re(rd_data, c_sdp_W_sub_weight); + v_im := unpack_complex_im(rd_data, c_sdp_W_sub_weight); sp_subband_weight_re <= v_re; sp_subband_weight_im <= v_im; - sp_subband_weight_gain <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_sub_weight); - sp_subband_weight_phase <= ARCTAN(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI; + sp_subband_weight_gain <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_sub_weight); + sp_subband_weight_phase <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI; -- . write - v_int := pack_complex(c_subband_weight_re, c_subband_weight_im, c_sdp_W_bf_weight); -- c_sdp_W_bf_weight = 16 bit - mmf_mm_bus_wr(c_mm_file_ram_equalizer_gains, v_A, v_int, tb_clk); + v_weight := pack_complex(re => c_subband_weight_re, im => c_subband_weight_im, w => c_sdp_W_sub_weight); -- c_sdp_W_sub_weight = 16 bit + mmf_mm_bus_wr(c_mm_file_ram_equalizer_gains, v_addr, v_weight, tb_clk); -- . read back - mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains, v_A, rd_data, tb_clk); - proc_common_wait_some_cycles(tb_clk, 1); - v_re := unpack_complex_re(rd_data, c_sdp_W_bf_weight); - v_im := unpack_complex_im(rd_data, c_sdp_W_bf_weight); + mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains, v_addr, rd_data, tb_clk); + v_re := unpack_complex_re(rd_data, c_sdp_W_sub_weight); + v_im := unpack_complex_im(rd_data, c_sdp_W_sub_weight); sp_subband_weight_re <= v_re; sp_subband_weight_im <= v_im; - sp_subband_weight_gain <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_sub_weight); - sp_subband_weight_phase <= ARCTAN(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI; + sp_subband_weight_gain <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_sub_weight); + sp_subband_weight_phase <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI; ---------------------------------------------------------------------------- -- Wait for enough WG data and start of sync interval @@ -382,7 +389,7 @@ BEGIN -- . there are c_sdp_S_pn = 12 signal inputs A, B, C, D, E, F, G, H, I, J, K, L -- . there are c_sdp_N_sub = 512 subbands per signal input (SI, = signal path, SP) -- . one complex WPFB can process two real inputs A, B, so there are c_sdp_P_pfb = 6 WPFB units, - -- but only read for the 1 WPFB unit of the selected g_sp, to speed up simulation + -- but only read for the 1 WPFB unit of the selected g_sp, to save sim time -- . the outputs for A, B are time multiplexed, c_sdp_Q_fft = 2, assume that they -- correspond to the c_sdp_N_pol = 2 signal polarizations -- . the subbands are output alternately so A0 B0 A1 B1 ... A511 B511 for input A, B @@ -390,18 +397,18 @@ BEGIN -- . the subband statistics are stored first lo word 0 then hi word 1 v_len := c_sdp_N_sub * c_sdp_N_pol * c_stat_data_sz; -- 2048 = 512 * 2 * 64/32 v_span := true_log_pow2(v_len); -- = 2048 - FOR I IN 0 TO v_len - 1 LOOP + FOR I IN 0 TO v_len-1 LOOP v_W := I MOD c_stat_data_sz; -- 0, 1 per statistics word, word index v_P := (I / c_stat_data_sz) MOD c_sdp_N_pol; -- 0, 1 per SP pol, polarization index v_B := I / (c_sdp_N_pol * c_stat_data_sz); -- subband index, range(N_sub = 512) per dual pol - v_A := I + c_pfb_index * v_span; -- MM address for WPFB unit of selected g_sp + v_addr := I + c_pfb_index * v_span; -- MM address for WPFB unit of selected g_sp IF v_W = 0 THEN -- low part - mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_A, rd_data, tb_clk); + mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_addr, rd_data, tb_clk); v_data_lo := rd_data; ELSE -- high part - mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_A, rd_data, tb_clk); + mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_addr, rd_data, tb_clk); v_data_hi := rd_data; v_stat_data := v_data_hi & v_data_lo; @@ -420,7 +427,7 @@ BEGIN proc_common_wait_some_cycles(tb_clk, 1); -- The sp_subband_power_leakage shows how much power from the input sinus at a specific - -- subband has leaked into the N_sub - 1 = 511 other subbands. The power ratio yields an + -- subband has leaked into the N_sub-1 = 511 other subbands. The power ratio yields an -- indication of the SNR, although that also depends on the SNR of the WG sinus. v_power := sp_subband_power_sum_arr(c_pol_index) - sp_subband_power; sp_subband_power_leakage <= v_power; @@ -444,36 +451,36 @@ BEGIN proc_common_wait_some_cycles(tb_clk, 1); --------------------------------------------------------------------------- - -- Print subband statistics + -- Log subband statistics --------------------------------------------------------------------------- - -- Selector - print_str("sst_offload_weighted_subbands = " & sl_to_str(sst_offload_weighted_subbands)); + -- Log selector + print_str("sst_offload_weighted_subbands = " & sl_to_str(sst_offload_weighted_subbands)); - -- Subband weight - print_str("sp_subband_weight_gain = " & real_to_str(sp_subband_weight_gain, 20, 6)); - print_str("sp_subband_weight_phase = " & real_to_str(sp_subband_weight_phase, 20, 6)); + -- Log subband weight + print_str("sp_subband_weight_gain = " & real_to_str(sp_subband_weight_gain, 20, 6)); + print_str("sp_subband_weight_phase = " & real_to_str(sp_subband_weight_phase, 20, 6)); - -- SST - print_str("sp_subband_power = " & real_to_str(sp_subband_power, 20, 0)); + -- Log SST + print_str("sp_subband_power = " & real_to_str(sp_subband_power, 20, 0)); + print_str("sp_subband_power / exp_subband_power = " & real_to_str(sp_subband_power / exp_subband_power, 20, 0)); - -- WPFB details are allready verified in tb of wpfb_unit_dev.vhd, so here - -- quality indicators like leakage and crosstalk are also reported out of - -- interest. - print_str("sp_subband_power_leakage = " & real_to_str(sp_subband_power_leakage, 20, 0)); - print_str("sp_subband_power_leakage_snr_dB = " & real_to_str(sp_subband_power_leakage_snr_dB, 20, 3)); - print_str("sp_subband_power_crosstalk = " & real_to_str(sp_subband_power_crosstalk, 20, 0)); - print_str("sp_subband_power_crosstalk_snr_db = " & real_to_str(sp_subband_power_crosstalk_snr_db, 20, 3)); + -- Log WPFB details, these are allready verified in tb of wpfb_unit_dev.vhd, so here + -- quality indicators like leakage and crosstalk are also reported out of interest. + print_str("sp_subband_power_leakage = " & real_to_str(sp_subband_power_leakage, 20, 0)); + print_str("sp_subband_power_leakage_snr_dB = " & real_to_str(sp_subband_power_leakage_snr_dB, 20, 3)); + print_str("sp_subband_power_crosstalk = " & real_to_str(sp_subband_power_crosstalk, 20, 0)); + print_str("sp_subband_power_crosstalk_snr_db = " & real_to_str(sp_subband_power_crosstalk_snr_db, 20, 3)); --------------------------------------------------------------------------- -- Verify subband statistics --------------------------------------------------------------------------- -- verify expected subband power based on WG power - ASSERT sp_subband_power > c_lo_factor * c_exp_subband_power REPORT "Wrong subband power for SP-" & NATURAL'IMAGE(g_sp) SEVERITY ERROR; - ASSERT sp_subband_power < c_hi_factor * c_exp_subband_power REPORT "Wrong subband power for SP-" & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + ASSERT sp_subband_power > c_lo_factor * exp_subband_power REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + ASSERT sp_subband_power < c_hi_factor * exp_subband_power REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; -- Verify expected SNR quality measures - ASSERT sp_subband_power_leakage_snr_dB > c_exp_subband_power_leakage_snr_dB REPORT "Wrong to much leakage for SP-" & NATURAL'IMAGE(g_sp) SEVERITY ERROR; - ASSERT sp_subband_power_crosstalk_snr_dB > c_exp_subband_power_crosstalk_snr_dB REPORT "Wrong to much crosstalk for SP-" & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + ASSERT sp_subband_power_leakage_snr_dB > c_exp_subband_power_leakage_snr_dB REPORT "Wrong to much leakage for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + ASSERT sp_subband_power_crosstalk_snr_dB > c_exp_subband_power_crosstalk_snr_dB REPORT "Wrong to much crosstalk for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; --------------------------------------------------------------------------- -- End Simulation