OpenCores
URL https://opencores.org/ocsvn/astron_wpfb/astron_wpfb/trunk

Subversion Repositories astron_wpfb

[/] [astron_wpfb/] [trunk/] [wpfb_unit_dev.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------
-- Author: Harm Jan Pepping : HJP at astron.nl: April 2012
--------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
--------------------------------------------------------------------------------
-- Purpose: Wideband polyphase filterbank with subband statistics and streaming interfaces.
--
-- Description:
--
-- 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.
--
-- The wpfb unit can handle a wideband factor >= 1 (g_wpfb.wb_factor) or
-- a narrowband factor >= 1 (2**g_wpfb.nof_chan).
-- . For wb_factor = 1 the wpfb_unit uses fft_r2_pipe
-- . For wb_factor > 1 the wpfb_unit uses fft_r2_wide
-- . For wb_factor >= 1 the wpfb_unit supports nof_chan >= 0, even though the
--   concept of channels is typically not useful when wb_factor > 1.
-- . 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.
--
-- . g_dont_flip_channels:
--   True preserves channel interleaving, set by g_wpfb.nof_chan>0, of the FFT
--   output when g_bit_flip=true to reorder the FFT output.
--   The g_dont_flip_channels applies for both complex input and two_real
--   input FFT. The g_dont_flip_channels is only implemented for the pipelined
--   fft_r2_pipe, because for g_wpfb.wb_factor=1 using g_wpfb.nof_chan>0 makes
--   sense, while for the fft_r2_wide with g_wpfb.wb_factor>1 using input
--   multiplexing via g_wpfb.nof_chan>0 makes less sense.
--
-- 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.
--
-- 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 inside the prefilter and
--   little-endian inside the FFT. 
--   When g_big_endian_wb_in=true then the WPFB input must be in big-endian
--   format, else in little-endian format.
--   For little-endian time index t increments in the same direction as the
--   wideband factor index P, so P = 0, 1, 2, 3 --> t0, t1, t2, t3.
--   For big-endian the time index t increments in the opposite direction of
--   the wideband factor index P, so P = 3, 2, 1, 0 --> t0, t1, t2, t3.
--   The WPFB output is fixed 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:
--
--   . 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
--   pfb_out_sosi_arr [nof_streams][wb_factor]           [bin]    cint with sync, BSN, sop, eop
--   out_sosi_arr     [nof_streams][wb_factor]           [bin]    cint with sync, BSN, sop, eop
-- 
--   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
--                |             |               | pfb_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 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
--      input     A  B  A  B  A  B  A  B
--
--   when nof_chan=1 then:
--     I  S P    bin frequency order    
--     7  1 3    12 12 13 13 14 14 15 15 12 12 13 13 14 14 15 15
--     6  1 2     8  8  9  9 10 10 11 11  8  8  9  9 10 10 11 11
--     5  1 1     4  4  5  5  6  6  7  7  4  4  5  5  6  6  7  7
--     4  1 0     0  0  1  1  2  2  3  3  0  0  1  1  2  2  3  3
--     3  0 3    12 12 13 13 14 14 15 15 12 12 13 13 14 14 15 15
--     2  0 2     8  8  9  9 10 10 11 11  8  8  9  9 10 10 11 11
--     1  0 1     4  4  5  5  6  6  7  7  4  4  5  5  6  6  7  7
--     0  0 0     0  0  1  1  2  2  3  3  0  0  1  1  2  2  3  3
--      input     A  B  A  B  A  B  A  B  A  B  A  B  A  B  A  B
--    channel     0....................0  1....................1
--
-- 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
--
--   when nof_chan=1 then:
--     I  S P    bin frequency order    
--     7  1 3    24 25 26 27 28 29 30 31 24 25 26 27 28 29 30 31
--     6  1 2    16 17 18 19 20 21 22 23 16 17 18 19 20 21 22 23
--     5  1 1     8  9 10 11 12 13 14 15  8  9 10 11 12 13 14 15 
--     4  1 0     0  1  2  3  4  5  6  7  0  1  2  3  4  5  6  7
--     3  0 3    24 25 26 27 28 29 30 31 24 25 26 27 28 29 30 31
--     2  0 2    16 17 18 19 20 21 22 23 16 17 18 19 20 21 22 23
--     1  0 1     8  9 10 11 12 13 14 15  8  9 10 11 12 13 14 15
--     0  0 0     0  1  2  3  4  5  6  7  0  1  2  3  4  5  6  7
--    channel     0....................0  1....................1
--
-- 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
-- 
--   when nof_chan=1 then:
--     I  S P    bin frequency order
--     7  1 3     8  9 10 11 12 13 14 15  8  9 10 11 12 13 14 15
--     6  1 2     0  1  2  3  4  5  6  7  0  1  2  3  4  5  6  7
--     5  1 1    24 25 26 27 28 29 30 31 24 25 26 27 28 29 30 31  
--     4  1 0    16 17 18 19 20 21 22 23 16 17 18 19 20 21 22 23
--     3  0 3     8  9 10 11 12 13 14 15  8  9 10 11 12 13 14 15 
--     2  0 2     0  1  2  3  4  5  6  7  0  1  2  3  4  5  6  7
--     1  0 1    24 25 26 27 28 29 30 31 24 25 26 27 28 29 30 31
--     0  0 0    16 17 18 19 20 21 22 23 16 17 18 19 20 21 22 23
--    channel     0....................0  1....................1
--
-- 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
--
--   when nof_chan=1 then:
--     I  S P    bin frequency order    
--     7  1 3     8  8 12 12 10 10 14 14  9  9 13 13 11 11 15 15
--     6  1 2    24 24 28 28 26 26 30 30 25 25 29 29 27 27 31 31
--     5  1 1     0  0  4  4  2  2  6  6  1  1  5  5  3  3  7  7  
--     4  1 0    16 16 20 20 18 18 22 22 17 17 21 21 19 19 23 23
--     3  0 3     8  8 12 12 10 10 14 14  9  9 13 13 11 11 15 15 
--     2  0 2    24 24 28 28 26 26 30 30 25 25 29 29 27 27 31 31
--     1  0 1     0  0  4  4  2  2  6  6  1  1  5  5  3  3  7  7
--     0  0 0    16 16 20 20 18 18 22 22 17 17 21 21 19 19 23 23
--    channel     0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1
--
-- II) Narrowband wb_factor = 1
--
-- 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
--      input     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
--
--   when nof_chan=1 then:
--     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  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  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
--      input     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  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
--     channel:   0............................................................................................0  1............................................................................................1
--
-- 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
--
--   when nof_chan=1 then:
--     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  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  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
--     channel:   0............................................................................................0  1............................................................................................1
--
-- 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
--
--   when nof_chan=1 then:
--     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 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 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
--     channel:   0............................................................................................0  1............................................................................................1
--
-- 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
--
--   when nof_chan=1 then:
--     I  S P    bin frequency order
--     1  1 0    16 16  0  0 24 24  8  8 20 20  4  4 28 28 12 12 18 18  2  2 26 26 10 10 22 22  6  6 30 30 14 14 17 17  1  1 25 25  9  9 21 21  5  5 29 29 13 13 19 19  3  3 27 27 11 11 23 23  7  7 31 31 15 15
--     0  0 0    16 16  0  0 24 24  8  8 20 20  4  4 28 28 12 12 18 18  2  2 26 26 10 10 22 22  6  6 30 30 14 14 17 17  1  1 25 25  9  9 21 21  5  5 29 29 13 13 19 19  3  3 27 27 11 11 23 23  7  7 31 31 15 15
--     channel:   0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1
--
-- 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.
--
 
library ieee, common_pkg_lib, dp_pkg_lib, astron_r2sdf_fft_lib, astron_statistics_lib, astron_filter_lib, astron_wb_fft_lib, astron_diagnostics_lib, astron_ram_lib, astron_mm_lib;
use IEEE.std_logic_1164.all;
use STD.textio.all;
use common_pkg_lib.common_pkg.all;
use astron_ram_lib.common_ram_pkg.all;
use dp_pkg_lib.dp_stream_pkg.ALL;
use astron_r2sdf_fft_lib.rTwoSDFPkg.all;
use astron_statistics_lib.all;
use astron_filter_lib.all;
use astron_filter_lib.fil_pkg.all;
use astron_wb_fft_lib.all;
use astron_wb_fft_lib.fft_pkg.all;
use work.wpfb_pkg.all;
 
entity wpfb_unit_dev is
  generic (
    g_big_endian_wb_in  : boolean           := true;
    g_wpfb              : t_wpfb;
    g_dont_flip_channels: boolean           := false;   -- True preserves channel interleaving for pipelined FFT
    g_use_prefilter     : boolean           := TRUE;
    g_stats_ena         : boolean           := TRUE;    -- Enables the statistics unit
    g_use_bg            : boolean           := FALSE;
    g_coefs_file_prefix : string            := "data/coefs_wide" -- File prefix for the coefficients files.
   );
  port (
    dp_rst             : in  std_logic := '0';
    dp_clk             : in  std_logic;
    mm_rst             : in  std_logic;
    mm_clk             : in  std_logic;
    ram_fil_coefs_mosi : in  t_mem_mosi;
    ram_fil_coefs_miso : out t_mem_miso := c_mem_miso_rst;
    ram_st_sst_mosi    : in  t_mem_mosi;                   -- Subband statistics registers
    ram_st_sst_miso    : out t_mem_miso := c_mem_miso_rst;
    reg_bg_ctrl_mosi   : in  t_mem_mosi;
    reg_bg_ctrl_miso   : out t_mem_miso;
    ram_bg_data_mosi   : in  t_mem_mosi;
    ram_bg_data_miso   : out t_mem_miso;
    in_sosi_arr        : in  t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
    fil_sosi_arr       : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
    out_sosi_arr       : out t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0)
  );
end entity wpfb_unit_dev;
 
architecture str of wpfb_unit_dev is
 
  constant c_nof_channels          : natural := 2**g_wpfb.nof_chan;
 
  constant c_nof_data_per_block    : natural := c_nof_channels * g_wpfb.nof_points;
  constant c_nof_valid_per_block   : natural := c_nof_data_per_block / g_wpfb.wb_factor;
 
  constant c_nof_stats             : natural := c_nof_valid_per_block;
 
  constant c_fil_ppf         : t_fil_ppf := (g_wpfb.wb_factor,
                                             g_wpfb.nof_chan,
                                             g_wpfb.nof_points,
                                             g_wpfb.nof_taps,
                                             c_nof_complex*g_wpfb.nof_wb_streams,  -- Complex FFT always requires 2 filter streams: real and imaginary
                                             g_wpfb.fil_backoff_w,
                                             g_wpfb.fil_in_dat_w,
                                             g_wpfb.fil_out_dat_w,
                                             g_wpfb.coef_dat_w);
 
  constant c_fft             : t_fft     := (g_wpfb.use_reorder,
                                             g_wpfb.use_fft_shift,
                                             g_wpfb.use_separate,
                                             g_wpfb.nof_chan,
                                             g_wpfb.wb_factor,
                                             0,
                                             g_wpfb.nof_points,
                                             g_wpfb.fft_in_dat_w,
                                             g_wpfb.fft_out_dat_w,
                                             g_wpfb.fft_out_gain_w,
                                             g_wpfb.stage_dat_w,
                                             g_wpfb.guard_w,
                                             g_wpfb.guard_enable,
                                             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, g_wpfb.nof_wb_streams*g_wpfb.wb_factor, 1);
  constant c_bg_data_file_prefix    : string  := "UNUSED";
 
  signal ram_st_sst_mosi_arr : t_mem_mosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal ram_st_sst_miso_arr : t_mem_miso_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0) := (others => c_mem_miso_rst);
 
  signal fil_in_arr          : t_fil_slv_arr(c_nof_complex*g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fil_in_val          : std_logic;
  signal fil_out_arr         : t_fil_slv_arr(c_nof_complex*g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fil_out_val         : std_logic;
 
  signal fft_in_re_arr       : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_in_im_arr       : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_in_val          : std_logic;
 
  signal fft_out_re_arr_i    : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_out_im_arr_i    : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_out_re_arr      : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_out_im_arr      : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_out_re_arr_pipe : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_out_im_arr_pipe : t_fft_slv_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  signal fft_out_val_arr     : std_logic_vector(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
 
  signal fft_out_sosi        : t_dp_sosi;
  signal fft_out_sosi_arr    : t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0) := (others => c_dp_sosi_rst);
 
  signal pfb_out_sosi_arr    : t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0) := (others => c_dp_sosi_rst);
 
  type reg_type is record
    in_sosi_arr : t_dp_sosi_arr(g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 downto 0);
  end record;
 
  signal r, rin : reg_type;
 
begin
 
  -- The complete input sosi arry is registered.
  comb : process(r, in_sosi_arr)
    variable v : reg_type;
  begin
    v             := r;
    v.in_sosi_arr := in_sosi_arr;
    rin           <= v;
  end process comb;
 
  regs : process(dp_clk)
  begin
    if rising_edge(dp_clk) then
      r <= rin;
    end if;
  end process;
 
  ---------------------------------------------------------------
  -- COMBINE MEMORY MAPPED INTERFACES
  ---------------------------------------------------------------
  -- Combine the internal array of mm interfaces for the subband
  -- statistics to one array that is connected to the port of the
  -- fft_wide_unit.
  u_mem_mux_sst : entity astron_mm_lib.common_mem_mux
  generic map (
    g_nof_mosi    => g_wpfb.nof_wb_streams*g_wpfb.wb_factor,
    g_mult_addr_w => ceil_log2(g_wpfb.stat_data_sz*c_nof_stats)
  )
  port map (
    mosi     => ram_st_sst_mosi,
    miso     => ram_st_sst_miso,
    mosi_arr => ram_st_sst_mosi_arr,
    miso_arr => ram_st_sst_miso_arr
  );
 
  gen_pfb : if g_use_bg = FALSE generate
    ---------------------------------------------------------------
    -- REWIRE THE DATA FOR WIDEBAND POLY PHASE FILTER
    ---------------------------------------------------------------
 
    -- 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
        fil_in_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex)   <= RESIZE_SVEC_32(r.in_sosi_arr(S*g_wpfb.wb_factor+P).re(g_wpfb.fil_in_dat_w-1 downto 0));
        fil_in_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex+1) <= RESIZE_SVEC_32(r.in_sosi_arr(S*g_wpfb.wb_factor+P).im(g_wpfb.fil_in_dat_w-1 downto 0));
      end generate;
    end generate;
    fil_in_val <= r.in_sosi_arr(0).valid;
 
    -- Wire fil_out_arr --> fil_sosi_arr
    wire_fil_sosi_streams: for S in 0 to g_wpfb.nof_wb_streams-1 generate
      wire_fil_sosi_wideband: for P in 0 to g_wpfb.wb_factor-1 generate
        fil_sosi_arr(S*g_wpfb.wb_factor+P).valid <= fil_out_val;
        fil_sosi_arr(S*g_wpfb.wb_factor+P).re    <= RESIZE_DP_DSP_DATA(fil_out_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex  ));
        fil_sosi_arr(S*g_wpfb.wb_factor+P).im    <= RESIZE_DP_DSP_DATA(fil_out_arr(P*g_wpfb.nof_wb_streams*c_nof_complex+S*c_nof_complex+1));
      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
        fft_in_re_arr(S*g_wpfb.wb_factor + 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 + 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
    ---------------------------------------------------------------
    gen_prefilter : IF g_use_prefilter = TRUE generate
      u_filter : entity astron_filter_lib.fil_ppf_wide
      generic map (
        g_big_endian_wb_in  => g_big_endian_wb_in,
        g_big_endian_wb_out => false,  -- 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
        g_fil_ppf           => c_fil_ppf,
        g_fil_ppf_pipeline  => g_wpfb.fil_pipeline,
        g_coefs_file_prefix => g_coefs_file_prefix
      )
      port map (
        dp_clk         => dp_clk,
        dp_rst         => dp_rst,
        mm_clk         => mm_clk,
        mm_rst         => mm_rst,
        ram_coefs_mosi => ram_fil_coefs_mosi,
        ram_coefs_miso => ram_fil_coefs_miso,
        in_dat_arr     => fil_in_arr,
        in_val         => fil_in_val,
        out_dat_arr    => fil_out_arr,
        out_val        => fil_out_val
      );
    end generate;
 
    -- Bypass filter
    no_prefilter : if g_use_prefilter = FALSE generate
      fil_out_arr <= fil_in_arr;
      fil_out_val <= fil_in_val;
    end generate;
 
    fft_in_val <= fil_out_val;
 
    ---------------------------------------------------------------
    -- THE WIDEBAND FFT
    ---------------------------------------------------------------
    gen_wideband_fft: if g_wpfb.wb_factor > 1  generate
      gen_fft_r2_wide_streams: for S in 0 to g_wpfb.nof_wb_streams-1 generate
        u_fft_r2_wide : entity astron_wb_fft_lib.fft_r2_wide
        generic map(
          g_fft          => c_fft,         -- generics for the WFFT
          g_pft_pipeline => g_wpfb.pft_pipeline,
          g_fft_pipeline => g_wpfb.fft_pipeline
        )
        port map(
          clk        => dp_clk,
          rst        => dp_rst,
          in_re_arr  => fft_in_re_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor),
          in_im_arr  => fft_in_im_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor),
          in_val     => fft_in_val,
          out_re_arr => fft_out_re_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor),
          out_im_arr => fft_out_im_arr((S+1)*g_wpfb.wb_factor-1 downto S*g_wpfb.wb_factor),
          out_val    => fft_out_val_arr(S)
        );
      end generate;
    end generate;
 
    ---------------------------------------------------------------
    -- THE PIPELINED FFT
    ---------------------------------------------------------------
    gen_pipeline_fft: if g_wpfb.wb_factor = 1  generate
      gen_fft_r2_pipe_streams: for S in 0 to g_wpfb.nof_wb_streams-1 generate
        u_fft_r2_pipe : entity astron_wb_fft_lib.fft_r2_pipe
        generic map(
          g_fft      => c_fft,
          g_dont_flip_channels => g_dont_flip_channels,
          g_pipeline => g_wpfb.fft_pipeline
        )
        port map(
          clk       => dp_clk,
          rst       => dp_rst,
          in_re     => fft_in_re_arr(S)(c_fft.in_dat_w-1 downto 0),
          in_im     => fft_in_im_arr(S)(c_fft.in_dat_w-1 downto 0),
          in_val    => fft_in_val,
          out_re    => fft_out_re_arr_i(S)(c_fft.out_dat_w-1 downto 0),
          out_im    => fft_out_im_arr_i(S)(c_fft.out_dat_w-1 downto 0),
          out_val   => fft_out_val_arr(S)
        );
 
        fft_out_re_arr(S) <= RESIZE_SVEC_32(fft_out_re_arr_i(S)(c_fft.out_dat_w-1 downto 0));
        fft_out_im_arr(S) <= RESIZE_SVEC_32(fft_out_im_arr_i(S)(c_fft.out_dat_w-1 downto 0));
      end generate;
    end generate;
 
    ---------------------------------------------------------------
    -- FFT CONTROL UNIT
    ---------------------------------------------------------------
 
    -- Capture input BSN at input sync and pass the captured input BSN it on to PFB output sync.
    -- The FFT output valid defines PFB output sync, sop, eop.
 
    fft_out_sosi.sync  <= r.in_sosi_arr(0).sync;  
    fft_out_sosi.bsn   <= r.in_sosi_arr(0).bsn;   
    fft_out_sosi.valid <= fft_out_val_arr(0);     
 
    wire_fft_out_sosi_arr : for I in 0 to g_wpfb.nof_wb_streams*g_wpfb.wb_factor-1 generate
      fft_out_sosi_arr(I).re    <= RESIZE_DP_DSP_DATA(fft_out_re_arr(I));
      fft_out_sosi_arr(I).im    <= RESIZE_DP_DSP_DATA(fft_out_im_arr(I));
      fft_out_sosi_arr(I).valid <=                    fft_out_val_arr(I);
    end generate;
 
    u_dp_block_gen_valid_arr : ENTITY work.dp_block_gen_valid_arr
    GENERIC MAP (
      g_nof_streams         => g_wpfb.nof_wb_streams*g_wpfb.wb_factor,
      g_nof_data_per_block  => c_nof_valid_per_block,
      g_nof_blk_per_sync    => g_wpfb.nof_blk_per_sync,
      g_check_input_sync    => false,
      g_nof_pages_bsn       => 1,
      g_restore_global_bsn  => true
    )
    PORT MAP (
      rst         => dp_rst,
      clk         => dp_clk,
      -- Streaming sink
      snk_in      => fft_out_sosi,
      snk_in_arr  => fft_out_sosi_arr,
      -- Streaming source
      src_out_arr => pfb_out_sosi_arr,
      -- Control
      enable      => '1'
    );
  end generate;
 
  ----------------------------------------------------------------------------
  -- Source: block generator
  ----------------------------------------------------------------------------
  gen_bg : if g_use_bg = TRUE generate
    u_bg : entity astron_diagnostics_lib.mms_diag_block_gen
    generic map(
      g_nof_streams      => g_wpfb.nof_wb_streams*g_wpfb.wb_factor,
      g_buf_dat_w        => c_nof_complex*g_wpfb.fft_out_dat_w,
      g_buf_addr_w       => c_bg_buf_adr_w,               -- Waveform buffer size 2**g_buf_addr_w nof samples
      g_file_index_arr   => c_bg_data_file_index_arr,
      g_file_name_prefix => c_bg_data_file_prefix
    )
    port map(
      -- System
      mm_rst           => mm_rst,
      mm_clk           => mm_clk,
      dp_rst           => dp_rst,
      dp_clk           => dp_clk,
      en_sync          => '0',
      -- MM interface
      reg_bg_ctrl_mosi => reg_bg_ctrl_mosi,
      reg_bg_ctrl_miso => reg_bg_ctrl_miso,
      ram_bg_data_mosi => ram_bg_data_mosi,
      ram_bg_data_miso => ram_bg_data_miso,
      -- ST interface
      out_sosi_arr     => pfb_out_sosi_arr
    );
  end generate;
 
 ---------------------------------------------------------------
  -- SUBBAND STATISTICS
  ---------------------------------------------------------------
  -- For all "wb_factor"x"nof_wb_streams" output streams of the
  -- wideband FFT a subband statistics unit is placed if the
  -- g_stats_ena is TRUE.
  -- Since the subband statistics module uses embedded DSP blocks
  -- for multiplication, the incoming data cannot be wider
  -- than 18 bit.
  gen_stats : if g_stats_ena = TRUE generate
    gen_stats_streams: for S in 0 to g_wpfb.nof_wb_streams-1 generate
      gen_stats_wideband: for P in 0 to g_wpfb.wb_factor-1 generate
        u_subband_stats : entity astron_statistics_lib.st_sst
        generic map(
          g_nof_stat      => c_nof_stats,
          g_in_data_w     => g_wpfb.fft_out_dat_w,
          g_stat_data_w   => g_wpfb.stat_data_w,
          g_stat_data_sz  => g_wpfb.stat_data_sz
        )
        port map (
          mm_rst          => mm_rst,
          mm_clk          => mm_clk,
          dp_rst          => dp_rst,
          dp_clk          => dp_clk,
          in_complex      => pfb_out_sosi_arr(S*g_wpfb.wb_factor+P),
          ram_st_sst_mosi => ram_st_sst_mosi_arr(S*g_wpfb.wb_factor+P),
          ram_st_sst_miso => ram_st_sst_miso_arr(S*g_wpfb.wb_factor+P)
        );
      end generate;
    end generate;
  end generate;
 
  -- Connect to the outside world
  out_sosi_arr <= pfb_out_sosi_arr;
 
end str;
 
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.