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

Merged to be the same as for unb2b.

parent fab95558
Branches
No related tags found
1 merge request!198Clarified reading one WPFB unit into sp_subband_powers_arr2. Updated comments....
Pipeline #24642 passed
......@@ -20,39 +20,47 @@
-------------------------------------------------------------------------------
--
-- Author: R. van der Walle, E. Kooistra
-- Author: R. van der Walle (original), E. Kooistra (updates)
-- Purpose: Self-checking testbench for simulating lofar2_unb2c_sdp_station_bf using WG data.
--
-- Description:
-- MM control actions:
--
-- 1) Enable calc mode for WG via reg_diag_wg with:
-- freq = 19.921875MHz
-- ampl = 0.5 * 2**13
-- 1) Enable calc mode for WG on signal input g_sp via reg_diag_wg with:
-- g_subband = 102 --> WG freq = 19.921875MHz
-- g_ampl = 1.0 --> WG ampl = 2**13
--
-- 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)
-- 3) Read and verify subband statistics (SST)
--
-- 4) Read beamlet statistics (BST) via ram_st_bst and verify with
-- c_exp_beamlet_power_sp_0 at c_sdp_N_sub-1 - c_subband_sp_0.
-- View sp_beamlet_power_0 in Wave window
-- 5) Compare SST with BST.
-- 6) Verify 10GbE output.
-- 4) Select subband g_subband for beamlet g_beamlet
--
-- 5) Apply BF weight (g_bf_gain, g_bf_phase) to g_beamlet X beam and Y beam
--
-- 6) Read and verify beamlet statistics (BST)
-- View sp_subband_sst in Wave window
-- View pol_beamlet_bst in Wave window
--
-- 7) Verify 10GbE output header and output payload for g_beamlet.
--
-- Usage:
-- > as 7 # default
-- > as 12 # for detailed debugging
-- # Manually add missing signal
-- > add wave -position insertpoint \
-- sim:/tb_lofar2_unb2c_sdp_station_bf/sp_subband_ssts_arr2 \
-- sim:/tb_lofar2_unb2c_sdp_station_bf/pol_beamlet_bsts_arr2
-- > 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, unb2c_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, lofar2_unb2c_sdp_station_lib;
USE IEEE.std_logic_1164.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_mem_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
......@@ -70,6 +78,17 @@ USE lofar2_sdp_lib.tb_sdp_pkg.ALL;
USE tech_pll_lib.tech_pll_component_pkg.ALL;
ENTITY tb_lofar2_unb2c_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_unb2c_sdp_station_bf;
ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
......@@ -95,16 +114,19 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
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_cross_clock_domain_latency : NATURAL := 20;
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_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_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_lo_factor : REAL := 1.0 - c_percentage; -- lower boundary
CONSTANT c_hi_factor : REAL := 1.0 + c_percentage; -- higher boundary
CONSTANT c_stat_percentage : REAL := 0.05; -- +-percentage margin that actual value may differ from expected value
CONSTANT c_stat_lo_factor : REAL := 1.0 - c_stat_percentage; -- lower 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
CONSTANT c_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := c_sdp_cep_eth_dst_mac; -- 00074306C700 = DOP36-eth0
......@@ -117,7 +139,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_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_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 := (
TO_UVEC(601, 16), -- station_id
......@@ -135,39 +157,72 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
);
-- WG
CONSTANT c_full_scale_ampl : REAL := REAL(2**(14-1)-1); -- = full scale of WG
CONSTANT c_bsn_start_wg : NATURAL := c_init_bsn + 2; -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values
CONSTANT c_ampl_sp_0 : NATURAL := 2**(c_sdp_W_adc-1) / 2; -- in number of lsb
-- .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_lsb : REAL := c_diag_wg_ampl_unit / REAL(c_wg_ampl_full_scale); -- amplitude in number of LSbit resolution steps
CONSTANT c_wg_ampl : NATURAL := NATURAL(g_wg_ampl * REAL(c_wg_ampl_full_scale)); -- in number of lsb
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
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
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_freq_offset : REAL := 0.0/11.0; -- in freq_unit
CONSTANT c_subband_sp_0 : REAL := 102.0; -- Select subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz
CONSTANT c_wg_ampl_lsb : REAL := c_diag_wg_ampl_unit / c_full_scale_ampl; -- amplitude in number of LSbit resolution steps
CONSTANT c_exp_wg_power_sp_0 : REAL := REAL(c_ampl_sp_0**2)/2.0 * REAL(c_nof_clk_per_sync);
-- 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_exp_sp_beamlet_power_ratio : REAL := 1.0/8.0; -- depends on internal WPFB quantization and FIR coefficients
CONSTANT c_exp_sp_beamlet_power_sum_ratio : REAL := c_exp_sp_beamlet_power_ratio; -- because all sinus power is expected in one subband
CONSTANT c_exp_beamlet_power_sp_0 : REAL := c_exp_wg_power_sp_0 * c_exp_sp_beamlet_power_ratio;
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_subband_phase_offset : REAL := -90.0; -- WG with zero phase sinues yields subband with -90 degrees phase (negative Im, zero Re)
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_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub);
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_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_N_beamlets_sdp-1); -- 2*488 = 976
-- BF
CONSTANT c_exp_beamlet_index : NATURAL := NATURAL(c_subband_sp_0) * c_sdp_N_pol_bf;
CONSTANT c_exp_beamlet_re : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"81"; -- = -127, derived from simulation
CONSTANT c_exp_beamlet_im : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"7F"; -- = +127, derived from simulation
-- . select
CONSTANT c_exp_beamlet_index : NATURAL := g_beamlet * c_sdp_N_pol_bf; -- in beamset 0
-- . 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
-- . 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_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_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_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
-- . 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_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;
......@@ -179,11 +234,15 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_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_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_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_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_reg_sdp_info : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_SDP_INFO";
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_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_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
-- Tb
......@@ -211,16 +270,32 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
-- WG
SIGNAL current_bsn_wg : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
-- WPFB
SIGNAL sp_subband_powers_arr2 : t_slv_64_subbands_arr(c_sdp_N_pol-1 DOWNTO 0); -- [sp][sub]
-- FSUB
-- . Read sp_subband_ssts_arr2 = SST for one WPFB unit that processes g_sp
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
SIGNAL sp_subband_sst : REAL := 0.0;
SIGNAL stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
SIGNAL sp_beamlet_powers_arr2 : t_slv_64_beamlets_arr(c_sdp_N_beamsets*c_sdp_N_pol_bf-1 DOWNTO 0); -- [sp][sub]
SIGNAL sp_beamlet_power_0 : REAL;
SIGNAL sp_beamlet_power_sum : t_real_arr(c_sdp_N_beamsets*c_sdp_N_pol_bf-1 DOWNTO 0) := (OTHERS=>0.0);
SIGNAL sp_beamlet_power_sum_0 : REAL;
SIGNAL sp_beamlet_power_ratio_0 : REAL;
SIGNAL sp_beamlet_power_sum_ratio_0 : REAL;
SIGNAL sp_beamlet_power_leakage_sum_0 : REAL;
-- . 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;
-- 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
SIGNAL rx_beamlet_arr_re : t_slv_8_arr(c_sdp_cep_nof_blocks_per_packet-1 DOWNTO 0); -- [3:0]
......@@ -309,7 +384,7 @@ BEGIN
g_sim_node_nr => c_node_nr,
g_wpfb => c_wpfb_sim,
g_bsn_nof_clk_per_sync => c_nof_clk_per_sync,
g_scope_selected_subband => NATURAL(c_subband_sp_0)
g_scope_selected_subband => g_subband
)
PORT MAP (
-- GENERAL
......@@ -421,12 +496,14 @@ BEGIN
p_mm_stimuli : PROCESS
VARIABLE v_bsn : NATURAL;
VARIABLE v_sp_beamlet_power : REAL;
VARIABLE v_sp_subband_power : REAL;
VARIABLE v_W, v_T, v_U, v_S, v_B : NATURAL; -- array indicies
VARIABLE v_re, v_im : INTEGER;
VARIABLE v_re_exp, v_im_exp : INTEGER;
VARIABLE v_offset : NATURAL;
VARIABLE v_sp_subband_sst : REAL := 0.0;
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_stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
VARIABLE v_len, v_span, v_offset, v_addr, v_sel : NATURAL; -- address ranges, indices
VARIABLE v_W, v_P, v_S, v_A, v_B, v_G : NATURAL; -- array indicies
VARIABLE v_re, v_im, v_weight : INTEGER;
VARIABLE v_re_exp, v_im_exp : REAL := 0.0;
BEGIN
-- Wait for DUT power up after reset
WAIT FOR 1 us;
......@@ -474,8 +551,15 @@ BEGIN
------------------------------------------------------------------------------
FOR bset IN 0 TO c_sdp_N_beamsets-1 LOOP
-- MM beamlet_scale
-- . write
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);
ASSERT TO_UINT(rd_beamlet_scale) = c_exp_beamlet_scale REPORT "Wrong MM read beamlet_scale for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR;
......@@ -560,17 +644,19 @@ BEGIN
pps_rst <= '0';
----------------------------------------------------------------------------
-- Enable WG
-- 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]
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 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, 2, INTEGER((c_subband_sp_0+c_wg_freq_offset) * c_wg_subband_freq_unit), tb_clk); -- freq
mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 3, INTEGER(REAL(c_ampl_sp_0) * c_wg_ampl_lsb), tb_clk); -- ampl
-- . Put wanted signal on g_sp input
v_offset := g_sp * c_mm_span_reg_diag_wg;
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, 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
mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO 0), tb_clk);
......@@ -584,7 +670,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, 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);
sst_offload_weighted_subbands <= NOT rd_data(0);
proc_common_wait_some_cycles(tb_clk, 1);
----------------------------------------------------------------------------
-- 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
----------------------------------------------------------------------------
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
c_sdp_T_sub, tb_clk);
......@@ -595,135 +791,186 @@ BEGIN
---------------------------------------------------------------------------
-- Read subband statistics
---------------------------------------------------------------------------
-- . the subband statistics are c_wpfb_sim.stat_data_sz = 2 word power values.
-- . there are c_sdp_N_sub = 512 subbands per signal path
-- . one complex WPFB can process two real inputs A, B, is c_sdp_Q_fft = c_sdp_N_pol = 2
-- . the subband statistics are c_stat_data_sz = 2 word power values.
-- . 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 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 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
FOR I IN 0 TO c_sdp_N_pol*c_sdp_N_sub*c_stat_data_sz-1 LOOP -- 2048 = 2 * 512 * 64/32
v_W := I MOD c_stat_data_sz; -- 0, 1 per statistics word
v_T := (I / c_stat_data_sz) MOD c_sdp_N_pol; -- 0, 1 per pol
v_U := I / (c_sdp_N_pol*c_stat_data_sz*c_sdp_N_sub); -- / 2048
v_S := v_T + v_U * c_sdp_N_pol;
v_B := (I / (c_sdp_N_pol*c_stat_data_sz)) MOD c_sdp_N_sub; -- 0:511 per dual pol
-- Only read sp 0, pol 0 (v_S = 0)
IF v_S=0 THEN
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
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_addr := I + c_pfb_index * v_span; -- MM address
-- Only read SST for g_subband for dual pol SP, to save sim time
IF g_read_all_SST = TRUE OR v_B = g_subband THEN
IF v_W=0 THEN
-- low part
mmf_mm_bus_rd(c_mm_file_ram_st_sst, I, rd_data, tb_clk);
sp_subband_powers_arr2(v_S)(v_B)(31 DOWNTO 0) <= rd_data;
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, I, rd_data, tb_clk);
sp_subband_powers_arr2(v_S)(v_B)(63 DOWNTO 32) <= rd_data;
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;
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 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
---------------------------------------------------------------------------
-- . the beamlet statistics are c_stat_data_sz = 2 word power values.
-- . there are c_sdp_S_sub_bf = 488 subbands per signal path
-- . the subbands are output alternately so A0 B0 A1 B1 ... A5487 B487 for input A, B
-- . the subband statistics multiple units appear in order in the ram_st_bst address map
-- . the subband statistics are stored first lo word 0 then hi word 1
FOR I IN 0 TO c_sdp_N_pol_bf*c_sdp_S_sub_bf*c_stat_data_sz-1 LOOP
v_W := I MOD c_stat_data_sz;
v_T := (I / c_stat_data_sz) MOD c_sdp_N_pol_bf;
v_U := I / (c_sdp_N_pol_bf*c_stat_data_sz*c_sdp_S_sub_bf);
v_S := v_T + v_U * c_sdp_N_pol_bf;
v_B := (I / (c_sdp_N_pol_bf*c_stat_data_sz)) MOD c_sdp_S_sub_bf;
-- Only read beamset 0, pol 0 (v_S = 0)
IF v_S=0 THEN
-- . there are c_sdp_S_sub_bf = 488 dual pol beamlets per beamset
-- . 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 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_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
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, polarization index
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_G := v_B + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp)
v_addr := I + 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
IF g_read_all_BST = TRUE OR v_B = g_beamlet THEN
IF v_W = 0 THEN
-- low part
--mmf_mm_bus_rd(c_mm_file_ram_st_bst, I+(c_sdp_N_pol_bf*c_sdp_N_sub*c_stat_data_sz), rd_data, tb_clk);
mmf_mm_bus_rd(c_mm_file_ram_st_bst, I, rd_data, tb_clk);
sp_beamlet_powers_arr2(v_S)(v_B)(31 DOWNTO 0) <= rd_data;
mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_addr, rd_data, tb_clk);
v_data_lo := rd_data;
ELSE
-- high part
--mmf_mm_bus_rd(c_mm_file_ram_st_bst, I+(c_sdp_N_pol_bf*c_sdp_N_sub*c_stat_data_sz), rd_data, tb_clk);
mmf_mm_bus_rd(c_mm_file_ram_st_bst, I, rd_data, tb_clk);
sp_beamlet_powers_arr2(v_S)(v_B)(63 DOWNTO 32) <= rd_data;
-- Convert STD_LOGIC_VECTOR to REAL
v_sp_beamlet_power := REAL(TO_UINT(rd_data(29 DOWNTO 0) &
sp_beamlet_powers_arr2(v_S)(v_B)(31 DOWNTO 30)))*2.0**30 +
REAL(TO_UINT(sp_beamlet_powers_arr2(v_S)(v_B)(29 DOWNTO 0)));
-- sum
sp_beamlet_power_sum(v_S) <= sp_beamlet_power_sum(v_S) + v_sp_beamlet_power;
mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_addr, rd_data, tb_clk);
v_data_hi := rd_data;
v_stat_data := v_data_hi & v_data_lo;
pol_beamlet_bsts_arr2(v_P)(v_G) <= v_stat_data;
stat_data <= v_stat_data; -- for time series view in Wave window
END IF;
END IF;
END LOOP;
END LOOP;
proc_common_wait_some_cycles(tb_clk, 1);
-- sp_beamlet_power_sum is the sum of all subband powers per SP, this value will be close to sp_beamlet_power
-- because the input is a sinus, so most power will be in 1 subband. The sp_beamlet_power_leakage_sum shows
-- how much power from the input sinus at a specific subband has leaked into the 511 other subbands.
sp_beamlet_power_0 <=
REAL(TO_UINT(sp_beamlet_powers_arr2(0)(INTEGER(ROUND(c_subband_sp_0)))(61 DOWNTO 30)))*2.0**30 +
REAL(TO_UINT(sp_beamlet_powers_arr2(0)(INTEGER(ROUND(c_subband_sp_0)))(29 DOWNTO 0)));
sp_beamlet_power_sum_0 <= sp_beamlet_power_sum(0);
-- Beamlet power of g_beamlet X and Y, same for both beamsets
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)
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
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
---------------------------------------------------------------------------
-- 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_T := I MOD c_sdp_N_pol;
v_U := I / (c_sdp_N_pol*c_sdp_S_sub_bf);
v_S := v_T + v_U * c_sdp_N_pol;
v_B := (I / c_sdp_N_pol) MOD c_sdp_S_sub_bf;
IF v_S=0 THEN
-- Convert STD_LOGIC_VECTOR to REAL
v_sp_beamlet_power := REAL(TO_UINT(rd_data(29 DOWNTO 0) &
sp_beamlet_powers_arr2(v_S)(v_B)(31 DOWNTO 30)))*2.0**30 +
REAL(TO_UINT(sp_beamlet_powers_arr2(v_S)(v_B)(29 DOWNTO 0)));
-- Convert STD_LOGIC_VECTOR to REAL
v_sp_subband_power := REAL(TO_UINT(rd_data(29 DOWNTO 0) &
sp_subband_powers_arr2(v_S)(v_B)(31 DOWNTO 30)))*2.0**30 +
REAL(TO_UINT(sp_subband_powers_arr2(v_S)(v_B)(29 DOWNTO 0)));
-- 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.
-- the difference should not be larger than 0.5% (+/- 2^13 for low values)
ASSERT v_sp_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_sp_beamlet_power) &" are not equal" SEVERITY ERROR;
ASSERT v_sp_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_sp_beamlet_power) &" are not equal" SEVERITY ERROR;
END IF;
print_str("");
print_str("WG:");
print_str(". c_wg_ampl = " & int_to_str(c_wg_ampl));
print_str(". c_exp_sp_power = " & real_to_str(c_exp_sp_power, 20, 1));
print_str(". c_exp_sp_ast = " & real_to_str(c_exp_sp_ast, 20, 1));
print_str("");
print_str("Subband selector:");
print_str(". sst_offload_weighted_subbands = " & sl_to_str(sst_offload_weighted_subbands));
print_str("");
print_str("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));
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;
-- verify expected subband power based on WG power
IF sp_beamlet_power_sum_0>0.0 THEN ASSERT sp_beamlet_power_0 > c_lo_factor * c_exp_beamlet_power_sp_0 REPORT "Wrong beamlet power for SP 0" SEVERITY ERROR; END IF;
IF sp_beamlet_power_sum_0>0.0 THEN ASSERT sp_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("");
print_str("Beamlet output:");
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_sp_beamlet_power_ratio in Wave window
IF sp_beamlet_power_sum_0>0.0 THEN sp_beamlet_power_ratio_0 <= sp_beamlet_power_0/sp_beamlet_power_sum_0; END IF;
---------------------------------------------------------------------------
-- Verify SST and BST
---------------------------------------------------------------------------
-- view c_exp_sp_beamlet_power_sum_ratio in Wave window
-- The sp_beamlet_power_sum_ratio show similar information as sp_beamlet_power_leakage_sum, because when
-- sp_beamlet_power_leakage_sum is small then sp_beamlet_power_sum_ratio ~= sp_beamlet_power_ratio.
IF sp_beamlet_power_sum_0>0.0 THEN sp_beamlet_power_sum_ratio_0 <= sp_beamlet_power_sum_0/sp_beamlet_power_0; END IF;
-- verify expected subband power based on WG power
ASSERT sp_subband_sst > c_stat_lo_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
ASSERT sp_subband_sst < c_stat_hi_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
-- View sp_beamlet_power_leakage_sum in Wave window
IF sp_beamlet_power_sum_0>0.0 THEN sp_beamlet_power_leakage_sum_0 <= sp_beamlet_power_sum_0 - sp_beamlet_power_0; END IF;
-- verify expected beamlet power based on WG power and BF weigths
--
-- 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_im := TO_SINT(rx_beamlet_list_im(c_exp_beamlet_index)); v_im_exp := TO_SINT(c_exp_beamlet_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_im = v_im_exp REPORT "Wrong 10GbE output (im) " & INTEGER'IMAGE(v_re) & " != " & INTEGER'IMAGE(v_re_exp) SEVERITY ERROR;
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 := c_exp_beamlet_output_im;
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_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
---------------------------------------------------------------------------
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);
WAIT;
END PROCESS;
......@@ -852,7 +1099,7 @@ BEGIN
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);
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_im(0) <= test_offload_sosi.data(63 DOWNTO 56);
rx_beamlet_arr_re(1) <= test_offload_sosi.data(39 DOWNTO 32); -- Y
......@@ -863,13 +1110,13 @@ BEGIN
rx_beamlet_arr_im(3) <= test_offload_sosi.data(15 DOWNTO 8);
IF I < c_sdp_cep_nof_beamlets_per_block/2 THEN
-- 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_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_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_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);
END IF;
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