diff --git a/libraries/dsp/fft/src/vhdl/fft_pkg.vhd b/libraries/dsp/fft/src/vhdl/fft_pkg.vhd index 2649fcc8d6b9b6b46f6889e2440e3b9822be2490..15a36eb5ee2220a5cd1fce0c6a5e1ba9be0c155f 100644 --- a/libraries/dsp/fft/src/vhdl/fft_pkg.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_pkg.vhd @@ -74,10 +74,6 @@ package body fft_pkg is 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; 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 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; diff --git a/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd b/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd index 620e5015c2a931fb2a5ef16c715cc472c4a5a9e5..7cd67dd0720fbb84683125d87c3414adab423097 100644 --- a/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_r2_par.vhd @@ -121,8 +121,6 @@ architecture str of fft_r2_par is return v_return; 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_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); @@ -193,7 +191,7 @@ begin -------------------------------------------------------------------------------- -- 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 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)); @@ -201,7 +199,7 @@ begin 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 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)); diff --git a/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd b/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd index 48bdd1ecbda311187ce4c5f49c08d4c841bc5d54..5581a438627b3d85dcb328ac0435f46e1666369d 100644 --- a/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_r2_wide.vhd @@ -23,27 +23,42 @@ -- Purpose: The fft_r2_wide unit performs a complex FFT that is partly pipelined -- 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 --- in such a way that the bins represent the frequencies in an --- incrementing way. --- If enabled the reordering is performed at both the pipelined --- stage and the parallel stage. --- The FFT shift for complex input is not supported. +-- * Complex input +-- For complex input use_separate = false. +-- +-- When use_reorder=true then the output bins of the FFT are re-ordered to +-- undo the bit-reversed (or bit-flipped) default radix 2 FFT output order. +-- 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: --- . This fft_r2_wide does not (yet) support wb_factor = 1 (= only 1 fft_r2_pipe) --- or wb_factor = g_fft.nof_points (= only 1 fft_r2_par). Fixing this is nice --- to have, but not essential. Care must be taken to properly account for --- guard_w and out_gain_w. Therefore probably it is most clear to use a --- structural approach that generates seperate instances for wb_factor = 1, --- wb_factor > 1 AND wb_factor < g_fft.nof_points, and wb_factor = g_fft.nof_points. +-- . This fft_r2_wide does not (yet) support wb_factor = 1 (= only a +-- fft_r2_pipe instance) or wb_factor = g_fft.nof_points (= only a +-- fft_r2_par instance). Fixing this is nice to have, but not essential. +-- Care must be taken to properly account for guard_w and out_gain_w. +-- Therefore probably it is most clear to use a structural approach that +-- 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; use IEEE.std_logic_1164.all; @@ -86,9 +101,10 @@ 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 begin 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_fft_shift := false; -- FFT shift function is forced to false. - v_return(I).twiddle_offset := I; -- Twiddle offset is set to the ordernumber 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).in_dat_w := input.stage_dat_w; -- Set the input width v_return(I).out_dat_w := input.stage_dat_w; -- Set the output width. @@ -107,14 +123,16 @@ architecture rtl of fft_r2_wide 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 begin - v_return.use_separate := false; -- Separate function is forced to false. - v_return.use_fft_shift := false; -- FFT shift function is forced to false. - 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.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.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.use_reorder := input.use_reorder; -- Pass on use_reorder + 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.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_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_enable := false; -- No input guard. return v_return; end; diff --git a/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_par.vhd b/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_par.vhd index f3d501d346df3ce1b59b52e0ef0032b011143499..a09e8a071b669eb33848ad5640519d8ba1239041 100644 --- a/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_par.vhd +++ b/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_par.vhd @@ -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_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; @@ -118,7 +119,8 @@ BEGIN u_rnd_two_real_noise : ENTITY work.tb_fft_r2_par GENERIC MAP (c_pipeline, c_fft_two_real, c_diff_margin, c_noise, 1280, c_dc_agwn, 1280, c_unused, 0, 1280, TRUE); -- 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_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_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_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_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); END tb; diff --git a/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_wide.vhd b/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_wide.vhd index 2cc803ae1748d71fcdddf927580e120c8bd2440f..ca32674640976d7ab829681f23251b8ff3eb7b2e 100644 --- a/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_wide.vhd +++ b/libraries/dsp/fft/tb/vhdl/tb_tb_fft_r2_wide.vhd @@ -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_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_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_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_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_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; @@ -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 -- 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_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_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_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_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_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_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_wb4_two_real, c_diff_margin, c_noise, 1280, c_dc_agwn, 1280, c_unused, 0, 1280, TRUE); -- 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_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_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_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_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_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; diff --git a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd index bfb1a80ab168e01d256a31ebc065e542de57e42c..4115932635b7eaf1bc6e3c358be495bbcacd9174 100644 --- a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd +++ b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd @@ -62,6 +62,18 @@ -- part are filtered independently and also use the same real FIR -- 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 -- the array notation: -- @@ -120,40 +132,122 @@ -- The frequency bin order at the output is obtained with reg_out_bin -- in the test bench tb_wpfb_unit_dev.vhd. -- --- Output example for wideband subband filterbank: --- . nof_streams = 2 --- . wb_factor = 4 --- . nof_points = 32 --- . use_reorder = true --- . use_separate = true --- - input A via in_dat_re --- - input B via in_dat_im +-- 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 --- 7 1 3 12 12 13 13 14 14 15 15 --- 6 1 2 8 8 9 9 10 10 11 11 --- 5 1 1 4 4 5 5 6 6 7 7 --- 4 1 0 0 0 1 1 2 2 3 3 --- 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 +-- 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 -- --- 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. +-- 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_chan = 0 +-- . wb_factor = 1 +-- . nof_points = 32 +-- . use_reorder = true +-- . use_fft_shift = false +-- . use_separate = true +-- - input A via in_sosi_arr().re +-- - input B via in_sosi_arr().im +-- +-- out_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 +-- ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ +-- 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 +-- +-- 2) Complex input +-- . nof_streams = 2 +-- . nof_chan = 0 +-- . wb_factor = 1 +-- . nof_points = 32 +-- . use_separate = false +-- - complex input via in_sosi_arr().re and im +-- 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: -- . The unit can handle only one sync at a time. Therfor the -- sync interval should be larger than the total pipeline diff --git a/libraries/dsp/wpfb/tb/vhdl/tb_tb_wpfb_unit_wide.vhd b/libraries/dsp/wpfb/tb/vhdl/tb_tb_wpfb_unit_wide.vhd index cd1feafb28d64a9f66abf893bad3daf4c2686add..9d79db8b79e7a8c0c7409ae189456f6b93523556 100644 --- a/libraries/dsp/wpfb/tb/vhdl/tb_tb_wpfb_unit_wide.vhd +++ b/libraries/dsp/wpfb/tb/vhdl/tb_tb_wpfb_unit_wide.vhd @@ -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, 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 CONSTANT c_wb1_complex_flipped_1024 : t_wpfb := (1, 1024, 0, 1, 16, 1, 8, 16, 16, @@ -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, 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 CONSTANT c_wb4_complex_flipped_1024 : t_wpfb := (4, 1024, 0, 1, 16, 1, 8, 16, 16, @@ -284,12 +296,14 @@ BEGIN u_act_wb4_complex_flipped_noise_64 : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex_flipped_64, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex_64, 3200, 3200, FALSE); -- * 32 point - u_act_wb4_complex_chirp : 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_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_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_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_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_streams : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex_4streams, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE); + u_act_wb4_complex_chirp : 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_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_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_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_streams : ENTITY work.tb_wpfb_unit_wide GENERIC MAP (c_wb4_complex_4streams, c_dm_3, c_pre_ab, c_pre_c, c_un, 0, c_un, 0, c_noise_complex, 1600, 1600, TRUE); END tb; 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 5b220ded5d2c6023a70fccf1b72c6541e5f2929a..3bf9b72e6ecac1e58c5de9801cb834992ac66136 100644 --- a/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd +++ b/libraries/dsp/wpfb/tb/vhdl/tb_wpfb_unit_wide.vhd @@ -66,9 +66,9 @@ use work.wpfb_pkg.all; entity tb_wpfb_unit_wide is generic( -- DUT generics - g_wpfb : t_wpfb := (4, 32, 0, 4, + g_wpfb : t_wpfb := (1, 32, 0, 2, 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); -- type t_wpfb is record -- -- General parameters for the wideband poly phase filter