diff --git a/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd b/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd index 38b199384cd40c7f3b028b249365dc91b3be08ec..fdf43ef38abef91ed6d8b85a8392eaf222ded968 100644 --- a/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd @@ -63,8 +63,7 @@ entity fft_r2_pipe is g_pipeline : t_fft_pipeline := c_fft_pipeline; -- generics for pipelining in each stage, defined in rTwoSDF_lib.rTwoSDFPkg g_dont_flip_channels : boolean := false; -- generic to prevent re-ordering of the channels g_r2_mul_extra_w : natural := 0; -- extra bits at rTwoWMul output in rTwoSDFStage to improve rTwoSDFStage output requantization - g_sepa_extra_w : natural := 0; -- extra LSbits in output of last rTwoSDFStage to improve two real separate requantization - g_sepa_switch_en : boolean := false -- when true apply switch/unswitch to two real inputs to mitigate quantization crosstalk + g_sepa_extra_w : natural := 0 -- extra LSbits in output of last rTwoSDFStage to improve two real separate requantization ); port ( clk : in std_logic; @@ -82,22 +81,28 @@ architecture str of fft_r2_pipe is constant c_pipeline_remove_lsb : natural := 0; + 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_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_raw_dat_extra_w : natural := sel_a_b(g_fft.use_separate, g_sepa_extra_w, 0); constant c_raw_dat_w : natural := g_fft.stage_dat_w + c_raw_dat_extra_w; - constant c_sepa_mitigate : std_logic := sel_a_b(g_fft.use_separate, '1', '0'); -- apply switch/unswitch to two real inputs to mitigate quantization crosstalk - constant c_switch_en : std_logic := sel_a_b(g_sepa_switch_en, c_sepa_mitigate, '0'); -- number the stage instances from c_nof_stages:1 -- . the data input for the first stage has index c_nof_stages -- . the data output of the last stage has index 0 type t_data_arr is array(c_nof_stages downto 0) of std_logic_vector(g_fft.stage_dat_w-1 downto 0); - signal switch_re : std_logic_vector(g_fft.in_dat_w-1 downto 0); - signal switch_im : std_logic_vector(g_fft.in_dat_w-1 downto 0); + signal in_dat_re : std_logic_vector(c_switch_dat_w-1 downto 0); + signal in_dat_im : std_logic_vector(c_switch_dat_w-1 downto 0); + signal in_dat_val : std_logic; + + signal switch_re : std_logic_vector(c_switch_dat_w-1 downto 0); + signal switch_im : std_logic_vector(c_switch_dat_w-1 downto 0); signal switch_val : std_logic; signal data_re : t_data_arr; @@ -123,16 +128,21 @@ begin -- the inputs per lock in a random pattern, when g_fft.use_separate = TRUE. ------------------------------------------------------------------------------ + -- Inputs + in_dat_re <= RESIZE_SVEC(in_re, c_switch_dat_w); + in_dat_im <= RESIZE_SVEC(in_im, c_switch_dat_w); + in_dat_val <= in_val; + u_switch : ENTITY work.fft_switch GENERIC MAP ( - g_fft_sz_w => ceil_log2(g_fft.nof_points), - g_dat_w => g_fft.in_dat_w + g_switch_en => c_switch_en, + g_fft_sz_w => c_switch_sz_w, + g_dat_w => c_switch_dat_w ) PORT MAP ( - in_re => in_re, - in_im => in_im, - in_val => in_val, - switch_en => c_switch_en, + in_re => in_dat_re, + in_im => in_dat_im, + in_val => in_dat_val, out_re => switch_re, out_im => switch_im, out_val => switch_val, @@ -140,7 +150,6 @@ begin rst => rst ); - -- Inputs data_re( c_nof_stages) <= scale_and_resize_svec(switch_re, c_in_scale_w, g_fft.stage_dat_w); data_im( c_nof_stages) <= scale_and_resize_svec(switch_im, c_in_scale_w, g_fft.stage_dat_w); data_val(c_nof_stages) <= switch_val; @@ -188,12 +197,11 @@ begin in_re => data_re(1), in_im => data_im(1), in_val => data_val(1), - out_re => last_re, - out_im => last_im, + out_re => last_re, -- = data_re(0), but may instead have c_raw_dat_w bits + out_im => last_im, -- = data_im(0), but may instead have c_raw_dat_w bits out_val => data_val(0) ); - ------------------------------------------------------------------------------ -- Optional output reorder and separation ------------------------------------------------------------------------------ @@ -287,14 +295,14 @@ begin -- Undo input random negation of u_switch at output when g_fft.use_separate = TRUE u_unswitch : ENTITY work.fft_unswitch GENERIC MAP ( - g_fft_sz_w => ceil_log2(g_fft.nof_points), - g_dat_w => g_fft.out_dat_w + g_switch_en => c_switch_en, + g_fft_sz_w => c_switch_sz_w, + g_dat_w => c_unswitch_dat_w ) PORT MAP ( in_re => quant_re, in_im => quant_im, in_val => quant_val, - switch_en => c_switch_en, out_re => out_re, out_im => out_im, out_val => out_val,