diff --git a/applications/lofar1/pfb2/hdllib.cfg b/applications/lofar1/pfb2/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..e6aff635245a72dbd483a934f68c04d07bb2ee75 --- /dev/null +++ b/applications/lofar1/pfb2/hdllib.cfg @@ -0,0 +1,17 @@ +hdl_lib_name = pfb2 +hdl_library_clause_name = pfb2_lib +hdl_lib_uses_synth = common dp pfs pft2 st +hdl_lib_uses_sim = +hdl_lib_technology = + +synth_files = + src/vhdl/pfb2.vhd + src/vhdl/pfb2_unit.vhd + +test_bench_files = + +regression_test_vhdl = + +[modelsim_project_file] + +[ise_project_file] diff --git a/applications/lofar1/pfb2/src/vhdl/pfb2.vhd b/applications/lofar1/pfb2/src/vhdl/pfb2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..62d2a5e3e91132b0e44dd76cdc4c9fba4381bb8a --- /dev/null +++ b/applications/lofar1/pfb2/src/vhdl/pfb2.vhd @@ -0,0 +1,143 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- +-- +-- Author: E. Kooistra +-- Purpose: Combine LOFAR1 pfs + pft2 into pfb2 with statistics and streaming +-- interfaces, similar as wpfb_unit_dev +-- Description: +-- +-- Remark: +-- . Convert between LOFAR1 sync timing 1 clk before sop and streaming data path +-- (DP) sync timing at sop. +-- . g_switch_en = '1' decorrelates rounding crosstalk between the X and Y output +-- that can occur due to PFT_MODE_REAL2. + +LIBRARY IEEE, common_lib, dp_lib, pfs_lib, pft2_lib; +USE IEEE.std_logic_1164.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE pft2_lib.pft_pkg.ALL; + +ENTITY pfb2 IS + GENERIC ( + g_nof_points : NATURAL := 1024; + + -- pfs + g_pfs_nof_taps : NATURAL := 16; + g_pfs_in_dat_w : NATURAL := 12; + g_pfs_out_dat_w : NATURAL := 18; + g_pfs_coef_dat_w : NATURAL := 16; + + -- pft2 + g_pft_mode : PFT_MODE_TYPE := PFT_MODE_REAL2; + g_pft_switch_en : STD_LOGIC := '1'; + g_pft_out_dat_w : NATURAL := 18 + ); + PORT ( + dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; + in_sosi : IN t_dp_sosi; + fil_sosi : OUT t_dp_sosi; + out_sosi : OUT t_dp_sosi + ); +END pfb2; + +ARCHITECTURE str OF pfb2 IS + + CONSTANT c_nof_coeffs : NATURAL := g_pfs_nof_taps*g_nof_points; + + SIGNAL pfs_in_dat_x : STD_LOGIC_VECTOR(g_pfs_in_dat_w-1 DOWNTO 0); + SIGNAL pfs_in_dat_y : STD_LOGIC_VECTOR(g_pfs_in_dat_w-1 DOWNTO 0); + SIGNAL pfs_in_val : STD_LOGIC; + SIGNAL pfs_in_sync : STD_LOGIC; + + SIGNAL fil_out_dat_x : STD_LOGIC_VECTOR(g_pfs_out_dat_w-1 DOWNTO 0); + SIGNAL fil_out_dat_y : STD_LOGIC_VECTOR(g_pfs_out_dat_w-1 DOWNTO 0); + SIGNAL fil_out_val : STD_LOGIC; + SIGNAL fil_out_sync : STD_LOGIC; + + SIGNAL pft_out_dat_re : STD_LOGIC_VECTOR(g_pft_out_dat_w-1 DOWNTO 0); + SIGNAL pft_out_dat_im : STD_LOGIC_VECTOR(g_pft_out_dat_w-1 DOWNTO 0); + SIGNAL pft_out_val : STD_LOGIC; + SIGNAL pft_out_sync : STD_LOGIC; + +BEGIN + + -- Delay in_sosi data with respect to sync to fit LOFAR1 sync timing + pfs_in_dat_x <= in_sosi.re(g_pfs_in_dat_w-1 DOWNTO 0) WHEN rising_edge(dp_clk); + pfs_in_dat_y <= in_sosi.im(g_pfs_in_dat_w-1 DOWNTO 0) WHEN rising_edge(dp_clk); + pfs_in_val <= in_sosi.valid WHEN rising_edge(dp_clk); + pfs_in_sync <= in_sosi.sync; + + pfs : ENTITY pfs_lib.pfs + GENERIC MAP ( + g_nof_bands => g_nof_points, + g_nof_taps => c_nof_coeffs, + g_in_dat_w => g_pfs_in_dat_w, + g_out_dat_w => g_pfs_out_dat_w, + g_coef_dat_w => g_pfs_coef_dat_w + ) + PORT MAP ( + in_dat_x => pfs_in_dat_x, + in_dat_y => pfs_in_dat_y, + in_val => pfs_in_val, + in_sync => pfs_in_sync, + out_dat_x => fil_out_dat_x, + out_dat_y => fil_out_dat_y, + out_val => fil_out_val, + out_sync => fil_out_sync, + clk => dp_clk, + rst => dp_rst, + restart => '0' + ); + + fil_sosi.re <= RESIZE_DP_DSP_DATA(fil_out_dat_x); + fil_sosi.im <= RESIZE_DP_DSP_DATA(fil_out_dat_y); + fil_sosi.valid <= fil_out_val; + fil_sosi.sync <= fil_out_sync; + + pft : ENTITY pft2_lib.pft + GENERIC MAP ( + g_fft_size_w => ceil_log2(g_nof_points), + g_in_dat_w => g_pfs_out_dat_w, + g_out_dat_w => g_pft_out_dat_w, + g_mode => PFT_MODE_REAL2 + ) + PORT MAP ( + in_re => fil_out_dat_x, + in_im => fil_out_dat_y, + in_val => fil_out_val, + in_sync => fil_out_sync, + switch_en => g_pft_switch_en, + out_re => pft_out_dat_re, + out_im => pft_out_dat_im, + out_val => pft_out_val, + out_sync => pft_out_sync, + clk => dp_clk, + rst => dp_rst + ); + + -- Delay pft sync with respect pft data to fit DP sync timing + out_sosi.re <= RESIZE_DP_DSP_DATA(pft_out_dat_re); + out_sosi.im <= RESIZE_DP_DSP_DATA(pft_out_dat_im); + out_sosi.valid <= pft_out_val; + out_sosi.sync <= pft_out_sync WHEN rising_edge(dp_clk); + +END str; diff --git a/applications/lofar1/pfb2/src/vhdl/pfb2_unit.vhd b/applications/lofar1/pfb2/src/vhdl/pfb2_unit.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c51c6277e87765c055725fe54d7d3b7dd14c0916 --- /dev/null +++ b/applications/lofar1/pfb2/src/vhdl/pfb2_unit.vhd @@ -0,0 +1,150 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- +-- +-- Author: E. Kooistra +-- Purpose: Combine LOFAR1 pfb2 with subband statistics (SST), similar as wpfb_unit_dev +-- Description: +-- . support multiple complex input streams via g_nof_streams +-- . 1 complex pfb2 per stream +-- . 1 complex pfb2 can process two real inputs with PFT_MODE_REAL2 +-- . pass on in_sosi.bsn +-- +-- Remark: + +LIBRARY IEEE, common_lib, dp_lib, pfs_lib, pft2_lib, st_lib; +USE IEEE.std_logic_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE pft2_lib.pft_pkg.ALL; + +ENTITY pfb2_unit IS + GENERIC ( + g_nof_streams : NATURAL := 1; -- number of pfb2 instances, 1 pfb2 per stream + g_nof_points : NATURAL := 1024; + + -- pfs + g_pfs_nof_taps : NATURAL := 16; + g_pfs_in_dat_w : NATURAL := 12; + g_pfs_out_dat_w : NATURAL := 18; + g_pfs_coef_dat_w : NATURAL := 16; + + -- pft2 + g_pft_mode : PFT_MODE_TYPE := PFT_MODE_REAL2; + g_pft_switch_en : STD_LOGIC := '1'; + g_pft_out_dat_w : NATURAL := 18; + + -- sst + g_sst_data_w : NATURAL := 64; -- nof bits for the SST power values + g_sst_data_sz : NATURAL := 2 -- nof MM 32b words to fit g_sst_data_w + ); + PORT ( + dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; + mm_rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC; + ram_st_sst_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- Subband statistics registers + ram_st_sst_miso : OUT t_mem_miso; + in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + fil_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + out_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) + ); +END pfb2_unit; + +ARCHITECTURE str OF pfb2_unit IS + + CONSTANT c_nof_stats : NATURAL := g_nof_points; -- SST X and SST Y are interleaved for PFT_MODE_REAL2 + + SIGNAL ram_st_sst_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 downto 0); + SIGNAL ram_st_sst_miso_arr : t_mem_miso_arr(g_nof_streams-1 downto 0) := (OTHERS => c_mem_miso_rst); + + SIGNAL pft_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + +BEGIN + + --------------------------------------------------------------- + -- Polyphase Filterbanks + --------------------------------------------------------------- + gen_pfb2: FOR I IN 0 TO g_nof_streams-1 GENERATE + u_pfb2 : ENTITY work.pfb2 + GENERIC MAP ( + g_nof_points => g_nof_points, + + -- pfs + g_pfs_nof_taps => g_pfs_nof_taps, + g_pfs_in_dat_w => g_pfs_in_dat_w, + g_pfs_out_dat_w => g_pfs_out_dat_w, + g_pfs_coef_dat_w => g_pfs_coef_dat_w, + + -- pft2 + g_pft_mode => g_pft_mode, + g_pft_switch_en => g_pft_switch_en, + g_pft_out_dat_w => g_pft_out_dat_w + ) + PORT MAP ( + dp_rst => dp_rst, + dp_clk => dp_clk, + in_sosi => in_sosi_arr(I), + fil_sosi => fil_sosi_arr(I), + out_sosi => pft_sosi_arr(I) + ); + END GENERATE; + + --------------------------------------------------------------- + -- Subband Statistics (SST) + --------------------------------------------------------------- + -- MM mux for SST + u_mem_mux_sst : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => ceil_log2(g_sst_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_sst: FOR I IN 0 TO g_nof_streams-1 GENERATE + u_sst : ENTITY st_lib.st_sst + GENERIC MAP ( + g_nof_stat => c_nof_stats, + g_in_data_w => g_pft_out_dat_w, + g_stat_data_w => g_sst_data_w, + g_stat_data_sz => g_sst_data_sz + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + in_complex => pft_sosi_arr(I), + ram_st_sst_mosi => ram_st_sst_mosi_arr(I), + ram_st_sst_miso => ram_st_sst_miso_arr(I) + ); + END GENERATE; + + out_sosi_arr <= pft_sosi_arr; + +end str; + + + diff --git a/applications/lofar1/pfb2/src/vhdl/wpfb_unit_dev.vhd b/applications/lofar1/pfb2/src/vhdl/wpfb_unit_dev.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8ce1683177a1d182ac838b7688556aefcd3723ff --- /dev/null +++ b/applications/lofar1/pfb2/src/vhdl/wpfb_unit_dev.vhd @@ -0,0 +1,718 @@ +-------------------------------------------------------------------------------- +-- 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_lib, dp_lib, rTwoSDF_lib, st_lib, filter_lib, fft_lib, diag_lib; +use IEEE.std_logic_1164.all; +use STD.textio.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; +use dp_lib.dp_stream_pkg.ALL; +use rTwoSDF_lib.rTwoSDFPkg.all; +use st_lib.all; +use filter_lib.all; +use filter_lib.fil_pkg.all; +use fft_lib.all; +use 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 := c_mem_mosi_rst; + ram_fil_coefs_miso : out t_mem_miso; + ram_st_sst_mosi : in t_mem_mosi := c_mem_mosi_rst; -- Subband statistics registers + ram_st_sst_miso : out t_mem_miso; + reg_bg_ctrl_mosi : in t_mem_mosi := c_mem_mosi_rst; + reg_bg_ctrl_miso : out t_mem_miso; + ram_bg_data_mosi : in t_mem_mosi := c_mem_mosi_rst; + 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 common_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 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 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 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 dp_lib.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 diag_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 st_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; + + + diff --git a/applications/lofar1/readme_lofar1.txt b/applications/lofar1/readme_lofar1.txt index 3750980993d0150120e40021de030a91c7b4319b..64324e75cfc400b87c2aa9d802f1f1b52ca35611 100644 --- a/applications/lofar1/readme_lofar1.txt +++ b/applications/lofar1/readme_lofar1.txt @@ -1,8 +1,35 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- +-- +-- Author: E. Kooistra + This readme describes how the PFB (= pfs + pft2) code of LOFAR1/RSP was ported to git for LOFAR2 Contents 1) Comparison of LOFAR1 and APERTIF polyphase filterbank (PFB) 2) Porting LOFAR1 PFB code to LOFAR2.0 + a) pfs + b) pft2 + c) Simulating tb/vhdl/tb_pft2.vhd +3) Create pfb2_unit.vhd that can replace wpfb_unit_dev.vhd + References: [1] LOFAR1 RSP firmware SVN repository https://svn.astron.nl/Station/trunk/RSP/ @@ -11,6 +38,8 @@ References: [4] APERTIF DSP firmware (rTwoSDF, filter, fft, wpfb) in LOFAR2.0 GIT repository https://git.astron.nl/desp/hdl/-/tree/master/libraries/dsp [5] APERTIF PFB MATLAB code in APERTIF firmware SVN repository https://svn.astron.nl/UniBoard_FP7/RadioHDL/trunk/applications/apertif/matlab/apertif_matlab_readme.txt + + 1) Comparison of LOFAR1 and APERTIF polyphase filterbank (PFB) - Advantages of LOFAR1 PFB (= pfs + pft2) are: . used in LOFAR1 @@ -21,9 +50,11 @@ References: . already available in LOFAR2.0 SDP + 2) Porting LOFAR1 PFB code to LOFAR2.0 - Porting from [1] to [3] -a) pfs/ + +a) pfs * hdllib.cfg : copy simulation files to data/ * src/vhdl/ - pfs_coefsbuf(str).vhd : @@ -32,7 +63,8 @@ a) pfs/ - pfs_filter(rtl).vhd : use ported common_mult_add.vhd from common_mult_lib * tb/vhdl/tb_pfs.vhd : ==> simulates OK . added usage comment -b) pft2/ at + +b) pft2 * hdllib.cfg : copy simulation files to data/ * src/vhdl/ - pft_bf(rtl).vhd : @@ -59,7 +91,13 @@ c) Simulating tb/vhdl/tb_pft2.vhd * Made tb_pft2.vhd self stopping and changed generics to g_pft_mode, g_name_x, g_name_y * Added multi tb_tb_pft2.vhd to verify ptf2 with all available *sig files. ==> tb_tb_pft2.vhd simulates OK using c_diff_max = 20 like in data/tc.tcl + + -d) Creating pfb2.vhd that can replace wpfb_unit_dev.vhd +3) Create pfb2_unit.vhd that can replace wpfb_unit_dev.vhd + * pfb2.vhd = pfs + pft2 + * pfb2_unit.vhd = multiple instances of pfb2 + sst, similar as wpfb_unit_dev.vhd for wideband factor wb = 1. + +