diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd index a9d90d2212382da37e08c0c84863e4b143aa2bee..523a0b955f37161dd6a2424b990487cb245f0b60 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_beamformer.vhd @@ -43,7 +43,10 @@ ENTITY node_sdp_beamformer IS g_sim : BOOLEAN := FALSE; g_sim_sdp : t_sdp_sim := c_sdp_sim; g_beamset_id : NATURAL := 0; - g_scope_selected_beamlet : NATURAL := 0 + g_scope_selected_beamlet : NATURAL := 0; + -- Use no default raw width, to force instance to set it + g_subband_raw_dat_w : NATURAL; -- default: c_sdp_W_subband; + g_subband_raw_fraction_w : NATURAL -- default: 0 ); PORT ( dp_clk : IN STD_LOGIC; @@ -149,7 +152,7 @@ BEGIN u_reorder_col_wide : ENTITY reorder_lib.reorder_col_wide GENERIC MAP ( g_wb_factor => c_sdp_P_pfb, -- g_wb_factor is only used for number of parallel streams - g_dsp_data_w => c_sdp_W_subband, + g_dsp_data_w => g_subband_raw_dat_w, g_nof_ch_in => c_sdp_N_sub * c_sdp_Q_fft, g_nof_ch_sel => c_sdp_S_sub_bf * c_sdp_Q_fft, g_select_file_prefix => c_bf_select_file_prefix, @@ -173,7 +176,9 @@ BEGIN --------------------------------------------------------------- u_sdp_beamformer_local : ENTITY work.sdp_beamformer_local GENERIC MAP ( - g_bf_weights_file_name => c_bf_weights_file_name + g_bf_weights_file_name => c_bf_weights_file_name, + g_raw_dat_w => g_subband_raw_dat_w, + g_raw_fraction_w => g_subband_raw_fraction_w ) PORT MAP ( dp_rst => dp_rst, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd index f62137fba3967fa6b505c38290a72bc8e46cb957..0acf498e35abdcf0a19c7cf3b31e99ea5f6f04cd 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd @@ -42,9 +42,12 @@ USE work.sdp_pkg.ALL; ENTITY node_sdp_correlator IS GENERIC ( - g_sim : BOOLEAN := FALSE; - g_sim_sdp : t_sdp_sim := c_sdp_sim; - g_P_sq : NATURAL := c_sdp_P_sq + g_sim : BOOLEAN := FALSE; + g_sim_sdp : t_sdp_sim := c_sdp_sim; + g_P_sq : NATURAL := c_sdp_P_sq; + -- Use no default raw width, to force instance to set it + g_subband_raw_dat_w : NATURAL; -- default: c_sdp_W_subband; + g_subband_raw_fraction_w : NATURAL -- default: 0 ); PORT ( dp_clk : IN STD_LOGIC; @@ -138,22 +141,26 @@ ARCHITECTURE str OF node_sdp_correlator IS SIGNAL prev_crosslets_info_rec : t_sdp_crosslets_info; SIGNAL nof_crosslets_reg : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0); SIGNAL nof_crosslets : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0); + BEGIN + --------------------------------------------------------------- -- Requantize 18b to 16b --------------------------------------------------------------- gen_requantize : FOR I IN 0 TO c_sdp_P_pfb-1 GENERATE u_dp_requantize : ENTITY dp_lib.dp_requantize GENERIC MAP ( - g_complex => TRUE, - g_representation => "SIGNED", - g_lsb_w => 0, - g_lsb_round => TRUE, - g_lsb_round_clip => FALSE, - g_msb_clip => TRUE, - g_msb_clip_symmetric => FALSE, - g_in_dat_w => c_sdp_W_subband, - g_out_dat_w => c_sdp_W_crosslet + g_complex => TRUE, + g_representation => "SIGNED", + g_lsb_w => g_subband_raw_fraction_w, + g_lsb_round => TRUE, -- round subband fraction + g_lsb_round_clip => FALSE, + g_msb_clip => TRUE, -- clip subband overflow + g_msb_clip_symmetric => FALSE, + g_pipeline_remove_lsb => 1, + g_pipeline_remove_msb => 1, + g_in_dat_w => g_subband_raw_dat_w, + g_out_dat_w => c_sdp_W_crosslet ) PORT MAP( rst => dp_rst, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd index 8f37ffab21acff1c735cf1f091cea7a41c204913..365230124efda6bd6aa490cfc64f2007b9b429c2 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_filterbank.vhd @@ -27,15 +27,32 @@ -- Description: -- . The subband filterbank seperates the incoming timestamped ADC samples into -- 512 frequency bands called subbands. --- . It implements a critically sampled poly-phase filterbank (PFB). The PFB consists of a --- poly-phase finite impulse response (PFIR) filter per real input and a --- complex fast fourier transform (FFT) per 2 real inputs. +-- . It implements a critically sampled poly-phase filterbank (PFB). The PFB +-- consists of a poly-phase finite impulse response (PFIR) filter per real +-- input and a complex fast fourier transform (FFT) per 2 real inputs. -- . The number of points of the FFT is 1024. +-- +-- . Subband widths: +-- - raw_sosi : c_subband_raw_dat_w bits +-- - quant_sosi : g_wpfb.fft_out_dat = c_sdp_W_subband bits +-- The quantized subbands are output and used for the SST. +-- The raw subbands are weighted by the equalizer and are output to allow +-- further weighting by the beamformer weights (in the BF) or to allow +-- different rounding (to c_sdp_W_crosslet bits in the XSub). +-- ____ __ +-- | | | | +-- | |--raw---->|EQ|--raw----------------------------> fsub_raw_sosi_arr +-- |WPFB| | |--quant--+-----------------------> fsub_quant_sosi_arr +-- | | |__| | ___ ___ +-- | | \-->| | | | +-- | |--quant------------------->|sel|---->|SST| +-- |____| |___| |___| +-- -- Remark: --- . +-- ------------------------------------------------------------------------------- -LIBRARY IEEE, common_lib, dp_lib, rTwoSDF_lib, wpfb_lib, filter_lib, si_lib, st_lib, mm_lib; +LIBRARY IEEE, common_lib, dp_lib, rTwoSDF_lib, fft_lib, wpfb_lib, filter_lib, si_lib, st_lib, mm_lib; USE IEEE.STD_LOGIC_1164.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; @@ -43,6 +60,7 @@ USE common_lib.common_network_layers_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; USE rTwoSDF_lib.rTwoSDFPkg.ALL; USE filter_lib.fil_pkg.ALL; +USE fft_lib.fft_pkg.ALL; USE wpfb_lib.wpfb_pkg.ALL; USE work.sdp_pkg.ALL; @@ -60,11 +78,11 @@ ENTITY node_sdp_filterbank IS dp_bsn_source_restart : IN STD_LOGIC; dp_bsn_source_new_interval : IN STD_LOGIC; - in_sosi_arr : IN t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0); - pfb_sosi_arr : OUT t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); - fsub_sosi_arr : OUT t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); - sst_udp_sosi : OUT t_dp_sosi; - sst_udp_siso : IN t_dp_siso := c_dp_siso_rst; + in_sosi_arr : IN t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0); -- c_sdp_W_adc bits + fsub_quant_sosi_arr: OUT t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); -- c_sdp_W_subband bits + fsub_raw_sosi_arr : OUT t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); -- c_sdp_W_subband + c_subband_raw_fraction_w bits + sst_udp_sosi : OUT t_dp_sosi; + sst_udp_siso : IN t_dp_siso := c_dp_siso_rst; mm_rst : IN STD_LOGIC; mm_clk : IN STD_LOGIC; @@ -100,9 +118,11 @@ ARCHITECTURE str OF node_sdp_filterbank IS CONSTANT c_coefs_file_prefix : STRING := "data/Coeffs16384Kaiser-quant_1wb"; CONSTANT c_gains_file_name : STRING := "data/gains_1024_complex_16b13f_unit"; -- Can be generated by src/python/sdp_hex.py - CONSTANT c_subband_equalizer_latency : NATURAL := 5; + CONSTANT c_nof_masters : POSITIVE := 2; -- for M&C MM access and for statistics offload MM access - CONSTANT c_nof_masters : POSITIVE := 2; + CONSTANT c_fft : t_fft := func_wpfb_map_wpfb_parameters_to_fft(g_wpfb); + CONSTANT c_subband_raw_dat_w : NATURAL := func_fft_raw_dat_w(c_fft); + CONSTANT c_subband_raw_fraction_w : NATURAL := func_fft_raw_fraction_w(c_fft); CONSTANT c_si_pipeline : NATURAL := 1; @@ -118,19 +138,33 @@ ARCHITECTURE str OF node_sdp_filterbank IS SIGNAL master_mosi_arr : t_mem_mosi_arr(0 TO c_nof_masters-1) := (OTHERS=>c_mem_mosi_rst); SIGNAL master_miso_arr : t_mem_miso_arr(0 TO c_nof_masters-1) := (OTHERS=>c_mem_miso_rst); - SIGNAL si_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL wpfb_unit_out_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL wpfb_unit_fil_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL wpfb_unit_in_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL subband_equalizer_out_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL dp_selector_out_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL scope_sosi_arr : t_dp_sosi_integer_arr(c_sdp_S_pn-1 DOWNTO 0); + SIGNAL si_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + + SIGNAL wpfb_unit_in_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_unit_fil_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_unit_out_raw_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_unit_out_quant_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + + SIGNAL subband_equalizer_raw_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL subband_equalizer_quant_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + + SIGNAL scope_wpfb_unit_out_quant_sosi_arr : t_dp_sosi_integer_arr(c_sdp_S_pn-1 DOWNTO 0); + SIGNAL scope_equalizer_quant_sosi_arr : t_dp_sosi_integer_arr(c_sdp_S_pn-1 DOWNTO 0); + + SIGNAL dp_selector_quant_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL selector_en : STD_LOGIC; SIGNAL weighted_subbands_flag : STD_LOGIC; + SIGNAL dp_bsn_source_restart_pipe : STD_LOGIC; + -- debug signals to view parameters in Wave Window + signal dbg_g_wpfb : t_wpfb := g_wpfb; + signal dbg_c_subband_raw_dat_w : natural := c_subband_raw_dat_w; + signal dbg_c_subband_raw_fraction_w : natural := c_subband_raw_fraction_w; + BEGIN + --------------------------------------------------------------- -- SPECTRAL INVERSION --------------------------------------------------------------- @@ -199,28 +233,29 @@ BEGIN in_sosi_arr => wpfb_unit_in_sosi_arr, fil_sosi_arr => wpfb_unit_fil_sosi_arr, - out_sosi_arr => wpfb_unit_out_sosi_arr, - + out_quant_sosi_arr => wpfb_unit_out_quant_sosi_arr, + out_raw_sosi_arr => wpfb_unit_out_raw_sosi_arr, + dp_bsn_source_restart => dp_bsn_source_restart_pipe ); - -- Output PFB streams - pfb_sosi_arr <= wpfb_unit_out_sosi_arr; - --------------------------------------------------------------- -- SUBBAND EQUALIZER --------------------------------------------------------------- u_sdp_subband_equalizer : ENTITY work.sdp_subband_equalizer GENERIC MAP ( - g_gains_file_name => c_gains_file_name + g_gains_file_name => c_gains_file_name, + g_raw_dat_w => c_subband_raw_dat_w, + g_raw_fraction_w => c_subband_raw_fraction_w ) PORT MAP( dp_clk => dp_clk, dp_rst => dp_rst, - in_sosi_arr => wpfb_unit_out_sosi_arr, - out_sosi_arr => subband_equalizer_out_sosi_arr, - + in_raw_sosi_arr => wpfb_unit_out_raw_sosi_arr, + out_raw_sosi_arr => subband_equalizer_raw_sosi_arr, + out_quant_sosi_arr => subband_equalizer_quant_sosi_arr, + mm_rst => mm_rst, mm_clk => mm_clk, @@ -229,15 +264,16 @@ BEGIN ); -- Output fsub streams - fsub_sosi_arr <= subband_equalizer_out_sosi_arr; + fsub_quant_sosi_arr <= subband_equalizer_quant_sosi_arr; + fsub_raw_sosi_arr <= subband_equalizer_raw_sosi_arr; --------------------------------------------------------------- - -- DP SELECTOR + -- DP SELECTOR for SST input --------------------------------------------------------------- u_dp_selector_arr : ENTITY dp_lib.dp_selector_arr GENERIC MAP ( g_nof_arr => c_sdp_P_pfb, - g_pipeline => c_subband_equalizer_latency + g_pipeline => c_sdp_subband_equalizer_latency ) PORT MAP ( mm_rst => mm_rst, @@ -248,20 +284,55 @@ BEGIN reg_selector_mosi => reg_selector_mosi, reg_selector_miso => reg_selector_miso, - pipe_sosi_arr => wpfb_unit_out_sosi_arr, - ref_sosi_arr => subband_equalizer_out_sosi_arr, - out_sosi_arr => dp_selector_out_sosi_arr, + pipe_sosi_arr => wpfb_unit_out_quant_sosi_arr, + ref_sosi_arr => subband_equalizer_quant_sosi_arr, + out_sosi_arr => dp_selector_quant_sosi_arr, selector_en => selector_en ); + --------------------------------------------------------------- + -- SIGNAL SCOPE + --------------------------------------------------------------- + -- synthesis translate_off + u_sdp_scope_wpfb : ENTITY work.sdp_scope + GENERIC MAP ( + g_sim => g_sim, + g_selection => g_scope_selected_subband, + g_nof_input => c_sdp_P_pfb, + g_n_deinterleave => c_sdp_Q_fft, + g_dat_w => c_sdp_W_subband + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + sp_sosi_arr => wpfb_unit_out_quant_sosi_arr, + scope_sosi_arr => scope_wpfb_unit_out_quant_sosi_arr + ); + + u_sdp_scope_equalizer : ENTITY work.sdp_scope + GENERIC MAP ( + g_sim => g_sim, + g_selection => g_scope_selected_subband, + g_nof_input => c_sdp_P_pfb, + g_n_deinterleave => c_sdp_Q_fft, + g_dat_w => c_sdp_W_subband + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + sp_sosi_arr => subband_equalizer_quant_sosi_arr, + scope_sosi_arr => scope_equalizer_quant_sosi_arr + ); + -- synthesis translate_on + --------------------------------------------------------------- -- SUBBAND STATISTICS --------------------------------------------------------------- gen_stats_streams: FOR I IN 0 TO c_sdp_P_pfb-1 GENERATE u_subband_stats : ENTITY st_lib.st_sst GENERIC MAP( - g_nof_stat => c_sdp_N_sub*c_sdp_Q_fft, + g_nof_stat => c_sdp_N_sub * c_sdp_Q_fft, g_in_data_w => c_sdp_W_subband, g_stat_data_w => g_wpfb.stat_data_w, g_stat_data_sz => g_wpfb.stat_data_sz, @@ -272,7 +343,7 @@ BEGIN mm_clk => mm_clk, dp_rst => dp_rst, dp_clk => dp_clk, - in_complex => dp_selector_out_sosi_arr(I), + in_complex => dp_selector_quant_sosi_arr(I), ram_st_sst_mosi => ram_st_sst_mosi_arr(I), ram_st_sst_miso => ram_st_sst_miso_arr(I) ); @@ -286,7 +357,7 @@ BEGIN u_mem_mux_sst : ENTITY common_lib.common_mem_mux GENERIC MAP ( g_nof_mosi => c_sdp_P_pfb, - g_mult_addr_w => ceil_log2(c_sdp_N_sub*c_sdp_Q_fft*g_wpfb.stat_data_sz) + g_mult_addr_w => ceil_log2(c_sdp_N_sub * c_sdp_Q_fft * g_wpfb.stat_data_sz) ) PORT MAP ( mosi => master_mem_mux_mosi, @@ -315,28 +386,10 @@ BEGIN mux_miso => master_mem_mux_miso ); - --------------------------------------------------------------- - -- SIGNAL SCOPE - --------------------------------------------------------------- - u_sdp_scope : ENTITY work.sdp_scope - GENERIC MAP ( - g_sim => g_sim, - g_selection => g_scope_selected_subband, - g_nof_input => c_sdp_P_pfb, - g_n_deinterleave => c_sdp_Q_fft, - g_dat_w => c_sdp_W_subband - ) - PORT MAP ( - clk => dp_clk, - rst => dp_rst, - sp_sosi_arr => subband_equalizer_out_sosi_arr, - scope_sosi_arr => scope_sosi_arr - ); - --------------------------------------------------------------- -- STATISTICS OFFLOAD --------------------------------------------------------------- - weighted_subbands_flag <= NOT selector_en; + weighted_subbands_flag <= NOT selector_en WHEN rising_edge(dp_clk); u_sdp_sst_udp_offload: ENTITY work.sdp_statistics_offload GENERIC MAP ( @@ -362,7 +415,7 @@ BEGIN reg_bsn_monitor_v2_offload_copi => reg_bsn_monitor_v2_sst_offload_copi, reg_bsn_monitor_v2_offload_cipo => reg_bsn_monitor_v2_sst_offload_cipo, - in_sosi => dp_selector_out_sosi_arr(0), + in_sosi => dp_selector_quant_sosi_arr(0), new_interval => dp_bsn_source_new_interval, out_sosi => sst_udp_sosi, diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd index ba01e264bb1e097b4c52a0d4b5eb161fcdb2f528..58022068e31c5168817e84bde4558e677f0d0951 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd @@ -25,6 +25,7 @@ -- . Implements the functionality of the complex subband filterbank (Fsub complex) in the -- DISTURB SDPFW design. -- Description: +-- . See https://support.astron.nl/confluence/display/DISTURB/DISTURB-2+Station+Digital+Processor+Design+Document -- . The subband filterbank seperates the incoming timestamped ADC samples into -- 512 frequency bands called subbands. -- . It implements a critically sampled poly-phase filterbank (PFB). The PFB consists of a @@ -63,7 +64,6 @@ ENTITY node_sdp_oversampled_filterbank IS dp_bsn_source_new_interval : IN STD_LOGIC; in_sosi_arr : IN t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0); - pfb_sosi_arr : OUT t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0); fsub_sosi_arr : OUT t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0); sst_udp_sosi : OUT t_dp_sosi; sst_udp_siso : IN t_dp_siso := c_dp_siso_rst; @@ -102,7 +102,9 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS CONSTANT c_coefs_file_prefix : STRING := "data/Coeffs16384Kaiser-quant_1wb"; CONSTANT c_gains_file_name : STRING := "data/gains_1024_complex_16b13f_unit"; -- Can be generated by src/python/sdp_hex.py - CONSTANT c_subband_equalizer_latency : NATURAL := 5; + -- Use quantized subbands + CONSTANT c_subband_raw_dat_w : NATURAL := c_sdp_W_subband; + CONSTANT c_subband_raw_fraction_w : NATURAL := 0; CONSTANT c_nof_masters : POSITIVE := 2; @@ -110,6 +112,9 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS CONSTANT c_complex_mult_pipeline : NATURAL := 3; CONSTANT c_complex_pfb_pipeline : NATURAL := 2; + -- Use WG as local oscillator, buf contains 16b sin and 16b cos + -- . c_sdp_W_local_oscillator = c_halfword_w = 16b + -- . c_sdp_W_local_oscillator_fraction = 16b - 1 sign bit = 15b CONSTANT c_buf : t_c_mem := (latency => 1, adr_w => ceil_log2(2 * c_sdp_N_fft), dat_w => c_nof_complex * c_halfword_w, @@ -118,7 +123,11 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS CONSTANT c_buf_file : STRING := "data/freq_shift_half_subband_2048x16_im_re.hex"; - CONSTANT c_wg_ctrl : t_diag_wg := (TO_UVEC(c_diag_wg_mode_repeat, c_diag_wg_mode_w), TO_UVEC(c_buf.nof_dat, c_diag_wg_nofsamples_w), (OTHERS => '0'), (OTHERS => '0'), (OTHERS => '0')); + CONSTANT c_wg_ctrl : t_diag_wg := (TO_UVEC(c_diag_wg_mode_repeat, c_diag_wg_mode_w), + TO_UVEC(c_buf.nof_dat, c_diag_wg_nofsamples_w), + (OTHERS => '0'), + (OTHERS => '0'), + (OTHERS => '0')); CONSTANT c_wg_phase_offset : NATURAL := 6; -- Compensate for WG start latency. In nof samples. CONSTANT c_fil_coefs_mem_addr_w : NATURAL := ceil_log2(c_sdp_N_fft * c_sdp_N_taps); @@ -138,6 +147,7 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS SIGNAL master_mosi_arr : t_mem_mosi_arr(0 TO c_nof_masters-1) := (OTHERS=>c_mem_mosi_rst); SIGNAL master_miso_arr : t_mem_miso_arr(0 TO c_nof_masters-1) := (OTHERS=>c_mem_miso_rst); + -- WG as local oscillator (LO) SIGNAL wg_rddata : STD_LOGIC_VECTOR(c_buf.dat_w -1 DOWNTO 0); SIGNAL wg_rdval : STD_LOGIC; SIGNAL wg_address : STD_LOGIC_VECTOR(c_buf.adr_w -1 DOWNTO 0); @@ -145,36 +155,47 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS SIGNAL wg_rd : STD_LOGIC; SIGNAL wg_out_dat : STD_LOGIC_VECTOR(c_buf.dat_w -1 DOWNTO 0); + -- Spectral Inversion (SI) SIGNAL si_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL si_sosi_0_piped : t_dp_sosi := c_dp_sosi_rst; + + -- Real input FFT + SIGNAL wpfb_unit_in_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_unit_fil_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL wpfb_unit_out_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL wpfb_unit_out_sosi_arr_piped : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL wpfb_unit_fil_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL wpfb_unit_in_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + -- Mixer to shift f_sub/2 SIGNAL complex_mult_src_out_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL requantize_src_out_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL wpfb_unit_complex_out_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL wpfb_unit_complex_fil_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_unit_complex_in_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_unit_complex_fil_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_unit_complex_out_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL wpfb_unit_out_resized_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL wpfb_fifo_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL wpfb_fifo_siso_arr : t_dp_siso_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_siso_rst); SIGNAL wpfb_resized_sosi_2arr : t_dp_sosi_2arr_2(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => (OTHERS => c_dp_sosi_rst)); SIGNAL wpfb_resized_siso_2arr : t_dp_siso_2arr_2(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => (OTHERS => c_dp_siso_rst)); + SIGNAL subband_equalizer_in_sosi_arr : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL subband_equalizer_out_sosi_arr : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL dp_selector_out_sosi_arr : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); - SIGNAL scope_sosi_arr : t_dp_sosi_integer_arr(c_sdp_R_os * c_sdp_S_pn-1 DOWNTO 0); + SIGNAL scope_equalizer_in_sosi_arr : t_dp_sosi_integer_arr(c_sdp_R_os * c_sdp_S_pn-1 DOWNTO 0); + SIGNAL scope_equalizer_out_sosi_arr : t_dp_sosi_integer_arr(c_sdp_R_os * c_sdp_S_pn-1 DOWNTO 0); SIGNAL selector_en : STD_LOGIC; SIGNAL weighted_subbands_flag : STD_LOGIC; + SIGNAL dp_bsn_source_restart_pipe : STD_LOGIC; SIGNAL dp_bsn_source_restart_delayed : STD_LOGIC; SIGNAL dp_bsn_source_restart_wg : STD_LOGIC; SIGNAL dp_bsn_source_restart_pipe_complex : STD_LOGIC; + BEGIN + --------------------------------------------------------------- -- SPECTRAL INVERSION --------------------------------------------------------------- @@ -244,8 +265,9 @@ BEGIN in_sosi_arr => wpfb_unit_in_sosi_arr, fil_sosi_arr => wpfb_unit_fil_sosi_arr, - out_sosi_arr => wpfb_unit_out_sosi_arr, - + out_quant_sosi_arr => wpfb_unit_out_sosi_arr, + out_raw_sosi_arr => OPEN, + dp_bsn_source_restart => dp_bsn_source_restart_pipe ); @@ -307,17 +329,15 @@ BEGIN ctrl => c_wg_ctrl, --- out_ovr => out_ovr, - out_dat => wg_out_dat --, --- out_val => wg_out_val, --- out_sync => out_sync + out_dat => wg_out_dat, + out_val => OPEN ); -- Complex mult gen_complex_mult: FOR I IN 0 TO c_sdp_S_pn-1 GENERATE u_common_complex_mult : ENTITY common_mult_lib.common_complex_mult GENERIC MAP ( - g_in_a_w => c_halfword_w, + g_in_a_w => c_halfword_w, -- = c_sdp_W_local_oscillator = 16 g_in_b_w => c_sdp_W_adc, g_out_p_w => c_halfword_w + c_sdp_W_adc, g_conjugate_b => FALSE @@ -341,26 +361,27 @@ BEGIN GENERIC MAP ( g_complex => TRUE, g_representation => "SIGNED", - g_lsb_w => c_sdp_W_fsub_wg_fraction, + g_lsb_w => c_sdp_W_local_oscillator_fraction, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, g_msb_clip => TRUE, g_msb_clip_symmetric => FALSE, - g_in_dat_w => c_halfword_w + c_sdp_W_adc, + g_pipeline_remove_lsb => 0, + g_pipeline_remove_msb => 0, + g_in_dat_w => c_halfword_w + c_sdp_W_adc, g_out_dat_w => c_sdp_W_adc ) PORT MAP ( rst => dp_rst, clk => dp_clk, -- ST sink - snk_in => complex_mult_src_out_arr(I), + snk_in => complex_mult_src_out_arr(I), -- ST source - src_out => requantize_src_out_arr(I) + src_out => requantize_src_out_arr(I) ); - END GENERATE; - -- Pipeline to compensate for complex mult. + -- Pipeline to compensate for complex mult and dp_requantize. u_dp_pipeline : ENTITY dp_lib.dp_pipeline GENERIC MAP ( g_pipeline => c_complex_mult_pipeline @@ -374,7 +395,7 @@ BEGIN src_out => si_sosi_0_piped ); - -- pipeline bsn restart signal to keep dp_bsn_source_restart aligned with si_sosi_arr + -- pipeline bsn restart signal to keep dp_bsn_source_restart aligned with si_sosi_arr u_common_pipeline_sl_cplx : ENTITY common_lib.common_pipeline_sl GENERIC MAP ( g_pipeline => c_complex_mult_pipeline @@ -415,8 +436,9 @@ BEGIN in_sosi_arr => wpfb_unit_complex_in_sosi_arr, fil_sosi_arr => wpfb_unit_complex_fil_sosi_arr, - out_sosi_arr => wpfb_unit_complex_out_sosi_arr, - + out_quant_sosi_arr => wpfb_unit_complex_out_sosi_arr, + out_raw_sosi_arr => OPEN, + dp_bsn_source_restart => dp_bsn_source_restart_pipe_complex ); @@ -497,9 +519,6 @@ BEGIN src_out_arr => subband_equalizer_in_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) ); - -- Output PFB streams - pfb_sosi_arr <= subband_equalizer_in_sosi_arr; - --------------------------------------------------------------- -- COMBINE MEMORY MAPPED INTERFACES OF RAM_FIL_COEFS --------------------------------------------------------------- @@ -521,14 +540,16 @@ BEGIN u_sdp_subband_equalizer : ENTITY work.sdp_subband_equalizer GENERIC MAP ( g_gains_file_name => c_gains_file_name, - g_nof_streams => c_sdp_R_os * c_sdp_P_pfb + g_nof_streams => c_sdp_R_os * c_sdp_P_pfb, + g_raw_dat_w => c_subband_raw_dat_w, + g_raw_fraction_w => c_subband_raw_fraction_w ) PORT MAP( dp_clk => dp_clk, dp_rst => dp_rst, - in_sosi_arr => subband_equalizer_in_sosi_arr, - out_sosi_arr => subband_equalizer_out_sosi_arr, + in_raw_sosi_arr => subband_equalizer_in_sosi_arr, + out_raw_sosi_arr => subband_equalizer_out_sosi_arr, mm_rst => mm_rst, mm_clk => mm_clk, @@ -546,7 +567,7 @@ BEGIN u_dp_selector_arr : ENTITY dp_lib.dp_selector_arr GENERIC MAP ( g_nof_arr => c_sdp_R_os * c_sdp_P_pfb, - g_pipeline => c_subband_equalizer_latency + g_pipeline => c_sdp_subband_equalizer_latency ) PORT MAP ( mm_rst => mm_rst, @@ -564,6 +585,41 @@ BEGIN selector_en => selector_en ); + --------------------------------------------------------------- + -- SIGNAL SCOPE + --------------------------------------------------------------- + -- synthesis translate_off + u_sdp_scope_equalizer_in : ENTITY work.sdp_scope + GENERIC MAP ( + g_sim => g_sim, + g_selection => g_scope_selected_subband, + g_nof_input => c_sdp_R_os * c_sdp_P_pfb, + g_n_deinterleave => c_sdp_Q_fft, + g_dat_w => c_sdp_W_subband + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + sp_sosi_arr => subband_equalizer_in_sosi_arr, + scope_sosi_arr => scope_equalizer_in_sosi_arr + ); + + u_sdp_scope_equalizer_out : ENTITY work.sdp_scope + GENERIC MAP ( + g_sim => g_sim, + g_selection => g_scope_selected_subband, + g_nof_input => c_sdp_R_os * c_sdp_P_pfb, + g_n_deinterleave => c_sdp_Q_fft, + g_dat_w => c_sdp_W_subband + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + sp_sosi_arr => subband_equalizer_out_sosi_arr, + scope_sosi_arr => scope_equalizer_out_sosi_arr + ); + -- synthesis translate_on + --------------------------------------------------------------- -- SUBBAND STATISTICS --------------------------------------------------------------- @@ -624,28 +680,10 @@ BEGIN mux_miso => master_mem_mux_miso ); - --------------------------------------------------------------- - -- SIGNAL SCOPE - --------------------------------------------------------------- - u_sdp_scope : ENTITY work.sdp_scope - GENERIC MAP ( - g_sim => g_sim, - g_selection => g_scope_selected_subband, - g_nof_input => c_sdp_R_os * c_sdp_P_pfb, - g_n_deinterleave => c_sdp_Q_fft, - g_dat_w => c_sdp_W_subband - ) - PORT MAP ( - clk => dp_clk, - rst => dp_rst, - sp_sosi_arr => subband_equalizer_out_sosi_arr, - scope_sosi_arr => scope_sosi_arr - ); - --------------------------------------------------------------- -- STATISTICS OFFLOAD --------------------------------------------------------------- - weighted_subbands_flag <= NOT selector_en; + weighted_subbands_flag <= NOT selector_en WHEN rising_edge(dp_clk); u_sdp_sst_udp_offload: ENTITY work.sdp_statistics_offload GENERIC MAP ( diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_local.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_local.vhd index 52c400be4bf76fb4abe06e3a83fcc38041216aa6..f37a393d3ece73b864950726243ad1af8a976291 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_local.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_local.vhd @@ -39,7 +39,10 @@ USE work.sdp_pkg.ALL; ENTITY sdp_beamformer_local IS GENERIC ( - g_bf_weights_file_name : STRING := "UNUSED" + g_bf_weights_file_name : STRING := "UNUSED"; + -- Use no default raw width, to force instance to set it + g_raw_dat_w : NATURAL; -- default: c_sdp_W_subband; + g_raw_fraction_w : NATURAL -- default: 0 ); PORT ( dp_clk : IN STD_LOGIC; @@ -62,15 +65,27 @@ ARCHITECTURE str OF sdp_beamformer_local IS CONSTANT c_bf_weights_latency : NATURAL := 5; -- 3 for complex multiplier + 2 RAM latency CONSTANT c_total_latency : NATURAL := 3 + c_bf_weights_latency + c_complex_adder_latency; - CONSTANT c_complex_adder_sum_w : NATURAL := c_sdp_W_bf_product + ceil_log2(c_sdp_S_pn); + -- Product width, do -1 to skip double sign bit in product + CONSTANT c_product_w : NATURAL := c_sdp_W_bf_weight + g_raw_dat_w - 1; + + -- With BF adder wrapping a c_complex_adder_sum_w = c_sdp_W_beamlet_sum is + -- in fact enough, because the MSbit will be simply removed. However, + -- it is fine to use wider BF adder, because the extra MSbits will likely + -- be optimized away by synthesis. If instead BF adder clipping was used + -- then it would be necessary to keep the extra bits, to avoid wrapping of + -- the sum. + CONSTANT c_complex_adder_sum_w : NATURAL := c_product_w + ceil_log2(c_sdp_S_pn); SIGNAL sub_sosi_arr : t_dp_sosi_arr(c_sdp_N_pol_bf*c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL bf_weights_out_sosi_arr : t_dp_sosi_arr(c_sdp_N_pol_bf*c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL bf_weights_x_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL bf_weights_y_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL deinterleaved_x_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL deinterleaved_y_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL interleave_out_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL complex_add_out_sosi : t_dp_sosi := c_dp_sosi_rst; SIGNAL pipelined_in_sosi : t_dp_sosi := c_dp_sosi_rst; SIGNAL dp_requantize_in_sosi : t_dp_sosi := c_dp_sosi_rst; @@ -94,7 +109,8 @@ BEGIN --------------------------------------------------------------- u_sdp_bf_weights : ENTITY work.sdp_bf_weights GENERIC MAP ( - g_gains_file_name => g_bf_weights_file_name + g_gains_file_name => g_bf_weights_file_name, + g_raw_dat_w => g_raw_dat_w ) PORT MAP( dp_clk => dp_clk, @@ -176,7 +192,7 @@ BEGIN u_dp_complex_add : ENTITY dp_lib.dp_complex_add GENERIC MAP( g_nof_inputs => c_sdp_S_pn, - g_data_w => c_sdp_W_bf_product + g_data_w => c_product_w ) PORT MAP( rst => dp_rst, @@ -217,11 +233,13 @@ BEGIN GENERIC MAP ( g_complex => TRUE, g_representation => "SIGNED", - g_lsb_w => c_sdp_W_bf_weight_fraction, + g_lsb_w => c_sdp_W_bf_weight_fraction + g_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, - g_msb_clip => FALSE, - g_msb_clip_symmetric => FALSE, + g_msb_clip => FALSE, -- wrap beamlet overflow + g_msb_clip_symmetric => FALSE, + g_pipeline_remove_lsb => 1, + g_pipeline_remove_msb => 0, -- no msb clipping, so no need for pipeline g_in_dat_w => c_complex_adder_sum_w, g_out_dat_w => c_sdp_W_beamlet_sum ) diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd index 3dec6eb52968ae1f86598a42c32e9e7771852cf2..bb4d4cb9b58037e2e0596d2d8ce0fbff4bee80c0 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bf_weights.vhd @@ -25,12 +25,13 @@ -- . Implements the functionality of sdp_bf_weights in the beamformer (BF) of -- the LOFAR2 SDPFW design. -- Description: --- The sdp_bf_weights.vhd consists of mms_dp_gain_serial_arr.vhd and --- some address counter logic to select the address of the subband weight. +-- . The sdp_bf_weights.vhd consists of mms_dp_gain_serial_arr.vhd and +-- some address counter logic to select the address of the subband weight. +-- . The sdp_bf_weights.vhd does no rounding, so output data width = input +-- data width = g_raw_dat_w. Rounding can be done after the BF adder stage. -- Remark: -- . sdp_bf_weights.vhd is similar to sdp_subband_equalizer.vhd. The --- difference is that they have a different purpose and that the --- sdp_subband_equalizer requantizes the output. +-- difference is that they have a different purpose. ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, dp_lib; @@ -42,7 +43,9 @@ USE work.sdp_pkg.ALL; ENTITY sdp_bf_weights IS GENERIC ( - g_gains_file_name : STRING := "UNUSED" + g_gains_file_name : STRING := "UNUSED"; + -- Use no default raw width, to force instance to set it + g_raw_dat_w : NATURAL -- default: c_sdp_W_subband; ); PORT ( dp_clk : IN STD_LOGIC; @@ -62,12 +65,18 @@ END sdp_bf_weights; ARCHITECTURE str OF sdp_bf_weights IS CONSTANT c_gain_addr_w : NATURAL := ceil_log2(c_sdp_Q_fft * c_sdp_S_sub_bf); - CONSTANT c_gain_out_dat_w : NATURAL := c_sdp_W_bf_weight + c_sdp_W_subband -1; + + -- Product width, do -1 to skip double sign bit in product + CONSTANT c_gain_out_dat_w : NATURAL := c_sdp_W_bf_weight + g_raw_dat_w - 1; + SIGNAL in_sosi : t_dp_sosi; SIGNAL cnt : NATURAL RANGE 0 TO c_sdp_Q_fft * c_sdp_S_sub_bf-1; SIGNAL gains_rd_address : STD_LOGIC_VECTOR(c_gain_addr_w-1 DOWNTO 0); BEGIN + + in_sosi <= in_sosi_arr(0); -- use ctrl from input [0] + --------------------------------------------------------------- -- Counter --------------------------------------------------------------- @@ -86,8 +95,8 @@ BEGIN v_Q := 0; v_BLET := 0; ELSIF rising_edge(dp_clk) THEN - IF in_sosi_arr(0).valid = '1' THEN - IF in_sosi_arr(0).eop = '1' THEN + IF in_sosi.valid = '1' THEN + IF in_sosi.eop = '1' THEN v_Q := 0; v_BLET := 0; ELSE @@ -118,7 +127,7 @@ BEGIN g_complex_data => TRUE, g_complex_gain => TRUE, g_gain_w => c_sdp_W_bf_weight, - g_in_dat_w => c_sdp_W_subband, + g_in_dat_w => g_raw_dat_w, g_out_dat_w => c_gain_out_dat_w, g_gains_file_name => g_gains_file_name ) diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd index f881389b6449c6b103f16031f52e9acee07e4394..cfd90432042d1c0a8599cc0bc38df728afd8c5c5 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -107,9 +107,9 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_W_bf_weight : NATURAL := 16; -- = w in s(w, p), s = signed CONSTANT c_sdp_W_bf_weight_fraction : NATURAL := 14; -- = p in s(w, p) CONSTANT c_sdp_W_bf_weight_magnitude : NATURAL := c_sdp_W_bf_weight - c_sdp_W_bf_weight_fraction - 1; -- = 1 - CONSTANT c_sdp_W_fsub_wg : NATURAL := 16; -- = w in s(w, p), s = signed - CONSTANT c_sdp_W_fsub_wg_fraction : NATURAL := 15; -- = p in s(w, p) - CONSTANT c_sdp_W_fsub_wg_magnitude : NATURAL := c_sdp_W_fsub_wg - c_sdp_W_fsub_wg_fraction - 1; -- = 0 + CONSTANT c_sdp_W_local_oscillator : NATURAL := 16; -- = w in s(w, p), s = signed + CONSTANT c_sdp_W_local_oscillator_fraction : NATURAL := 15; -- = p in s(w, p) + CONSTANT c_sdp_W_local_oscillator_magnitude : NATURAL := c_sdp_W_local_oscillator - c_sdp_W_local_oscillator_fraction - 1; -- = 0 CONSTANT c_sdp_N_ring_nof_mac10g : NATURAL := 3; -- for sdp_station_xsub_ring design. -- Derived constants @@ -129,7 +129,6 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_P_pfb : NATURAL := c_sdp_S_pn / c_sdp_Q_fft; -- = 6 PFB units, for 6 signal input pairs CONSTANT c_sdp_T_adc : TIME := (10**6 / c_sdp_f_adc_MHz) * 1 ps; -- = 5 ns @ 200MHz CONSTANT c_sdp_T_sub : TIME := c_sdp_N_fft * c_sdp_T_adc; -- = 5.12 us @ 200MHz - CONSTANT c_sdp_W_bf_product : NATURAL := c_sdp_W_subband + c_sdp_W_bf_weight -1; CONSTANT c_sdp_X_sq : NATURAL := c_sdp_S_pn * c_sdp_S_pn; -- = 144 CONSTANT c_sdp_block_period : NATURAL := c_sdp_N_fft * 1000 / c_sdp_f_adc_MHz; -- = 5120 [ns] CONSTANT c_sdp_N_beamlets_sdp : NATURAL := c_sdp_N_beamsets * c_sdp_S_sub_bf; -- = 976 @@ -176,17 +175,18 @@ PACKAGE sdp_pkg is true, false, true, 23, c_sdp_W_subband, 1, 24, 1, true, 54, c_sdp_W_statistic_sz, 195313, c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline); -- = c_wpfb_lofar2_subbands_dts_18b - CONSTANT c_sdp_wpfb_complex_subbands : t_wpfb := - (1, c_sdp_N_fft, 0, c_sdp_S_pn, - c_sdp_N_taps, 1, c_sdp_W_adc, 23, c_sdp_W_fir_coef, - true, false, false, 23, c_sdp_W_subband, 1, 24, 1, true, 54, c_sdp_W_statistic_sz, 195313, - c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline); -- = c_wpfb_lofar2_subbands_dts_18b + CONSTANT c_sdp_wpfb_complex_subbands : t_wpfb := func_wpfb_map_real_input_wpfb_parameters_to_complex_input(c_sdp_wpfb_subbands); -- DC gain of WPFB FIR filter obtained from applications/lofar2/model/run_pfir_coef.m using application = 'lofar_subband' -- Not used in RTL, only used in test benches to verify expected suband levels CONSTANT c_sdp_wpfb_fir_filter_dc_gain : REAL := c_fil_lofar1_fir_filter_dc_gain; -- = 0.994817, almost unit DC gain CONSTANT c_sdp_wpfb_subband_sp_ampl_ratio : REAL := func_wpfb_subband_gain(c_sdp_wpfb_subbands, c_sdp_wpfb_fir_filter_dc_gain); + ----------------------------------------------------------------------------- + -- Subband Equalizer + ----------------------------------------------------------------------------- + CONSTANT c_sdp_subband_equalizer_latency : NATURAL := 7; + ----------------------------------------------------------------------------- -- Statistics offload ----------------------------------------------------------------------------- diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd index 90e1a6ab1a9df2782be6b82791db11f27ca7638d..08ede03ff0d1dd72d00546aba4555cdc750a1234 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd @@ -23,14 +23,21 @@ -- Purpose: -- Core design for Lofar2 SDP station -- Description: --- Combines sdp nodes. Contains the UniBoard2 HW version independent LOFAR2 SDP application code. +-- * Combines sdp nodes. Contains the UniBoard2 HW version independent LOFAR2 +-- SDP application code. +-- * Supports default PFB for LOFAR2 [1] +-- - Uses raw subband input to improve the accuracy of weighted subbands +-- and weighted beamlets +-- * Supports 2x oversampled PFB for DISTURB2 [2] +-- - Still uses quantized subband input, because using raw subbands might +-- require too many DSP multipliers. -- References: -- [1] LOFAR2 SDP FW: https://support.astron.nl/confluence/display/L2M/L4+SDP+Firmware+Design+Document --- [2] DISTURB2 revision: https://support.astron.nl/confluence/x/vIIjBQ +-- [2] DISTURB2 design revision: https://support.astron.nl/confluence/x/vIIjBQ -- [3] SST, SST_OS packets: https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD ------------------------------------------------------------------------------- -LIBRARY IEEE, common_lib, diag_lib, dp_lib, tech_jesd204b_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, nw_10GbE_lib, eth_lib, ring_lib; +LIBRARY IEEE, common_lib, diag_lib, dp_lib, tech_jesd204b_lib, fft_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, nw_10GbE_lib, eth_lib, ring_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; USE common_lib.common_pkg.ALL; @@ -39,6 +46,7 @@ USE common_lib.common_network_layers_pkg.ALL; USE common_lib.common_field_pkg.ALL; USE diag_lib.diag_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; +USE fft_lib.fft_pkg.ALL; USE wpfb_lib.wpfb_pkg.ALL; USE work.sdp_pkg.ALL; USE eth_lib.eth_pkg.ALL; @@ -376,6 +384,14 @@ END sdp_station; ARCHITECTURE str OF sdp_station IS + -- WPFB subband width + CONSTANT c_fft : t_fft := func_wpfb_map_wpfb_parameters_to_fft(g_wpfb); + CONSTANT c_fft_raw_dat_w : NATURAL := func_fft_raw_dat_w(c_fft); + CONSTANT c_fft_raw_fraction_w : NATURAL := func_fft_raw_fraction_w(c_fft); + + CONSTANT c_subband_raw_dat_w : NATURAL := sel_a_b(g_use_oversample, c_sdp_W_subband, c_fft_raw_dat_w); + CONSTANT c_subband_raw_fraction_w : NATURAL := sel_a_b(g_use_oversample, 0, c_fft_raw_fraction_w); + -- Make Tx FIFOs at least c_fifo_tx_fill_margin larger than needed to fit the largest Tx packet CONSTANT c_fifo_tx_fill_margin : NATURAL := 10; -- >= c_fifo_fill_margin = 6 that is used in dp_fifo_fill_eop @@ -520,9 +536,9 @@ ARCHITECTURE str OF sdp_station IS ---------------------------------------------- SIGNAL ait_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0); - SIGNAL fsub_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); -- weighted subbands - SIGNAL fsub_oversampled_sosi_arr : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0); - SIGNAL fsub_sosi_2arr : t_dp_sosi_2arr_pfb(c_sdp_N_beamsets-1 DOWNTO 0); + SIGNAL fsub_raw_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); + SIGNAL fsub_oversampled_sosi_arr : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0); + SIGNAL fsub_raw_sosi_2arr : t_dp_sosi_2arr_pfb(c_sdp_N_beamsets-1 DOWNTO 0); SIGNAL xst_bs_sosi : t_dp_sosi; -- block sync reference for Xsub ring latency monitor SIGNAL bf_bs_sosi : t_dp_sosi; -- block sync reference for BF ring latency monitor @@ -713,7 +729,7 @@ BEGIN dp_rst => dp_rst, in_sosi_arr => ait_sosi_arr, - fsub_sosi_arr => fsub_sosi_arr, + fsub_raw_sosi_arr => fsub_raw_sosi_arr, dp_bsn_source_restart => dp_bsn_source_restart, dp_bsn_source_new_interval => dp_bsn_source_new_interval, @@ -749,8 +765,9 @@ BEGIN udp_src_port => sst_udp_src_port ); - gen_bf_sosi : FOR I IN 0 TO c_sdp_N_beamsets-1 GENERATE - fsub_sosi_2arr(I) <= fsub_sosi_arr; + gen_bf_sosi : FOR I IN 0 TO c_sdp_N_beamsets-1 GENERATE + -- Wire same subbands to all beamsets + fsub_raw_sosi_2arr(I) <= fsub_raw_sosi_arr; END GENERATE; END GENERATE; @@ -807,10 +824,14 @@ BEGIN udp_src_port => sst_udp_src_port ); - fsub_sosi_arr <= fsub_oversampled_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); -- Lower part contains normal subbands, higher part contains shifted subbands. + -- Lower part contains normal subbands, higher part contains shifted subbands. + -- . Use normal subbands for subband correlator + fsub_raw_sosi_arr <= fsub_oversampled_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); - fsub_sosi_2arr(0) <= fsub_sosi_arr; - fsub_sosi_2arr(1) <= fsub_oversampled_sosi_arr(2 * c_sdp_P_pfb-1 DOWNTO c_sdp_P_pfb); -- Use second beamset for oversampled subbands + -- . Use first beamset for normal subbands + -- Use second beamset for oversampled subbands + fsub_raw_sosi_2arr(0) <= fsub_oversampled_sosi_arr( c_sdp_P_pfb-1 DOWNTO 0); + fsub_raw_sosi_2arr(1) <= fsub_oversampled_sosi_arr(2 * c_sdp_P_pfb-1 DOWNTO c_sdp_P_pfb); END GENERATE; END GENERATE; @@ -821,15 +842,17 @@ BEGIN gen_use_xsub : IF g_use_xsub GENERATE u_xsub : ENTITY work.node_sdp_correlator GENERIC MAP( - g_sim => g_sim, - g_sim_sdp => g_sim_sdp, - g_P_sq => g_P_sq + g_sim => g_sim, + g_sim_sdp => g_sim_sdp, + g_P_sq => g_P_sq, + g_subband_raw_dat_w => c_subband_raw_dat_w, + g_subband_raw_fraction_w => c_subband_raw_fraction_w ) PORT MAP( dp_clk => dp_clk, dp_rst => dp_rst, - in_sosi_arr => fsub_sosi_arr, + in_sosi_arr => fsub_raw_sosi_arr, xst_udp_sosi => udp_tx_sosi_arr(1), xst_udp_siso => udp_tx_siso_arr(1), @@ -886,13 +909,15 @@ BEGIN g_sim => g_sim, g_sim_sdp => g_sim_sdp, g_beamset_id => beamset_id, - g_scope_selected_beamlet => g_scope_selected_subband + g_scope_selected_beamlet => g_scope_selected_subband, + g_subband_raw_dat_w => c_subband_raw_dat_w, + g_subband_raw_fraction_w => c_subband_raw_fraction_w ) PORT MAP( dp_clk => dp_clk, dp_rst => dp_rst, - in_sosi_arr => fsub_sosi_2arr(beamset_id), + in_sosi_arr => fsub_raw_sosi_2arr(beamset_id), from_ri_sosi => bf_from_ri_sosi_arr(beamset_id), to_ri_sosi => bf_to_ri_sosi_arr(beamset_id), bf_udp_sosi => bf_udp_sosi_arr(beamset_id), @@ -1233,7 +1258,7 @@ BEGIN END GENERATE; gen_bf_ring : IF g_use_bf GENERATE - bf_bs_sosi <= fsub_sosi_arr(0); + bf_bs_sosi <= fsub_raw_sosi_arr(0); gen_beamset_ring : FOR beamset_id IN 0 TO c_sdp_N_beamsets-1 GENERATE u_ring_lane_bf : ENTITY ring_lib.ring_lane diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd index f337da198f9eb4334e72899c5bdf348db38ee59b..69f6daea5876037e6e19ee2b6be75c98bf1c20da 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd @@ -25,11 +25,14 @@ -- . Implements the functionality of the subband equalizer in the subband -- filterbank (Fsub) of the LOFAR2 SDPFW design. -- Description: --- The sdp_subband_equalizer.vhd consists of mms_dp_gain_serial_arr.vhd and --- some address counter logic to select the address of the subband weight --- and a dp_requantize.vhd component. +-- . The sdp_subband_equalizer.vhd consists of mms_dp_gain_serial_arr.vhd and +-- some address counter logic to select the address of the subband weight +-- and a dp_requantize.vhd component. +-- . Subband widths: +-- - raw_sosi : g_raw_dat_w bits +-- - quant_sosi : c_quant_dat_w = g_raw_dat_w - g_raw_fraction_w bits -- Remark: --- . +-- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, dp_lib; @@ -41,15 +44,19 @@ USE work.sdp_pkg.ALL; ENTITY sdp_subband_equalizer IS GENERIC ( - g_gains_file_name : STRING := "UNUSED"; - g_nof_streams : NATURAL := c_sdp_P_pfb + g_gains_file_name : STRING := "UNUSED"; + g_nof_streams : NATURAL := c_sdp_P_pfb; + -- Use no default raw width, to force instance to set it + g_raw_dat_w : NATURAL; -- default: c_sdp_W_subband; + g_raw_fraction_w : NATURAL -- default: 0 ); PORT ( dp_clk : IN STD_LOGIC; dp_rst : IN STD_LOGIC; - in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); - out_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + in_raw_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_raw_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_quant_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); mm_rst : IN STD_LOGIC; mm_clk : IN STD_LOGIC; @@ -62,17 +69,29 @@ END sdp_subband_equalizer; ARCHITECTURE str OF sdp_subband_equalizer IS CONSTANT c_gain_addr_w : NATURAL := ceil_log2(c_sdp_Q_fft * c_sdp_N_sub); - CONSTANT c_gain_out_dat_w : NATURAL := c_sdp_W_sub_weight + c_sdp_W_subband -1; + + -- Product width, do -1 to skip double sign bit in product + CONSTANT c_gain_out_dat_w : NATURAL := c_sdp_W_sub_weight + g_raw_dat_w - 1; + + CONSTANT c_quant_dat_w : NATURAL := g_raw_dat_w - g_raw_fraction_w; + -- Pipeline requantization to easy timing closure + CONSTANT c_pipeline_remove_lsb : NATURAL := 1; + CONSTANT c_pipeline_remove_msb : NATURAL := 1; + + SIGNAL in_sosi : t_dp_sosi; SIGNAL cnt : NATURAL RANGE 0 TO c_sdp_Q_fft * c_sdp_N_sub-1; SIGNAL gains_rd_address : STD_LOGIC_VECTOR(c_gain_addr_w-1 DOWNTO 0); - SIGNAL dp_gain_serial_out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL weighted_raw_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); BEGIN - --------------------------------------------------------------- - -- Counter - --------------------------------------------------------------- - -- The subband weigths per PN are stored as + + in_sosi <= in_raw_sosi_arr(0); -- use ctrl from input [0] + + ----------------------------------------------------------------------------- + -- Counter + ----------------------------------------------------------------------------- + -- The subband weigths per PN are stored as -- (cint16)subband_weights[S_pn/Q_fft]_[Q_fft][N_sub], but have -- to be applied according the subband data order -- fsub[S_pn/Q_fft]_[N_sub][Q_fft]. Therefore the counter in @@ -87,8 +106,8 @@ BEGIN v_Q := 0; v_SUB := 0; ELSIF rising_edge(dp_clk) THEN - IF in_sosi_arr(0).valid = '1' THEN - IF in_sosi_arr(0).eop = '1' THEN + IF in_sosi.valid = '1' THEN + IF in_sosi.eop = '1' THEN v_Q := 0; v_SUB := 0; ELSE @@ -109,9 +128,9 @@ BEGIN END PROCESS; gains_rd_address <= TO_UVEC(cnt, c_gain_addr_w); - --------------------------------------------------------------- - -- Gain - --------------------------------------------------------------- + ----------------------------------------------------------------------------- + -- Gain + ----------------------------------------------------------------------------- u_mms_dp_gain_serial_arr : ENTITY dp_lib.mms_dp_gain_serial_arr GENERIC MAP ( g_nof_streams => g_nof_streams, @@ -119,7 +138,7 @@ BEGIN g_complex_data => TRUE, g_complex_gain => TRUE, g_gain_w => c_sdp_W_sub_weight, - g_in_dat_w => c_sdp_W_subband, + g_in_dat_w => g_raw_dat_w, g_out_dat_w => c_gain_out_dat_w, g_gains_file_name => g_gains_file_name ) @@ -137,33 +156,64 @@ BEGIN -- ST interface gains_rd_address => gains_rd_address, - in_sosi_arr => in_sosi_arr, - out_sosi_arr => dp_gain_serial_out_sosi_arr + in_sosi_arr => in_raw_sosi_arr, + out_sosi_arr => weighted_raw_sosi_arr ); - --------------------------------------------------------------- + ----------------------------------------------------------------------------- -- Requantize - --------------------------------------------------------------- + ----------------------------------------------------------------------------- + gen_dp_requantize : FOR I IN 0 TO g_nof_streams-1 GENERATE - u_dp_requantize : ENTITY dp_lib.dp_requantize + -- For raw output only round the c_sdp_W_sub_weight_fraction, and keep the + -- g_raw_fraction_w, so that the output width remains the same as the input + -- width g_raw_dat_w. + u_dp_requantize_out_raw : ENTITY dp_lib.dp_requantize + GENERIC MAP ( + g_complex => TRUE, + g_representation => "SIGNED", + g_lsb_w => c_sdp_W_sub_weight_fraction, + g_lsb_round => TRUE, + g_lsb_round_clip => FALSE, + g_msb_clip => TRUE, -- clip subband overflow + g_msb_clip_symmetric => FALSE, + g_pipeline_remove_lsb => c_pipeline_remove_lsb, + g_pipeline_remove_msb => c_pipeline_remove_msb, + g_in_dat_w => c_gain_out_dat_w, + g_out_dat_w => g_raw_dat_w + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + -- ST sink + snk_in => weighted_raw_sosi_arr(I), + -- ST source + src_out => out_raw_sosi_arr(I) + ); + + -- For quant output round the entire fraction, so that the output width + -- becomes c_quant_dat_w. + u_dp_requantize_out_quant : ENTITY dp_lib.dp_requantize GENERIC MAP ( g_complex => TRUE, g_representation => "SIGNED", - g_lsb_w => c_sdp_W_sub_weight_fraction, + g_lsb_w => c_sdp_W_sub_weight_fraction + g_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, - g_msb_clip => TRUE, + g_msb_clip => TRUE, -- clip subband overflow g_msb_clip_symmetric => FALSE, - g_in_dat_w => c_gain_out_dat_w, - g_out_dat_w => c_sdp_W_subband + g_pipeline_remove_lsb => c_pipeline_remove_lsb, + g_pipeline_remove_msb => c_pipeline_remove_msb, + g_in_dat_w => c_gain_out_dat_w, + g_out_dat_w => c_quant_dat_w ) PORT MAP ( rst => dp_rst, clk => dp_clk, -- ST sink - snk_in => dp_gain_serial_out_sosi_arr(I), + snk_in => weighted_raw_sosi_arr(I), -- ST source - src_out => out_sosi_arr(I) + src_out => out_quant_sosi_arr(I) ); END GENERATE; END str; diff --git a/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd b/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd index 66551c1bc892ba343176675715242c43d81916b7..a7e72974601c0c47dd94097ae9cf90a7255a2f58 100644 --- a/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd +++ b/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd @@ -135,7 +135,7 @@ BEGIN snk_out_arr(i).xon <= src_in_arr(i).xon; -- Wire hdr_fields_out_arr - p_hdr_fields_out_arr : PROCESS(mm_fields_slv_out_arr, hdr_fields_in_arr) + p_hdr_fields_out_arr : PROCESS(mm_fields_slv_out_arr, hdr_fields_in_arr, field_override_arr) VARIABLE v_hi : NATURAL; VARIABLE v_lo : NATURAL; BEGIN diff --git a/libraries/dsp/fft/src/vhdl/fft_pkg.vhd b/libraries/dsp/fft/src/vhdl/fft_pkg.vhd index a177c9b2360167cb6ca9a00f118b3f452a61de4c..0bc0660dc204809979e679aaa7bec5b6bf6ab7db 100644 --- a/libraries/dsp/fft/src/vhdl/fft_pkg.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_pkg.vhd @@ -69,7 +69,16 @@ package fft_pkg is -- Check consistancy of the FFT parameters function fft_r2_parameter_asserts(g_fft : t_fft) return boolean; -- the return value is void, because always true or abort due to failure - + + -- FFT input width + function func_fft_in_scale_w(g_fft : t_fft) return natural; + + -- FFT output width + -- Removed MSbits Quantized data Rounded LSbits + -- c_raw_dat_w = c_fft.out_gain_w + c_fft.out_dat_w + c_raw_fraction_w + function func_fft_raw_dat_w(g_fft : t_fft) return natural; + function func_fft_raw_fraction_w(g_fft : t_fft) return natural; + -- Definitions for fft slv array (an array can not have unconstraint elements, so choose sufficiently wide 32 bit slv elements) subtype t_fft_slv_arr is t_slv_32_arr; -- use subtype to ease interfacing to existing types and to have central definition for rtwo components constant c_fft_slv_w : natural := 32; -- match slv width of t_fft_slv_arr @@ -106,7 +115,31 @@ package body fft_pkg is assert g_fft.use_fft_shift=false report "fft_r2 : with use_separate there cannot be use_fft_shift for two real inputs" severity failure; end if; return true; - end; + end; + + -- Scale input data to MSbits of stage data, with g_fft.guard_w bits backoff if g_fft.guard_enable = true + function func_fft_in_scale_w(g_fft : t_fft) return natural is + constant c_in_scale_w : natural := g_fft.stage_dat_w - g_fft.in_dat_w - sel_a_b(g_fft.guard_enable, g_fft.guard_w, 0); + begin + return c_in_scale_w; + end func_fft_in_scale_w; + + -- Raw output data width is equal to the internal data width of the FFT + function func_fft_raw_dat_w(g_fft : t_fft) return natural is + constant c_sepa_growth_w : natural := sel_a_b(g_fft.use_separate, 1, 0); -- add one bit for add sub growth in separate + constant c_raw_dat_w : natural := g_fft.stage_dat_w + c_sepa_growth_w; + begin + return c_raw_dat_w; + end func_fft_raw_dat_w; + + -- Number of LSbits in the raw output data that represent the fraction bits in c_raw_dat_w. + function func_fft_raw_fraction_w(g_fft : t_fft) return natural is + constant c_raw_dat_w : natural := func_fft_raw_dat_w(g_fft); + constant c_raw_fraction_w : natural := c_raw_dat_w - g_fft.out_dat_w - g_fft.out_gain_w; + begin + return c_raw_fraction_w; + end func_fft_raw_fraction_w; + function to_fft_svec(n : integer) return std_logic_vector is begin diff --git a/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd b/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd index 02bf10f3cdc378575e093c4651fad58d5891f3ff..aca22cb6ad028a06e9c358b338d56b84a5ac1fb6 100644 --- a/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd @@ -127,15 +127,12 @@ architecture str of fft_r2_par is constant c_pipeline_remove_lsb : natural := 1; constant c_nof_stages : natural := ceil_log2(g_fft.nof_points); - constant c_nof_bf_per_stage : natural := g_fft.nof_points/2; - constant c_in_scale_w_tester : integer := g_fft.stage_dat_w - g_fft.in_dat_w - sel_a_b(g_fft.guard_enable, g_fft.guard_w, 0); - constant c_in_scale_w : natural := sel_a_b(c_in_scale_w_tester > 0, c_in_scale_w_tester, 0); -- Only scale when in_dat_w is not too big. - - constant c_out_scale_w : integer := g_fft.stage_dat_w - g_fft.out_dat_w - g_fft.out_gain_w; -- Estimate number of LSBs to throw away when > 0 or insert when < 0 + constant c_nof_bf_per_stage : natural := g_fft.nof_points/2; + + constant c_in_scale_w : natural := func_fft_in_scale_w(g_fft); + constant c_raw_fraction_w : natural := func_fft_raw_fraction_w(g_fft); + constant c_raw_dat_w : natural := func_fft_raw_dat_w(g_fft); - constant c_sepa_growth_w : natural := sel_a_b(g_fft.use_separate, 1, 0); -- add one bit for add sub growth in separate - constant c_raw_dat_w : natural := g_fft.stage_dat_w + c_sepa_growth_w; - type t_stage_dat_arr is array (integer range <>) of std_logic_vector(g_fft.stage_dat_w-1 downto 0); type t_stage_raw_arr is array (integer range <>) of std_logic_vector(c_raw_dat_w-1 downto 0); type t_data_arr2 is array(c_nof_stages downto 0) of t_stage_dat_arr(g_fft.nof_points-1 downto 0); @@ -158,6 +155,12 @@ architecture str of fft_r2_par is signal fft_im_arr : t_stage_raw_arr(g_fft.nof_points-1 downto 0); signal fft_val : std_logic; + -- debug signals to view parameters in Wave Window + signal dbg_g_g_fft : t_fft := g_fft; + signal dbg_c_in_scale_w : natural := c_in_scale_w; + signal dbg_c_raw_fraction_w : natural := c_raw_fraction_w; + signal dbg_c_raw_dat_w : natural := c_raw_dat_w; + begin ------------------------------------------------------------------------------ @@ -378,7 +381,7 @@ begin u_requantize_re : entity common_lib.common_requantize generic map ( g_representation => "SIGNED", - g_lsb_w => c_out_scale_w + c_sepa_growth_w, + g_lsb_w => c_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, g_msb_clip => FALSE, @@ -398,7 +401,7 @@ begin u_requantize_im : entity common_lib.common_requantize generic map ( g_representation => "SIGNED", - g_lsb_w => c_out_scale_w + c_sepa_growth_w, + g_lsb_w => c_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, g_msb_clip => FALSE, diff --git a/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd b/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd index 8f3d64e600c1f9e10a087cd2d92210f3aef931aa..fb54876255fc2dc4474ef12659c55ec7b8b3fd41 100644 --- a/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd @@ -56,7 +56,19 @@ -- -- c0f0 c0f1 c0f2 ... c0f15 c1f0 c1f1 c1f2 ... c1f15 (c0f0 means channel 0, frequency bin 0) -- --- +-- . Output subband widths: +-- - out_quant_re/im : g_fft.out_dat_w bits (within c_32 word) +-- - out_raw_re/im : c_raw_dat_w bits (within c_32 word) +-- The out_quant carries subbands of g_fft.out_dat_w bits, so the +-- c_raw_fraction_w fraction bits in c_raw_dat_w have been rounded. +-- The out_raw carries subbands of c_raw_dat_w bits, that still have the +-- c_raw_fraction_w fraction bits. The out_raw subbands are suitable for +-- further weighting or alternative rounding. +-- Note that c_raw_dat_w and c_raw_fraction_w depend on g_fft.use_separate. +-- For real input data FFT there is one fraction bit more than for complex +-- input FFT, due to the adder stage in the separate function. +-- Both out_quant and out_raw use FFT out_val, so they have the same timing. +-- library ieee, common_lib, rTwoSDF_lib; use IEEE.std_logic_1164.all; @@ -72,33 +84,37 @@ entity fft_r2_pipe is g_dont_flip_channels : boolean := false -- generic to prevent re-ordering of the channels ); port ( - clk : in std_logic; - rst : in std_logic := '0'; - in_re : in std_logic_vector(g_fft.in_dat_w-1 downto 0); - in_im : in std_logic_vector(g_fft.in_dat_w-1 downto 0); - in_val : in std_logic := '1'; - out_re : out std_logic_vector(g_fft.out_dat_w-1 downto 0); - out_im : out std_logic_vector(g_fft.out_dat_w-1 downto 0); - out_val : out std_logic + clk : in std_logic; + rst : in std_logic := '0'; + in_re : in std_logic_vector(g_fft.in_dat_w-1 downto 0); + in_im : in std_logic_vector(g_fft.in_dat_w-1 downto 0); + in_val : in std_logic := '1'; + out_quant_re : out std_logic_vector(g_fft.out_dat_w-1 downto 0); + out_quant_im : out std_logic_vector(g_fft.out_dat_w-1 downto 0); + -- use c_32 width as in t_fft_slv_arr, to allow leaving OUT port open, actual width is c_raw_dat_w + out_raw_re : out std_logic_vector(c_32-1 DOWNTO 0); + out_raw_im : out std_logic_vector(c_32-1 DOWNTO 0); + out_val : out std_logic ); end entity fft_r2_pipe; architecture str of fft_r2_pipe is - constant c_pipeline_remove_lsb : natural := 0; + constant c_pipeline_remove_lsb : natural := 1; -- to easy timing closure constant c_switch_en : boolean := g_fft.use_separate; -- default do apply switch/unswitch per real input to mitigate quantization crosstalk constant c_switch_sz_w : natural := ceil_log2(g_fft.nof_points) + g_fft.nof_chan; constant c_switch_dat_w : natural := g_fft.in_dat_w + 1; -- add 1 extra bit to fit negation of most negative value per real input switch function - constant c_unswitch_dat_w : natural := g_fft.out_dat_w; -- no need for extra bit, because most negative value cannot occur in output constant c_switch_seed1 : STD_LOGIC_VECTOR(c_fft_lfsr_len-1 DOWNTO 0) := fft_switch_new_seed(c_fft_switch_seed1, g_instance_index); constant c_switch_seed2 : STD_LOGIC_VECTOR(c_fft_lfsr_len-1 DOWNTO 0) := fft_switch_new_seed(c_fft_switch_seed2, g_instance_index); constant c_nof_stages : natural := ceil_log2(g_fft.nof_points); - constant c_stage_offset : natural := true_log2(g_fft.wb_factor); -- Stage offset is required for twiddle generation in wideband fft - constant c_in_scale_w : natural := g_fft.stage_dat_w - g_fft.in_dat_w - sel_a_b(g_fft.guard_enable, g_fft.guard_w, 0); - constant c_out_scale_w : integer := g_fft.stage_dat_w - g_fft.out_dat_w - g_fft.out_gain_w; -- Estimate number of LSBs to throw throw away when > 0 or insert when < 0 - constant c_sepa_growth_w : natural := sel_a_b(g_fft.use_separate, 1, 0); -- add one bit for add sub growth in separate - constant c_raw_dat_w : natural := g_fft.stage_dat_w + c_sepa_growth_w; + constant c_stage_offset : natural := true_log2(g_fft.wb_factor); -- Stage offset is required for twiddle generation in wideband fft + + constant c_in_scale_w : natural := func_fft_in_scale_w(g_fft); + constant c_raw_fraction_w : natural := func_fft_raw_fraction_w(g_fft); + constant c_raw_dat_w : natural := func_fft_raw_dat_w(g_fft); + + constant c_unswitch_dat_w : natural := c_raw_dat_w; -- no need for extra bit, because most negative value cannot occur in FFT output -- number the stage instances from c_nof_stages:1 -- . the data input for the first stage has index c_nof_stages @@ -119,13 +135,20 @@ architecture str of fft_r2_pipe is signal in_cplx : std_logic_vector(c_nof_complex*g_fft.stage_dat_w-1 downto 0); signal out_cplx : std_logic_vector(c_nof_complex*c_raw_dat_w-1 downto 0); - signal raw_out_re : std_logic_vector(c_raw_dat_w-1 downto 0); - signal raw_out_im : std_logic_vector(c_raw_dat_w-1 downto 0); - signal raw_out_val : std_logic; - signal quant_re : std_logic_vector(g_fft.out_dat_w-1 downto 0); - signal quant_im : std_logic_vector(g_fft.out_dat_w-1 downto 0); - signal quant_val : std_logic; + signal fft_out_re : std_logic_vector(c_raw_dat_w-1 downto 0); + signal fft_out_im : std_logic_vector(c_raw_dat_w-1 downto 0); + signal fft_out_val : std_logic; + + signal raw_re : std_logic_vector(c_raw_dat_w-1 downto 0); + signal raw_im : std_logic_vector(c_raw_dat_w-1 downto 0); + signal raw_val : std_logic; + + -- debug signals to view parameters in Wave Window + signal dbg_g_g_fft : t_fft := g_fft; + signal dbg_c_in_scale_w : natural := c_in_scale_w; + signal dbg_c_raw_fraction_w : natural := c_raw_fraction_w; + signal dbg_c_raw_dat_w : natural := c_raw_dat_w; begin @@ -229,30 +252,53 @@ begin in_dat => in_cplx, -- c_nof_complex * g_fft.stage_dat_w in_val => data_val(0), out_dat => out_cplx, -- c_nof_complex * c_raw_dat_w - out_val => raw_out_val + out_val => fft_out_val ); -- c_raw_dat_w = g_fft.stage_dat_w when g_fft.use_separate = false -- c_raw_dat_w = g_fft.stage_dat_w + 1 when g_fft.use_separate = true - raw_out_re <= out_cplx( c_raw_dat_w-1 downto 0); - raw_out_im <= out_cplx(2*c_raw_dat_w-1 downto c_raw_dat_w); + fft_out_re <= out_cplx( c_raw_dat_w-1 downto 0); + fft_out_im <= out_cplx(2*c_raw_dat_w-1 downto c_raw_dat_w); end generate; no_reorder_no_seperate : if g_fft.use_separate=false and g_fft.use_reorder=false generate -- c_raw_dat_w = g_fft.stage_dat_w because g_fft.use_separate = false - raw_out_re <= data_re(0); - raw_out_im <= data_im(0); - raw_out_val <= data_val(0); + fft_out_re <= data_re(0); + fft_out_im <= data_im(0); + fft_out_val <= data_val(0); end generate; - + + ------------------------------------------------------------------------------ + -- Undo input random negation of u_switch at FFT output when c_switch_en = + -- g_fft.use_separate = TRUE + ------------------------------------------------------------------------------ + u_unswitch : ENTITY work.fft_unswitch + GENERIC MAP ( + g_switch_en => c_switch_en, + g_seed1 => c_switch_seed1, + g_seed2 => c_switch_seed2, + g_fft_sz_w => c_switch_sz_w, + g_dat_w => c_unswitch_dat_w + ) + PORT MAP ( + in_re => fft_out_re, + in_im => fft_out_im, + in_val => fft_out_val, + out_re => raw_re, + out_im => raw_im, + out_val => raw_val, + clk => clk, + rst => rst + ); + ------------------------------------------------------------------------------ - -- pipelined FFT output requantization + -- Pipelined FFT output requantization ------------------------------------------------------------------------------ u_requantize_re : entity common_lib.common_requantize generic map ( g_representation => "SIGNED", - g_lsb_w => c_out_scale_w + c_sepa_growth_w, + g_lsb_w => c_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, g_msb_clip => FALSE, @@ -264,15 +310,15 @@ begin ) port map ( clk => clk, - in_dat => raw_out_re, - out_dat => quant_re, + in_dat => raw_re, + out_dat => out_quant_re, out_ovr => open ); u_requantize_im : entity common_lib.common_requantize generic map ( g_representation => "SIGNED", - g_lsb_w => c_out_scale_w + c_sepa_growth_w, + g_lsb_w => c_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, g_msb_clip => FALSE, @@ -284,41 +330,54 @@ begin ) port map ( clk => clk, - in_dat => raw_out_im, - out_dat => quant_im, + in_dat => raw_im, + out_dat => out_quant_im, out_ovr => open ); - -- Valid Output - u_out_val : entity common_lib.common_pipeline_sl + u_quant_val : entity common_lib.common_pipeline_sl generic map ( g_pipeline => c_pipeline_remove_lsb ) port map ( rst => rst, clk => clk, - in_dat => raw_out_val, - out_dat => quant_val + in_dat => raw_val, + out_dat => out_val ); - - -- Undo input random negation of u_switch at output when g_fft.use_separate = TRUE - u_unswitch : ENTITY work.fft_unswitch - GENERIC MAP ( - g_switch_en => c_switch_en, - g_seed1 => c_switch_seed1, - g_seed2 => c_switch_seed2, - g_fft_sz_w => c_switch_sz_w, - g_dat_w => c_unswitch_dat_w + + ------------------------------------------------------------------------------ + -- Pipelined FFT raw output register + ------------------------------------------------------------------------------ + + -- . Pipeline out_raw to align with out_quant, so they can share + -- out_val. + u_out_raw_re : entity common_lib.common_pipeline + generic map ( + g_representation => "SIGNED", + g_pipeline => c_pipeline_remove_lsb, + g_in_dat_w => c_raw_dat_w, + g_out_dat_w => c_32 ) - PORT MAP ( - in_re => quant_re, - in_im => quant_im, - in_val => quant_val, - out_re => out_re, - out_im => out_im, - out_val => out_val, - clk => clk, - rst => rst + port map ( + rst => rst, + clk => clk, + in_dat => raw_re, + out_dat => out_raw_re + ); + + u_out_raw_im : entity common_lib.common_pipeline + generic map ( + g_representation => "SIGNED", + g_pipeline => c_pipeline_remove_lsb, + g_in_dat_w => c_raw_dat_w, + g_out_dat_w => c_32 + ) + port map ( + rst => rst, + clk => clk, + in_dat => raw_im, + out_dat => out_raw_im ); end str; diff --git a/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd b/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd index 017e5b1384983d66a423fe605f4259e54fc1d4ae..209ac150ba20fbde3b23005f8a1eaf9716fc53fd 100644 --- a/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd @@ -148,12 +148,9 @@ architecture rtl of fft_r2_wide is constant c_fft_r2_pipe_arr : t_fft_arr(g_fft.wb_factor-1 downto 0) := func_create_generic_for_pipe_fft(g_fft); constant c_fft_r2_par : t_fft := func_create_generic_for_par_fft(g_fft); - constant c_in_scale_w : natural := g_fft.stage_dat_w - g_fft.in_dat_w - sel_a_b(g_fft.guard_enable, g_fft.guard_w, 0); - - constant c_out_scale_w : integer := c_fft_r2_par.out_dat_w - g_fft.out_dat_w - g_fft.out_gain_w; -- Estimate number of LSBs to throw away when > 0 or insert when < 0 - - constant c_sepa_growth_w : natural := sel_a_b(g_fft.use_separate, 1, 0); -- add one bit for add sub growth in separate - constant c_raw_dat_w : natural := g_fft.stage_dat_w + c_sepa_growth_w; + constant c_in_scale_w : natural := func_fft_in_scale_w(g_fft); + constant c_raw_fraction_w : natural := func_fft_raw_fraction_w(g_fft); + constant c_raw_dat_w : natural := func_fft_raw_dat_w(g_fft); -- g_fft.wb_factor = 1 signal fft_pipe_out_re : std_logic_vector(g_fft.out_dat_w-1 downto 0); @@ -179,6 +176,12 @@ architecture rtl of fft_r2_wide is signal sep_out_im_arr : t_fft_slv_arr(g_fft.wb_factor-1 downto 0); signal sep_out_val : std_logic; + -- debug signals to view parameters in Wave Window + signal dbg_g_g_fft : t_fft := g_fft; + signal dbg_c_in_scale_w : natural := c_in_scale_w; + signal dbg_c_raw_fraction_w : natural := c_raw_fraction_w; + signal dbg_c_raw_dat_w : natural := c_raw_dat_w; + begin -- Default to fft_r2_pipe when g_fft.wb_factor=1 @@ -189,14 +192,14 @@ begin g_pipeline => g_pft_pipeline ) port map ( - clk => clk, - rst => rst, - in_re => in_re_arr(0)(g_fft.in_dat_w-1 downto 0), - in_im => in_im_arr(0)(g_fft.in_dat_w-1 downto 0), - in_val => in_val, - out_re => fft_pipe_out_re, - out_im => fft_pipe_out_im, - out_val => out_val + clk => clk, + rst => rst, + in_re => in_re_arr(0)(g_fft.in_dat_w-1 downto 0), + in_im => in_im_arr(0)(g_fft.in_dat_w-1 downto 0), + in_val => in_val, + out_quant_re => fft_pipe_out_re, + out_quant_im => fft_pipe_out_im, + out_val => out_val ); out_re_arr(0) <= resize_fft_svec(fft_pipe_out_re); @@ -244,14 +247,14 @@ begin g_pipeline => g_pft_pipeline -- pipeline generics for the pipelined FFTs ) port map ( - clk => clk, - rst => rst, - in_re => in_fft_pipe_re_arr(I)(c_fft_r2_pipe_arr(I).in_dat_w-1 downto 0), - in_im => in_fft_pipe_im_arr(I)(c_fft_r2_pipe_arr(I).in_dat_w-1 downto 0), - in_val => in_val, - out_re => out_fft_pipe_re_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0), - out_im => out_fft_pipe_im_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0), - out_val => out_fft_pipe_val(I) + clk => clk, + rst => rst, + in_re => in_fft_pipe_re_arr(I)(c_fft_r2_pipe_arr(I).in_dat_w-1 downto 0), + in_im => in_fft_pipe_im_arr(I)(c_fft_r2_pipe_arr(I).in_dat_w-1 downto 0), + in_val => in_val, + out_quant_re => out_fft_pipe_re_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0), + out_quant_im => out_fft_pipe_im_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0), + out_val => out_fft_pipe_val(I) ); end generate; @@ -321,7 +324,7 @@ begin u_requantize_output_re : entity common_lib.common_requantize generic map ( g_representation => "SIGNED", - g_lsb_w => c_out_scale_w + c_sepa_growth_w, + g_lsb_w => c_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, g_msb_clip => FALSE, @@ -341,7 +344,7 @@ begin u_requantize_output_im : entity common_lib.common_requantize generic map ( g_representation => "SIGNED", - g_lsb_w => c_out_scale_w + c_sepa_growth_w, + g_lsb_w => c_raw_fraction_w, g_lsb_round => TRUE, g_lsb_round_clip => FALSE, g_msb_clip => FALSE, diff --git a/libraries/dsp/fft/src/vhdl/fft_reorder_sepa_pipe.vhd b/libraries/dsp/fft/src/vhdl/fft_reorder_sepa_pipe.vhd index b363745caf022d3cf0e9716eef1cfcaea424c8e5..d0c2a68febe92359e6b1fd86ad60b8bcd29cb70a 100644 --- a/libraries/dsp/fft/src/vhdl/fft_reorder_sepa_pipe.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_reorder_sepa_pipe.vhd @@ -51,9 +51,9 @@ entity fft_reorder_sepa_pipe is port ( clk : in std_logic; rst : in std_logic; - in_dat : in std_logic_vector; -- c_dat_w + in_dat : in std_logic_vector; -- c_dat_w (Im & Re) in_val : in std_logic; - out_dat : out std_logic_vector; -- c_dat_w when g_separate = false, else c_dat_w + 2 + out_dat : out std_logic_vector; -- c_dat_w when g_separate = false, else c_dat_w + 2 (Im & Re, with 1 extra bit for both) out_val : out std_logic ); end entity fft_reorder_sepa_pipe; @@ -105,6 +105,14 @@ architecture rtl of fft_reorder_sepa_pipe is signal r, rin : reg_type; + -- debug signals to view parameters in Wave Window + signal dbg_c_nof_channels : natural := c_nof_channels; + signal dbg_c_dat_w : natural := c_dat_w; + signal dbg_c_page_size : natural := c_page_size; + signal dbg_c_adr_points_w : natural := c_adr_points_w; + signal dbg_c_adr_chan_w : natural := c_adr_chan_w; + signal dbg_c_adr_tot_w : natural := c_adr_tot_w; + begin out_dat_i <= rd_dat; diff --git a/libraries/dsp/fft/tb/vhdl/tb_fft_r2_pipe.vhd b/libraries/dsp/fft/tb/vhdl/tb_fft_r2_pipe.vhd index 35a6684bc3a7ef5e41fc9c130657dbb9e6932831..785430c6b0eed06f91fe6aa92a884cb690527afd 100644 --- a/libraries/dsp/fft/tb/vhdl/tb_fft_r2_pipe.vhd +++ b/libraries/dsp/fft/tb/vhdl/tb_fft_r2_pipe.vhd @@ -331,14 +331,14 @@ begin g_fft => g_fft ) port map ( - clk => clk, - rst => rst, - in_re => in_dat_a, - in_im => in_dat_b, - in_val => in_val, - out_re => out_re, - out_im => out_im, - out_val => out_val + clk => clk, + rst => rst, + in_re => in_dat_a, + in_im => in_dat_b, + in_val => in_val, + out_quant_re => out_re, + out_quant_im => out_im, + out_val => out_val ); -- Separate output @@ -447,4 +447,4 @@ begin diff_re_c_scope <= exp_re_c_scope - out_re_c_scope; diff_im_c_scope <= exp_im_c_scope - out_im_c_scope; -end tb; \ No newline at end of file +end tb; diff --git a/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2.vhd b/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2.vhd index 2a0c51f25adf5c83d54404aae4ed0b8784cc5538..b744daefe029d7e092e19d06993ed5b1b6e29bfe 100644 --- a/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2.vhd +++ b/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2.vhd @@ -278,14 +278,14 @@ BEGIN g_fft => c_fft ) port map( - clk => dp_clk, - rst => dp_rst, - in_re => in_re_arr(0)(c_fft.in_dat_w-1 DOWNTO 0), - in_im => in_im_arr(0)(c_fft.in_dat_w-1 DOWNTO 0), - in_val => in_val, - out_re => out_re_arr(0)(c_fft.out_dat_w-1 DOWNTO 0), - out_im => out_im_arr(0)(c_fft.out_dat_w-1 DOWNTO 0), - out_val => out_val + clk => dp_clk, + rst => dp_rst, + in_re => in_re_arr(0)(c_fft.in_dat_w-1 DOWNTO 0), + in_im => in_im_arr(0)(c_fft.in_dat_w-1 DOWNTO 0), + in_val => in_val, + out_quant_re => out_re_arr(0)(c_fft.out_dat_w-1 DOWNTO 0), + out_quant_im => out_im_arr(0)(c_fft.out_dat_w-1 DOWNTO 0), + out_val => out_val ); END GENERATE; diff --git a/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2_pipe.vhd b/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2_pipe.vhd index 675d4d64816ce09d098d7f7f6f870a2ccda7f0a6..549f82b0c46759d313182de4a8572810f15aec0c 100644 --- a/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2_pipe.vhd +++ b/libraries/dsp/fft/tb/vhdl/tb_mmf_fft_r2_pipe.vhd @@ -219,14 +219,14 @@ BEGIN g_fft => g_fft -- generics for the FFT ) port map( - clk => dp_clk, - rst => dp_rst, - in_re => in_re, - in_im => in_im, - in_val => in_val, - out_re => out_re, - out_im => out_im, - out_val => out_val + clk => dp_clk, + rst => dp_rst, + in_re => in_re, + in_im => in_im, + in_val => in_val, + out_quant_re => out_re, + out_quant_im => out_im, + out_val => out_val ); ss_out_sosi_re_arr(0).data <= RESIZE_SVEC(out_re, ss_out_sosi_re_arr(0).data'LENGTH); diff --git a/libraries/dsp/verify_pfb/tb_verify_pfb_response.vhd b/libraries/dsp/verify_pfb/tb_verify_pfb_response.vhd index 22eeddb4d0affcfca21099f55f73a8a4c1032987..27c61530d005115d4c572c7073d6fd93e5d60d5e 100644 --- a/libraries/dsp/verify_pfb/tb_verify_pfb_response.vhd +++ b/libraries/dsp/verify_pfb/tb_verify_pfb_response.vhd @@ -190,6 +190,7 @@ ARCHITECTURE tb OF tb_verify_pfb_response IS SIGNAL fil_blk_cnt : NATURAL := 0; -- count blocks per sync interval -- Output + SIGNAL raw_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0); SIGNAL out_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0); SIGNAL out_sosi : t_dp_sosi; SIGNAL out_re : INTEGER; @@ -372,7 +373,8 @@ BEGIN ram_fil_coefs_miso => ram_fil_coefs_miso, in_sosi_arr => in_sosi_arr, fil_sosi_arr => fil_sosi_arr, - out_sosi_arr => out_sosi_arr + out_quant_sosi_arr => out_sosi_arr, + out_raw_sosi_arr => raw_sosi_arr ); END GENERATE; diff --git a/libraries/dsp/verify_pfb/tb_verify_pfb_wg.vhd b/libraries/dsp/verify_pfb/tb_verify_pfb_wg.vhd index 85e9724b6bf862de675c64c66c245a9d04bb8b9c..ae037d75901159bc5d7251caa5ecb4dab5917714 100644 --- a/libraries/dsp/verify_pfb/tb_verify_pfb_wg.vhd +++ b/libraries/dsp/verify_pfb/tb_verify_pfb_wg.vhd @@ -156,7 +156,7 @@ ENTITY tb_verify_pfb_wg IS -- FFT g_fft_out_dat_w : NATURAL := 18; -- = W_subband, number of output bits g_fft_out_gain_w : NATURAL := 1; -- = 1, output gain factor applied after the last stage output, before requantization to out_dat_w - g_fft_stage_dat_w : NATURAL := 27; -- = c_dsp_mult_w = 18, number of bits that are used inter-stage + g_fft_stage_dat_w : NATURAL := 24; -- = c_dsp_mult_w = 18, number of bits that are used inter-stage g_fft_guard_w : NATURAL := 1; -- = 2 g_switch_en : STD_LOGIC := '0' -- two real input decorrelation option in PFB2 ); @@ -486,6 +486,7 @@ ARCHITECTURE tb OF tb_verify_pfb_wg IS SIGNAL wpfb_measured_proc_gain_b_dB : REAL := 0.0; -- Output + SIGNAL raw_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0); SIGNAL out_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0); SIGNAL out_sosi : t_dp_sosi; SIGNAL out_re : INTEGER; @@ -1136,7 +1137,8 @@ BEGIN ram_st_sst_miso => ram_st_sst_miso, in_sosi_arr => in_sosi_arr, fil_sosi_arr => fil_sosi_arr, - out_sosi_arr => out_sosi_arr + out_quant_sosi_arr => out_sosi_arr, + out_raw_sosi_arr => raw_sosi_arr ); END GENERATE; diff --git a/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd b/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd index 71d31450368ce939a3edb09a389f35b33b9b1acc..df393099f59b8a03f4552ca659018513b4ca3ad2 100644 --- a/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd +++ b/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd @@ -70,6 +70,14 @@ package wpfb_pkg is fil_pipeline : t_fil_ppf_pipeline; -- Pipeline settings for the filter units end record; + ----------------------------------------------------------------------------- + -- Map WPFB parameters + ----------------------------------------------------------------------------- + function func_wpfb_map_wpfb_parameters_to_fil_ppf(g_wpfb : t_wpfb) return t_fil_ppf; + function func_wpfb_map_wpfb_parameters_to_fft(g_wpfb : t_wpfb) return t_fft; + + function func_wpfb_map_real_input_wpfb_parameters_to_complex_input(g_wpfb : t_wpfb) return t_wpfb; + ----------------------------------------------------------------------------- -- LOFAR2 subband filter ----------------------------------------------------------------------------- @@ -246,6 +254,50 @@ end package wpfb_pkg; package body wpfb_pkg is + function func_wpfb_map_wpfb_parameters_to_fil_ppf(g_wpfb : t_wpfb) return t_fil_ppf is + constant c_fil_ppf : t_fil_ppf := (g_wpfb.wb_factor, + g_wpfb.nof_chan, + g_wpfb.nof_points, + g_wpfb.nof_taps, + c_nof_complex*g_wpfb.nof_wb_streams, -- Complex FFT always requires 2 filter streams: real and imaginary + g_wpfb.fil_backoff_w, + g_wpfb.fil_in_dat_w, + g_wpfb.fil_out_dat_w, + g_wpfb.coef_dat_w); + begin + return c_fil_ppf; + end func_wpfb_map_wpfb_parameters_to_fil_ppf; + + function func_wpfb_map_wpfb_parameters_to_fft(g_wpfb : t_wpfb) return t_fft is + constant c_fft : t_fft := (g_wpfb.use_reorder, + g_wpfb.use_fft_shift, + g_wpfb.use_separate, + g_wpfb.nof_chan, + g_wpfb.wb_factor, + 0, + g_wpfb.nof_points, + g_wpfb.fft_in_dat_w, + g_wpfb.fft_out_dat_w, + g_wpfb.fft_out_gain_w, + g_wpfb.stage_dat_w, + g_wpfb.guard_w, + g_wpfb.guard_enable, + g_wpfb.stat_data_w, + g_wpfb.stat_data_sz); + begin + return c_fft; + end func_wpfb_map_wpfb_parameters_to_fft; + + + function func_wpfb_map_real_input_wpfb_parameters_to_complex_input(g_wpfb : t_wpfb) return t_wpfb is + variable v_wpfb : t_wpfb := g_wpfb; + begin + v_wpfb.nof_wb_streams := c_nof_complex * v_wpfb.nof_wb_streams; + v_wpfb.use_separate := false; + return v_wpfb; + end func_wpfb_map_real_input_wpfb_parameters_to_complex_input; + + function func_wpfb_subband_scale_w(wpfb : t_wpfb) return natural is begin return wpfb.fft_out_dat_w + wpfb.fft_out_gain_w - (wpfb.fil_in_dat_w + wpfb.fil_backoff_w); diff --git a/libraries/dsp/wpfb/src/vhdl/wpfb_unit.vhd b/libraries/dsp/wpfb/src/vhdl/wpfb_unit.vhd index 2bfba7f1b141b0ee0e70896f8ae6a283bbce238a..fceeb8f5f2b6cdb659cffa92c5c4657fef554260 100644 --- a/libraries/dsp/wpfb/src/vhdl/wpfb_unit.vhd +++ b/libraries/dsp/wpfb/src/vhdl/wpfb_unit.vhd @@ -90,32 +90,8 @@ architecture str of wpfb_unit is constant c_nof_stats : natural := 2**g_wpfb.nof_chan * g_wpfb.nof_points/g_wpfb.wb_factor; - constant c_fil_ppf : t_fil_ppf := (g_wpfb.wb_factor, - g_wpfb.nof_chan, - g_wpfb.nof_points, - g_wpfb.nof_taps, - c_nof_complex*g_wpfb.nof_wb_streams, -- Complex FFT always requires 2 filter streams: real and imaginary - g_wpfb.fil_backoff_w, - g_wpfb.fil_in_dat_w, - g_wpfb.fil_out_dat_w, - g_wpfb.coef_dat_w); - - constant c_fft : t_fft := (g_wpfb.use_reorder, - g_wpfb.use_fft_shift, - g_wpfb.use_separate, - g_wpfb.nof_chan, - g_wpfb.wb_factor, - 0, - g_wpfb.nof_points, - g_wpfb.fft_in_dat_w, - g_wpfb.fft_out_dat_w, - g_wpfb.fft_out_gain_w, - g_wpfb.stage_dat_w, - g_wpfb.guard_w, - g_wpfb.guard_enable, - g_wpfb.stat_data_w, - g_wpfb.stat_data_sz); - + constant c_fil_ppf : t_fil_ppf := func_wpfb_map_wpfb_parameters_to_fil_ppf(g_wpfb); + constant c_fft : t_fft := func_wpfb_map_wpfb_parameters_to_fft(g_wpfb); constant c_bg_buf_adr_w : natural := ceil_log2(g_wpfb.nof_points/g_wpfb.wb_factor); constant c_bg_data_file_index_arr : t_nat_natural_arr := array_init(0, g_wpfb.nof_wb_streams*g_wpfb.wb_factor, 1); @@ -315,14 +291,14 @@ begin g_pipeline => g_wpfb.fft_pipeline ) port map( - clk => dp_clk, - rst => dp_rst, - in_re => fft_in_re_arr(I)(c_fft.in_dat_w-1 downto 0), - in_im => fft_in_im_arr(I)(c_fft.in_dat_w-1 downto 0), - in_val => fft_in_val, - out_re => fft_out_re_arr_i(I)(c_fft.out_dat_w-1 downto 0), - out_im => fft_out_im_arr_i(I)(c_fft.out_dat_w-1 downto 0), - out_val => fft_out_val(I) + clk => dp_clk, + rst => dp_rst, + in_re => fft_in_re_arr(I)(c_fft.in_dat_w-1 downto 0), + in_im => fft_in_im_arr(I)(c_fft.in_dat_w-1 downto 0), + in_val => fft_in_val, + out_quant_re => fft_out_re_arr_i(I)(c_fft.out_dat_w-1 downto 0), + out_quant_im => fft_out_im_arr_i(I)(c_fft.out_dat_w-1 downto 0), + out_val => fft_out_val(I) ); fft_out_re_arr(I) <= RESIZE_SVEC(fft_out_re_arr_i(I)(c_fft.out_dat_w-1 downto 0), fft_out_re_arr(I)'length); fft_out_im_arr(I) <= RESIZE_SVEC(fft_out_im_arr_i(I)(c_fft.out_dat_w-1 downto 0), fft_out_im_arr(I)'length); diff --git a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd index ae905b69951111ea497fa1c49801a2886790ed0f..0fe902a0f51912405ad2943852bac6b7606c1a24 100644 --- a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd +++ b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd @@ -69,7 +69,7 @@ -- part are filtered independently and also use the same real FIR -- coefficients. -- --- Note that: +-- Remarks: -- . The same P of all streams are grouped the in filter and all P per -- stream are grouped in the FFT. Hence the WPFB input is grouped per -- P for all wideband streams to allow FIR coefficients reuse per P @@ -88,6 +88,19 @@ -- incrementing order. However the precise frequency bin order depends -- on the reorder generics. -- +-- . Output subband widths: +-- - out_quant_sosi_arr : c_fft.out_dat_w bits (within c_32 word) +-- - out_raw_sosi_arr : c_raw_dat_w bits (within c_32 word) +-- The out_quant carries subbands of c_fft.out_dat_w bits, so the +-- c_raw_fraction_w fraction bits in c_raw_dat_w have been rounded. +-- The out_raw carries subbands of c_raw_dat_w bits, that still have the +-- c_raw_fraction_w fraction bits. The out_raw subbands are suitable for +-- further weighting or alternative rounding. +-- Note that c_raw_dat_w and c_raw_fraction_w depend on c_fft.use_separate. +-- For real input data FFT there is one fraction bit more than for complex +-- input FFT, due to the adder stage in the separate function. +-- Both out_quant and out_raw use FFT out_val, so they have the same timing. +-- -- When wb_factor = 4 and nof_wb_streams = 2 the mapping is as follows using -- the array notation: -- @@ -96,26 +109,24 @@ -- . P = wideband factor index -- . t = time index -- --- parallel serial type --- in_sosi_arr [nof_streams][wb_factor] [t] cint +-- parallel serial type +-- in_sosi_arr [nof_streams][wb_factor] [t] cint -- --- fil_in_arr [wb_factor][nof_streams][complex] [t] int --- fil_out_arr [wb_factor][nof_streams][complex] [t] int +-- fil_in_arr [wb_factor][nof_streams][complex] [t] int +-- fil_out_arr [wb_factor][nof_streams][complex] [t] int -- --- fil_sosi_arr [nof_streams][wb_factor] [t] cint --- fft_in_re_arr [nof_streams][wb_factor] [t] int --- fft_in_im_arr [nof_streams][wb_factor] [t] int --- fft_out_re_arr [nof_streams][wb_factor] [bin] int --- fft_out_im_arr [nof_streams][wb_factor] [bin] int --- fft_out_sosi_arr [nof_streams][wb_factor] [bin] cint --- pfb_out_sosi_arr [nof_streams][wb_factor] [bin] cint with sync, BSN, sop, eop --- out_sosi_arr [nof_streams][wb_factor] [bin] cint with sync, BSN, sop, eop --- --- in_sosi_arr | fil_in_arr | fft_in_re_arr | fft_out_re_arr --- fil_sosi_arr | fil_out_arr | fft_in_im_arr | fft_out_im_arr --- | | | fft_out_sosi_arr --- | | | pfb_out_sosi_arr --- | | | out_sosi_arr +-- fil_sosi_arr [nof_streams][wb_factor] [t] cint +-- fft_in_re_arr [nof_streams][wb_factor] [t] int +-- fft_in_im_arr [nof_streams][wb_factor] [t] int +-- fft_out_quant_re_arr [nof_streams][wb_factor] [bin] int +-- fft_out_quant_im_arr [nof_streams][wb_factor] [bin] int +-- pfb_out_quant_sosi_arr [nof_streams][wb_factor] [bin] cint with sync, BSN, sop, eop +-- out_quant_sosi_arr [nof_streams][wb_factor] [bin] cint with sync, BSN, sop, eop +-- +-- in_sosi_arr | fil_in_arr | fft_in_re_arr | fft_out_quant_re_arr +-- fil_sosi_arr | fil_out_arr | fft_in_im_arr | fft_out_quant_im_arr +-- | | | pfb_out_quant_sosi_arr +-- | | | out_quant_sosi_arr -- | | | -- I S P t | I P S | I S P t | I S P -- 7 1 3 0 | 15 3 1 IM | 7 1 3 3 | 7 1 3 @@ -162,7 +173,7 @@ -- I) Wideband wb_factor = 4 -- 1) Two real inputs: -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order . nof_streams = 2 -- 7 1 3 12 12 13 13 14 14 15 15 . wb_factor = 4 -- 6 1 2 8 8 9 9 10 10 11 11 . nof_points = 32 @@ -189,7 +200,7 @@ -- -- 2a) Complex input with fft_shift: -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order . nof_streams = 2 -- 7 1 3 24 25 26 27 28 29 30 31 . wb_factor = 4 -- 6 1 2 16 17 18 19 20 21 22 23 . nof_points = 32 @@ -214,7 +225,7 @@ -- -- 2b) Complex input with reorder, but no fft_shift: -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order . nof_streams = 2 -- 7 1 3 8 9 10 11 12 13 14 15 . wb_factor = 4 -- 6 1 2 0 1 2 3 4 5 6 7 . nof_points = 32 @@ -239,7 +250,7 @@ -- -- 2c) Complex input without reorder (so bit flipped): -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order . nof_streams = 2 -- 7 1 3 8 12 10 14 9 13 11 15 . wb_factor = 4 -- 6 1 2 24 28 26 30 25 29 27 31 . nof_points = 32 @@ -276,7 +287,7 @@ -- - input A via in_sosi_arr().re -- - input B via in_sosi_arr().im -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order -- 1 1 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 -- 0 0 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 @@ -299,7 +310,7 @@ -- 2a) Complex input with fft_shift (so use_reorder = true, use_fft_shift = true) -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order -- 1 1 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 -- 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @@ -312,7 +323,7 @@ -- -- 2b) Complex input with reorder but no fft_shift (so use_reorder = true, use_fft_shift = false) -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order -- 1 1 0 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -- 0 0 0 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @@ -325,7 +336,7 @@ -- -- 2c) Complex input without reorder (so use_reorder = false, use_fft_shift = false) -- --- out_sosi_arr: +-- out_quant_sosi_arr: -- I S P bin frequency order -- 1 1 0 16 0 24 8 20 4 28 12 18 2 26 10 22 6 30 14 17 1 25 9 21 5 29 13 19 3 27 11 23 7 31 15 -- 0 0 0 16 0 24 8 20 4 28 12 18 2 26 10 22 6 30 14 17 1 25 9 21 5 29 13 19 3 27 11 23 7 31 15 @@ -382,7 +393,8 @@ entity wpfb_unit_dev is ram_bg_data_miso : out t_mem_miso; in_sosi_arr : in t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); fil_sosi_arr : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - out_sosi_arr : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + out_quant_sosi_arr : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + out_raw_sosi_arr : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); dp_bsn_source_restart : in std_logic := '0' ); end entity wpfb_unit_dev; @@ -396,34 +408,14 @@ architecture str of wpfb_unit_dev is constant c_nof_stats : natural := c_nof_valid_per_block; - constant c_fil_ppf : t_fil_ppf := (g_wpfb.wb_factor, - g_wpfb.nof_chan, - g_wpfb.nof_points, - g_wpfb.nof_taps, - c_nof_complex*g_wpfb.nof_wb_streams, -- Complex FFT always requires 2 filter streams: real and imaginary - g_wpfb.fil_backoff_w, - g_wpfb.fil_in_dat_w, - g_wpfb.fil_out_dat_w, - g_wpfb.coef_dat_w); - - constant c_fft : t_fft := (g_wpfb.use_reorder, - g_wpfb.use_fft_shift, - g_wpfb.use_separate, - g_wpfb.nof_chan, - g_wpfb.wb_factor, - 0, - g_wpfb.nof_points, - g_wpfb.fft_in_dat_w, - g_wpfb.fft_out_dat_w, - g_wpfb.fft_out_gain_w, - g_wpfb.stage_dat_w, - g_wpfb.guard_w, - g_wpfb.guard_enable, - g_wpfb.stat_data_w, - g_wpfb.stat_data_sz); + constant c_fil_ppf : t_fil_ppf := func_wpfb_map_wpfb_parameters_to_fil_ppf(g_wpfb); + constant c_fft : t_fft := func_wpfb_map_wpfb_parameters_to_fft(g_wpfb); constant c_fft_r2_check : boolean := fft_r2_parameter_asserts(c_fft); + constant c_raw_fraction_w : natural := func_fft_raw_fraction_w(c_fft); + constant c_raw_dat_w : natural := func_fft_raw_dat_w(c_fft); + constant c_bg_buf_adr_w : natural := ceil_log2(g_wpfb.nof_points/g_wpfb.wb_factor); constant c_bg_data_file_index_arr : t_nat_natural_arr := array_init(0, g_wpfb.nof_wb_streams*g_wpfb.wb_factor, 1); constant c_bg_data_file_prefix : string := "UNUSED"; @@ -440,15 +432,15 @@ architecture str of wpfb_unit_dev is signal fft_in_im_arr : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); signal fft_in_val : std_logic; - signal fft_out_re_arr_i : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - signal fft_out_im_arr_i : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - signal fft_out_re_arr : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - signal fft_out_im_arr : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - signal fft_out_re_arr_pipe : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - signal fft_out_im_arr_pipe : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - signal fft_out_val_arr : std_logic_vector(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + signal fft_out_quant_re_arr_i : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + signal fft_out_quant_im_arr_i : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + signal fft_out_quant_re_arr : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + signal fft_out_quant_im_arr : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + signal fft_out_raw_re_arr : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + signal fft_out_raw_im_arr : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); + signal fft_out_val_arr : std_logic_vector(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0); - signal pfb_out_sosi_arr : t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0) := (others => c_dp_sosi_rst); + signal pfb_out_quant_sosi_arr : t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0) := (others => c_dp_sosi_rst); signal ctrl_pfb_out_sosi : t_dp_sosi := c_dp_sosi_rst; type reg_type is record @@ -458,6 +450,13 @@ architecture str of wpfb_unit_dev is signal r, rin : reg_type; + -- Debug signals to view parameters in Wave Window + signal dbg_g_wpfb : t_wpfb := g_wpfb; + signal dbg_c_fil_ppf : t_fil_ppf := c_fil_ppf; + signal dbg_c_fft : t_fft := c_fft; + signal dbg_c_raw_fraction_w : natural := c_raw_fraction_w; + signal dbg_c_raw_dat_w : natural := c_raw_dat_w; + begin -- The complete input sosi arry is registered. @@ -581,8 +580,8 @@ begin in_re_arr => fft_in_re_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor), in_im_arr => fft_in_im_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor), in_val => fft_in_val, - out_re_arr => fft_out_re_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor), - out_im_arr => fft_out_im_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor), + out_re_arr => fft_out_quant_re_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor), + out_im_arr => fft_out_quant_im_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor), out_val => fft_out_val_arr(S) ); end generate; @@ -601,18 +600,20 @@ begin g_dont_flip_channels => g_dont_flip_channels ) port map( - clk => dp_clk, - rst => dp_rst, - in_re => fft_in_re_arr(S)(c_fft.in_dat_w-1 downto 0), - in_im => fft_in_im_arr(S)(c_fft.in_dat_w-1 downto 0), - in_val => fft_in_val, - out_re => fft_out_re_arr_i(S)(c_fft.out_dat_w-1 downto 0), - out_im => fft_out_im_arr_i(S)(c_fft.out_dat_w-1 downto 0), - out_val => fft_out_val_arr(S) + clk => dp_clk, + rst => dp_rst, + in_re => fft_in_re_arr(S)(c_fft.in_dat_w-1 downto 0), + in_im => fft_in_im_arr(S)(c_fft.in_dat_w-1 downto 0), + in_val => fft_in_val, + out_quant_re => fft_out_quant_re_arr_i(S)(c_fft.out_dat_w-1 downto 0), + out_quant_im => fft_out_quant_im_arr_i(S)(c_fft.out_dat_w-1 downto 0), + out_raw_re => fft_out_raw_re_arr(S), + out_raw_im => fft_out_raw_im_arr(S), + out_val => fft_out_val_arr(S) ); - fft_out_re_arr(S) <= RESIZE_SVEC_32(fft_out_re_arr_i(S)(c_fft.out_dat_w-1 downto 0)); - fft_out_im_arr(S) <= RESIZE_SVEC_32(fft_out_im_arr_i(S)(c_fft.out_dat_w-1 downto 0)); + fft_out_quant_re_arr(S) <= RESIZE_SVEC_32(fft_out_quant_re_arr_i(S)(c_fft.out_dat_w-1 downto 0)); + fft_out_quant_im_arr(S) <= RESIZE_SVEC_32(fft_out_quant_im_arr_i(S)(c_fft.out_dat_w-1 downto 0)); end generate; end generate; @@ -637,14 +638,26 @@ begin out_sosi => ctrl_pfb_out_sosi ); - wire_pfb_out_sosi_arr : for I in 0 to g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 generate - pfb_out_sosi_arr(I).re <= RESIZE_DP_DSP_DATA(fft_out_re_arr(I)); - pfb_out_sosi_arr(I).im <= RESIZE_DP_DSP_DATA(fft_out_im_arr(I)); - pfb_out_sosi_arr(I).valid <= ctrl_pfb_out_sosi.valid; - pfb_out_sosi_arr(I).sync <= ctrl_pfb_out_sosi.sync; - pfb_out_sosi_arr(I).bsn <= ctrl_pfb_out_sosi.bsn; - pfb_out_sosi_arr(I).sop <= ctrl_pfb_out_sosi.sop; - pfb_out_sosi_arr(I).eop <= ctrl_pfb_out_sosi.eop; + -- wire pfb_out_quant_sosi_arr that is used for SST and for out_quant_sosi_arr + wire_pfb_out_quant_sosi_arr : for I in 0 to g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 generate + pfb_out_quant_sosi_arr(I).re <= RESIZE_DP_DSP_DATA(fft_out_quant_re_arr(I)); + pfb_out_quant_sosi_arr(I).im <= RESIZE_DP_DSP_DATA(fft_out_quant_im_arr(I)); + pfb_out_quant_sosi_arr(I).valid <= ctrl_pfb_out_sosi.valid; + pfb_out_quant_sosi_arr(I).sync <= ctrl_pfb_out_sosi.sync; + pfb_out_quant_sosi_arr(I).bsn <= ctrl_pfb_out_sosi.bsn; + pfb_out_quant_sosi_arr(I).sop <= ctrl_pfb_out_sosi.sop; + pfb_out_quant_sosi_arr(I).eop <= ctrl_pfb_out_sosi.eop; + end generate; + + -- directly wire out_raw_sosi_arr + wire_out_raw_sosi_arr : for I in 0 to g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 generate + out_raw_sosi_arr(I).re <= RESIZE_DP_DSP_DATA(fft_out_raw_re_arr(I)); + out_raw_sosi_arr(I).im <= RESIZE_DP_DSP_DATA(fft_out_raw_im_arr(I)); + out_raw_sosi_arr(I).valid <= ctrl_pfb_out_sosi.valid; + out_raw_sosi_arr(I).sync <= ctrl_pfb_out_sosi.sync; + out_raw_sosi_arr(I).bsn <= ctrl_pfb_out_sosi.bsn; + out_raw_sosi_arr(I).sop <= ctrl_pfb_out_sosi.sop; + out_raw_sosi_arr(I).eop <= ctrl_pfb_out_sosi.eop; end generate; end generate; @@ -673,7 +686,7 @@ begin ram_bg_data_mosi => ram_bg_data_mosi, ram_bg_data_miso => ram_bg_data_miso, -- ST interface - out_sosi_arr => pfb_out_sosi_arr + out_sosi_arr => pfb_out_quant_sosi_arr ); end generate; @@ -701,7 +714,7 @@ begin mm_clk => mm_clk, dp_rst => dp_rst, dp_clk => dp_clk, - in_complex => pfb_out_sosi_arr(S*g_wpfb.wb_factor+P), + in_complex => pfb_out_quant_sosi_arr(S*g_wpfb.wb_factor+P), ram_st_sst_mosi => ram_st_sst_mosi_arr(S*g_wpfb.wb_factor+P), ram_st_sst_miso => ram_st_sst_miso_arr(S*g_wpfb.wb_factor+P) ); @@ -710,7 +723,7 @@ begin end generate; -- Connect to the outside world - out_sosi_arr <= pfb_out_sosi_arr; + out_quant_sosi_arr <= pfb_out_quant_sosi_arr; end str; diff --git a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd index f789359e1d3410443b43e3e84fa048ff4c21290c..07485ee366434759edc83d99e9b99b8bc6a57e91 100644 --- a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd +++ b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_dev.vhd @@ -330,7 +330,8 @@ BEGIN ram_bg_data_mosi => ram_diag_bg_pfb_mosi, ram_bg_data_miso => ram_diag_bg_pfb_miso, in_sosi_arr => bg_sosi_arr, - out_sosi_arr => out_sosi_arr + out_quant_sosi_arr => out_sosi_arr, + out_raw_sosi_arr => open ); time_map : process is diff --git a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd index d385e8f7cfe41cbcfee9ae6e1713c7d263d71383..caa83e1592b49ac73aadcebf2c52fc65a1d80159 100644 --- a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd +++ b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd @@ -486,7 +486,8 @@ begin ram_bg_data_miso => open, in_sosi_arr => in_sosi_arr, fil_sosi_arr => fil_sosi_arr, - out_sosi_arr => out_sosi_arr + out_quant_sosi_arr => out_sosi_arr, + out_raw_sosi_arr => open ); p_fil_sosi_arr : process(fil_sosi_arr) diff --git a/libraries/io/nw_10GbE/tb/vhdl/tb_nw_arp_request.vhd b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_arp_request.vhd index 950aedd237ca96781c34831b29d3124098ea8cb4..c714f21e19e894a650f7c5d228dd3031da41e96b 100644 --- a/libraries/io/nw_10GbE/tb/vhdl/tb_nw_arp_request.vhd +++ b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_arp_request.vhd @@ -45,6 +45,9 @@ END tb_nw_arp_request; ARCHITECTURE tb OF tb_nw_arp_request IS + -- Use c_tb_timeout to raise ERROR if there is no result + CONSTANT c_tb_timeout : NATURAL := 100; + SIGNAL tb_end : STD_LOGIC := '0'; SIGNAL clk : STD_LOGIC := '1'; SIGNAL dp_pps : STD_LOGIC := '1'; @@ -77,8 +80,11 @@ BEGIN dp_pps <= '0'; proc_common_wait_some_cycles(clk, 10); src_in.ready <= '1'; - proc_common_wait_until_evt(clk, src_out.eop); + proc_common_wait_until_evt(c_tb_timeout, clk, src_out.eop); tb_end <= '1'; + -- End with WAIT to avoid Warning: (vcom-1090) Possible infinite loop: + -- Process contains no WAIT statement. + WAIT; END PROCESS; dut: ENTITY work.nw_arp_request diff --git a/libraries/io/nw_10GbE/tb/vhdl/tb_nw_ping_response.vhd b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_ping_response.vhd index 0f38f4ae42540a7d0a57eb17e156bf3d5bbe9795..a5c3c5dc6b0bc19d22db83473062d9d1140873f3 100644 --- a/libraries/io/nw_10GbE/tb/vhdl/tb_nw_ping_response.vhd +++ b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_ping_response.vhd @@ -42,6 +42,9 @@ END tb_nw_ping_response; ARCHITECTURE tb OF tb_nw_ping_response IS + -- Use c_tb_timeout to raise ERROR if there is no result + CONSTANT c_tb_timeout : NATURAL := 100; + CONSTANT c_data_w : NATURAL := 64; CONSTANT c_nof_ping_packet_fields : NATURAL := 21; @@ -183,9 +186,12 @@ BEGIN p_tb_end : PROCESS BEGIN FOR I IN 0 TO 2*c_nof_ping_responses LOOP - proc_common_wait_until_evt(clk, nw_ping_response_src_out.eop); + proc_common_wait_until_evt(c_tb_timeout, clk, nw_ping_response_src_out.eop); END LOOP; tb_end <= '1'; + -- End with WAIT to avoid Warning: (vcom-1090) Possible infinite loop: + -- Process contains no WAIT statement. + WAIT; END PROCESS; nw_ping_response_src_in.xon <= '1';