diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd index 7bcf835fb5c49bba726ee98c827543ee67fda100..890adcf1280cebffbcaa6e3b85af6f8f4fbdf231 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd @@ -21,37 +21,87 @@ ------------------------------------------------------------------------------- -- -- Author: R. van der Walle (original), E. Kooistra (updates) --- Purpose: Self-checking testbench for simulating lofar2_unb2c_sdp_station_bf using WG data. +-- Purpose: Self-checking testbench for simulating lofar2_unb2c_sdp_station_bf +-- using WG data. -- -- Description: +-- This tb is a balance between verification coverage and keeping it simple: +-- - Use only one signal input (g_sp), put small unused signal on the other +-- signal inputs. +-- - Use different BF weight for the two beamlet polarizations (g_bf_*_gain, +-- and g_bf_*_phase) of signal input g_sp. Keep BF weight for the other +-- signal inputs = 0 to block them from the beamlet. +-- - Select one beamlet for the subband (g_beamlet). +-- - Use same stimuli for both beamsets. +-- -- MM control actions: -- --- 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 +-- 1) Enable calc mode for WG on signal input (si) g_sp via reg_diag_wg with: +-- g_subband = 102 --> 102 * f_sub = 19.921875 MHz +-- g_wg_ampl = 1.0 --> 1.0 yield WG ampl = 2**13 +-- g_wg_phase --> subband phase +-- Use g_unused_ampl = 0.1 and g_unused_phase = 0.0 for the other signal +-- inputs, that are not used in the BF. -- --- 2) Read current BSN from reg_bsn_scheduler_wg and write reg_bsn_scheduler_wg --- to trigger start of WG at BSN. +-- 2) Read current BSN from reg_bsn_scheduler_wg and write +-- reg_bsn_scheduler_wg to trigger start of WG at BSN. -- --- 3) Read and verify subband statistics (SST) +-- 3) Read and verify subband statistics (SST) for g_sp. This also reads the +-- SST of the other signal input of the WPFB that processes g_sp. +-- +-- 4) Select subband g_subband for beamlets in g_beamlet +-- +-- 5) Apply BF weight to g_beamlet X beam and Y beam, so for example if g_sp +-- = 3, then w_x3 = g_bf_x_gain/phase and w_y3 = = g_bf_x_gain/phase. The +-- other BF weights are 0. -- --- 4) Select subband g_subband for beamlet g_beamlet +-- WG BF BF +-- si weight weight +-- X Y +-- 0 -----> * w_x0 ..+ +-- \--------------|----> * w_y0 ..+ +-- 1 -----> * w_x1 ..+ | +-- \--------------|----> * w_y1 ..+ +-- 2 -----> * w_x2 ..+ | +-- \--------------|----> * w_y2 ..+ +-- 3 -----> * w_x3 ..+ | +-- \--------------|----> * w_y3 ..+ +-- 4 -----> * w_x4 ..+ | +-- \--------------|----> * w_y4 ..+ +-- 5 -----> * w_x5 ..+ | +-- \--------------|----> * w_y5 ..+ +-- 6 -----> * w_x6 ..+ | +-- \--------------|----> * w_y6 ..+ +-- 7 -----> * w_x7 ..+ | +-- \--------------|----> * w_y7 ..+ +-- 8 -----> * w_x8 ..+ | +-- \--------------|----> * w_y8 ..+ +-- 9 -----> * w_x9 ..+ | +-- \--------------|----> * w_y9 ..+ +-- 10 -----> * w_x10 ..+ | +-- \--------------|----> * w_y10 ..+ +-- 11 -----> * w_x11 ..+ | +-- \--------------|----> * w_y11 ..+ +-- | | +-- \----------------|---> beamlet_x +-- \--> beamlet_y -- --- 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 +-- View sp_sst in Wave window +-- View bst_x_arr, bst_y_arr in Wave window -- -- 7) Verify 10GbE output header and output payload for g_beamlet. +-- View rx_beamlet_sosi +-- View rx_beamlet_cnt (in analog format) -- -- 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 +-- sim:/tb_lofar2_unb2c_sdp_station_bf/sp_ssts_arr2 \ +-- sim:/tb_lofar2_unb2c_sdp_station_bf/bsts_arr2 -- > run -a -- Takes about 40 m when g_read_all_* = FALSE -- Takes about 1h 5 m when g_read_all_* = TRUE @@ -79,13 +129,18 @@ 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_sp : NATURAL := 3; -- WG signal path index in range(S_pn = 12) g_wg_ampl : REAL := 1.0; -- WG normalized amplitude + g_wg_phase : REAL := 0.0; -- WG phase in degrees = subband phase + g_unused_ampl : REAL := 0.1; -- WG normalized amplitude for unused sp + g_unused_phase : REAL := 0.0; -- WG phase in degrees for unused sp 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_bf_x_gain : REAL := 0.7; -- g_beamlet X BF weight normalized gain + g_bf_y_gain : REAL := 0.6; -- g_beamlet Y BF weight normalized gain + g_bf_x_phase : REAL := 30.0; -- g_beamlet X BF weight phase rotation in degrees + g_bf_y_phase : REAL := 40.0; -- g_beamlet Y 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 ); @@ -124,6 +179,8 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS 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_nof_beamlets_per_data : NATURAL := 2; -- 2 dual pol beamlets (= XY, XY) per 64b data word + CONSTANT c_beamlet_output_delta : INTEGER := 2; -- +-delta margin -- header fields @@ -156,20 +213,22 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS 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_wg_unused_ampl : NATURAL := NATURAL(g_unused_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 + CONSTANT c_wg_phase : REAL := g_wg_phase + c_wg_phase_offset; -- WG phase in degrees + CONSTANT c_wg_unused_phase : REAL := g_unused_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 -- WPFB 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 : REAL := g_wg_phase; -- wanted subband phase in degrees = WG phase at sop 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 @@ -182,47 +241,60 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS 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 + -- BF X-pol and Y-pol -- . select - CONSTANT c_exp_beamlet_index : NATURAL := g_beamlet * c_sdp_N_pol_bf; -- in beamset 0 + CONSTANT c_exp_beamlet_x_index : NATURAL := g_beamlet * c_sdp_N_pol_bf; -- in beamset 0 + CONSTANT c_exp_beamlet_y_index : NATURAL := g_beamlet * c_sdp_N_pol_bf + 1; -- 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)); + CONSTANT c_bf_x_weight_re : INTEGER := INTEGER(g_bf_x_gain * REAL(c_sdp_unit_bf_weight) * COS(g_bf_x_phase * MATH_2_PI / 360.0)); + CONSTANT c_bf_x_weight_im : INTEGER := INTEGER(g_bf_x_gain * REAL(c_sdp_unit_bf_weight) * SIN(g_bf_x_phase * MATH_2_PI / 360.0)); + CONSTANT c_bf_y_weight_re : INTEGER := INTEGER(g_bf_y_gain * REAL(c_sdp_unit_bf_weight) * COS(g_bf_y_phase * MATH_2_PI / 360.0)); + CONSTANT c_bf_y_weight_im : INTEGER := INTEGER(g_bf_y_gain * REAL(c_sdp_unit_bf_weight) * SIN(g_bf_y_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); + CONSTANT c_exp_beamlet_x_ampl : REAL := c_exp_subband_ampl * g_bf_x_gain; + CONSTANT c_exp_beamlet_x_phase : REAL := c_subband_phase_offset + c_subband_weight_phase + g_bf_x_phase; + CONSTANT c_exp_beamlet_x_re : REAL := c_exp_beamlet_x_ampl * COS(c_exp_beamlet_x_phase * MATH_2_PI / 360.0); + CONSTANT c_exp_beamlet_x_im : REAL := c_exp_beamlet_x_ampl * SIN(c_exp_beamlet_x_phase * MATH_2_PI / 360.0); + CONSTANT c_exp_beamlet_y_ampl : REAL := c_exp_subband_ampl * g_bf_y_gain; + CONSTANT c_exp_beamlet_y_phase : REAL := c_subband_phase_offset + c_subband_weight_phase + g_bf_y_phase; + CONSTANT c_exp_beamlet_y_re : REAL := c_exp_beamlet_y_ampl * COS(c_exp_beamlet_y_phase * MATH_2_PI / 360.0); + CONSTANT c_exp_beamlet_y_im : REAL := c_exp_beamlet_y_ampl * SIN(c_exp_beamlet_y_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) + CONSTANT c_exp_beamlet_x_power : REAL := c_exp_beamlet_x_ampl**2.0; -- complex, so no divide by 2 + CONSTANT c_exp_beamlet_x_bst : REAL := c_exp_subband_sst * g_bf_x_gain**2.0; -- = c_exp_beamlet_x_power * REAL(c_nof_block_per_sync) + CONSTANT c_exp_beamlet_y_power : REAL := c_exp_beamlet_y_ampl**2.0; -- complex, so no divide by 2 + CONSTANT c_exp_beamlet_y_bst : REAL := c_exp_subband_sst * g_bf_y_gain**2.0; -- = c_exp_beamlet_y_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; + CONSTANT c_exp_beamlet_x_output_ampl : REAL := c_exp_beamlet_x_ampl * g_beamlet_scale; + CONSTANT c_exp_beamlet_x_output_phase : REAL := c_exp_beamlet_x_phase; + CONSTANT c_exp_beamlet_x_output_re : REAL := c_exp_beamlet_x_re * g_beamlet_scale; + CONSTANT c_exp_beamlet_x_output_im : REAL := c_exp_beamlet_x_im * g_beamlet_scale; + CONSTANT c_exp_beamlet_y_output_ampl : REAL := c_exp_beamlet_y_ampl * g_beamlet_scale; + CONSTANT c_exp_beamlet_y_output_phase : REAL := c_exp_beamlet_y_phase; + CONSTANT c_exp_beamlet_y_output_re : REAL := c_exp_beamlet_y_re * g_beamlet_scale; + CONSTANT c_exp_beamlet_y_output_im : REAL := c_exp_beamlet_y_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; + 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_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_bf*c_stat_data_sz); + 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_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_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; + 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; - CONSTANT c_mm_span_reg_hdr_dat : NATURAL := 2**c_addr_w_reg_hdr_dat; - CONSTANT c_mm_span_reg_dp_xonoff : NATURAL := 2**c_addr_w_reg_dp_xonoff; - CONSTANT c_mm_span_ram_st_bst : NATURAL := 2**c_addr_w_ram_st_bst; + 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; + CONSTANT c_mm_span_reg_hdr_dat : NATURAL := 2**c_addr_w_reg_hdr_dat; + CONSTANT c_mm_span_reg_dp_xonoff : NATURAL := 2**c_addr_w_reg_dp_xonoff; + CONSTANT c_mm_span_ram_st_bst : NATURAL := 2**c_addr_w_ram_st_bst; CONSTANT c_mm_file_reg_ppsh : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "PIO_PPS"; CONSTANT c_mm_file_reg_bsn_source_v2 : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2"; @@ -262,16 +334,16 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS SIGNAL rd_cep_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0); -- 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); -- 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); + -- . Read sp_ssts_arr2 = SST for one WPFB unit that processes g_sp + SIGNAL sp_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_sst : REAL := 0.0; + SIGNAL stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); -- . Selector - SIGNAL sst_offload_weighted_subbands : STD_LOGIC; + SIGNAL sst_weighted_subbands_flag : STD_LOGIC; -- . Subband equalizer SIGNAL sp_subband_weight_re : INTEGER := 0; @@ -280,47 +352,59 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS 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] - SIGNAL rx_beamlet_arr_im : t_slv_8_arr(c_sdp_cep_nof_blocks_per_packet-1 DOWNTO 0); -- [3:0] - SIGNAL rx_beamlet_cnt : NATURAL; - SIGNAL rx_beamlet_valid : STD_LOGIC; + -- . beamlet subband selection + 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 + + -- . beamlet X-pol + SIGNAL sp_bf_x_weights_re_arr : t_integer_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_x_weights_im_arr : t_integer_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_x_weights_gain_arr : t_real_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_x_weights_phase_arr : t_real_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0.0); + -- . beamlet Y-pol + SIGNAL sp_bf_y_weights_re_arr : t_integer_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_y_weights_im_arr : t_integer_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_y_weights_gain_arr : t_real_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_y_weights_phase_arr : t_real_arr(0 TO c_sdp_S_pn-1) := (OTHERS => 0.0); - SIGNAL rx_beamlet_list_re : t_slv_8_arr(c_sdp_cep_nof_beamlets_per_block * c_sdp_N_pol_bf-1 DOWNTO 0); -- [488 * 2-1:0] = [975:0] - SIGNAL rx_beamlet_list_im : t_slv_8_arr(c_sdp_cep_nof_beamlets_per_block * c_sdp_N_pol_bf-1 DOWNTO 0); -- [488 * 2-1:0] = [975:0] + -- . BST + SIGNAL bsts_arr2 : t_slv_64_beamlets_arr(c_sdp_N_pol_bf-1 DOWNTO 0); -- [pol_bf][blet] + SIGNAL bst_x_arr : t_real_arr(0 TO c_sdp_N_beamsets-1) := (OTHERS => 0.0); -- [bset] for BF X pol + SIGNAL bst_y_arr : t_real_arr(0 TO c_sdp_N_beamsets-1) := (OTHERS => 0.0); -- [bset] for BF Y pol + -- CEP model + -- . 10GbE SIGNAL tr_10GbE_src_out : t_dp_sosi; SIGNAL tr_10GbE_src_in : t_dp_siso; SIGNAL tr_ref_clk_312 : STD_LOGIC := '0'; SIGNAL tr_ref_clk_156 : STD_LOGIC := '0'; SIGNAL tr_ref_rst_156 : STD_LOGIC := '0'; - -- dp_offload_rx - SIGNAL offload_rx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst; - SIGNAL offload_rx_hdr_dat_miso : t_mem_miso; + -- . dp_offload_rx + SIGNAL rx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL rx_hdr_dat_miso : t_mem_miso; + + SIGNAL rx_hdr_fields_out : STD_LOGIC_VECTOR(1023 DOWNTO 0); + SIGNAL rx_hdr_fields_raw : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0'); + + -- Beamlets packets header + SIGNAL rx_sdp_cep_header : t_sdp_cep_header; + SIGNAL exp_sdp_cep_header : t_sdp_cep_header; + SIGNAL exp_dp_bsn : NATURAL; - SIGNAL test_offload_en : STD_LOGIC := '0'; - SIGNAL test_offload_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); -- 64 bit - SIGNAL test_offload_sosi : t_dp_sosi := c_dp_sosi_rst; - SIGNAL test_offload_sop_cnt : NATURAL := 0; - SIGNAL test_offload_eop_cnt : NATURAL := 0; + -- Beamlets packets data + SIGNAL rx_beamlet_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); -- 64 bit + SIGNAL rx_beamlet_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL rx_beamlet_sop_cnt : NATURAL := 0; + SIGNAL rx_beamlet_eop_cnt : NATURAL := 0; + + 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_im : t_slv_8_arr(c_sdp_cep_nof_blocks_per_packet-1 DOWNTO 0); -- [3:0] + SIGNAL rx_beamlet_cnt : NATURAL; + SIGNAL rx_beamlet_valid : STD_LOGIC; - SIGNAL rx_hdr_fields_out : STD_LOGIC_VECTOR(1023 DOWNTO 0); - SIGNAL rx_hdr_fields_raw : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0'); - SIGNAL rx_sdp_cep_header : t_sdp_cep_header; - SIGNAL exp_sdp_cep_header : t_sdp_cep_header; - SIGNAL exp_dp_bsn : NATURAL; + SIGNAL rx_beamlet_list_re : t_slv_8_arr(c_sdp_cep_nof_beamlets_per_block * c_sdp_N_pol_bf-1 DOWNTO 0); -- [488 * 2-1:0] = [975:0] + SIGNAL rx_beamlet_list_im : t_slv_8_arr(c_sdp_cep_nof_beamlets_per_block * c_sdp_N_pol_bf-1 DOWNTO 0); -- [488 * 2-1:0] = [975:0] -- DUT SIGNAL ext_clk : STD_LOGIC := '0'; @@ -416,6 +500,9 @@ BEGIN JESD204B_SYNC_N => jesd204b_sync_n ); + ------------------------------------------------------------------------------ + -- CEP model + ------------------------------------------------------------------------------ u_unb2_board_clk644_pll : ENTITY tech_pll_lib.tech_pll_xgmii_mac_clocks PORT MAP ( refclk_644 => SA_CLK, @@ -471,13 +558,13 @@ BEGIN dp_rst => dest_rst, dp_clk => ext_clk, - reg_hdr_dat_mosi => offload_rx_hdr_dat_mosi, - reg_hdr_dat_miso => offload_rx_hdr_dat_miso, + reg_hdr_dat_mosi => rx_hdr_dat_mosi, + reg_hdr_dat_miso => rx_hdr_dat_miso, snk_in_arr(0) => tr_10GbE_src_out, snk_out_arr(0) => tr_10GbE_src_in, - src_out_arr(0) => test_offload_sosi, + src_out_arr(0) => rx_beamlet_sosi, hdr_fields_out_arr(0) => rx_hdr_fields_out, hdr_fields_raw_arr(0) => rx_hdr_fields_raw @@ -489,13 +576,13 @@ BEGIN tb_clk <= NOT tb_clk AFTER c_tb_clk_period/2; -- Testbench MM clock p_mm_stimuli : PROCESS - VARIABLE v_bsn : NATURAL; - VARIABLE v_sp_subband_sst : REAL := 0.0; - VARIABLE v_pol_beamlet_bst : REAL := 0.0; + VARIABLE v_bsn : NATURAL; + VARIABLE v_sp_sst : REAL := 0.0; + VARIABLE v_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_W, v_P, v_PB, 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 @@ -635,12 +722,21 @@ BEGIN -- 1 : phase[15:0] -- 2 : freq[30:0] -- 3 : ampl[16:0] - -- . 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 + -- . Put wanted signal on g_sp input and unused signal on the other inputs + FOR S IN 0 TO c_sdp_S_pn-1 LOOP + v_offset := S * c_mm_span_reg_diag_wg; + IF s = g_sp THEN + 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 + ELSE + 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_unused_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_unused_ampl) * c_wg_ampl_lsb), tb_clk); -- ampl + END IF; + END LOOP; -- Read current BSN mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO 0), tb_clk); @@ -658,7 +754,7 @@ BEGIN -- 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); + sst_weighted_subbands_flag <= NOT rd_data(0); proc_common_wait_some_cycles(tb_clk, 1); ---------------------------------------------------------------------------- @@ -716,7 +812,7 @@ BEGIN proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window ---------------------------------------------------------------------------- - -- Write beamlet weight for g_beamlet + -- Write beamlet weight for g_beamlet in S_sub_bf ---------------------------------------------------------------------------- -- . MM format: (cint16)RAM_BF_WEIGHTS[N_beamsets][N_pol_bf][A_pn]_[N_pol][S_sub_bf] @@ -724,38 +820,61 @@ BEGIN 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); + FOR PB IN 0 TO c_sdp_N_pol_bf-1 LOOP + -- Same BF weights for both beamlet polarizations + 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 + IF PB = 0 THEN + v_weight := pack_complex(re => c_bf_x_weight_re, im => c_bf_x_weight_im, w => c_sdp_W_bf_weight); + ELSE + v_weight := pack_complex(re => c_bf_y_weight_re, im => c_bf_y_weight_im, w => c_sdp_W_bf_weight); + END IF; + ELSE + -- default set all weights to zero + v_weight := 0; + END IF; + v_addr := g_beamlet; -- beamlet index + v_addr := v_addr + P * c_sdp_S_sub_bf; -- antenna input polarization address offset + v_addr := v_addr + A * v_span; -- antenna input address offset + v_addr := v_addr + PB * c_sdp_A_pn * v_span; -- beamlet polarization address offset + v_addr := v_addr + U * c_mm_span_ram_bf_weights; -- beamset address offset + mmf_mm_bus_wr(c_mm_file_ram_bf_weights, v_addr, v_weight, tb_clk); + END LOOP; END LOOP; END LOOP; END LOOP; - -- . read back BF weights for g_beamlet + -- . read back BF weights for g_beamlet in S_sub_bf 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; + FOR PB IN 0 TO c_sdp_N_pol_bf-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; -- beamlet index + v_addr := v_addr + P * c_sdp_S_sub_bf; -- antenna input polarization address offset + v_addr := v_addr + A * v_span; -- antenna input address offset + v_addr := v_addr + PB * c_sdp_A_pn * v_span; -- beamlet polarization address offset + v_addr := v_addr + U * c_mm_span_ram_bf_weights; -- beamset address offset + 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 and both beamlet polarizations, + -- so fine to use only one sp_bf_x_weights_*_arr() + v_S := A * c_sdp_N_pol + P; + IF PB = 0 THEN + sp_bf_x_weights_re_arr(v_S) <= v_re; + sp_bf_x_weights_im_arr(v_S) <= v_im; + sp_bf_x_weights_gain_arr(v_S) <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_bf_weight); + sp_bf_x_weights_phase_arr(v_S) <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI; + ELSE + sp_bf_y_weights_re_arr(v_S) <= v_re; + sp_bf_y_weights_im_arr(v_S) <= v_im; + sp_bf_y_weights_gain_arr(v_S) <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_bf_weight); + sp_bf_y_weights_phase_arr(v_S) <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI; + END IF; + END LOOP; END LOOP; END LOOP; END LOOP; @@ -804,7 +923,7 @@ BEGIN 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; + sp_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; @@ -812,10 +931,7 @@ BEGIN 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)); + sp_sst <= TO_UREAL(sp_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 @@ -831,8 +947,8 @@ BEGIN 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_W := I MOD c_stat_data_sz; -- 0, 1 per statistics word, word index + v_PB := (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 @@ -848,7 +964,7 @@ BEGIN 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; + bsts_arr2(v_PB)(v_G) <= v_stat_data; stat_data <= v_stat_data; -- for time series view in Wave window END IF; END IF; @@ -859,8 +975,8 @@ BEGIN -- 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 + bst_x_arr(U) <= TO_UREAL(bsts_arr2(0)(v_G)); -- X pol beamlet + bst_y_arr(U) <= TO_UREAL(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 @@ -875,10 +991,6 @@ BEGIN 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)); @@ -886,69 +998,88 @@ BEGIN print_str(""); print_str("SST results:"); + print_str(". sst_weighted_subbands_flag = " & sl_to_str(sst_weighted_subbands_flag)); + print_str(""); 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(". sp_sst = " & real_to_str(sp_sst, 20, 1)); + print_str(". sp_sst / c_exp_subband_sst = " & real_to_str(sp_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(". c_exp_beamlet_x_ampl = " & int_to_str(NATURAL(c_exp_beamlet_x_ampl))); + print_str(". c_exp_beamlet_x_power = " & real_to_str(c_exp_beamlet_x_power, 20, 1)); + print_str(". c_exp_beamlet_x_bst = " & real_to_str(c_exp_beamlet_x_bst, 20, 1)); + print_str(""); + print_str(". c_exp_beamlet_y_ampl = " & int_to_str(NATURAL(c_exp_beamlet_y_ampl))); + print_str(". c_exp_beamlet_y_power = " & real_to_str(c_exp_beamlet_y_power, 20, 1)); + print_str(". c_exp_beamlet_y_bst = " & real_to_str(c_exp_beamlet_y_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)); + print_str(". bst_x_arr(" & INTEGER'IMAGE(v_G) & ") = " & real_to_str(bst_x_arr(U), 20, 1)); + print_str(". bst_y_arr(" & INTEGER'IMAGE(v_G) & ") = " & real_to_str(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)); + print_str(". bst_x_arr(" & INTEGER'IMAGE(v_G) & ") / c_exp_beamlet_x_bst = " & real_to_str(bst_x_arr(U) / c_exp_beamlet_x_bst, 20, 6)); + print_str(". bst_y_arr(" & INTEGER'IMAGE(v_G) & ") / c_exp_beamlet_y_bst = " & real_to_str(bst_y_arr(U) / c_exp_beamlet_y_bst, 20, 6)); END LOOP; 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))); - + print_str(". c_exp_beamlet_scale = " & int_to_str(c_exp_beamlet_scale)); + print_str(""); + print_str(". c_exp_beamlet_x_output_ampl = " & int_to_str(NATURAL(c_exp_beamlet_x_output_ampl))); + print_str(". c_exp_beamlet_x_output_phase = " & int_to_str(INTEGER(c_exp_beamlet_x_output_phase))); + print_str(". c_exp_beamlet_x_output_re = " & int_to_str(INTEGER(c_exp_beamlet_x_output_re))); + print_str(". c_exp_beamlet_x_output_im = " & int_to_str(INTEGER(c_exp_beamlet_x_output_im))); + print_str(""); + print_str(". c_exp_beamlet_y_output_ampl = " & int_to_str(NATURAL(c_exp_beamlet_y_output_ampl))); + print_str(". c_exp_beamlet_y_output_phase = " & int_to_str(INTEGER(c_exp_beamlet_y_output_phase))); + print_str(". c_exp_beamlet_y_output_re = " & int_to_str(INTEGER(c_exp_beamlet_y_output_re))); + print_str(". c_exp_beamlet_y_output_im = " & int_to_str(INTEGER(c_exp_beamlet_y_output_im))); + --------------------------------------------------------------------------- - -- Verify SST and BST + -- Verify SST --------------------------------------------------------------------------- - -- 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; + ASSERT sp_sst > c_stat_lo_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + ASSERT sp_sst < c_stat_hi_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + --------------------------------------------------------------------------- + -- Verify BST + --------------------------------------------------------------------------- -- 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; + -- X-pol + ASSERT bst_x_arr(U) < c_stat_hi_factor * c_exp_beamlet_x_bst REPORT "Wrong beamlet X power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; + ASSERT bst_x_arr(U) > c_stat_lo_factor * c_exp_beamlet_x_bst REPORT "Wrong beamlet X power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; + -- Y-pol + ASSERT bst_y_arr(U) > c_stat_lo_factor * c_exp_beamlet_y_bst REPORT "Wrong beamlet Y power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; + ASSERT bst_y_arr(U) < c_stat_hi_factor * c_exp_beamlet_y_bst REPORT "Wrong beamlet Y power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; END LOOP; --------------------------------------------------------------------------- -- Verify beamlet output in 10GbE UDP offload --------------------------------------------------------------------------- - 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; + -- X-pol + v_re := TO_SINT(rx_beamlet_list_re(c_exp_beamlet_x_index)); v_re_exp := c_exp_beamlet_x_output_re; + v_im := TO_SINT(rx_beamlet_list_im(c_exp_beamlet_x_index)); v_im_exp := c_exp_beamlet_x_output_im; + ASSERT v_re > INTEGER(v_re_exp) - c_beamlet_output_delta REPORT "Wrong beamlet X 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 beamlet X 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 beamlet X 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 beamlet X output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR; + -- Y-pol + v_re := TO_SINT(rx_beamlet_list_re(c_exp_beamlet_y_index)); v_re_exp := c_exp_beamlet_y_output_re; + v_im := TO_SINT(rx_beamlet_list_im(c_exp_beamlet_y_index)); v_im_exp := c_exp_beamlet_y_output_im; + ASSERT v_re > INTEGER(v_re_exp) - c_beamlet_output_delta REPORT "Wrong beamlet Y 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 beamlet Y 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 beamlet Y 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 beamlet Y output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR; --------------------------------------------------------------------------- -- End Simulation @@ -967,22 +1098,22 @@ BEGIN p_test_counters : PROCESS(ext_clk) BEGIN IF rising_edge(ext_clk) THEN - -- Count test_offload_sosi packets - IF test_offload_sosi.sop = '1' THEN - test_offload_sop_cnt <= test_offload_sop_cnt + 1; -- early count + -- Count rx_beamlet_sosi packets + IF rx_beamlet_sosi.sop = '1' THEN + rx_beamlet_sop_cnt <= rx_beamlet_sop_cnt + 1; -- early count END IF; - IF test_offload_sosi.eop = '1' THEN - test_offload_eop_cnt <= test_offload_eop_cnt + 1; -- after count + IF rx_beamlet_sosi.eop = '1' THEN + rx_beamlet_eop_cnt <= rx_beamlet_eop_cnt + 1; -- after count END IF; END IF; END PROCESS; - -- Count sync intervals using in_sosi.sync, because there is no test_offload_sosi.sync + -- Count sync intervals using in_sosi.sync, because there is no rx_beamlet_sosi.sync in_sync_cnt <= in_sync_cnt + 1 WHEN rising_edge(ext_clk) AND in_sync = '1'; - test_sync_cnt <= in_sync_cnt - 1; -- optionally adjust to fit test_offload_sosi + test_sync_cnt <= in_sync_cnt - 1; -- optionally adjust to fit rx_beamlet_sosi - -- Prepare exp_sdp_cep_header before test_offload_sosi.eop, so that - -- p_exp_sdp_cep_header can verify it at test_offload_sosi.eop. + -- Prepare exp_sdp_cep_header before rx_beamlet_sosi.eop, so that + -- p_exp_sdp_cep_header can verify it at rx_beamlet_sosi.eop. p_exp_sdp_cep_header : PROCESS(exp_dp_bsn) BEGIN @@ -1044,10 +1175,10 @@ BEGIN WAIT UNTIL rising_edge(ext_clk); -- Prepare exp_sdp_cep_header at sop, so that it can be verified at eop - IF test_offload_sosi.sop = '1' THEN + IF rx_beamlet_sosi.sop = '1' THEN -- Expected BSN increments by c_sdp_cep_nof_blocks_per_packet = 4 blocks per packet - IF test_offload_sop_cnt MOD c_sdp_N_beamsets = 0 THEN - exp_dp_bsn <= c_init_bsn + (test_offload_sop_cnt / c_sdp_N_beamsets) * c_sdp_cep_nof_blocks_per_packet; + IF rx_beamlet_sop_cnt MOD c_sdp_N_beamsets = 0 THEN + exp_dp_bsn <= c_init_bsn + (rx_beamlet_sop_cnt / c_sdp_N_beamsets) * c_sdp_cep_nof_blocks_per_packet; END IF; END IF; @@ -1056,7 +1187,7 @@ BEGIN -- or 1, but the order in which the packets arrive is undetermined. -- Therefore accept any beamlet_index MOD c_sdp_S_sub_bf = 0 as correct -- in func_sdp_verify_cep_header(). - IF test_offload_sosi.eop = '1' THEN + IF rx_beamlet_sosi.eop = '1' THEN v_bool := func_sdp_verify_cep_header(rx_sdp_cep_header, exp_sdp_cep_header); END IF; END PROCESS; @@ -1072,47 +1203,47 @@ BEGIN -- . expect c_sdp_cep_nof_beamlets_per_block = c_sdp_S_sub_bf = 488 dual pol -- and complex beamlets per packet, so 2 dual pol beamlets/64b data word. -- . Beamlets array is stored big endian in the data, so X index 0 first in - -- MSByte of test_offload_sosi.data. + -- MSByte of rx_beamlet_sosi.data. p_rx_cep_beamlets : PROCESS BEGIN rx_beamlet_cnt <= 0; rx_beamlet_valid <= '0'; -- Wait until start of a beamlet packet, capture only first block in packet - proc_common_wait_until_high(ext_clk, test_offload_sosi.sop); - -- 2 dual pol beamlets (= XY, XY) per 64b data word - 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, rx_beamlet_sosi.sop); + -- c_nof_beamlets_per_data = 2 dual pol beamlets (= XY, XY) per 64b data word + FOR I IN 0 TO (c_sdp_cep_nof_blocks_per_packet * c_sdp_cep_nof_beamlets_per_block / c_nof_beamlets_per_data)-1 LOOP + proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid); rx_beamlet_valid <= '1'; -- 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 - rx_beamlet_arr_im(1) <= test_offload_sosi.data(47 DOWNTO 40); - rx_beamlet_arr_re(2) <= test_offload_sosi.data(23 DOWNTO 16); -- X - rx_beamlet_arr_im(2) <= test_offload_sosi.data(31 DOWNTO 24); - rx_beamlet_arr_re(3) <= test_offload_sosi.data( 7 DOWNTO 0); -- Y - rx_beamlet_arr_im(3) <= test_offload_sosi.data(15 DOWNTO 8); - IF I < c_sdp_cep_nof_beamlets_per_block/2 THEN + rx_beamlet_arr_re(0) <= rx_beamlet_sosi.data(55 DOWNTO 48); -- X + rx_beamlet_arr_im(0) <= rx_beamlet_sosi.data(63 DOWNTO 56); + rx_beamlet_arr_re(1) <= rx_beamlet_sosi.data(39 DOWNTO 32); -- Y + rx_beamlet_arr_im(1) <= rx_beamlet_sosi.data(47 DOWNTO 40); + rx_beamlet_arr_re(2) <= rx_beamlet_sosi.data(23 DOWNTO 16); -- X + rx_beamlet_arr_im(2) <= rx_beamlet_sosi.data(31 DOWNTO 24); + rx_beamlet_arr_re(3) <= rx_beamlet_sosi.data( 7 DOWNTO 0); -- Y + rx_beamlet_arr_im(3) <= rx_beamlet_sosi.data(15 DOWNTO 8); + IF I < c_sdp_cep_nof_beamlets_per_block / c_nof_beamlets_per_data 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); -- 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); -- 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); -- 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); -- Y - rx_beamlet_list_im(I*4 + 3) <= test_offload_sosi.data(15 DOWNTO 8); + rx_beamlet_list_re(I*4 + 0) <= rx_beamlet_sosi.data(55 DOWNTO 48); -- X + rx_beamlet_list_im(I*4 + 0) <= rx_beamlet_sosi.data(63 DOWNTO 56); + rx_beamlet_list_re(I*4 + 1) <= rx_beamlet_sosi.data(39 DOWNTO 32); -- Y + rx_beamlet_list_im(I*4 + 1) <= rx_beamlet_sosi.data(47 DOWNTO 40); + rx_beamlet_list_re(I*4 + 2) <= rx_beamlet_sosi.data(23 DOWNTO 16); -- X + rx_beamlet_list_im(I*4 + 2) <= rx_beamlet_sosi.data(31 DOWNTO 24); + rx_beamlet_list_re(I*4 + 3) <= rx_beamlet_sosi.data( 7 DOWNTO 0); -- Y + rx_beamlet_list_im(I*4 + 3) <= rx_beamlet_sosi.data(15 DOWNTO 8); END IF; - proc_common_wait_until_high(ext_clk, test_offload_sosi.valid); + proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid); -- Use at least one WAIT instead of proc_common_wait_some_cycles() to -- avoid Modelsim warning: (vcom-1090) Possible infinite loop: Process -- contains no WAIT statement. WAIT UNTIL rising_edge(ext_clk); rx_beamlet_valid <= '0'; - rx_beamlet_cnt <= (rx_beamlet_cnt + 4) MOD c_sdp_cep_nof_beamlets_per_block; -- 4 blocks/packet + rx_beamlet_cnt <= (rx_beamlet_cnt + c_nof_beamlets_per_data) MOD c_sdp_cep_nof_beamlets_per_block; -- 4 blocks/packet END LOOP; END PROCESS; -- To view the 64 bit 10GbE offload data more easily in the Wave window - test_offload_data <= test_offload_sosi.data(c_longword_w-1 DOWNTO 0); + rx_beamlet_data <= rx_beamlet_sosi.data(c_longword_w-1 DOWNTO 0); END tb;