Skip to content
Snippets Groups Projects
Commit 4bdc79e2 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Use beamlet output value verification based on derived expected value. Improved logging.

parent 6eb369ae
No related branches found
No related tags found
1 merge request!198Clarified reading one WPFB unit into sp_subband_powers_arr2. Updated comments....
...@@ -20,39 +20,49 @@ ...@@ -20,39 +20,49 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- --
-- Author: R. van der Walle, E. Kooistra -- Author: R. van der Walle (original), E. Kooistra (updates)
-- Purpose: Self-checking testbench for simulating lofar2_unb2b_sdp_station_bf using WG data. -- Purpose: Self-checking testbench for simulating lofar2_unb2b_sdp_station_bf using WG data.
-- --
-- Description: -- Description:
-- MM control actions: -- MM control actions:
-- --
-- 1) Enable calc mode for WG via reg_diag_wg with: -- 1) Enable calc mode for WG on signal input g_sp via reg_diag_wg with:
-- freq = 19.921875MHz -- g_subband = 102 --> WG freq = 19.921875MHz
-- ampl = 0.5 * 2**13 -- g_ampl = 1.0 --> WG ampl = 2**13
-- --
-- 2) Read current BSN from reg_bsn_scheduler_wg and write reg_bsn_scheduler_wg -- 2) Read current BSN from reg_bsn_scheduler_wg and write reg_bsn_scheduler_wg
-- to trigger start of WG at BSN. -- to trigger start of WG at BSN.
-- --
-- 3) Read subband statistics (SST) -- 3) Read subband statistics (SST)
-- --
-- 4) Read beamlet statistics (BST) via ram_st_bst and verify with -- 4) Select subband g_subband for beamlet g_beamlet
-- c_exp_beamlet_power_sp_0 at c_sdp_N_sub-1 - c_subband_sp_0. --
-- View pol_beamlet_power_0 in Wave window -- 5) Apply BF weight (g_bf_gain, g_bf_phase) to g_beamlet X beam and Y beam
-- 5) Compare SST with BST. --
-- 6) Verify 10GbE output. -- 6) Read beamlet statistics (BST) via MM and verify with
-- View sp_subband_sst in Wave window
-- View pol_beamlet_bst in Wave window
--
-- 7) Compare SST with BST.
--
-- 8) Verify 10GbE output header and output payload for g_beamlet.
-- --
-- --
-- Usage: -- Usage:
-- > as 7 # default -- > as 7 # default
-- > as 12 # for detailed debugging -- > as 12 # for detailed debugging
-- > add wave -position insertpoint \
-- sim:/tb_lofar2_unb2b_sdp_station_bf/sp_subband_ssts_arr2 \
-- sim:/tb_lofar2_unb2b_sdp_station_bf/pol_beamlet_bsts_arr2
-- > run -a -- > run -a
-- Takes about 40 m -- Takes about 40 m when g_read_all_* = FALSE
-- Takes about 1h 5 m when g_read_all_* = TRUE
-- --
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, unb2b_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, lofar2_unb2b_sdp_station_lib; LIBRARY IEEE, common_lib, unb2b_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, lofar2_unb2b_sdp_station_lib;
USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL; USE IEEE.numeric_std.ALL;
USE IEEE.MATH_REAL.ALL; USE IEEE.math_real.ALL;
USE common_lib.common_pkg.ALL; USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL; USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_field_pkg.ALL; USE common_lib.common_field_pkg.ALL;
...@@ -70,6 +80,17 @@ USE lofar2_sdp_lib.tb_sdp_pkg.ALL; ...@@ -70,6 +80,17 @@ USE lofar2_sdp_lib.tb_sdp_pkg.ALL;
USE tech_pll_lib.tech_pll_component_pkg.ALL; USE tech_pll_lib.tech_pll_component_pkg.ALL;
ENTITY tb_lofar2_unb2b_sdp_station_bf IS ENTITY tb_lofar2_unb2b_sdp_station_bf IS
GENERIC (
g_sp : NATURAL := 0; -- WG signal path index in range(S_pn = 12)
g_wg_ampl : REAL := 1.0; -- WG normalized amplitude
g_subband : NATURAL := 102; -- select g_subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz
g_beamlet : NATURAL := 10; -- map g_subband to g_beamlet index in beamset in range(c_sdp_S_sub_bf = 488)
g_beamlet_scale : REAL := 1.0 / 2.0**9; -- g_beamlet output scale factor
g_bf_gain : REAL := 1.0; -- g_beamlet BF weight normalized gain
g_bf_phase : REAL := 30.0; -- g_beamlet BF weight phase rotation in degrees
g_read_all_SST : BOOLEAN := FALSE; -- when FALSE only read SST for g_subband, to save sim time
g_read_all_BST : BOOLEAN := FALSE -- when FALSE only read BST for g_beamlet, to save sim time
);
END tb_lofar2_unb2b_sdp_station_bf; END tb_lofar2_unb2b_sdp_station_bf;
ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS
...@@ -95,16 +116,19 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS ...@@ -95,16 +116,19 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS
CONSTANT c_sa_clk_period : TIME := tech_pll_clk_644_period; -- 644MHz CONSTANT c_sa_clk_period : TIME := tech_pll_clk_644_period; -- 644MHz
CONSTANT c_tb_clk_period : TIME := 100 ps; -- use fast tb_clk to speed up M&C CONSTANT c_tb_clk_period : TIME := 100 ps; -- use fast tb_clk to speed up M&C
CONSTANT c_cross_clock_domain_latency : NATURAL := 20;
CONSTANT c_nof_block_per_sync : NATURAL := 16; CONSTANT c_nof_block_per_sync : NATURAL := 16;
CONSTANT c_nof_clk_per_sync : NATURAL := c_nof_block_per_sync * c_sdp_N_fft; CONSTANT c_nof_clk_per_sync : NATURAL := c_nof_block_per_sync * c_sdp_N_fft;
CONSTANT c_pps_period : NATURAL := c_nof_clk_per_sync; CONSTANT c_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_wpfb_sim : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync);
CONSTANT c_stat_data_sz : NATURAL := c_longword_sz/c_word_sz; -- = 2 CONSTANT c_stat_data_sz : NATURAL := c_wpfb_sim.stat_data_sz; -- = 2
CONSTANT c_percentage : REAL := 0.05; -- percentage that actual value may differ from expected value CONSTANT c_stat_percentage : REAL := 0.05; -- +-percentage margin that actual value may differ from expected value
CONSTANT c_lo_factor : REAL := 1.0 - c_percentage; -- lower boundary CONSTANT c_stat_lo_factor : REAL := 1.0 - c_stat_percentage; -- lower boundary
CONSTANT c_hi_factor : REAL := 1.0 + c_percentage; -- higher boundary CONSTANT c_stat_hi_factor : REAL := 1.0 + c_stat_percentage; -- higher boundary
CONSTANT c_beamlet_output_delta : INTEGER := 2; -- +-delta margin
-- header fields -- header fields
CONSTANT c_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := c_sdp_cep_eth_dst_mac; -- 00074306C700 = DOP36-eth0 CONSTANT c_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := c_sdp_cep_eth_dst_mac; -- 00074306C700 = DOP36-eth0
...@@ -117,7 +141,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS ...@@ -117,7 +141,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS
CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDE#; -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDE#; -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window
CONSTANT c_exp_beamlet_scale : NATURAL := 2**15; CONSTANT c_exp_beamlet_scale : NATURAL := NATURAL(g_beamlet_scale * REAL(c_sdp_unit_beamlet_scale)); -- c_sdp_unit_beamlet_scale = 2**15;
CONSTANT c_exp_sdp_info : t_sdp_info := ( CONSTANT c_exp_sdp_info : t_sdp_info := (
TO_UVEC(601, 16), -- station_id TO_UVEC(601, 16), -- station_id
...@@ -139,38 +163,68 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS ...@@ -139,38 +163,68 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS
-- .ampl -- .ampl
CONSTANT c_wg_ampl_full_scale : NATURAL := 2**(c_sdp_W_adc-1); -- full scale (FS) of WG, will just cause clipping of +FS to +FS-1 CONSTANT c_wg_ampl_full_scale : NATURAL := 2**(c_sdp_W_adc-1); -- full scale (FS) of WG, will just cause clipping of +FS to +FS-1
CONSTANT c_wg_ampl_lsb : REAL := c_diag_wg_ampl_unit / REAL(c_wg_ampl_full_scale); -- amplitude in number of LSbit resolution steps CONSTANT c_wg_ampl_lsb : REAL := c_diag_wg_ampl_unit / REAL(c_wg_ampl_full_scale); -- amplitude in number of LSbit resolution steps
CONSTANT c_ampl_sp_0 : NATURAL := c_wg_ampl_full_scale / 2; -- in number of lsb CONSTANT c_wg_ampl : NATURAL := NATURAL(g_wg_ampl * REAL(c_wg_ampl_full_scale)); -- in number of lsb
CONSTANT c_exp_wg_power_sp_0 : REAL := REAL(c_ampl_sp_0**2)/2.0 * REAL(c_nof_clk_per_sync); CONSTANT c_exp_sp_power : REAL := REAL(c_wg_ampl**2) / 2.0;
CONSTANT c_exp_sp_ast : REAL := c_exp_sp_power * REAL(c_nof_clk_per_sync);
-- . phase -- . phase
CONSTANT c_phase_sp_0 : REAL := 0.0; -- phase offset in degrees CONSTANT c_subband_phase : REAL := 0.0; -- wanted subband phase in degrees = WG phase at sop
CONSTANT c_subband_freq : REAL := REAL(g_subband) / REAL(c_sdp_N_fft); -- normalized by fs = f_adc = 200 MHz = dp_clk rate
CONSTANT c_wg_latency : INTEGER := c_diag_wg_latency - 0; -- -0 to account for BSN scheduler start trigger latency
CONSTANT c_wg_phase_offset : REAL := 360.0 * REAL(c_wg_latency) * c_subband_freq; -- c_diag_wg_latency is in dp_clk cycles
CONSTANT c_wg_phase : REAL := c_subband_phase + c_wg_phase_offset; -- WG phase in degrees
-- . freq -- . freq
CONSTANT c_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_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_subband_sp_0 : NATURAL := 102; -- Select subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz
-- WPFB -- WPFB
CONSTANT c_wb_leakage_bin : NATURAL := c_wpfb_sim.nof_points / c_wpfb_sim.wb_factor; -- = 256, leakage will occur in this bin if FIR wb_factor is reversed CONSTANT c_pol_index : NATURAL := g_sp MOD c_sdp_Q_fft;
CONSTANT c_exp_pol_beamlet_power_ratio : REAL := 1.0/8.0; -- depends on internal WPFB quantization and FIR coefficients 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_pol_beamlet_power_sum_ratio : REAL := c_exp_pol_beamlet_power_ratio; -- because all sinus power is expected in one subband CONSTANT c_subband_phase_offset : REAL := -90.0; -- WG with zero phase sinues yields subband with -90 degrees phase (negative Im, zero Re)
CONSTANT c_exp_beamlet_power_sp_0 : REAL := c_exp_wg_power_sp_0 * c_exp_pol_beamlet_power_ratio; CONSTANT c_subband_weight_gain : REAL := 1.0; -- use default unit subband weights
CONSTANT c_subband_weight_phase : REAL := 0.0; -- use default unit subband weights
CONSTANT c_exp_subband_sp_ampl_ratio : REAL := 7.96; -- ~= 8 for unit FIR DC gain, depends on internal WPFB quantization and FIR coefficients
CONSTANT c_exp_subband_ampl : REAL := REAL(c_wg_ampl) * c_exp_subband_sp_ampl_ratio * c_subband_weight_gain;
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);
TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL; 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); TYPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub-1); -- 512
TYPE t_slv_64_beamlets_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_S_sub_bf); TYPE t_slv_64_beamlets_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_beamlets_sdp-1); -- 2*488 = 976
-- BF -- BF
CONSTANT c_exp_beamlet_index : NATURAL := c_subband_sp_0 * c_sdp_N_pol_bf; -- . select
CONSTANT c_exp_beamlet_re : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"81"; -- = -127, derived from simulation CONSTANT c_exp_beamlet_index : NATURAL := g_beamlet * c_sdp_N_pol_bf; -- in beamset 0
CONSTANT c_exp_beamlet_im : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"7F"; -- = +127, derived from simulation -- . Beamlet weights for selected g_sp
CONSTANT c_bf_weight_re : INTEGER := INTEGER(g_bf_gain * REAL(c_sdp_unit_bf_weight) * COS(g_bf_phase * MATH_2_PI / 360.0));
CONSTANT c_bf_weight_im : INTEGER := INTEGER(g_bf_gain * REAL(c_sdp_unit_bf_weight) * SIN(g_bf_phase * MATH_2_PI / 360.0));
-- . Beamlet internal
CONSTANT c_exp_beamlet_ampl : REAL := c_exp_subband_ampl * g_bf_gain;
CONSTANT c_exp_beamlet_phase : REAL := c_subband_phase_offset + c_subband_weight_phase + g_bf_phase;
CONSTANT c_exp_beamlet_re : REAL := c_exp_beamlet_ampl * COS(c_exp_beamlet_phase * MATH_2_PI / 360.0);
CONSTANT c_exp_beamlet_im : REAL := c_exp_beamlet_ampl * SIN(c_exp_beamlet_phase * MATH_2_PI / 360.0);
-- . BST
CONSTANT c_exp_beamlet_power : REAL := c_exp_beamlet_ampl**2.0; -- complex, so no divide by 2
CONSTANT c_exp_beamlet_bst : REAL := c_exp_subband_sst * g_bf_gain**2.0; -- = c_exp_beamlet_power * REAL(c_nof_block_per_sync)
-- . Beamlet output
CONSTANT c_exp_beamlet_output_ampl : REAL := c_exp_beamlet_ampl * g_beamlet_scale;
CONSTANT c_exp_beamlet_output_phase : REAL := c_exp_beamlet_phase;
CONSTANT c_exp_beamlet_output_re : REAL := c_exp_beamlet_re * g_beamlet_scale;
CONSTANT c_exp_beamlet_output_im : REAL := c_exp_beamlet_im * g_beamlet_scale;
-- MM -- MM
-- . Address widths of a single MM instance -- . Address widths of a single MM instance
-- . c_sdp_S_pn = 12 instances
CONSTANT c_addr_w_reg_diag_wg : NATURAL := 2;
-- . c_sdp_N_beamsets = 2 instances
CONSTANT c_addr_w_ram_ss_ss_wide : NATURAL := ceil_log2( c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); CONSTANT c_addr_w_ram_ss_ss_wide : NATURAL := ceil_log2( c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft);
CONSTANT c_addr_w_ram_bf_weights : NATURAL := ceil_log2(c_sdp_N_pol * c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); CONSTANT c_addr_w_ram_bf_weights : NATURAL := ceil_log2(c_sdp_N_pol_bf * c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft);
CONSTANT c_addr_w_reg_bf_scale : NATURAL := 1; CONSTANT c_addr_w_reg_bf_scale : NATURAL := 1;
CONSTANT c_addr_w_reg_hdr_dat : NATURAL := ceil_log2(field_nof_words(c_sdp_cep_hdr_field_arr, c_word_w)); CONSTANT c_addr_w_reg_hdr_dat : NATURAL := ceil_log2(field_nof_words(c_sdp_cep_hdr_field_arr, c_word_w));
CONSTANT c_addr_w_reg_dp_xonoff : NATURAL := 1; CONSTANT c_addr_w_reg_dp_xonoff : NATURAL := 1;
CONSTANT c_addr_w_ram_st_bst : NATURAL := ceil_log2(c_sdp_S_sub_bf*c_sdp_N_pol*(c_longword_sz/c_word_sz)); CONSTANT c_addr_w_ram_st_bst : NATURAL := ceil_log2(c_sdp_S_sub_bf*c_sdp_N_pol_bf*c_stat_data_sz);
-- . Address spans of a single MM instance -- . Address spans of a single MM instance
-- . c_sdp_S_pn = 12 instances
CONSTANT c_mm_span_reg_diag_wg : NATURAL := 2**c_addr_w_reg_diag_wg;
-- . c_sdp_N_beamsets = 2 instances
CONSTANT c_mm_span_ram_ss_ss_wide : NATURAL := 2**c_addr_w_ram_ss_ss_wide; CONSTANT c_mm_span_ram_ss_ss_wide : NATURAL := 2**c_addr_w_ram_ss_ss_wide;
CONSTANT c_mm_span_ram_bf_weights : NATURAL := 2**c_addr_w_ram_bf_weights; CONSTANT c_mm_span_ram_bf_weights : NATURAL := 2**c_addr_w_ram_bf_weights;
CONSTANT c_mm_span_reg_bf_scale : NATURAL := 2**c_addr_w_reg_bf_scale; CONSTANT c_mm_span_reg_bf_scale : NATURAL := 2**c_addr_w_reg_bf_scale;
...@@ -182,11 +236,15 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS ...@@ -182,11 +236,15 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS
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_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_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_diag_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG";
CONSTANT c_mm_file_ram_equalizer_gains : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_EQUALIZER_GAINS";
CONSTANT c_mm_file_reg_dp_selector : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_SELECTOR";
CONSTANT c_mm_file_ram_st_sst : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_SST";
CONSTANT c_mm_file_ram_st_bst : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_BST"; CONSTANT c_mm_file_ram_st_bst : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_BST";
CONSTANT c_mm_file_reg_dp_xonoff : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_XONOFF"; CONSTANT c_mm_file_reg_dp_xonoff : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_XONOFF";
CONSTANT c_mm_file_ram_st_sst : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_SST"; CONSTANT c_mm_file_ram_ss_ss_wide : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_SS_SS_WIDE";
CONSTANT c_mm_file_reg_sdp_info : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_SDP_INFO"; CONSTANT c_mm_file_ram_bf_weights : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_BF_WEIGHTS";
CONSTANT c_mm_file_reg_bf_scale : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BF_SCALE"; CONSTANT c_mm_file_reg_bf_scale : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BF_SCALE";
CONSTANT c_mm_file_reg_sdp_info : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_SDP_INFO";
CONSTANT c_mm_file_reg_hdr_dat : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_HDR_DAT"; -- c_sdp_N_beamsets = 2 beamsets CONSTANT c_mm_file_reg_hdr_dat : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_HDR_DAT"; -- c_sdp_N_beamsets = 2 beamsets
-- Tb -- Tb
...@@ -214,20 +272,32 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS ...@@ -214,20 +272,32 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_sdp_station_bf IS
-- WG -- WG
SIGNAL current_bsn_wg : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); SIGNAL current_bsn_wg : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
-- WPFB -- FSUB
-- . Read sp_subband_powers_arr2 = SST for both sp 0 and 1, because these -- . Read sp_subband_ssts_arr2 = SST for one WPFB unit that processes g_sp
-- are processed by the same PFB, to see the quantization crosstalk of SIGNAL sp_subband_ssts_arr2 : t_slv_64_subbands_arr(c_sdp_N_pol-1 DOWNTO 0); -- [pol][sub], for X,Y pair of A, B
-- the separate function in the PFB. No need to also read the SST for SIGNAL sp_subband_sst : REAL := 0.0;
-- sp 2 : 11. SIGNAL stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
SIGNAL sp_subband_powers_arr2 : t_slv_64_subbands_arr(c_sdp_N_pol-1 DOWNTO 0); -- [pol][sub], for X,Y pair of sp0, sp1
-- . Selector
SIGNAL pol_beamlet_powers_arr2 : t_slv_64_beamlets_arr(c_sdp_N_beamsets*c_sdp_N_pol_bf-1 DOWNTO 0); -- [bset*pol][blet] SIGNAL sst_offload_weighted_subbands : STD_LOGIC;
SIGNAL pol_beamlet_power_0 : REAL;
SIGNAL pol_beamlet_power_sum : t_real_arr(c_sdp_N_beamsets*c_sdp_N_pol_bf-1 DOWNTO 0) := (OTHERS=>0.0); -- . Subband equalizer
SIGNAL pol_beamlet_power_sum_0 : REAL; SIGNAL sp_subband_weight_re : INTEGER := 0;
SIGNAL pol_beamlet_power_ratio_0 : REAL; SIGNAL sp_subband_weight_im : INTEGER := 0;
SIGNAL pol_beamlet_power_sum_ratio_0 : REAL; SIGNAL sp_subband_weight_gain : REAL := 0.0;
SIGNAL pol_beamlet_power_leakage_sum_0 : REAL; SIGNAL sp_subband_weight_phase : REAL := 0.0;
-- BF
SIGNAL sp_subband_select : NATURAL := 0;
SIGNAL sp_subband_select_arr : t_natural_arr(0 TO c_sdp_S_sub_bf * c_sdp_N_pol-1) := (OTHERS => 0); -- Q_fft = N_pol = 2
SIGNAL sp_bf_weights_re_arr : t_integer_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0);
SIGNAL sp_bf_weights_im_arr : t_integer_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0);
SIGNAL sp_bf_weights_gain_arr : t_real_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0.0);
SIGNAL sp_bf_weights_phase_arr : t_real_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0.0);
SIGNAL pol_beamlet_bsts_arr2 : t_slv_64_beamlets_arr(c_sdp_N_pol_bf-1 DOWNTO 0); -- [pol_bf][blet]
SIGNAL pol_beamlet_bst_X_arr : t_real_arr(0 TO c_sdp_N_beamsets-1) := (OTHERS => 0.0); -- [bset]
SIGNAL pol_beamlet_bst_Y_arr : t_real_arr(0 TO c_sdp_N_beamsets-1) := (OTHERS => 0.0); -- [bset]
-- 10GbE -- 10GbE
SIGNAL rx_beamlet_arr_re : t_slv_8_arr(c_sdp_cep_nof_blocks_per_packet-1 DOWNTO 0); -- [3:0] SIGNAL rx_beamlet_arr_re : t_slv_8_arr(c_sdp_cep_nof_blocks_per_packet-1 DOWNTO 0); -- [3:0]
...@@ -326,7 +396,7 @@ BEGIN ...@@ -326,7 +396,7 @@ BEGIN
g_sim_node_nr => c_node_nr, g_sim_node_nr => c_node_nr,
g_wpfb => c_wpfb_sim, g_wpfb => c_wpfb_sim,
g_bsn_nof_clk_per_sync => c_nof_clk_per_sync, g_bsn_nof_clk_per_sync => c_nof_clk_per_sync,
g_scope_selected_subband => c_subband_sp_0 g_scope_selected_subband => g_subband
) )
PORT MAP ( PORT MAP (
-- GENERAL -- GENERAL
...@@ -446,15 +516,14 @@ BEGIN ...@@ -446,15 +516,14 @@ BEGIN
p_mm_stimuli : PROCESS p_mm_stimuli : PROCESS
VARIABLE v_bsn : NATURAL; VARIABLE v_bsn : NATURAL;
VARIABLE v_sp_subband_power : REAL; VARIABLE v_sp_subband_sst : REAL := 0.0;
VARIABLE v_pol_beamlet_power : REAL; VARIABLE v_pol_beamlet_bst : REAL := 0.0;
VARIABLE v_data_lo, v_data_hi : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); 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_stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
VARIABLE v_len, v_span, v_A : NATURAL; -- address ranges, indices VARIABLE v_len, v_span, v_offset, v_addr, v_sel : NATURAL; -- address ranges, indices
VARIABLE v_W, v_P, v_U, v_S, v_B : NATURAL; -- array indicies VARIABLE v_W, v_P, v_S, v_A, v_B, v_G : NATURAL; -- array indicies
VARIABLE v_re, v_im : INTEGER; VARIABLE v_re, v_im, v_weight : INTEGER;
VARIABLE v_re_exp, v_im_exp : INTEGER; VARIABLE v_re_exp, v_im_exp : REAL := 0.0;
VARIABLE v_offset : NATURAL;
BEGIN BEGIN
-- Wait for DUT power up after reset -- Wait for DUT power up after reset
WAIT FOR 1 us; WAIT FOR 1 us;
...@@ -502,8 +571,15 @@ BEGIN ...@@ -502,8 +571,15 @@ BEGIN
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
FOR bset IN 0 TO c_sdp_N_beamsets-1 LOOP FOR bset IN 0 TO c_sdp_N_beamsets-1 LOOP
-- MM beamlet_scale -- MM beamlet_scale
-- . write
v_offset := bset * c_mm_span_reg_bf_scale; v_offset := bset * c_mm_span_reg_bf_scale;
mmf_mm_bus_rd(c_mm_file_reg_bf_scale, v_offset + 0, rd_data, tb_clk); rd_beamlet_scale <= rd_data(15 DOWNTO 0); mmf_mm_bus_wr(c_mm_file_reg_bf_scale, v_offset + 0, c_exp_beamlet_scale, tb_clk);
proc_common_wait_some_cycles(tb_clk, c_cross_clock_domain_latency);
proc_common_wait_some_cycles(ext_clk, c_cross_clock_domain_latency);
-- . readback
mmf_mm_bus_rd(c_mm_file_reg_bf_scale, v_offset + 0, rd_data, tb_clk);
rd_beamlet_scale <= rd_data(15 DOWNTO 0);
proc_common_wait_some_cycles(tb_clk, 1); proc_common_wait_some_cycles(tb_clk, 1);
ASSERT TO_UINT(rd_beamlet_scale) = c_exp_beamlet_scale REPORT "Wrong MM read beamlet_scale for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR; ASSERT TO_UINT(rd_beamlet_scale) = c_exp_beamlet_scale REPORT "Wrong MM read beamlet_scale for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR;
...@@ -588,17 +664,19 @@ BEGIN ...@@ -588,17 +664,19 @@ BEGIN
pps_rst <= '0'; pps_rst <= '0';
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Enable WG -- Enable and start WG
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- 0 : mode[7:0] --> off=0, calc=1, repeat=2, single=3) -- 0 : mode[7:0] --> off=0, calc=1, repeat=2, single=3)
-- nof_samples[31:16] --> <= c_ram_wg_size=1024 -- nof_samples[31:16] --> <= c_ram_wg_size=1024
-- 1 : phase[15:0] -- 1 : phase[15:0]
-- 2 : freq[30:0] -- 2 : freq[30:0]
-- 3 : ampl[16:0] -- 3 : ampl[16:0]
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc -- . Put wanted signal on g_sp input
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 1, INTEGER(c_phase_sp_0 * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees v_offset := g_sp * c_mm_span_reg_diag_wg;
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 2, INTEGER(REAL(c_subband_sp_0) * c_wg_subband_freq_unit), tb_clk); -- freq mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 3, INTEGER(REAL(c_ampl_sp_0) * c_wg_ampl_lsb), tb_clk); -- ampl mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_wg_phase * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 2, INTEGER(REAL(g_subband) * c_wg_subband_freq_unit), tb_clk); -- freq
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, INTEGER(REAL(c_wg_ampl) * c_wg_ampl_lsb), tb_clk); -- ampl
-- Read current BSN -- 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, 0, current_bsn_wg(31 DOWNTO 0), tb_clk);
...@@ -612,7 +690,117 @@ BEGIN ...@@ -612,7 +690,117 @@ BEGIN
mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 0, v_bsn, tb_clk); -- first write low then high part mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 0, v_bsn, 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 mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 1, 0, tb_clk); -- assume v_bsn < 2**31-1
----------------------------------------------------------------------------
-- 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);
----------------------------------------------------------------------------
-- Subband weight
----------------------------------------------------------------------------
-- . 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_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 <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI;
-- No need to write subband weight, because default it is unit weight
----------------------------------------------------------------------------
-- Subband select to map subband to beamlet
----------------------------------------------------------------------------
-- . MM format: (uint16)RAM_SS_SS_WIDE[N_beamsets][A_pn]_[S_sub_bf][Q_fft], Q_fft = N_pol = 2
-- . write selection, only for g_beamlet to save sim time
v_span := true_log_pow2(c_sdp_N_pol * c_sdp_S_sub_bf); -- = 1024
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
-- Same selection for both beamsets
-- Select beamlet g_beamlet to subband g_subband
FOR A IN 0 TO c_sdp_A_pn-1 LOOP
-- Same selection to all SP
FOR P IN 0 TO c_sdp_N_pol-1 LOOP
v_addr := P + g_beamlet * c_sdp_N_pol + A * v_span + U * c_mm_span_ram_ss_ss_wide;
v_sel := P + g_subband * c_sdp_N_pol;
mmf_mm_bus_wr(c_mm_file_ram_ss_ss_wide, v_addr, v_sel, tb_clk);
END LOOP;
END LOOP;
END LOOP;
-- . read back selection for g_sp = c_pfb_index * c_sdp_N_pol + c_pol_index
v_P := c_pol_index;
v_A := c_pfb_index;
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
-- Same selection for both beamsets, so fine to use only one sp_subband_select_arr()
FOR B IN 0 TO c_sdp_S_sub_bf-1 LOOP
-- Same selection for all SP, so fine to only read subband selection for g_sp
v_addr := v_P + B * c_sdp_N_pol + v_A * v_span + U * c_mm_span_ram_ss_ss_wide;
mmf_mm_bus_rd(c_mm_file_ram_ss_ss_wide, v_addr, rd_data, tb_clk);
v_sel := (TO_UINT(rd_data) - v_P) / c_sdp_N_pol;
sp_subband_select_arr(B) <= v_sel;
sp_subband_select <= v_sel; -- for time series view in Wave window
END LOOP;
END LOOP;
proc_common_wait_some_cycles(tb_clk, 1);
proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window
----------------------------------------------------------------------------
-- Write beamlet weight for g_beamlet
----------------------------------------------------------------------------
-- . MM format: (cint16)RAM_BF_WEIGHTS[N_beamsets][N_pol_bf][A_pn]_[N_pol][S_sub_bf]
-- . write BF weights, only for g_beamlet to save sim time
v_span := true_log_pow2(c_sdp_N_pol * c_sdp_S_sub_bf); -- = 1024
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
-- Same BF weights for both beamsets
FOR A IN 0 TO c_sdp_A_pn-1 LOOP
FOR P IN 0 TO c_sdp_N_pol-1 LOOP
v_S := A * c_sdp_N_pol + P;
IF v_S = g_sp THEN
-- use generic BF weight for g_sp in g_beamlet
v_weight := pack_complex(re => c_bf_weight_re, im => c_bf_weight_im, w => c_sdp_W_bf_weight);
ELSE
-- default set all weights to zero
v_weight := 0;
END IF;
v_addr := g_beamlet + A * v_span + U * c_mm_span_ram_bf_weights;
v_addr := v_addr + P * c_sdp_S_sub_bf;
mmf_mm_bus_wr(c_mm_file_ram_bf_weights, v_addr, v_weight, tb_clk);
END LOOP;
END LOOP;
END LOOP;
-- . read back BF weights for g_beamlet
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
FOR A IN 0 TO c_sdp_A_pn-1 LOOP
FOR P IN 0 TO c_sdp_N_pol-1 LOOP
v_addr := g_beamlet + A * v_span + U * c_mm_span_ram_bf_weights;
v_addr := v_addr + P * c_sdp_S_sub_bf;
mmf_mm_bus_rd(c_mm_file_ram_bf_weights, v_addr, rd_data, tb_clk);
v_re := unpack_complex_re(rd_data, c_sdp_W_bf_weight);
v_im := unpack_complex_im(rd_data, c_sdp_W_bf_weight);
-- same BF weights for both beamsets, so fine to use only one sp_bf_weights_*_arr()
v_S := A * c_sdp_N_pol + P;
sp_bf_weights_re_arr(v_S) <= v_re;
sp_bf_weights_im_arr(v_S) <= v_im;
sp_bf_weights_gain_arr(v_S) <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_bf_weight);
sp_bf_weights_phase_arr(v_S) <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI;
END LOOP;
END LOOP;
END LOOP;
proc_common_wait_some_cycles(tb_clk, 1);
proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window
----------------------------------------------------------------------------
-- Wait for enough WG data and start of sync interval -- Wait for enough WG data and start of sync interval
----------------------------------------------------------------------------
mmf_mm_wait_until_value(c_mm_file_reg_bsn_scheduler_wg, 0, -- read BSN low mmf_mm_wait_until_value(c_mm_file_reg_bsn_scheduler_wg, 0, -- read BSN low
"UNSIGNED", rd_data, ">=", c_init_bsn + c_nof_block_per_sync*3, -- this is the wait until condition "UNSIGNED", rd_data, ">=", c_init_bsn + c_nof_block_per_sync*3, -- this is the wait until condition
c_sdp_T_sub, tb_clk); c_sdp_T_sub, tb_clk);
...@@ -623,134 +811,186 @@ BEGIN ...@@ -623,134 +811,186 @@ BEGIN
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- Read subband statistics -- Read subband statistics
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- . the subband statistics are c_wpfb_sim.stat_data_sz = 2 word power values. -- . the subband statistics are c_stat_data_sz = 2 word power values.
-- . there are c_sdp_N_sub = 512 subbands per signal path -- . there are c_sdp_S_pn = 12 signal inputs A, B, C, D, E, F, G, H, I, J, K, L
-- . one complex WPFB can process two real inputs A, B, is c_sdp_Q_fft = c_sdp_N_pol = 2 -- . 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 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 -- . the subbands are output alternately so A0 B0 A1 B1 ... A511 B511 for input A, B
-- . the subband statistics for multiple WPFB units appear in order in the ram_st_sst address map -- . the subband statistics multiple WPFB units appear in order in the ram_st_sst address map
-- . the subband statistics are stored first lo word 0 then hi word 1 -- . 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_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_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, poilarization index v_P := (I / c_stat_data_sz) MOD c_sdp_N_pol; -- 0, 1 per SP pol, polarization index
v_U := I / v_len; -- / 2048, pfb unit index, range(P_pfb = 6) v_B := I / (c_sdp_N_pol * c_stat_data_sz); -- subband index, range(N_sub = 512) per dual pol
v_S := v_P + v_U * c_sdp_N_pol; -- signal input index, range(S_pn = 12) v_addr := I + c_pfb_index * v_span; -- MM address
v_B := (I / (c_sdp_N_pol * c_stat_data_sz)) MOD c_sdp_N_sub; -- subband index, range(N_sub = 512) per dual pol -- Only read SST for g_subband for dual pol SP, to save sim time
v_A := I; -- MM address (v_len = v_span) IF g_read_all_SST = TRUE OR v_B = g_subband THEN
-- Only read sp 0 and sp 1 (v_S = 0, v_S = 1) to see digital crosstalk between two real inputs of PFB
IF v_U = 0 THEN -- v_U = 0 is equivalent to signal input index v_S = 0 OR v_S = 1
IF v_W = 0 THEN IF v_W = 0 THEN
-- low part -- 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; v_data_lo := rd_data;
ELSE ELSE
-- high part -- 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_data_hi := rd_data;
v_stat_data := v_data_hi & v_data_lo; v_stat_data := v_data_hi & v_data_lo;
sp_subband_powers_arr2(v_S)(v_B) <= v_stat_data; sp_subband_ssts_arr2(v_P)(v_B) <= v_stat_data;
stat_data <= v_stat_data; -- for time series view in Wave window
END IF; END IF;
END IF; END IF;
END LOOP; END LOOP;
proc_common_wait_some_cycles(tb_clk, 1);
-- Subband power of g_subband in g_sp
-- . For the selected g_subband in g_sp the sp_subband_sst will be close
-- to sp_subband_sst_sum_arr(c_pol_index), because the input is a
-- sinus, so most power will be in 1 subband.
sp_subband_sst <= TO_UREAL(sp_subband_ssts_arr2(c_pol_index)(g_subband));
proc_common_wait_some_cycles(tb_clk, 1);
proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- Read beamlet statistics -- Read beamlet statistics
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- . the beamlet statistics are c_stat_data_sz = 2 word power values. -- . the beamlet statistics are c_stat_data_sz = 2 word power values.
-- . there are c_sdp_S_sub_bf = 488 dual pol beamlets -- . there are c_sdp_S_sub_bf = 488 dual pol beamlets per beamset
-- . the beamlets are output alternately so A0 B0 A1 B1 ... A487 B487 for input A, B -- . the beamlets are output alternately so X0 Y0 X1 Y1 ... X487 Y487 for polarizations X, Y
-- . the beamlet statistics for multiple beamsets appear in order in the ram_st_bst address map -- . the beamlet statistics for multiple beamsets appear in order in the ram_st_bst address map
-- . the beamlet statistics are stored first lo word 0 then hi word 1 -- . the beamlet statistics are stored first lo word 0 then hi word 1
v_len := c_sdp_S_sub_bf * c_sdp_N_pol_bf * c_stat_data_sz; -- = 1952 = 488 * 2 * 64/32 v_len := c_sdp_S_sub_bf * c_sdp_N_pol_bf * c_stat_data_sz; -- = 1952 = 488 * 2 * 64/32
v_span := true_log_pow2(v_len); -- = 2048 v_span := true_log_pow2(v_len); -- = 2048
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
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_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_bf; -- 0, 1 per BF pol, poilarization index v_P := (I / c_stat_data_sz) MOD c_sdp_N_pol_bf; -- 0, 1 per BF pol, polarization index
v_U := I / v_len; -- / 1952, beamset unit index, range(N_beamsets = 2) v_B := I / (c_sdp_N_pol_bf * c_stat_data_sz); -- beamlet index in beamset, range(S_sub_bf = 488) per dual pol
v_S := v_P + v_U * c_sdp_N_pol_bf; -- beamset * pol index, range(N_beamsets * N_pol_bf = 4) v_G := v_B + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp)
v_B := (I / (c_sdp_N_pol_bf * c_stat_data_sz)) MOD c_sdp_S_sub_bf; -- beamlet index, range(S_sub_bf = 488) per dual pol v_addr := I + U * v_span; -- MM address
v_A := I MOD v_len + v_U * v_span; -- MM address --Only read BST for g_beamlet and dual pol_bf 0 and 1 and for both beamsets, to save sim time
-- Only read beamset 0, pol 0 and 1 (v_U = 0) IF g_read_all_BST = TRUE OR v_B = g_beamlet THEN
IF v_U = 0 THEN -- v_U = 0 is equivalent to beamset * pol index v_S = 0 OR v_S = 1
IF v_W = 0 THEN IF v_W = 0 THEN
-- low part -- low part
mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_A, rd_data, tb_clk); mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_addr, rd_data, tb_clk);
v_data_lo := rd_data; v_data_lo := rd_data;
ELSE ELSE
-- high part -- high part
mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_A, rd_data, tb_clk); mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_addr, rd_data, tb_clk);
v_data_hi := rd_data; v_data_hi := rd_data;
v_stat_data := v_data_hi & v_data_lo; v_stat_data := v_data_hi & v_data_lo;
pol_beamlet_powers_arr2(v_S)(v_B) <= v_stat_data; pol_beamlet_bsts_arr2(v_P)(v_G) <= v_stat_data;
stat_data <= v_stat_data; -- for time series view in Wave window
-- sum
v_pol_beamlet_power := TO_UREAL(v_stat_data);
pol_beamlet_power_sum(v_S) <= pol_beamlet_power_sum(v_S) + v_pol_beamlet_power;
END IF; END IF;
END IF; END IF;
END LOOP; END LOOP;
END LOOP;
proc_common_wait_some_cycles(tb_clk, 1);
-- pol_beamlet_power_sum is the sum of all subband powers per SP, this value will be close to pol_beamlet_power -- Beamlet power of g_beamlet X and Y, same for both beamsets
-- because the input is a sinus, so most power will be in 1 subband. The pol_beamlet_power_leakage_sum shows FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
-- how much power from the input sinus at a specific subband has leaked into the 511 other subbands. v_G := g_beamlet + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp)
pol_beamlet_power_0 <= TO_UREAL(pol_beamlet_powers_arr2(0)(c_subband_sp_0)); pol_beamlet_bst_X_arr(U) <= TO_UREAL(pol_beamlet_bsts_arr2(0)(v_G)); -- X pol beamlet
pol_beamlet_bst_Y_arr(U) <= TO_UREAL(pol_beamlet_bsts_arr2(1)(v_G)); -- Y pol beamlet
pol_beamlet_power_sum_0 <= pol_beamlet_power_sum(0); END LOOP;
proc_common_wait_some_cycles(tb_clk, 1); proc_common_wait_some_cycles(tb_clk, 1);
proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- Verify subband statistics -- Log WG, subband and beamlet statistics
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
FOR I IN 0 TO c_sdp_N_pol*c_sdp_S_sub_bf-1 LOOP
v_P := I MOD c_sdp_N_pol; print_str("");
v_U := I / (c_sdp_N_pol*c_sdp_S_sub_bf); print_str("WG:");
v_S := v_P + v_U * c_sdp_N_pol; print_str(". c_wg_ampl = " & int_to_str(c_wg_ampl));
v_B := (I / c_sdp_N_pol) MOD c_sdp_S_sub_bf; print_str(". c_exp_sp_power = " & real_to_str(c_exp_sp_power, 20, 1));
IF v_S = 0 THEN print_str(". c_exp_sp_ast = " & real_to_str(c_exp_sp_ast, 20, 1));
-- Convert STD_LOGIC_VECTOR to REAL
v_pol_beamlet_power := TO_UREAL(pol_beamlet_powers_arr2(v_S)(v_B)); print_str("");
print_str("Subband selector:");
-- Convert STD_LOGIC_VECTOR to REAL print_str(". sst_offload_weighted_subbands = " & sl_to_str(sst_offload_weighted_subbands));
v_sp_subband_power := TO_UREAL(sp_subband_powers_arr2(v_S)(v_B));
print_str("");
-- verify if subband power and beamlet power are the same. This is expected because we only use 1 WG input and the BF weights have unit value. print_str("Subband weight:");
-- the difference should not be larger than 0.5% (+/- 2^13 for low values) print_str(". sp_subband_weight_gain = " & real_to_str(sp_subband_weight_gain, 20, 6));
ASSERT v_pol_beamlet_power > 0.995 * v_sp_subband_power -2.0**13 REPORT "index ("& integer'image(v_S) &","& integer'image(v_B) &"): Subband power = "& real'image(v_sp_subband_power) &" and Beamlet power = "& real'image(v_pol_beamlet_power) &" are not equal" SEVERITY ERROR; print_str(". sp_subband_weight_phase = " & real_to_str(sp_subband_weight_phase, 20, 6));
ASSERT v_pol_beamlet_power < 1.005 * v_sp_subband_power +2.0**13 REPORT "index ("& integer'image(v_S) &","& integer'image(v_B) &"): Subband power = "& real'image(v_sp_subband_power) &" and Beamlet power = "& real'image(v_pol_beamlet_power) &" are not equal" SEVERITY ERROR;
END IF; print_str("");
print_str("SST results:");
print_str(". c_exp_subband_ampl = " & int_to_str(NATURAL(c_exp_subband_ampl)));
print_str(". c_exp_subband_power = " & real_to_str(c_exp_subband_power, 20, 1));
print_str(". c_exp_subband_sst = " & real_to_str(c_exp_subband_sst, 20, 1));
print_str("");
print_str(". sp_subband_sst = " & real_to_str(sp_subband_sst, 20, 1));
print_str(". sp_subband_sst / c_exp_subband_sst = " & real_to_str(sp_subband_sst / c_exp_subband_sst, 20, 6));
print_str("");
print_str("BST results:");
print_str(". c_exp_beamlet_ampl = " & int_to_str(NATURAL(c_exp_beamlet_ampl)));
print_str(". c_exp_beamlet_power = " & real_to_str(c_exp_beamlet_power, 20, 1));
print_str(". c_exp_beamlet_bst = " & real_to_str(c_exp_beamlet_bst, 20, 1));
print_str("");
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
v_G := g_beamlet + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp)
print_str(". pol_beamlet_bst_X beamlet(" & INTEGER'IMAGE(v_G) & ") = " & real_to_str(pol_beamlet_bst_X_arr(U), 20, 1));
print_str(". pol_beamlet_bst_Y beamlet(" & INTEGER'IMAGE(v_G) & ") = " & real_to_str(pol_beamlet_bst_Y_arr(U), 20, 1));
END LOOP;
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
v_G := g_beamlet + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp)
print_str(". pol_beamlet_bst_X beamlet(" & INTEGER'IMAGE(v_G) & ") / c_exp_beamlet_bst = " & real_to_str(pol_beamlet_bst_X_arr(U) / c_exp_beamlet_bst, 20, 6));
print_str(". pol_beamlet_bst_Y beamlet(" & INTEGER'IMAGE(v_G) & ") / c_exp_beamlet_bst = " & real_to_str(pol_beamlet_bst_Y_arr(U) / c_exp_beamlet_bst, 20, 6));
END LOOP; END LOOP;
-- verify expected subband power based on WG power print_str("");
IF pol_beamlet_power_sum_0>0.0 THEN ASSERT pol_beamlet_power_0 > c_lo_factor * c_exp_beamlet_power_sp_0 REPORT "Wrong beamlet power for SP 0" SEVERITY ERROR; END IF; print_str("Beamlet output:");
IF pol_beamlet_power_sum_0>0.0 THEN ASSERT pol_beamlet_power_0 < c_hi_factor * c_exp_beamlet_power_sp_0 REPORT "Wrong beamlet power for SP 0" SEVERITY ERROR; END IF; print_str(". rd_beamlet_scale = " & int_to_str(TO_UINT(rd_beamlet_scale)));
print_str(". c_exp_beamlet_output_ampl = " & int_to_str(NATURAL(c_exp_beamlet_output_ampl)));
-- view c_exp_pol_beamlet_power_ratio in Wave window ---------------------------------------------------------------------------
IF pol_beamlet_power_sum_0>0.0 THEN pol_beamlet_power_ratio_0 <= pol_beamlet_power_0/pol_beamlet_power_sum_0; END IF; -- Verify SST and BST
---------------------------------------------------------------------------
-- view c_exp_pol_beamlet_power_sum_ratio in Wave window -- verify expected subband power based on WG power
-- The pol_beamlet_power_sum_ratio show similar information as pol_beamlet_power_leakage_sum, because when ASSERT sp_subband_sst > c_stat_lo_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
-- pol_beamlet_power_leakage_sum is small then pol_beamlet_power_sum_ratio ~= pol_beamlet_power_ratio. ASSERT sp_subband_sst < c_stat_hi_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
IF pol_beamlet_power_sum_0>0.0 THEN pol_beamlet_power_sum_ratio_0 <= pol_beamlet_power_sum_0/pol_beamlet_power_0; END IF;
-- View pol_beamlet_power_leakage_sum in Wave window -- verify expected beamlet power based on WG power and BF weigths
IF pol_beamlet_power_sum_0>0.0 THEN pol_beamlet_power_leakage_sum_0 <= pol_beamlet_power_sum_0 - pol_beamlet_power_0; END IF; --
-- All co and cross polarization weights are equal: w = w_xx = w_xy = w_yx = w_yy
-- With one g_sp either SP X or SP Y is used, so the other antenna polarization is 0
-- Hence the c_exp_beamlet_bst will be the same for beamlet X and Y independent of whether g_sp is an X or Y signal input:
-- g_sp = X --> w_xx --> beamlet X = c_exp_beamlet_bst
-- g_sp = Y --> w_xy --> beamlet X = c_exp_beamlet_bst
-- g_sp = X --> w_yx --> beamlet Y = c_exp_beamlet_bst
-- g_sp = Y --> w_yy --> beamlet Y = c_exp_beamlet_bst
--
FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
ASSERT pol_beamlet_bst_X_arr(U) > c_stat_lo_factor * c_exp_beamlet_bst REPORT "Wrong beamlet power for X in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR;
ASSERT pol_beamlet_bst_X_arr(U) < c_stat_hi_factor * c_exp_beamlet_bst REPORT "Wrong beamlet power for X in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR;
ASSERT pol_beamlet_bst_Y_arr(U) > c_stat_lo_factor * c_exp_beamlet_bst REPORT "Wrong beamlet power for Y in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR;
ASSERT pol_beamlet_bst_Y_arr(U) < c_stat_hi_factor * c_exp_beamlet_bst REPORT "Wrong beamlet power for Y in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR;
END LOOP;
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- Verify 10GbE UDP offload -- Verify beamlet output in 10GbE UDP offload
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
v_re := TO_SINT(rx_beamlet_list_re(c_exp_beamlet_index)); v_re_exp := TO_SINT(c_exp_beamlet_re); v_re := TO_SINT(rx_beamlet_list_re(c_exp_beamlet_index)); v_re_exp := c_exp_beamlet_output_re;
v_im := TO_SINT(rx_beamlet_list_im(c_exp_beamlet_index)); v_im_exp := TO_SINT(c_exp_beamlet_im); v_im := TO_SINT(rx_beamlet_list_im(c_exp_beamlet_index)); v_im_exp := c_exp_beamlet_output_im;
ASSERT v_re = v_re_exp REPORT "Wrong 10GbE output (re) " & INTEGER'IMAGE(v_re) & " != " & INTEGER'IMAGE(v_re_exp) SEVERITY ERROR; ASSERT v_re > INTEGER(v_re_exp) - c_beamlet_output_delta REPORT "Wrong 10GbE output (re) " & INTEGER'IMAGE(v_re) & " != " & REAL'IMAGE(v_re_exp) SEVERITY ERROR;
ASSERT v_im = v_im_exp REPORT "Wrong 10GbE output (im) " & INTEGER'IMAGE(v_re) & " != " & INTEGER'IMAGE(v_re_exp) SEVERITY ERROR; ASSERT v_re < INTEGER(v_re_exp) + c_beamlet_output_delta REPORT "Wrong 10GbE output (re) " & INTEGER'IMAGE(v_re) & " != " & REAL'IMAGE(v_re_exp) SEVERITY ERROR;
ASSERT v_im > INTEGER(v_im_exp) - c_beamlet_output_delta REPORT "Wrong 10GbE output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR;
ASSERT v_im < INTEGER(v_im_exp) + c_beamlet_output_delta REPORT "Wrong 10GbE output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR;
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- End Simulation -- End Simulation
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
tb_almost_end <= '1'; tb_almost_end <= '1';
proc_common_wait_some_cycles(ext_clk, 100); proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window
proc_common_stop_simulation(TRUE, ext_clk, tb_almost_end, tb_end); proc_common_stop_simulation(TRUE, ext_clk, tb_almost_end, tb_end);
WAIT; WAIT;
END PROCESS; END PROCESS;
...@@ -879,7 +1119,7 @@ BEGIN ...@@ -879,7 +1119,7 @@ BEGIN
FOR I IN 0 TO (c_sdp_cep_nof_blocks_per_packet * c_sdp_cep_nof_beamlets_per_block/2)-1 LOOP FOR I IN 0 TO (c_sdp_cep_nof_blocks_per_packet * c_sdp_cep_nof_beamlets_per_block/2)-1 LOOP
proc_common_wait_until_high(ext_clk, test_offload_sosi.valid); proc_common_wait_until_high(ext_clk, test_offload_sosi.valid);
rx_beamlet_valid <= '1'; rx_beamlet_valid <= '1';
-- Capture rx beamlets per longword in rx_beamlet_arr -- Capture rx beamlets per longword in rx_beamlet_arr, for time series view in Wave window
rx_beamlet_arr_re(0) <= test_offload_sosi.data(55 DOWNTO 48); -- X rx_beamlet_arr_re(0) <= test_offload_sosi.data(55 DOWNTO 48); -- X
rx_beamlet_arr_im(0) <= test_offload_sosi.data(63 DOWNTO 56); rx_beamlet_arr_im(0) <= test_offload_sosi.data(63 DOWNTO 56);
rx_beamlet_arr_re(1) <= test_offload_sosi.data(39 DOWNTO 32); -- Y rx_beamlet_arr_re(1) <= test_offload_sosi.data(39 DOWNTO 32); -- Y
...@@ -890,13 +1130,13 @@ BEGIN ...@@ -890,13 +1130,13 @@ BEGIN
rx_beamlet_arr_im(3) <= test_offload_sosi.data(15 DOWNTO 8); rx_beamlet_arr_im(3) <= test_offload_sosi.data(15 DOWNTO 8);
IF I < c_sdp_cep_nof_beamlets_per_block/2 THEN IF I < c_sdp_cep_nof_beamlets_per_block/2 THEN
-- Only capture the first beamlets block of each packet in rx_beamlet_list -- Only capture the first beamlets block of each packet in rx_beamlet_list
rx_beamlet_list_re(I*4 + 0) <= test_offload_sosi.data(55 DOWNTO 48); rx_beamlet_list_re(I*4 + 0) <= test_offload_sosi.data(55 DOWNTO 48); -- X
rx_beamlet_list_im(I*4 + 0) <= test_offload_sosi.data(63 DOWNTO 56); rx_beamlet_list_im(I*4 + 0) <= test_offload_sosi.data(63 DOWNTO 56);
rx_beamlet_list_re(I*4 + 1) <= test_offload_sosi.data(39 DOWNTO 32); rx_beamlet_list_re(I*4 + 1) <= test_offload_sosi.data(39 DOWNTO 32); -- Y
rx_beamlet_list_im(I*4 + 1) <= test_offload_sosi.data(47 DOWNTO 40); rx_beamlet_list_im(I*4 + 1) <= test_offload_sosi.data(47 DOWNTO 40);
rx_beamlet_list_re(I*4 + 2) <= test_offload_sosi.data(23 DOWNTO 16); rx_beamlet_list_re(I*4 + 2) <= test_offload_sosi.data(23 DOWNTO 16); -- X
rx_beamlet_list_im(I*4 + 2) <= test_offload_sosi.data(31 DOWNTO 24); rx_beamlet_list_im(I*4 + 2) <= test_offload_sosi.data(31 DOWNTO 24);
rx_beamlet_list_re(I*4 + 3) <= test_offload_sosi.data( 7 DOWNTO 0); rx_beamlet_list_re(I*4 + 3) <= test_offload_sosi.data( 7 DOWNTO 0); -- Y
rx_beamlet_list_im(I*4 + 3) <= test_offload_sosi.data(15 DOWNTO 8); rx_beamlet_list_im(I*4 + 3) <= test_offload_sosi.data(15 DOWNTO 8);
END IF; END IF;
proc_common_wait_until_high(ext_clk, test_offload_sosi.valid); proc_common_wait_until_high(ext_clk, test_offload_sosi.valid);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment