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

Pass on and verify g_fft.use_fft_shift also for wb_factor>1. Improved output format descriptions.

parent b9640972
No related branches found
No related tags found
No related merge requests found
...@@ -74,10 +74,6 @@ package body fft_pkg is ...@@ -74,10 +74,6 @@ package body fft_pkg is
if g_fft.nof_chan>0 then if g_fft.nof_chan>0 then
assert g_fft.wb_factor=1 report "fft_r2: nof_chan > 0 is only supported for wb_factor = 1" severity failure; assert g_fft.wb_factor=1 report "fft_r2: nof_chan > 0 is only supported for wb_factor = 1" severity failure;
end if; end if;
-- use_fft_shift
if g_fft.use_fft_shift=true then
assert g_fft.wb_factor=1 report "fft_r2 : use_fft_shift for complex input is only supported for wb_factor=1" severity failure;
end if;
-- use_reorder -- use_reorder
if g_fft.use_reorder=false then if g_fft.use_reorder=false then
assert g_fft.use_separate=false report "fft_r2 : without use_reorder there cannot be use_separate for two real inputs" severity failure; assert g_fft.use_separate=false report "fft_r2 : without use_reorder there cannot be use_separate for two real inputs" severity failure;
......
...@@ -121,8 +121,6 @@ architecture str of fft_r2_par is ...@@ -121,8 +121,6 @@ architecture str of fft_r2_par is
return v_return; return v_return;
end; end;
constant c_fft_shift : boolean := false; -- FIXME: add fft_shift to g_fft record
constant c_nof_stages : natural := ceil_log2(g_fft.nof_points); 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_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_tester : integer := g_fft.stage_dat_w - g_fft.in_dat_w - sel_a_b(g_fft.guard_enable, g_fft.guard_w, 0);
...@@ -193,7 +191,7 @@ begin ...@@ -193,7 +191,7 @@ begin
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Optional output reorder -- Optional output reorder
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
gen_reorder : if g_fft.use_reorder and not c_fft_shift generate gen_reorder : if g_fft.use_reorder and not g_fft.use_fft_shift generate
-- unflip the bin indices for complex and also required to prepare for g_fft.use_separate of two real -- unflip the bin indices for complex and also required to prepare for g_fft.use_separate of two real
gen_reordering : for I in 0 to g_fft.nof_points - 1 generate gen_reordering : for I in 0 to g_fft.nof_points - 1 generate
int_re_arr(I) <= data_re(0)(flip(I, c_nof_stages)); int_re_arr(I) <= data_re(0)(flip(I, c_nof_stages));
...@@ -201,7 +199,7 @@ begin ...@@ -201,7 +199,7 @@ begin
end generate; end generate;
end generate; end generate;
gen_fft_shift : if g_fft.use_reorder and c_fft_shift generate gen_fft_shift : if g_fft.use_reorder and g_fft.use_fft_shift generate
-- unflip the bin indices and apply fft_shift for complex only, to have bin frequencies from negative via zero to positive -- unflip the bin indices and apply fft_shift for complex only, to have bin frequencies from negative via zero to positive
gen_reordering : for I in 0 to g_fft.nof_points - 1 generate gen_reordering : for I in 0 to g_fft.nof_points - 1 generate
int_re_arr(fft_shift(I, c_nof_stages)) <= data_re(0)(flip(I, c_nof_stages)); int_re_arr(fft_shift(I, c_nof_stages)) <= data_re(0)(flip(I, c_nof_stages));
......
...@@ -23,27 +23,42 @@ ...@@ -23,27 +23,42 @@
-- Purpose: The fft_r2_wide unit performs a complex FFT that is partly pipelined -- Purpose: The fft_r2_wide unit performs a complex FFT that is partly pipelined
-- and partly parallel. -- and partly parallel.
-- --
-- Description: There are two optional features: -- Description:
-- The fft_r2_wide supports:
-- --
-- * Reordering: When enabled the output bins of the FFT are re-ordered in -- * Complex input
-- in such a way that the bins represent the frequencies in an -- For complex input use_separate = false.
-- incrementing way. --
-- If enabled the reordering is performed at both the pipelined -- When use_reorder=true then the output bins of the FFT are re-ordered to
-- stage and the parallel stage. -- undo the bit-reversed (or bit-flipped) default radix 2 FFT output order.
-- The FFT shift for complex input is not supported. -- The fft_r2_wide then outputs first 0 Hz and the positive frequencies
-- and then the negative frequencies. The use_reorder is performed at both
-- the pipelined stage and the parallel stage.
--
-- When use_fft_shift=true then the fft_r2_wide then outputs the frequency
-- bins in incrementing order, so first the negative frequencies, then 0 Hz
-- and then the positive frequencies.
-- When use_fft_shift = true then also use_reorder must be true.
--
-- * Two real inputs:
-- When use_separate=true then the fft_r2_wide can be used to process two
-- real streams. The first real stream (A) presented on the real input, the
-- second real stream (B) presented on the imaginary input. The separation
-- unit outputs the spectrum of A and B in an alternating way.
-- When use_separate = true then also use_reorder must be true.
-- When use_separate = true then the use_fft_shift must be false, because
-- fft_shift() only applies to spectra for complex input.
-- --
-- * Separation: When enabled the fft_r2_wide can be used to process two real streams.
-- The first real stream (A) presented on the real input, the second
-- real stream (B) presented on the imaginary input.
-- The separation unit outputs the spectrum of A and B in
-- an alternating way: A(0), B(0), A(1), B(1).... etc
-- Remark: -- Remark:
-- . This fft_r2_wide does not (yet) support wb_factor = 1 (= only 1 fft_r2_pipe) -- . This fft_r2_wide does not (yet) support wb_factor = 1 (= only a
-- or wb_factor = g_fft.nof_points (= only 1 fft_r2_par). Fixing this is nice -- fft_r2_pipe instance) or wb_factor = g_fft.nof_points (= only a
-- to have, but not essential. Care must be taken to properly account for -- fft_r2_par instance). Fixing this is nice to have, but not essential.
-- guard_w and out_gain_w. Therefore probably it is most clear to use a -- Care must be taken to properly account for guard_w and out_gain_w.
-- structural approach that generates seperate instances for wb_factor = 1, -- Therefore probably it is most clear to use a structural approach that
-- wb_factor > 1 AND wb_factor < g_fft.nof_points, and wb_factor = g_fft.nof_points. -- would generate seperate instances for each case:
-- . wb_factor = 1
-- . wb_factor > 1 AND wb_factor < g_fft.nof_points
-- . wb_factor = g_fft.nof_points.
library ieee, common_lib, rTwoSDF_lib; library ieee, common_lib, rTwoSDF_lib;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
...@@ -86,8 +101,9 @@ architecture rtl of fft_r2_wide is ...@@ -86,8 +101,9 @@ architecture rtl of fft_r2_wide is
variable v_return : t_fft_arr(input.wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values variable v_return : t_fft_arr(input.wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values
begin begin
for I in 0 to input.wb_factor-1 loop for I in 0 to input.wb_factor-1 loop
v_return(I).use_reorder := input.use_reorder; -- Pass on use_reorder
v_return(I).use_fft_shift := false; -- FFT shift function is forced to false
v_return(I).use_separate := false; -- Separate function is forced to false. v_return(I).use_separate := false; -- Separate function is forced to false.
v_return(I).use_fft_shift := false; -- FFT shift function is forced to false.
v_return(I).twiddle_offset := I; -- Twiddle offset is set to the order number of the pipelined fft. v_return(I).twiddle_offset := I; -- Twiddle offset is set to the order number of the pipelined fft.
v_return(I).nof_points := v_nof_points; -- Set the nof points v_return(I).nof_points := v_nof_points; -- Set the nof points
v_return(I).in_dat_w := input.stage_dat_w; -- Set the input width v_return(I).in_dat_w := input.stage_dat_w; -- Set the input width
...@@ -107,12 +123,14 @@ architecture rtl of fft_r2_wide is ...@@ -107,12 +123,14 @@ architecture rtl of fft_r2_wide is
function func_create_generic_for_par_fft(input : t_fft) return t_fft is function func_create_generic_for_par_fft(input : t_fft) return t_fft is
variable v_return : t_fft := input; -- Variable that holds the return value variable v_return : t_fft := input; -- Variable that holds the return value
begin begin
v_return.use_separate := false; -- Separate function is forced to false. v_return.use_reorder := input.use_reorder; -- Pass on use_reorder
v_return.use_fft_shift := false; -- FFT shift function is forced to false. v_return.use_fft_shift := input.use_fft_shift; -- Pass on use_fft_shift
v_return.use_separate := false; -- Separate function is forced to false, because it is handled outside the parallel fft
v_return.twiddle_offset := 0; -- Twiddle offset is forced to 0, which is also the input.twiddle_offset default
v_return.nof_points := input.wb_factor; -- Set the number of points to wb_factor v_return.nof_points := input.wb_factor; -- Set the number of points to wb_factor
v_return.in_dat_w := input.stage_dat_w; -- Specify the input width v_return.in_dat_w := input.stage_dat_w; -- Specify the input width
v_return.out_dat_w := input.stage_dat_w; -- Output width v_return.out_dat_w := input.stage_dat_w; -- Output width
v_return.out_gain_w := 0; -- Output gain is forced to 0, because it is taken care of outside parallel fft v_return.out_gain_w := 0; -- Output gain is forced to 0, because it is handled outside the parallel fft
v_return.guard_w := input.guard_w; -- Set the guard_w here to skip the scaling on the last stages v_return.guard_w := input.guard_w; -- Set the guard_w here to skip the scaling on the last stages
v_return.guard_enable := false; -- No input guard. v_return.guard_enable := false; -- No input guard.
return v_return; return v_return;
......
...@@ -43,7 +43,8 @@ ARCHITECTURE tb OF tb_tb_fft_r2_par IS ...@@ -43,7 +43,8 @@ ARCHITECTURE tb OF tb_tb_fft_r2_par IS
CONSTANT c_fft_two_real : t_fft := ( true, false, true, 0, 1, 0, 128, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2); CONSTANT c_fft_two_real : t_fft := ( true, false, true, 0, 1, 0, 128, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_fft_complex : t_fft := ( true, false, false, 0, 1, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2); CONSTANT c_fft_complex : t_fft := ( true, false, false, 0, 1, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_fft_flipped_complex : t_fft := (false, false, false, 0, 1, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2); CONSTANT c_fft_complex_fft_shift : t_fft := ( true, true, false, 0, 1, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_fft_complex_flipped : t_fft := (false, false, false, 0, 1, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_diff_margin : natural := 2; CONSTANT c_diff_margin : natural := 2;
...@@ -119,6 +120,7 @@ BEGIN ...@@ -119,6 +120,7 @@ BEGIN
-- Complex input data -- Complex input data
u_act_complex_chirp : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 12800, FALSE); u_act_complex_chirp : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 12800, FALSE);
u_act_flipped_complex : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_flipped_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 1280, FALSE); u_act_complex_fft_shift : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_complex_fft_shift, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 1280, FALSE);
u_act_complex_flipped : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_complex_flipped, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 1280, FALSE);
u_rnd_complex_noise : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_noise_complex, 640, 640, TRUE); u_rnd_complex_noise : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_noise_complex, 640, 640, TRUE);
END tb; END tb;
...@@ -43,9 +43,10 @@ ARCHITECTURE tb OF tb_tb_fft_r2_wide IS ...@@ -43,9 +43,10 @@ ARCHITECTURE tb OF tb_tb_fft_r2_wide IS
CONSTANT c_pipeline : t_fft_pipeline := (1, 1, 3, 1, 1, 0, 0, 1); CONSTANT c_pipeline : t_fft_pipeline := (1, 1, 3, 1, 1, 0, 0, 1);
CONSTANT c_fft_two_real : t_fft := ( true, false, true, 0, 4, 0, 128, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2); CONSTANT c_fft_wb4_two_real : t_fft := ( true, false, true, 0, 4, 0, 128, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_fft_complex : t_fft := ( true, false, false, 0, 4, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2); CONSTANT c_fft_wb4_complex : t_fft := ( true, false, false, 0, 4, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_fft_complex_flipped : t_fft := (false, false, false, 0, 4, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2); CONSTANT c_fft_wb4_complex_fft_shift : t_fft := ( true, true, false, 0, 4, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_fft_wb4_complex_flipped : t_fft := (false, false, false, 0, 4, 0, 64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);
CONSTANT c_diff_margin : natural := 2; CONSTANT c_diff_margin : natural := 2;
...@@ -145,13 +146,14 @@ BEGIN ...@@ -145,13 +146,14 @@ BEGIN
-- g_enable_in_val_gaps : boolean := TRUE -- when false then in_val flow control active continuously, else with random inactive gaps -- g_enable_in_val_gaps : boolean := TRUE -- when false then in_val flow control active continuously, else with random inactive gaps
-- Two real input data A and B -- Two real input data A and B
u_act_two_real_chirp : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_two_real, c_diff_margin, c_sinusoid_chirp, 25600, c_impulse_chirp, 25600, c_unused, 0, 25600, FALSE); u_act_two_real_chirp : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_two_real, c_diff_margin, c_sinusoid_chirp, 25600, c_impulse_chirp, 25600, c_unused, 0, 25600, FALSE);
u_act_two_real_a0 : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_two_real, c_diff_margin, c_zero, 25600, c_impulse_chirp, 25600, c_unused, 0, 5120, FALSE); u_act_two_real_a0 : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_two_real, c_diff_margin, c_zero, 25600, c_impulse_chirp, 25600, c_unused, 0, 5120, FALSE);
u_act_two_real_b0 : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_two_real, c_diff_margin, c_sinusoid_chirp, 25600, c_zero, 25600, c_unused, 0, 5120, FALSE); u_act_two_real_b0 : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_two_real, c_diff_margin, c_sinusoid_chirp, 25600, c_zero, 25600, c_unused, 0, 5120, FALSE);
u_rnd_two_real_noise : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_two_real, c_diff_margin, c_noise, 1280, c_dc_agwn, 1280, c_unused, 0, 1280, TRUE); u_rnd_two_real_noise : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_two_real, c_diff_margin, c_noise, 1280, c_dc_agwn, 1280, c_unused, 0, 1280, TRUE);
-- Complex input data -- Complex input data
u_act_complex_chirp : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 12800, FALSE); u_act_complex_chirp : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 12800, FALSE);
u_act_complex_flipped : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_complex_flipped, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 1280, FALSE); u_act_complex_fft_shift : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_complex_fft_shift, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 1280, FALSE);
u_rnd_complex_noise : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_noise_complex, 640, 640, TRUE); u_act_complex_flipped : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_complex_flipped, c_diff_margin, c_unused, 0, c_unused, 0, c_phasor_chirp, 12800, 1280, FALSE);
u_rnd_complex_noise : ENTITY work.tb_fft_r2_wide GENERIC MAP (c_pipeline, c_fft_wb4_complex, c_diff_margin, c_unused, 0, c_unused, 0, c_noise_complex, 640, 640, TRUE);
END tb; END tb;
...@@ -62,6 +62,18 @@ ...@@ -62,6 +62,18 @@
-- part are filtered independently and also use the same real FIR -- part are filtered independently and also use the same real FIR
-- coefficients. -- coefficients.
-- --
-- Note that:
-- . 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
-- for all wideband streams. The WPFB output is grouped per wideband
-- stream to have all P together.
-- . The wideband time index t is big-endian in the filter and
-- little-endian in the FFT. Hence the WPFB input is big-endian in
-- time. The WPFB output is little-endian, so with frequency bins in
-- incrementing order. However the precise frequency bin order depends
-- on the reorder generics.
--
-- When wb_factor = 4 and nof_wb_streams = 2 the mapping is as follows using -- When wb_factor = 4 and nof_wb_streams = 2 the mapping is as follows using
-- the array notation: -- the array notation:
-- --
...@@ -120,40 +132,122 @@ ...@@ -120,40 +132,122 @@
-- The frequency bin order at the output is obtained with reg_out_bin -- The frequency bin order at the output is obtained with reg_out_bin
-- in the test bench tb_wpfb_unit_dev.vhd. -- in the test bench tb_wpfb_unit_dev.vhd.
-- --
-- Output example for wideband subband filterbank: -- Output examples:
--
-- Frequency bins:
-- fs = sample frequency
-- Bb = fs/nof_points = bin bandwidth
--
-- 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
-- ^ ^ ^ ^ ^
-- <--------- negative bin frequencies ---------> 0 <---------- positive bin frequencies ------->
-- -fs/2 -Bb 0 +Bb +fs/2-Bb
--
-- I) Wideband wb_factor = 4
-- 1) Two real inputs:
--
-- out_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
-- 5 1 1 4 4 5 5 6 6 7 7 . use_reorder = true
-- 4 1 0 0 0 1 1 2 2 3 3 . use_fft_shift = false
-- 3 0 3 12 12 13 13 14 14 15 15 . use_separate = true
-- 2 0 2 8 8 9 9 10 10 11 11 - input A via in_sosi_arr().re
-- 1 0 1 4 4 5 5 6 6 7 7 - input B via in_sosi_arr().im
-- 0 0 0 0 0 1 1 2 2 3 3
-- ^ ^ ^ ^ ^ ^ ^ ^
-- A B A B A B A B
--
-- 2a) Complex input with fft_shift:
--
-- out_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
-- 5 1 1 8 9 10 11 12 13 14 15 . use_reorder = true
-- 4 1 0 0 1 2 3 4 5 6 7 . use_fft_shift = true
-- 3 0 3 24 25 26 27 28 29 30 31 . use_separate = false
-- 2 0 2 16 17 18 19 20 21 22 23 - complex input via in_sosi_arr().re and im
-- 1 0 1 8 9 10 11 12 13 14 15
-- 0 0 0 0 1 2 3 4 5 6 7
--
-- 2b) Complex input with reorder, but no fft_shift:
--
-- out_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
-- 5 1 1 24 25 26 27 28 29 30 31 . use_reorder = true
-- 4 1 0 16 17 18 19 20 21 22 23 . use_fft_shift = false
-- 3 0 3 8 9 10 11 12 13 14 15 . use_separate = false
-- 2 0 2 0 1 2 3 4 5 6 7 - complex input via in_sosi_arr().re and im
-- 1 0 1 24 25 26 27 28 29 30 31
-- 0 0 0 16 17 18 19 20 21 22 23
--
-- 2c) Complex input without reorder (so bit flipped):
--
-- out_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
-- 5 1 1 0 4 2 6 1 5 3 7 . use_reorder = false
-- 4 1 0 16 20 18 22 17 21 19 23 . use_fft_shift = false
-- 3 0 3 8 12 10 14 9 13 11 15 . use_separate = false
-- 2 0 2 24 28 26 30 25 29 27 31 - complex input via in_sosi_arr().re and im
-- 1 0 1 0 4 2 6 1 5 3 7
-- 0 0 0 16 20 18 22 17 21 19 23
--
-- II) Narrowband wb_factor = 1, nof_chan = 0
--
-- 1) Two real inputs:
--
-- . nof_streams = 2 -- . nof_streams = 2
-- . wb_factor = 4 -- . nof_chan = 0
-- . wb_factor = 1
-- . nof_points = 32 -- . nof_points = 32
-- . use_reorder = true -- . use_reorder = true
-- . use_fft_shift = false
-- . use_separate = true -- . use_separate = true
-- - input A via in_dat_re -- - input A via in_sosi_arr().re
-- - input B via in_dat_im -- - input B via in_sosi_arr().im
-- --
-- out_sosi_arr: -- out_sosi_arr:
-- I S P bin frequency order -- I S P bin frequency order
-- 7 1 3 12 12 13 13 14 14 15 15 -- 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
-- 6 1 2 8 8 9 9 10 10 11 11 -- 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
-- 5 1 1 4 4 5 5 6 6 7 7 -- ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
-- 4 1 0 0 0 1 1 2 2 3 3 -- A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B
-- 3 0 3 12 12 13 13 14 14 15 15
-- 2 0 2 8 8 9 9 10 10 11 11
-- 1 0 1 4 4 5 5 6 6 7 7
-- 0 0 0 0 0 1 1 2 2 3 3
-- ^ ^ ^ ^ ^ ^ ^ ^
-- A B A B A B A B
-- --
-- Note that: -- 2) Complex input
-- . The same P of all streams are grouped the in filter and all P per -- . nof_streams = 2
-- stream are grouped in the FFT. Hence the WPFB input is grouped per -- . nof_chan = 0
-- P for all wideband streams to allow FIR coefficients reuse per P -- . wb_factor = 1
-- for all wideband streams. The WPFB output is grouped per wideband -- . nof_points = 32
-- stream to have all P together. -- . use_separate = false
-- . The wideband time index t is big-endian in the filter and -- - complex input via in_sosi_arr().re and im
-- little-endian in the FFT. Hence the WPFB input is big-endian in
-- time. The WPFB output is little-endian, so with frequency bins in
-- incrementing order. However the precise frequency bin order depends
-- on the reorder generics.
-- 2a) Complex input with fft_shift (so use_reorder = true, use_fft_shift = true)
--
-- out_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
--
-- 2b) Complex input with reorder but no fft_shift (so use_reorder = true, use_fft_shift = false)
--
-- out_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
--
-- 2c) Complex input without reorder (so use_reorder = false, use_fft_shift = false)
--
-- out_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
--
-- Remarks: -- Remarks:
-- . The unit can handle only one sync at a time. Therfor the -- . The unit can handle only one sync at a time. Therfor the
-- sync interval should be larger than the total pipeline -- sync interval should be larger than the total pipeline
......
...@@ -92,6 +92,12 @@ ARCHITECTURE tb OF tb_tb_wpfb_unit_wide IS ...@@ -92,6 +92,12 @@ ARCHITECTURE tb OF tb_tb_wpfb_unit_wide IS
true, false, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2, true, false, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2,
c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline); c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
-- wb 1, complex fft_shift
CONSTANT c_wb1_complex_fft_shift : t_wpfb := (1, 32, 0, 1,
16, 1, 8, 16, 16,
true, true, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2,
c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
-- wb 1, complex without reorder -- wb 1, complex without reorder
CONSTANT c_wb1_complex_flipped_1024 : t_wpfb := (1, 1024, 0, 1, CONSTANT c_wb1_complex_flipped_1024 : t_wpfb := (1, 1024, 0, 1,
16, 1, 8, 16, 16, 16, 1, 8, 16, 16,
...@@ -124,6 +130,12 @@ ARCHITECTURE tb OF tb_tb_wpfb_unit_wide IS ...@@ -124,6 +130,12 @@ ARCHITECTURE tb OF tb_tb_wpfb_unit_wide IS
true, false, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2, true, false, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2,
c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline); c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
-- wb 4, complex fft_shift
CONSTANT c_wb4_complex_fft_shift : t_wpfb := (4, 32, 0, 1,
16, 1, 8, 16, 16,
true, true, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2,
c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
-- wb 4, complex without reorder -- wb 4, complex without reorder
CONSTANT c_wb4_complex_flipped_1024 : t_wpfb := (4, 1024, 0, 1, CONSTANT c_wb4_complex_flipped_1024 : t_wpfb := (4, 1024, 0, 1,
16, 1, 8, 16, 16, 16, 1, 8, 16, 16,
...@@ -288,6 +300,8 @@ BEGIN ...@@ -288,6 +300,8 @@ BEGIN
u_act_wb4_complex_flipped : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex_flipped, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor_chirp, 6400, 6400, FALSE); u_act_wb4_complex_flipped : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex_flipped, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor_chirp, 6400, 6400, FALSE);
u_rnd_wb1_complex_phasor : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb1_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor, 1600, 1600, TRUE); u_rnd_wb1_complex_phasor : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb1_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor, 1600, 1600, TRUE);
u_rnd_wb4_complex_phasor : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor, 1600, 1600, TRUE); u_rnd_wb4_complex_phasor : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor, 1600, 1600, TRUE);
u_rnd_wb1_complex_fft_shift_phasor : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb1_complex_fft_shift, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor, 1600, 1600, TRUE);
u_rnd_wb4_complex_fft_shift_phasor : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex_fft_shift, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_phasor, 1600, 1600, TRUE);
u_rnd_wb1_complex_noise : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb1_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE); u_rnd_wb1_complex_noise : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb1_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE);
u_rnd_wb1_complex_noise_streams : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb1_complex_4streams, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE); u_rnd_wb1_complex_noise_streams : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb1_complex_4streams, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE);
u_rnd_wb4_complex_noise : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE); u_rnd_wb4_complex_noise : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE);
......
...@@ -66,9 +66,9 @@ use work.wpfb_pkg.all; ...@@ -66,9 +66,9 @@ use work.wpfb_pkg.all;
entity tb_wpfb_unit_wide is entity tb_wpfb_unit_wide is
generic( generic(
-- DUT generics -- DUT generics
g_wpfb : t_wpfb := (4, 32, 0, 4, g_wpfb : t_wpfb := (1, 32, 0, 2,
16, 1, 8, 16, 16, 16, 1, 8, 16, 16,
true, false, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2, false, false, false, 16, 16, 0, c_dsp_mult_w, 2, true, 56, 2,
c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline); c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
-- type t_wpfb is record -- type t_wpfb is record
-- -- General parameters for the wideband poly phase filter -- -- General parameters for the wideband poly phase filter
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment