Skip to content
Snippets Groups Projects
Commit 788f8c6f authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Use functions to defined FFT input and output widths.

parent 2abac46d
No related branches found
No related tags found
1 merge request!289Rename c_sdp_W_fsub_wg into c_sdp_W_local_oscillator. Use...
......@@ -69,7 +69,12 @@ 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 and output widths
function func_fft_in_scale_w(g_fft : t_fft) return natural;
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 +111,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
......
......@@ -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,
......
......@@ -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;
......@@ -88,7 +100,7 @@ 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;
......@@ -96,11 +108,12 @@ architecture str of fft_r2_pipe is
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
......@@ -134,8 +147,7 @@ architecture str of fft_r2_pipe is
-- 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_out_scale_w : integer := c_out_scale_w;
signal dbg_c_sepa_growth_w : natural := c_sepa_growth_w;
signal dbg_c_raw_fraction_w : natural := c_raw_fraction_w;
signal dbg_c_raw_dat_w : natural := c_raw_dat_w;
begin
......@@ -286,7 +298,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,
......@@ -306,7 +318,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,
......@@ -336,9 +348,10 @@ begin
------------------------------------------------------------------------------
-- Pipelined FFT raw output register
-- . Pipeline out_raw_* to align with out_quant_*, so they can share out_val
------------------------------------------------------------------------------
-- . 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",
......
......@@ -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);
......@@ -182,8 +179,7 @@ architecture rtl of fft_r2_wide is
-- 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_out_scale_w : integer := c_out_scale_w;
signal dbg_c_sepa_growth_w : natural := c_sepa_growth_w;
signal dbg_c_raw_fraction_w : natural := c_raw_fraction_w;
signal dbg_c_raw_dat_w : natural := c_raw_dat_w;
begin
......@@ -328,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,
......@@ -348,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,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment