From b434adf97722035a30d867abfb4f216bb35f8400 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Tue, 4 Oct 2022 15:18:26 +0200 Subject: [PATCH] Clarify tb working by using g_first_gn, g_nof_rn and g_global_sp. --- .../tb_lofar2_unb2c_sdp_station_bf_ring.vhd | 394 ++++++++++-------- 1 file changed, 214 insertions(+), 180 deletions(-) diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd index 84baf1ad8b..35a57bab05 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd @@ -26,41 +26,41 @@ -- -- Description: -- This tb is a balance between verification coverage and keeping it simple: --- - Use only one signal input (g_sp). Put same remnant WG signal on the --- other signal inputs. +-- - Use only one signal input (g_global_sp) with strong WG. Put same remnant +-- weak WG signal on the other g_nof_rn * S_pn - 1 signal inputs. -- - Use different BF weight for the two beamlet polarizations (g_bf_x_gain, --- g_bf_x_phase and g_bf_y_phase, g_bf_y_phase) of signal input g_sp. +-- g_bf_x_phase and g_bf_y_phase, g_bf_y_phase) of signal input g_global_sp. -- Using different BF weights for the N_pol_bf = 2 BF polarizations allows -- verification of the dual polarization beamlet. --- - Use same remnant BF weight for the other S_pn - 1 = 11 signal inputs. +-- - Use same remnant BF weight for the other g_nof_rn * S_pn - 1 signal inputs. -- The remnant signal inputs and BF weights allow verifying the BF sum if -- they are not 0. Using the same settings for all remnant SP simplyfies -- the tb, while still testing the BF sum. --- - Select one beamlet for the subband (g_beamlet). Selecting one beamlet --- other than the default beamlet for the subband is sufficient to verify --- the beamlet subband select. +-- - Select one beamlet (g_beamlet) for the subband (g_subband). Selecting +-- one beamlet other than the default beamlet for the subband is sufficient +-- to verify the beamlet subband select. -- - Use same stimuli for both beamsets. -- -- MM control actions: -- --- 1) Enable calc mode for WG on signal input (si) g_sp via reg_diag_wg with: +-- 1) Enable calc mode for WG on signal input (si) g_global_sp via reg_diag_wg with: -- g_subband = 102 --> 102 * f_sub = 19.921875 MHz -- g_sp_ampl = 1.0 --> 1.0 yield WG ampl = 2**13 -- g_sp_phase --> subband phase --- Use g_sp_remnant_ampl = 0.1 and g_sp_remnant_phase = 0.0 for the other --- S_pn-1 = 11 signal inputs, than g_sp, that are not used in the BF. +-- Use g_sp_remnant_ampl = 0.1 and g_sp_remnant_phase = 0.0 for all other +-- g_nof_rn * S_pn - 1 signal inputs, than g_global_sp, 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. -- --- 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. +-- 3) Read and verify subband statistics (SST) for g_global_sp. This also reads the +-- SST of the other signal input of the WPFB that processes g_global_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. +-- 5) Apply BF weight to g_beamlet X beam and Y beam, so for example if g_global_sp +-- = 3, then w_x3 = g_bf_x_gain,phase and w_y3 = g_bf_y_gain,phase. The +-- BF weights for all other beamlets (/= g_beamlet) are 0. -- -- WG BF BF -- si weight weight @@ -93,7 +93,6 @@ -- \----------------|---> beamlet_x -- \--> beamlet_y -- --- -- 6) Read and verify beamlet statistics (BST) -- View sp_sst in Wave window -- View bst_x_arr, bst_y_arr in Wave window @@ -109,7 +108,7 @@ -- Usage: -- > as 7 # default -- > as 12 # for detailed debugging --- # Manually add missing signal +-- # Manually add missing signals and constants using objects in GUI -- > add wave -position insertpoint \ -- sim:/tb_lofar2_unb2c_sdp_station_bf_ring/sp_ssts_arr2 \ -- sim:/tb_lofar2_unb2c_sdp_station_bf_ring/bsts_arr2 @@ -139,7 +138,9 @@ USE tech_pll_lib.tech_pll_component_pkg.ALL; ENTITY tb_lofar2_unb2c_sdp_station_bf_ring IS GENERIC ( - g_sp : NATURAL := 3; -- WG signal path (SP) index in range(S_pn = 12) + g_first_gn : NATURAL := 0; -- first global node (GN) in ring + g_nof_rn : NATURAL := 2; -- nof ring nodes (RN) in ring + g_global_sp : NATURAL := 3; -- WG gloabl signal path (SP) index in range(g_first_gn * S_pn, (g_first_gn + g_nof_rn) * S_pn - 1), S_pn = 12 g_sp_ampl : REAL := 0.5; -- WG normalized amplitude g_sp_phase : REAL := -110.0; -- WG phase in degrees = subband phase g_sp_remnant_ampl : REAL := 0.1; -- WG normalized amplitude for remnant sp @@ -147,14 +148,14 @@ ENTITY tb_lofar2_unb2c_sdp_station_bf_ring IS g_subband : NATURAL := 102; -- select g_subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz g_beamlet : NATURAL := c_sdp_S_sub_bf-1; -- 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_x_gain : REAL := 0.7; -- g_beamlet X BF weight normalized gain for g_sp - g_bf_y_gain : REAL := 0.6; -- g_beamlet Y BF weight normalized gain for g_sp - g_bf_x_phase : REAL := 30.0; -- g_beamlet X BF weight phase rotation in degrees for g_sp - g_bf_y_phase : REAL := 40.0; -- g_beamlet Y BF weight phase rotation in degrees for g_sp + g_bf_x_gain : REAL := 0.7; -- g_beamlet X BF weight normalized gain for g_global_sp + g_bf_y_gain : REAL := 0.6; -- g_beamlet Y BF weight normalized gain for g_global_sp + g_bf_x_phase : REAL := 30.0; -- g_beamlet X BF weight phase rotation in degrees for g_global_sp + g_bf_y_phase : REAL := 40.0; -- g_beamlet Y BF weight phase rotation in degrees for g_global_sp g_bf_remnant_x_gain : REAL := 0.05; -- g_beamlet X BF weight normalized gain for remnant sp g_bf_remnant_y_gain : REAL := 0.04; -- g_beamlet Y BF weight normalized gain for remnant sp - g_bf_remnant_x_phase : REAL := 170.0; -- g_beamlet X BF weight phase rotation in degrees for g_sp - g_bf_remnant_y_phase : REAL := -135.0; -- g_beamlet Y BF weight phase rotation in degrees for g_sp + g_bf_remnant_x_phase : REAL := 170.0; -- g_beamlet X BF weight phase rotation in degrees for remnant sp + g_bf_remnant_y_phase : REAL := -135.0; -- g_beamlet Y BF weight phase rotation in degrees for remnant sp 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 ); @@ -163,16 +164,21 @@ END tb_lofar2_unb2c_sdp_station_bf_ring; ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS CONSTANT c_sim : BOOLEAN := TRUE; - CONSTANT c_unb_nr : NATURAL := 0; -- UniBoard 0 - CONSTANT c_node_nr : NATURAL := 0; - CONSTANT c_nof_rn : NATURAL := 2; - CONSTANT c_last_unb_nr : NATURAL := (c_nof_rn-1) / c_quad; - CONSTANT c_last_rn_nr : NATURAL := c_nof_rn-1; - CONSTANT c_gn_index : NATURAL := c_unb_nr * c_quad + c_nof_rn-1; -- end node GN + CONSTANT c_first_unb_nr : NATURAL := g_first_gn / c_quad; -- c_quad = 4 FPGAs per UniBoard2 + CONSTANT c_first_node_nr : NATURAL := g_first_gn MOD c_quad; -- first node_nr in range(c_quad) = [0:3] on c_first_unb_nr + CONSTANT c_last_rn : NATURAL := g_nof_rn - 1; -- first RN has index 0 by definition. + CONSTANT c_last_gn : NATURAL := g_first_gn + c_last_rn; -- last global node (GN) in ring + CONSTANT c_last_unb_nr : NATURAL := c_last_gn / c_quad; + CONSTANT c_last_node_nr : NATURAL := c_last_gn MOD c_quad; + CONSTANT c_global_sp_gn : NATURAL := g_global_sp / c_sdp_S_pn; -- global node (GN) of where g_global_sp is located + CONSTANT c_local_sp : NATURAL := g_global_sp MOD c_sdp_S_pn; -- local SP index of g_global_sp on c_global_sp_gn + CONSTANT c_global_sp_unb_nr : NATURAL := c_global_sp_gn / c_quad; -- unb_nr of where g_global_sp is located + CONSTANT c_global_sp_node_nr : NATURAL := c_global_sp_gn MOD c_quad; -- unb_nr of where g_global_sp is located + CONSTANT c_init_bsn : NATURAL := 17; -- some recognizable value >= 0 CONSTANT c_nof_lanes : NATURAL := c_sdp_N_beamsets; - CONSTANT c_id : STD_LOGIC_VECTOR(7 DOWNTO 0) := TO_UVEC(c_gn_index, 8); + CONSTANT c_last_id : STD_LOGIC_VECTOR(7 DOWNTO 0) := TO_UVEC(c_last_gn, 8); CONSTANT c_version : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00"; CONSTANT c_fw_version : t_unb2c_board_fw_version := (1, 0); @@ -199,11 +205,11 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS CONSTANT c_beamlet_output_delta : INTEGER := 2; -- +-delta margin -- header fields - CONSTANT c_cep_eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := c_sdp_cep_eth_src_mac_47_16 & func_sdp_gn_index_to_mac_15_0(c_gn_index); - CONSTANT c_cep_ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0) := c_sdp_cep_ip_src_addr_31_16 & func_sdp_gn_index_to_ip_15_0(c_gn_index); - CONSTANT c_cep_udp_src_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := c_sdp_cep_udp_src_port_15_8 & c_id; -- D0 & c_id + CONSTANT c_cep_eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := c_sdp_cep_eth_src_mac_47_16 & func_sdp_gn_index_to_mac_15_0(c_last_gn); + CONSTANT c_cep_ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0) := c_sdp_cep_ip_src_addr_31_16 & func_sdp_gn_index_to_ip_15_0(c_last_gn); + CONSTANT c_cep_udp_src_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := c_sdp_cep_udp_src_port_15_8 & c_last_id; -- D0 & c_last_id - CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDD#; -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window for c_nof_rn = 2. + CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDD#; -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window for g_nof_rn = 2. 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_beamlet_index : NATURAL := 0; -- depends on beamset bset * c_sdp_S_sub_bf @@ -234,8 +240,8 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS CONSTANT c_wg_remnant_phase : REAL := g_sp_remnant_phase + c_wg_phase_offset; -- WG phase in degrees -- 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_pol_index : NATURAL := c_local_sp MOD c_sdp_Q_fft; + CONSTANT c_pfb_index : NATURAL := c_local_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 sinus 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 @@ -255,7 +261,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS -- . select CONSTANT c_exp_beamlet_x_index : NATURAL := g_beamlet * c_sdp_N_pol_bf; -- X index in beamset 0 CONSTANT c_exp_beamlet_y_index : NATURAL := g_beamlet * c_sdp_N_pol_bf + 1; -- Y index in beamset 0 - -- . Beamlet weights for selected g_sp + -- . Beamlet weights for selected g_global_sp CONSTANT c_bf_x_weight_re : INTEGER := INTEGER(COMPLEX_RE(g_bf_x_gain * REAL(c_sdp_unit_bf_weight), g_bf_x_phase)); CONSTANT c_bf_x_weight_im : INTEGER := INTEGER(COMPLEX_IM(g_bf_x_gain * REAL(c_sdp_unit_bf_weight), g_bf_x_phase)); CONSTANT c_bf_y_weight_re : INTEGER := INTEGER(COMPLEX_RE(g_bf_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_y_phase)); @@ -265,10 +271,10 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS CONSTANT c_bf_remnant_y_weight_re : INTEGER := INTEGER(COMPLEX_RE(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase)); CONSTANT c_bf_remnant_y_weight_im : INTEGER := INTEGER(COMPLEX_IM(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase)); - -- Model the SDP beamformer for one g_sp and S_pn-1 = 11 remnant signal inputs + -- Model the SDP beamformer for one g_global_sp and g_nof_rn * S_pn - 1 remnant signal inputs FUNCTION bf_calculate_expected_beamlet(sp_subband_ampl, sp_subband_phase, sp_bf_gain, sp_bf_phase, rem_subband_ampl, rem_subband_phase, rem_bf_gain, rem_bf_phase : REAL) RETURN t_real_arr IS -- 0:3 = ampl, phase, re, im - CONSTANT c_nof_rem : REAL := REAL(c_nof_rn * c_sdp_S_pn - 1); -- BF for one g_sp and N_rn * S_PN - 1 remnant signal inputs + CONSTANT c_nof_rem : REAL := REAL(g_nof_rn * c_sdp_S_pn - 1); -- BF for one g_global_sp and N_rn * S_PN - 1 remnant signal inputs VARIABLE v_sp_ampl, v_sp_phase, v_sp_re, v_sp_im : REAL; VARIABLE v_rem_ampl, v_rem_phase, v_rem_re, v_rem_im : REAL; VARIABLE v_sum_ampl, v_sum_phase, v_sum_re, v_sum_im : REAL; @@ -345,21 +351,19 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS 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"; - 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_last_unb_nr, c_last_rn_nr MOD c_quad) & "RAM_ST_BST"; --end RN - CONSTANT c_mm_file_reg_stat_enable_bst : STRING := mmf_unb_file_prefix(c_unb_nr + c_last_unb_nr, c_last_rn_nr MOD c_quad) & "REG_STAT_ENABLE_BST"; --end RN - CONSTANT c_mm_file_reg_dp_xonoff : STRING := mmf_unb_file_prefix(c_unb_nr + c_last_unb_nr, c_last_rn_nr MOD c_quad) & "REG_DP_XONOFF"; --end RN - 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 + -- Use c_mm_file_reg_* on c_last_gn for MM accesses to only last node in ring, e.g. for control beamlet output, read BSN, read back + -- Use mmf_unb_file_prefix() and range(g_nof_rn) for MM access loop to all nodes in ring, e.g. for control BSN source, BF weights + CONSTANT c_mm_file_reg_bsn_scheduler_wg : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "REG_BSN_SCHEDULER"; -- read current BSN + CONSTANT c_mm_file_ram_equalizer_gains : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "RAM_EQUALIZER_GAINS"; -- read default subband weight + CONSTANT c_mm_file_reg_dp_selector : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "REG_DP_SELECTOR"; -- read sst_weighted_subbands_flag + CONSTANT c_mm_file_ram_st_sst : STRING := mmf_unb_file_prefix(c_global_sp_unb_nr, c_global_sp_node_nr) & "RAM_ST_SST"; -- read SST from GN with g_global_sp + CONSTANT c_mm_file_ram_st_bst : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "RAM_ST_BST"; -- read BST + CONSTANT c_mm_file_reg_stat_enable_bst : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "REG_STAT_ENABLE_BST"; -- control BST offload + CONSTANT c_mm_file_reg_dp_xonoff : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "REG_DP_XONOFF"; -- beamlet output + CONSTANT c_mm_file_ram_ss_ss_wide : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "RAM_SS_SS_WIDE"; --readback + CONSTANT c_mm_file_ram_bf_weights : STRING := mmf_unb_file_prefix(c_global_sp_unb_nr, c_global_sp_node_nr) & "RAM_BF_WEIGHTS"; -- readback from GN with g_global_sp + CONSTANT c_mm_file_reg_bf_scale : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "REG_BF_SCALE"; -- readback + CONSTANT c_mm_file_reg_hdr_dat : STRING := mmf_unb_file_prefix(c_last_unb_nr, c_last_node_nr) & "REG_HDR_DAT"; -- control beamlet output -- Tb SIGNAL stimuli_done : STD_LOGIC := '0'; @@ -382,15 +386,15 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS SIGNAL rd_cep_eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); SIGNAL rd_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); SIGNAL rd_cep_ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); - SIGNAL rd_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); SIGNAL rd_cep_ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); + SIGNAL rd_cep_udp_src_port : STD_LOGIC_VECTOR(15 DOWNTO 0); 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); -- FSUB - -- . Read sp_ssts_arr2 = SST for one WPFB unit that processes g_sp + -- . Read sp_ssts_arr2 = SST for one WPFB unit that processes g_global_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); @@ -410,15 +414,15 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS 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_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); - SIGNAL sp_bf_x_weights_im_arr : t_integer_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); - SIGNAL sp_bf_x_weights_gain_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); - SIGNAL sp_bf_x_weights_phase_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_x_weights_re_arr : t_integer_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_x_weights_im_arr : t_integer_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_x_weights_gain_arr : t_real_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_x_weights_phase_arr : t_real_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); -- . beamlet Y-pol - SIGNAL sp_bf_y_weights_re_arr : t_integer_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); - SIGNAL sp_bf_y_weights_im_arr : t_integer_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); - SIGNAL sp_bf_y_weights_gain_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); - SIGNAL sp_bf_y_weights_phase_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_y_weights_re_arr : t_integer_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_y_weights_im_arr : t_integer_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_y_weights_gain_arr : t_real_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_y_weights_phase_arr : t_real_arr(0 TO g_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); -- . BST SIGNAL bsts_arr2 : t_slv_64_beamlets_arr(c_sdp_N_pol_bf-1 DOWNTO 0); -- [pol_bf][blet] @@ -472,13 +476,13 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0); SIGNAL SA_CLK : STD_LOGIC := '1'; - SIGNAL i_QSFP_0_TX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); - SIGNAL i_QSFP_0_RX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); - SIGNAL i_RING_0_TX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); - SIGNAL i_RING_0_RX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); - SIGNAL i_RING_1_TX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); - SIGNAL i_RING_1_RX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); - SIGNAL i_QSFP_1_lpbk : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_QSFP_0_TX : t_unb2c_board_qsfp_bus_2arr(c_last_rn DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_QSFP_0_RX : t_unb2c_board_qsfp_bus_2arr(c_last_rn DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_0_TX : t_unb2c_board_qsfp_bus_2arr(c_last_rn DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_0_RX : t_unb2c_board_qsfp_bus_2arr(c_last_rn DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_1_TX : t_unb2c_board_qsfp_bus_2arr(c_last_rn DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_1_RX : t_unb2c_board_qsfp_bus_2arr(c_last_rn DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_QSFP_1_lpbk : t_unb2c_board_qsfp_bus_2arr(c_last_rn DOWNTO 0) := (OTHERS => (OTHERS => '0')); -- back transceivers SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0); @@ -512,14 +516,14 @@ BEGIN ------------------------------------------------------------------------------ -- DUT ------------------------------------------------------------------------------ - gen_dut : FOR RN IN 0 TO c_nof_rn -1 GENERATE + gen_dut : FOR RN IN 0 TO c_last_rn GENERATE u_lofar_unb2c_sdp_station_bf : ENTITY lofar2_unb2c_sdp_station_lib.lofar2_unb2c_sdp_station GENERIC MAP ( g_design_name => "lofar2_unb2c_sdp_station_bf_ring", g_design_note => "", g_sim => c_sim, - g_sim_unb_nr => c_unb_nr + (RN / c_quad), - g_sim_node_nr => RN MOD c_quad, + g_sim_unb_nr => (g_first_gn + RN) / c_quad, + g_sim_node_nr => (g_first_gn + RN) MOD c_quad, g_wpfb => c_wpfb_sim, g_bsn_nof_clk_per_sync => c_nof_clk_per_sync, g_scope_selected_subband => g_subband @@ -534,7 +538,7 @@ BEGIN -- Others VERSION => c_version, - ID => ( TO_UVEC(RN / c_quad, c_unb2c_board_nof_uniboard_w) & TO_UVEC(RN MOD c_quad, c_unb2c_board_nof_chip_w) ), + ID => ( TO_UVEC((g_first_gn + RN) / c_quad, c_unb2c_board_nof_uniboard_w) & TO_UVEC((g_first_gn + RN) MOD c_quad, c_unb2c_board_nof_chip_w) ), TESTIO => open, -- 1GbE Control Interface @@ -572,17 +576,16 @@ BEGIN END GENERATE; -- Ring connections - gen_ring : FOR I IN 0 TO c_nof_rn -2 GENERATE + gen_ring : FOR RN IN 0 TO c_last_rn-1 GENERATE -- Connect consecutive nodes with RING interfaces (PCB) - i_RING_0_RX(I+1) <= i_RING_1_TX(I); - i_RING_1_RX(I) <= i_RING_0_TX(I+1); + i_RING_0_RX(RN + 1) <= i_RING_1_TX(RN); + i_RING_1_RX(RN) <= i_RING_0_TX(RN + 1); END GENERATE; -- Connect first and last nodes with QSFP interface. - i_QSFP_0_RX(0) <= i_QSFP_0_TX(c_nof_rn-1); - i_QSFP_0_RX(c_nof_rn-1) <= i_QSFP_0_TX(0); + i_QSFP_0_RX(0) <= i_QSFP_0_TX(c_last_rn); + i_QSFP_0_RX(c_last_rn) <= i_QSFP_0_TX(0); - ------------------------------------------------------------------------------ -- CEP model @@ -619,7 +622,7 @@ BEGIN dp_rst => dest_rst, dp_clk => ext_clk, - serial_rx_arr(0) => i_QSFP_1_lpbk(c_nof_rn-1)(0), -- Last RN must be used as end node. + serial_rx_arr(0) => i_QSFP_1_lpbk(c_last_rn)(0), -- Last RN must be used as end node. src_out_arr(0) => tr_10GbE_src_out, src_in_arr(0) => tr_10GbE_src_in @@ -660,6 +663,7 @@ BEGIN tb_clk <= NOT tb_clk AFTER c_tb_clk_period/2; -- Testbench MM clock p_mm_stimuli : PROCESS + VARIABLE v_gn : NATURAL; VARIABLE v_bsn : NATURAL; VARIABLE v_sp_sst : REAL := 0.0; VARIABLE v_bst : REAL := 0.0; @@ -722,16 +726,17 @@ BEGIN -- . Write - FOR RN IN 0 TO c_nof_rn-1 LOOP - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 7, TO_UINT(c_exp_sdp_info.station_id), tb_clk); - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk); - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk); - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk); - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk); + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 7, TO_UINT(c_exp_sdp_info.station_id), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk); -- . Read - mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 3, rd_data, tb_clk); rd_sdp_info.f_adc <= rd_data(0); - mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 2, rd_data, tb_clk); rd_sdp_info.fsub_type <= rd_data(0); - mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 0, rd_data, tb_clk); rd_sdp_info.block_period <= rd_data(15 DOWNTO 0); + mmf_mm_bus_rd(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 3, rd_data, tb_clk); rd_sdp_info.f_adc <= rd_data(0); + mmf_mm_bus_rd(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 2, rd_data, tb_clk); rd_sdp_info.fsub_type <= rd_data(0); + mmf_mm_bus_rd(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_SDP_INFO", 0, rd_data, tb_clk); rd_sdp_info.block_period <= rd_data(15 DOWNTO 0); END LOOP; proc_common_wait_some_cycles(tb_clk, 1); @@ -744,13 +749,13 @@ BEGIN ---- Set and check BF per beamset ------------------------------------------------------------------------------ FOR bset IN 0 TO c_sdp_N_beamsets-1 LOOP - -- MM beamlet_scale + ---------------------------------------------------------------------------- + -- MM beamlet_scale on last node + ---------------------------------------------------------------------------- -- . write v_offset := bset * c_mm_span_reg_bf_scale; - FOR RN IN 0 TO c_nof_rn-1 LOOP - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BF_SCALE", v_offset + 0, c_exp_beamlet_scale, tb_clk); - END LOOP; - proc_common_wait_cross_clock_domain_latency(c_mm_clk_period, c_ext_clk_period); + mmf_mm_bus_wr(c_mm_file_reg_bf_scale, v_offset + 0, c_exp_beamlet_scale, tb_clk); + proc_common_wait_cross_clock_domain_latency(c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency*2); -- . readback mmf_mm_bus_rd(c_mm_file_reg_bf_scale, v_offset + 0, rd_data, tb_clk); @@ -758,6 +763,9 @@ BEGIN 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; + ---------------------------------------------------------------------------- + -- Set CEP beamlets output MAC,IP,UDP port on last node + ---------------------------------------------------------------------------- -- CEP beamlet output header -- c_sdp_cep_hdr_field_arr : t_common_field_arr(c_sdp_cep_nof_hdr_fields-1 DOWNTO 0) := ( -- 40 "eth_dst_mac" ), "RW", 48, field_default(c_sdp_cep_eth_dst_mac) ), @@ -827,7 +835,7 @@ BEGIN ASSERT UNSIGNED(rd_cep_udp_dst_port) = 0 REPORT "Wrong MM read rd_cep_udp_dst_port != 0 for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR; -- Write tb defaults - -- . Use sim default dst and src MAC, IP, UDP port from sdp_pkg.vhd and based on c_gn_index + -- . Use sim default dst and src MAC, IP, UDP port from sdp_pkg.vhd and based on c_last_gn mmf_mm_bus_wr(c_mm_file_reg_hdr_dat, v_offset + 39, TO_UINT(c_cep_eth_src_mac(47 DOWNTO 32)), tb_clk); mmf_mm_bus_wr(c_mm_file_reg_hdr_dat, v_offset + 38, TO_SINT(c_cep_eth_src_mac(31 DOWNTO 0)), tb_clk); -- use signed to fit 32 b in INTEGER mmf_mm_bus_wr(c_mm_file_reg_hdr_dat, v_offset + 26, TO_SINT(c_cep_ip_src_addr), tb_clk); -- use signed to fit 32 b in INTEGER @@ -857,13 +865,13 @@ BEGIN ASSERT rd_cep_udp_dst_port = c_sdp_cep_udp_dst_port REPORT "Wrong MM read rd_cep_udp_dst_port for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR; ---------------------------------------------------------------------------- - -- Enable BST offload on end node (not verified here, but only for view in Wave window) + -- Enable BST offload on last node (not verified here, but only for view in Wave window) ---------------------------------------------------------------------------- v_offset := bset * c_mm_span_reg_stat_enable_bst; mmf_mm_bus_wr(c_mm_file_reg_stat_enable_bst, v_offset + 0, 1, tb_clk); ---------------------------------------------------------------------------- - -- Enable beamlet output on end node (dp_xonoff) + -- Enable beamlet output on last node (dp_xonoff) ---------------------------------------------------------------------------- v_offset := bset * c_mm_span_reg_dp_xonoff; mmf_mm_bus_wr(c_mm_file_reg_dp_xonoff, v_offset + 0, 1, tb_clk); @@ -872,11 +880,12 @@ BEGIN ---------------------------------------------------------------------------- -- Enable BS ---------------------------------------------------------------------------- - FOR RN IN 0 TO c_nof_rn-1 LOOP - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 2, c_init_bsn, tb_clk); -- Init BSN - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 3, 0, tb_clk); -- Write high part a - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 1, c_nof_clk_per_sync, tb_clk); -- nof_block_per_syn - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 0, 16#00000003#, tb_clk); -- Enable BS at PPS + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_BSN_SOURCE_V2", 2, c_init_bsn, tb_clk); -- Init BSN + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_BSN_SOURCE_V2", 3, 0, tb_clk); -- Write high part a + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_BSN_SOURCE_V2", 1, c_nof_clk_per_sync, tb_clk); -- nof_block_per_syn + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_BSN_SOURCE_V2", 0, 16#00000003#, tb_clk); -- Enable BS at PPS END LOOP; -- Release PPS pulser, to get first PPS now and to start BSN source @@ -887,28 +896,42 @@ BEGIN -- Ring config ---------------------------------------------------------------------------- -- Write ring configuration to all nodes. - FOR RN IN 0 TO c_nof_rn-1 LOOP - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_INFO", 2, c_nof_rn, tb_clk); -- N_rn - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_INFO", 3, 0, tb_clk); -- O_rn + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 2, g_nof_rn, tb_clk); -- N_rn + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 3, g_first_gn, tb_clk); -- O_rn END LOOP; - -- Start node specific settings - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr, 0) & "REG_RING_INFO", 0, 1, tb_clk); -- use_ring_to_previous_rn = 1 - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr, 0) & "REG_RING_INFO", 1, 0, tb_clk); -- use_ring_to_next_rn = 0 - - -- End node specific settings - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + c_last_unb_nr, c_last_rn_nr MOD c_quad) & "REG_RING_INFO", 0, 0, tb_clk); -- use_ring_to_previous_rn = 0 - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + c_last_unb_nr, c_last_rn_nr MOD c_quad) & "REG_RING_INFO", 1, 1, tb_clk); -- use_ring_to_next_rn = 1 - - -- Access scheme 1. Each RN uses and sends them along the ring. - FOR RN IN 0 TO c_nof_rn-1 LOOP + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + IF v_gn = g_first_gn THEN + -- Start node specific settings + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 0, 1, tb_clk); -- use_cable_to_previous_rn = 1 + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 1, 0, tb_clk); -- use_cable_to_next_rn = 0 + ELSIF v_gn = c_last_gn THEN + -- End node specific settings + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 0, 0, tb_clk); -- use_cable_to_previous_rn = 0 + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 1, 1, tb_clk); -- use_cable_to_next_rn = 1 + ELSE + -- Use same settings for all nodes in between + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 0, 0, tb_clk); -- use_cable_to_previous_rn = 0 + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_INFO", 1, 0, tb_clk); -- use_cable_to_next_rn = 0 + END IF; + END LOOP; + + -- Access scheme 1 for beamformer. + -- Use transport_nof_hops = 0 on last nodes to stop remote input for first node. The + -- alternative is to use transport_nof_hops = 1 on all nodes and let the BSN aligner + -- on the first node disable its remote input. + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; FOR I IN 0 TO c_nof_lanes-1 LOOP - IF RN = c_nof_rn-1 THEN + IF RN = c_last_rn THEN -- End RN, so set transport_nof_hops to 0. - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_LANE_INFO_BF", I*2+1, 0, tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_LANE_INFO_BF", I*2+1, 0, tb_clk); ELSE -- Set transport_nof_hops to 1 on all nodes. - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_LANE_INFO_BF", I*2+1, 1, tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_RING_LANE_INFO_BF", I*2+1, 1, tb_clk); END IF; END LOOP; END LOOP; @@ -921,24 +944,26 @@ BEGIN -- 1 : phase[15:0] -- 2 : freq[30:0] -- 3 : ampl[16:0] - -- . Put wanted signal on g_sp input and remnant signal on the other inputs - FOR RN IN 0 TO c_nof_rn-1 LOOP - FOR I IN 0 TO c_sdp_S_pn-1 LOOP - IF RN * c_sdp_S_pn + I = g_sp THEN - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 1, INTEGER(c_wg_phase * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 2, INTEGER(REAL(g_subband) * c_sdp_wg_subband_freq_unit), tb_clk); -- freq - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 3, INTEGER(REAL(c_wg_ampl) * c_sdp_wg_ampl_lsb), tb_clk); -- ampl + -- . Put wanted signal on g_global_sp input and remnant signal on all g_nof_rn * S_pn - 1 other inputs + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + FOR S IN 0 TO c_sdp_S_pn-1 LOOP + IF RN * c_sdp_S_pn + S = g_global_sp THEN + -- Strong WG signal at g_global_sp + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 1, INTEGER(c_wg_phase * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 2, INTEGER(REAL(g_subband) * c_sdp_wg_subband_freq_unit), tb_clk); -- freq + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 3, INTEGER(REAL(c_wg_ampl) * c_sdp_wg_ampl_lsb), tb_clk); -- ampl ELSE - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 1, INTEGER(c_wg_remnant_phase * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 2, INTEGER(REAL(g_subband) * c_sdp_wg_subband_freq_unit), tb_clk); -- freq - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 3, INTEGER(REAL(c_wg_remnant_ampl) * c_sdp_wg_ampl_lsb), tb_clk); -- ampl + -- Weak WG signal on all other (remnant) SP + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 1, INTEGER(c_wg_remnant_phase * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 2, INTEGER(REAL(g_subband) * c_sdp_wg_subband_freq_unit), tb_clk); -- freq + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_WG", S*4 + 3, INTEGER(REAL(c_wg_remnant_ampl) * c_sdp_wg_ampl_lsb), tb_clk); -- ampl END IF; END LOOP; END LOOP; - -- Read current BSN mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO 0), tb_clk); mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 1, current_bsn_wg(63 DOWNTO 32), tb_clk); @@ -948,9 +973,10 @@ BEGIN v_bsn := TO_UINT(current_bsn_wg) + 2; ASSERT v_bsn <= c_bsn_start_wg REPORT "Too late to start WG: " & int_to_str(v_bsn) & " > " & int_to_str(c_bsn_start_wg) SEVERITY ERROR; - FOR RN IN 0 TO c_nof_rn-1 LOOP - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SCHEDULER", 0, c_bsn_start_wg, tb_clk); -- first write low then high part - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SCHEDULER", 1, 0, tb_clk); -- assume v_bsn < 2**31-1 + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_BSN_SCHEDULER", 0, c_bsn_start_wg, tb_clk); -- first write low then high part + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "REG_BSN_SCHEDULER", 1, 0, tb_clk); -- assume v_bsn < 2**31-1 END LOOP; ---------------------------------------------------------------------------- @@ -965,7 +991,7 @@ BEGIN ---------------------------------------------------------------------------- -- . 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; + v_addr := c_local_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); @@ -992,20 +1018,21 @@ BEGIN 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; - FOR RN IN 0 TO c_nof_rn-1 LOOP - mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "RAM_SS_SS_WIDE", v_addr, v_sel, tb_clk); + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "RAM_SS_SS_WIDE", v_addr, v_sel, tb_clk); END LOOP; END LOOP; END LOOP; END LOOP; - -- . read back selection for g_sp = c_pfb_index * c_sdp_N_pol + c_pol_index + -- . read back selection for c_local_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 + -- Same selection for all SP, so fine to only read subband selection for c_local_sp on last node 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; @@ -1023,16 +1050,18 @@ BEGIN -- . 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 RN IN 0 TO c_nof_rn-1 LOOP + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP -- Same BF weights for both beamsets FOR PB IN 0 TO c_sdp_N_pol_bf-1 LOOP - -- Same BF weights for both beamlet polarizations + -- Different 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 := RN * c_sdp_S_pn + A * c_sdp_N_pol + P; - IF v_S = g_sp THEN - -- use generic BF weight for g_sp in g_beamlet + -- Different BF weights for g_global_sp and the remnant sp + IF v_S = g_global_sp THEN + -- use generic BF weight for g_global_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 @@ -1046,12 +1075,13 @@ BEGIN v_weight := pack_complex(re => c_bf_remnant_y_weight_re, im => c_bf_remnant_y_weight_im, w => c_sdp_W_bf_weight); END IF; END IF; + -- Only need to set BF weight for g_beamlet, keep other beamlet BF weights at zero rst default. 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(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "RAM_BF_WEIGHTS", v_addr, v_weight, tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(v_gn / c_quad, v_gn MOD c_quad) & "RAM_BF_WEIGHTS", v_addr, v_weight, tb_clk); END LOOP; END LOOP; END LOOP; @@ -1059,32 +1089,35 @@ BEGIN END LOOP; -- . read back BF weights for g_beamlet in S_sub_bf - FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP - 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) <= COMPLEX_RADIUS(v_re, v_im) / REAL(c_sdp_unit_bf_weight); - sp_bf_x_weights_phase_arr(v_S) <= COMPLEX_PHASE(v_re, v_im); - 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) <= COMPLEX_RADIUS(v_re, v_im) / REAL(c_sdp_unit_bf_weight); - sp_bf_y_weights_phase_arr(v_S) <= COMPLEX_PHASE(v_re, v_im); - END IF; + FOR RN IN 0 TO c_last_rn LOOP + v_gn := g_first_gn + RN; + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + 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 := RN * c_sdp_S_pn + 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) <= COMPLEX_RADIUS(v_re, v_im) / REAL(c_sdp_unit_bf_weight); + sp_bf_x_weights_phase_arr(v_S) <= COMPLEX_PHASE(v_re, v_im); + 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) <= COMPLEX_RADIUS(v_re, v_im) / REAL(c_sdp_unit_bf_weight); + sp_bf_y_weights_phase_arr(v_S) <= COMPLEX_PHASE(v_re, v_im); + END IF; + END LOOP; END LOOP; END LOOP; END LOOP; @@ -1103,13 +1136,13 @@ BEGIN stimuli_done <= '1'; --------------------------------------------------------------------------- - -- Read subband statistics + -- Read subband statistics from node with g_global_sp --------------------------------------------------------------------------- -- . 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 + -- but only read for the 1 WPFB unit of the selected g_global_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 @@ -1141,13 +1174,13 @@ BEGIN END LOOP; proc_common_wait_some_cycles(tb_clk, 1); - -- Subband power of g_subband in g_sp + -- Subband power of g_subband in g_global_sp 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 --------------------------------------------------------------------------- - -- Read beamlet statistics from end node + -- Read beamlet statistics from last node --------------------------------------------------------------------------- -- . the beamlet statistics are c_stat_data_sz = 2 word power values. -- . there are c_sdp_S_sub_bf = 488 dual pol beamlets per beamset @@ -1258,8 +1291,8 @@ BEGIN -- Verify SST --------------------------------------------------------------------------- -- verify expected subband power based on WG power - 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; + ASSERT sp_sst > c_stat_lo_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_global_sp) SEVERITY ERROR; + ASSERT sp_sst < c_stat_hi_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_global_sp) SEVERITY ERROR; --------------------------------------------------------------------------- -- Verify BST @@ -1328,7 +1361,7 @@ BEGIN exp_sdp_cep_header <= func_sdp_compose_cep_header(c_exp_ip_header_checksum, c_exp_sdp_info, - c_gn_index, + c_last_gn, c_exp_beamlet_scale, c_exp_beamlet_index, exp_dp_bsn); @@ -1412,4 +1445,5 @@ BEGIN -- To view the 64 bit 10GbE offload data more easily in the Wave window rx_beamlet_data <= rx_beamlet_sosi.data(c_longword_w-1 DOWNTO 0); + END tb; -- GitLab