diff --git a/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd b/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd index 317095e9c7782275905d7452814afd6cc8567373..38b199384cd40c7f3b028b249365dc91b3be08ec 100644 --- a/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_r2_pipe.vhd @@ -63,7 +63,8 @@ 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_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 ); port ( clk : in std_logic; @@ -87,12 +88,18 @@ architecture str of fft_r2_pipe is 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 switch_val : std_logic; + signal data_re : t_data_arr; signal data_im : t_data_arr; signal last_re : std_logic_vector(c_raw_dat_w-1 downto 0); @@ -105,13 +112,39 @@ architecture str of fft_r2_pipe is 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; + begin + ------------------------------------------------------------------------------ + -- Mitigate quantization noise crosstalk between two real inputs by negating + -- the inputs per lock in a random pattern, when g_fft.use_separate = TRUE. + ------------------------------------------------------------------------------ + + 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 + ) + PORT MAP ( + in_re => in_re, + in_im => in_im, + in_val => in_val, + switch_en => c_switch_en, + out_re => switch_re, + out_im => switch_im, + out_val => switch_val, + clk => clk, + rst => rst + ); + -- Inputs - data_re( c_nof_stages) <= scale_and_resize_svec(in_re, c_in_scale_w, g_fft.stage_dat_w); - data_im( c_nof_stages) <= scale_and_resize_svec(in_im, c_in_scale_w, g_fft.stage_dat_w); - data_val(c_nof_stages) <= in_val; - + 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; + ------------------------------------------------------------------------------ -- pipelined FFT stages ------------------------------------------------------------------------------ @@ -190,7 +223,7 @@ begin end generate; - no_reorder_no_generate : if(g_fft.use_separate=false and g_fft.use_reorder=false) generate + no_reorder_no_seperate : if(g_fft.use_separate=false and g_fft.use_reorder=false) generate raw_out_re <= last_re; raw_out_im <= last_im; raw_out_val <= data_val(0); @@ -215,7 +248,7 @@ begin port map ( clk => clk, in_dat => raw_out_re, - out_dat => out_re, + out_dat => quant_re, out_ovr => open ); @@ -235,7 +268,7 @@ begin port map ( clk => clk, in_dat => raw_out_im, - out_dat => out_im, + out_dat => quant_im, out_ovr => open ); @@ -248,8 +281,26 @@ begin rst => rst, clk => clk, in_dat => raw_out_val, - out_dat => out_val + out_dat => quant_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_fft_sz_w => ceil_log2(g_fft.nof_points), + g_dat_w => g_fft.out_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, + clk => clk, + rst => rst + ); + end str;