diff --git a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd index 208c5a29718f453331a614db353c2bf35a5d2b24..bfb1a80ab168e01d256a31ebc065e542de57e42c 100644 --- a/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd +++ b/libraries/dsp/wpfb/src/vhdl/wpfb_unit_dev.vhd @@ -20,41 +20,145 @@ -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- -------------------------------------------------------------------------------- --- Purpose: Wideband FFT with Subband Statistics and streaming interfaces. +-- Purpose: Wideband polyphase filterbank with subband statistics and streaming interfaces. -- --- Description: This unit connects an incoming array of streaming interfaces --- to the wideband fft. The output of the wideband fft is --- connected to a set of subband statistics units. The statistics --- can be read via the memory mapped interface. --- A control unit takes care of the correct composition of the --- output streams(sop,eop,sync,bsn,err). +-- Description: -- --- The wpfb unit can handle a wideband factor > 1 (g_wpfb.wb_factor) or --- a narrowband factor > 1 (g_wpfb.nof_chan). Both factors can NOT be --- used (> 1) at the same time. --- . For wb_factor = 1 the wpfb_unit uses fft_r2_pipe and supports nof_chan >= 0 --- . For wb_factor > 1 the wpfb_unit uses fft_r2_wide --- . For wb_factor = 1 the wpfb_unit supports nof_chan >= 0 --- . For wb_factor > 1 the wpfb_unit only supports nof_chan = 0, because the --- concept of channels is void when wb_factor > 0. --- . The wpfb_unit does support use_reorder. --- . The wpfb_unit does support use_separate. --- . The wpfb_unit does support input flow control with invalid gaps in the --- input. +-- This WPFB unit connects an incoming array of streaming interfaces to the +-- wideband pft + fft. +-- The output of the wideband fft is connected to a set of subband statistics +-- units. The statistics can be read via the memory mapped interface. +-- A control unit takes care of the correct composition of the control of the +-- output streams regarding sop, eop, sync, bsn, err. -- --- Remarks: . The unit can handle only one sync at a time. Therfor the --- sync interval should be larger than the total pipeline --- stages of the wideband fft. +-- The wpfb unit can handle a wideband factor > 1 (g_wpfb.wb_factor) or +-- a narrowband factor > 1 (g_wpfb.nof_chan). Both factors can NOT be +-- used (> 1) at the same time. +-- . For wb_factor = 1 the wpfb_unit uses fft_r2_pipe and supports nof_chan >= 0 +-- . For wb_factor > 1 the wpfb_unit uses fft_r2_wide +-- . For wb_factor = 1 the wpfb_unit supports nof_chan >= 0 +-- . For wb_factor > 1 the wpfb_unit only supports nof_chan = 0, because the +-- concept of channels is void when wb_factor > 0. +-- . The wpfb_unit does support use_reorder. +-- . The wpfb_unit does support use_separate. +-- . The wpfb_unit does support input flow control with invalid gaps in the +-- input. +-- +-- . g_coefs_file_prefix: +-- The g_coefs_file_prefix points to the location where the files +-- with the initial content for the coefficients memories are located and +-- is described in fil_ppf_wide.vhd. +-- +-- . fft_out_gain_w +-- For two real input typically fft_out_gain_w = 1 is used to compensate for +-- the divide by 2 in the separate function that is done because real input +-- frequency bins have norm 0.5. For complex input typically fft_out_gain_w +-- = 0, because the complex bins have norm 1. +-- +-- The reordering to the fil_ppf_wide is done such that the FIR filter +-- coefficients are reused. The same filter coefficients are used for all +-- streams. The filter has real coefficients, because the filterbank +-- channels are symmetrical in frequency. The real part and the imaginary +-- part are filtered independently and also use the same real FIR +-- coefficients. +-- +-- When wb_factor = 4 and nof_wb_streams = 2 the mapping is as follows using +-- the array notation: +-- +-- . I = array index +-- . S = stream index of a wideband stream +-- . P = wideband factor index +-- . t = time index +-- +-- parallel serial type +-- in_sosi_arr [nof_streams][wb_factor] [t] cint +-- +-- fil_in_arr [wb_factor][nof_streams][complex] [t] int +-- fil_out_arr [wb_factor][nof_streams][complex] [t] int +-- +-- fil_sosi_arr [nof_streams][wb_factor] [t] cint +-- fft_in_re_arr [nof_streams][wb_factor] [t] int +-- fft_in_im_arr [nof_streams][wb_factor] [t] int +-- fft_out_re_arr [nof_streams][wb_factor] [bin] int +-- fft_out_im_arr [nof_streams][wb_factor] [bin] int +-- fft_out_sosi_arr [nof_streams][wb_factor] [bin] cint +-- out_sosi_arr [nof_streams][wb_factor] [bin] cint +-- +-- in_sosi_arr | fil_in_arr | fft_in_re_arr | fft_out_re_arr +-- fil_sosi_arr | fil_out_arr | fft_in_im_arr | fft_out_im_arr +-- | | | fft_out_sosi_arr +-- | | | out_sosi_arr +-- | | | +-- I S P t | I P S | I S P t | I S P +-- 7 1 3 0 | 15 3 1 IM | 7 1 3 3 | 7 1 3 +-- 6 1 2 1 | 14 3 1 RE | 6 1 2 2 | 6 1 2 +-- 5 1 1 2 | 13 3 0 IM | 5 1 1 1 | 5 1 1 +-- 4 1 0 3 | 12 3 0 RE | 4 1 0 0 | 4 1 0 +-- 3 0 3 0 | 11 2 1 IM | 3 0 3 3 | 3 0 3 +-- 2 0 2 1 | 10 2 1 RE | 2 0 2 2 | 2 0 2 +-- 1 0 1 2 | 9 2 0 IM | 1 0 1 1 | 1 0 1 +-- 0 0 0 3 | 8 2 0 RE | 0 0 0 0 | 0 0 0 +-- | 7 1 1 IM | | +-- ^ | 6 1 1 RE | ^ | +-- big | 5 1 0 IM | little | +-- endian | 4 1 0 RE | endian | +-- | 3 0 1 IM | | +-- | 2 0 1 RE | | +-- | 1 0 0 IM | | +-- | 0 0 0 RE | | +-- +-- The WPFB output are the frequency bins per transformed block: +-- . subbands, in case ot two real input or +-- . channels, in case of complex input +-- +-- The order of the WPFB output depends on the g_fft fields: +-- . wb_factor +-- . use_reorder +-- . use_fft_shift +-- . use_separate +-- +-- 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 +-- +-- 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 +-- 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. + +-- Remarks: +-- . The unit can handle only one sync at a time. Therfor the +-- sync interval should be larger than the total pipeline +-- stages of the wideband fft. -- --- . The g_coefs_file_prefix points to the location where the files --- with the initial content for the coefficients memories are located. --- These files can be created using the python script: create_mifs.py --- create_mifs.py is located in $UNB/Firmware/dsp/filter/src/python/ --- It is possible to create the mif files based on every possible --- configuration of the filterbank in terms of: --- * wb_factor --- * nof points --- * nof_taps library ieee, common_lib, dp_lib, rTwoSDF_lib, st_lib, filter_lib, fft_lib, diag_lib; use IEEE.std_logic_1164.all; @@ -128,6 +232,8 @@ architecture str of wpfb_unit_dev is g_wpfb.stat_data_w, g_wpfb.stat_data_sz); + constant c_fft_r2_check : boolean := fft_r2_parameter_asserts(c_fft); + constant c_bg_buf_adr_w : natural := ceil_log2(g_wpfb.nof_points/g_wpfb.wb_factor); constant c_bg_data_file_index_arr : t_nat_natural_arr := array_init(0, 4, 1); constant c_bg_data_file_prefix : string := "UNUSED"; @@ -170,11 +276,6 @@ architecture str of wpfb_unit_dev is begin - --------------------------------------------------------------- - -- CHECK IF PROVIDED GENERICS ARE ALLOWED. - --------------------------------------------------------------- - assert not(g_wpfb.nof_chan /= 0 and g_wpfb.wb_factor /= 1 and rising_edge(dp_clk)) report "nof_chan must be 0 when wb_factor > 1" severity FAILURE; - -- The complete input sosi arry is registered. comb : process(r, in_sosi_arr) variable v : reg_type; @@ -213,47 +314,7 @@ begin --------------------------------------------------------------- -- REWIRE THE DATA FOR WIDEBAND POLY PHASE FILTER --------------------------------------------------------------- - -- The reordering to the fil_ppf_wide is done such that the FIR filter - -- coefficients are reused. The same filter coefficients are used for - -- all streams. The filter has real coefficients, because the - -- filterbank channels are symmetrical in frequency. The real part and - -- the imaginary part are filtered independently and also use the - -- same real FIR coefficients. - -- - -- When wb_factor = 4 and nof_wb_streams = 2 the mapping is as - -- follows (i = array index, S = wb stream index, P = wideband factor - -- index, t = time index): - -- - -- parallel serial type - -- in_sosi_arr [nof_streams][wb_factor] [t] cint - -- fil_in_arr [wb_factor][nof_streams][complex] [t] int - -- - -- in_sosi_arr | fil_in_arr | fft_in_re_arr | fft_out_re_arr - -- fil_sosi_arr | fil_out_arr | fft_in_im_arr | fft_out_im_arr - -- | | | fft_out_sosi_arr - -- | | | out_sosi_arr - -- | | | - -- i S P t | i P S | i S P t | i S P - -- 0 0 0 3 | 0 0 0 RE | 0 0 0 0 | 0 0 0 - -- 1 0 1 2 | 1 0 0 IM | 1 0 1 1 | 1 0 1 - -- 2 0 2 1 | 2 0 1 RE | 2 0 2 2 | 2 0 2 - -- 3 0 3 0 | 3 0 1 IM | 3 0 3 3 | 3 0 3 - -- 4 1 0 3 | 4 1 0 RE | 4 1 0 0 | 4 1 0 - -- 5 1 1 2 | 5 1 0 IM | 5 1 1 1 | 5 1 1 - -- 6 1 2 1 | 6 1 1 RE | 6 1 2 2 | 6 1 2 - -- 7 1 3 0 | 7 1 1 IM | 7 1 3 3 | 7 1 3 - -- | 8 2 0 RE | | - -- ^ | 9 2 0 IM | ^ | - -- big | 10 2 1 RE | little | - -- endian | 11 2 1 IM | endian | - -- | 12 3 0 RE | | - -- | 13 3 0 IM | | - -- | 14 3 1 RE | | - -- | 15 3 1 IM | | - -- - -- Note that wideband time index t is big-endian in the filter and - -- little-endian in the FFT - + -- Wire in_sosi_arr --> fil_in_arr wire_fil_in_wideband: for P in 0 to g_wpfb.wb_factor-1 generate wire_fil_in_streams: for S in 0 to g_wpfb.nof_wb_streams-1 generate @@ -272,6 +333,15 @@ begin end generate; end generate; + -- Wire fil_out_arr --> fft_in_re_arr, fft_in_im_arr + wire_fft_in_streams: for S in 0 to g_wpfb.nof_wb_streams-1 generate + wire_fft_in_wideband: for P in 0 to g_wpfb.wb_factor-1 generate + -- reverse wideband order from big-endian [3:0] = [t0,t1,t2,t3] in fil_ppf_wide to little-endian [3:0] = [t3,t2,t1,t0] in fft_r2_wide + fft_in_re_arr(S*g_wpfb.wb_factor + g_wpfb.wb_factor-1-P) <= fil_out_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex); + fft_in_im_arr(S*g_wpfb.wb_factor + g_wpfb.wb_factor-1-P) <= fil_out_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex+1); + end generate; + end generate; + --------------------------------------------------------------- -- THE POLY PHASE FILTER --------------------------------------------------------------- @@ -305,14 +375,6 @@ begin fft_in_val <= fil_out_val; - wire_fft_in_streams: for S in 0 to g_wpfb.nof_wb_streams-1 generate - wire_fft_in_wideband: for P in 0 to g_wpfb.wb_factor-1 generate - -- reverse wideband order from big-endian [3:0] = [t0,t1,t2,t3] in fil_ppf_wide to little-endian [3:0] = [t3,t2,t1,t0] in fft_r2_wide - fft_in_re_arr(S*g_wpfb.wb_factor + g_wpfb.wb_factor-1-P) <= fil_out_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex); - fft_in_im_arr(S*g_wpfb.wb_factor + g_wpfb.wb_factor-1-P) <= fil_out_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex+1); - end generate; - end generate; - --------------------------------------------------------------- -- THE WIDEBAND FFT ---------------------------------------------------------------