diff --git a/libraries/dsp/filter/src/vhdl/fil_pkg.vhd b/libraries/dsp/filter/src/vhdl/fil_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..ff20ddc66866d096ae79f3d09a9e59fdb0bda71f --- /dev/null +++ b/libraries/dsp/filter/src/vhdl/fil_pkg.vhd @@ -0,0 +1,67 @@ +------------------------------------------------------------------------------- +-- Author: Harm Jan Pepping : pepping at astron.nl: 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/>. +-- +------------------------------------------------------------------------------- + +library ieee, common_lib; +use IEEE.std_logic_1164.all; +use common_lib.common_pkg.all; + +package fil_pkg is + + -- Parameters for the (wideband) poly phase filter. + type t_fil_ppf is record + wb_factor : natural; -- = 1, the wideband factor + nof_chan : natural; -- = default 0, defines the number of channels (=time-multiplexed input signals): nof channels = 2**nof_chan + nof_bands : natural; -- = 1024, the number of subbands is N (N=nof_points of the FFT) + nof_taps : natural; -- = 16, the number of FIR taps per subband + nof_streams : natural; -- = 1, the number of streams that are served by the same coefficients. + in_dat_w : natural; -- = 8, number of input bits per stream + out_dat_w : natural; -- = 16, number of output bits per stream + coef_dat_w : natural; -- = 16, data width of the FIR coefficients + end record; + + constant c_fil_ppf : t_fil_ppf := (1, 0, 1024, 16, 1, 8, 16, 16); + + -- Definitions for fil slv array (an array can not have unconstraint elements, so choose sufficiently wide 32 bit slv elements) + subtype t_fil_slv_arr is t_slv_32_arr; -- use subtype to ease interfacing to existing types and to have central definition for filter components + constant c_fil_data_w : natural := 32; -- match slv width of t_fil_slv_arr + + -- Record with the pipeline settings for the filter units. + type t_fil_ppf_pipeline is record + -- generic for the taps and coefficients memory + mem_delay : natural; -- = 1 + -- generics for the multiplier in in the filter unit + mult_input : natural; -- = 1 + mult_product : natural; -- = 1 + mult_output : natural; -- = 1 + -- generics for the adder tree in in the filter unit + adder_stage : natural; -- = 1 + -- generics for the requantizer in the filter unit + requant_remove_lsb : natural; -- = 1 + requant_remove_msb : natural; -- = 0 + end record; + + constant c_fil_ppf_pipeline : t_fil_ppf_pipeline := (1, 1, 1, 1, 1, 1, 0); + +end package fil_pkg; + +package body fil_pkg is +end fil_pkg; + diff --git a/libraries/dsp/filter/src/vhdl/fil_ppf_ctrl.vhd b/libraries/dsp/filter/src/vhdl/fil_ppf_ctrl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..7e5e83f6fa2a193e6a4dea6059c34514f893122e --- /dev/null +++ b/libraries/dsp/filter/src/vhdl/fil_ppf_ctrl.vhd @@ -0,0 +1,142 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2009 +-- 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: Controlling the data streams for the filter units +-- +-- Description: This unit prepairs the data streams for the ppf_filter +-- unit. Incoming data (in_dat) is combined with stored +-- data (taps_in_vec) to generate a new vector that is +-- offered to the filter unit: taps_out_vec. +-- +-- It also delays the in_val signal in order to generate +-- the out_val that is proper alligned with the output data +-- that is coming from the filter unit. +-- + +library IEEE, common_lib; +use IEEE.std_logic_1164.ALL; +use IEEE.numeric_std.ALL; +use common_lib.common_pkg.ALL; +use work.fil_pkg.ALL; + +entity fil_ppf_ctrl is + generic ( + g_fil_ppf : t_fil_ppf; + g_fil_ppf_pipeline : t_fil_ppf_pipeline + ); + port ( + rst : in std_logic := '0'; + clk : in std_logic; + in_dat : in std_logic_vector; + in_val : in std_logic; + taps_in_vec : in std_logic_vector; + taps_rdaddr : out std_logic_vector; + taps_wraddr : out std_logic_vector; + taps_wren : out std_logic; + taps_out_vec: out std_logic_vector; + out_val : out std_logic + ); +end fil_ppf_ctrl; + +architecture rtl of fil_ppf_ctrl is + + type t_in_dat_delay is array (g_fil_ppf_pipeline.mem_delay downto 0) of std_logic_vector(g_fil_ppf.in_dat_w*g_fil_ppf.nof_streams-1 downto 0); + + constant c_addr_w : natural := ceil_log2(g_fil_ppf.nof_bands * (2**g_fil_ppf.nof_chan)); + constant c_ctrl_latency : natural := 1; -- due to taps_out_vec register + constant c_mult_latency : natural := g_fil_ppf_pipeline.mult_input + g_fil_ppf_pipeline.mult_product + g_fil_ppf_pipeline.mult_output; + constant c_adder_latency : natural := ceil_log2(g_fil_ppf.nof_taps) * g_fil_ppf_pipeline.adder_stage; + + constant c_filter_zdly : natural := g_fil_ppf.nof_bands * (2**g_fil_ppf.nof_chan); + constant c_tot_latency : natural := g_fil_ppf_pipeline.mem_delay + c_ctrl_latency + c_mult_latency + + c_adder_latency + c_filter_zdly + g_fil_ppf_pipeline.requant_remove_lsb + + g_fil_ppf_pipeline.requant_remove_msb; + constant c_single_taps_vec_w : natural := g_fil_ppf.in_dat_w*g_fil_ppf.nof_taps; + constant c_taps_vec_w : natural := c_single_taps_vec_w*g_fil_ppf.nof_streams; + + type reg_type is record + in_dat_arr : t_in_dat_delay; -- Input register for the data + val_dly : std_logic_vector(c_tot_latency-1 downto 0); -- Delay register for the valid signal + rd_addr : std_logic_vector(c_addr_w-1 downto 0); -- The read address + wr_addr : std_logic_vector(c_addr_w-1 downto 0); -- The write address + wr_en : std_logic; -- Write enable signal for the taps memory + taps_out_vec : std_logic_vector(c_taps_vec_w-1 downto 0); -- Output register containing the next taps data + end record; + + signal r, rin : reg_type; + +begin + + comb : process(r, rst, in_val, in_dat, taps_in_vec) + variable v : reg_type; + begin + + v := r; + v.wr_en := '0'; + + -- Perform the shifting for the shiftregister for the valid signal and the input data: + v.val_dly(0) := in_val; + v.val_dly(c_tot_latency-1 downto 1) := r.val_dly(c_tot_latency-2 downto 0); + v.in_dat_arr(0) := RESIZE_SVEC(in_dat, r.in_dat_arr(0)'LENGTH); + v.in_dat_arr(g_fil_ppf_pipeline.mem_delay downto 1) := r.in_dat_arr(g_fil_ppf_pipeline.mem_delay-1 downto 0); + + if(r.val_dly(0) = '1') then -- Wait for incoming data + v.rd_addr := INCR_UVEC(r.rd_addr, 1); + end if; + + if(r.val_dly(g_fil_ppf_pipeline.mem_delay+1) = '1') then + v.wr_addr := INCR_UVEC(r.wr_addr, 1); + end if; + + if(r.val_dly(g_fil_ppf_pipeline.mem_delay) = '1') then + for I in 0 to g_fil_ppf.nof_streams-1 loop + v.taps_out_vec((I+1)*c_single_taps_vec_w-1 downto I*c_single_taps_vec_w) := taps_in_vec((I+1)*c_single_taps_vec_w - g_fil_ppf.in_dat_w -1 downto I*c_single_taps_vec_w) & r.in_dat_arr(g_fil_ppf_pipeline.mem_delay)((I+1)*g_fil_ppf.in_dat_w-1 downto I*g_fil_ppf.in_dat_w); + end loop; + --v.taps_out_vec := taps_in_vec(taps_in_vec'HIGH - g_fil_ppf.in_dat_w downto 0) & r.in_dat_arr(g_fil_ppf_pipeline.mem_delay); + v.wr_en := '1'; + end if; + + if(rst = '1') then + v.in_dat_arr := (others => (others => '0')); + v.val_dly := (others => '0'); + v.rd_addr := (others => '0'); + v.wr_addr := (others => '0'); + v.wr_en := '0'; + v.taps_out_vec := (others => '0'); + end if; + + rin <= v; + + end process comb; + + regs : process(clk) + begin + if rising_edge(clk) then + r <= rin; + end if; + end process; + + taps_rdaddr <= r.rd_addr; + taps_wraddr <= r.wr_addr; + taps_wren <= r.wr_en; + taps_out_vec <= r.taps_out_vec; + out_val <= r.val_dly(c_tot_latency-1); + +end rtl; diff --git a/libraries/dsp/filter/src/vhdl/fil_ppf_filter.vhd b/libraries/dsp/filter/src/vhdl/fil_ppf_filter.vhd new file mode 100644 index 0000000000000000000000000000000000000000..db3de4152c20e73091b04717d0f0371ff8c68ad4 --- /dev/null +++ b/libraries/dsp/filter/src/vhdl/fil_ppf_filter.vhd @@ -0,0 +1,136 @@ +------------------------------------------------------------------------------- +-- +-- 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: A FIR filter implementation. +-- +-- Description: This unit instantiates a multiplier for every tap. +-- All output of the mutipliers are added using an +-- adder-tree structure. +-- +-- Remarks: . +-- + +library IEEE, common_lib; +use IEEE.std_logic_1164.ALL; +use IEEE.numeric_std.ALL; +use common_lib.common_pkg.ALL; +use work.fil_pkg.ALL; + +entity fil_ppf_filter is + generic ( + g_fil_ppf : t_fil_ppf; + g_fil_ppf_pipeline : t_fil_ppf_pipeline + ); + port ( + clk : in std_logic; + rst : in std_logic; + taps : in std_logic_vector; + coefs : in std_logic_vector; + result : out std_logic_vector + ); +end fil_ppf_filter; + +architecture rtl of fil_ppf_filter is + + constant c_prod_w : natural := g_fil_ppf.in_dat_w + g_fil_ppf.coef_dat_w - c_sign_w; -- skip double sign bit + constant c_gain_w : natural := 0; -- no need for adder bit growth so fixed 0, because filter coefficients should have DC gain <= 1. + -- The adder tree bit growth depends on DC gain of FIR coefficients, not on ceil_log2(g_fil_ppf.nof_taps). + constant c_sum_w : natural := c_prod_w + c_gain_w; + constant c_ppf_lsb_w : natural := c_sum_w - g_fil_ppf.out_dat_w; + + signal prod_vec : std_logic_vector(g_fil_ppf.nof_taps*c_prod_w-1 downto 0); + signal adder_out : std_logic_vector(c_sum_w-1 downto 0) := (others => '0'); + signal requant_out : std_logic_vector(g_fil_ppf.out_dat_w-1 downto 0); + + signal in_taps : std_logic_vector(g_fil_ppf.in_dat_w*g_fil_ppf.nof_taps-1 downto 0); + +begin + + in_taps <= taps; -- Use this help signal to create a 'HIGH downto 0 vector again. + --------------------------------------------------------------- + -- GENERATE THE MUTIPLIERS + --------------------------------------------------------------- + -- For every tap a unique multiplier is instantiated that + -- multiplies the data tap with the corresponding filter coefficient + gen_multipliers : for I in 0 to g_fil_ppf.nof_taps-1 generate + u_multiplier : entity common_lib.common_mult(stratix4) + generic map ( + g_in_a_w => g_fil_ppf.in_dat_w, + g_in_b_w => g_fil_ppf.coef_dat_w, + g_out_p_w => c_prod_w, + g_nof_mult => 1, + g_pipeline_input => g_fil_ppf_pipeline.mult_input, + g_pipeline_product => g_fil_ppf_pipeline.mult_product, + g_pipeline_output => g_fil_ppf_pipeline.mult_output, + g_representation => "SIGNED" + ) + port map ( + rst => rst, + clk => clk, + clken => '1', + in_a => in_taps((I+1)*g_fil_ppf.in_dat_w-1 downto I*g_fil_ppf.in_dat_w), + in_b => coefs((I+1)*g_fil_ppf.coef_dat_w-1 downto I*g_fil_ppf.coef_dat_w), + out_p => prod_vec((I+1)*c_prod_w-1 downto I*c_prod_w) + ); + end generate; + + --------------------------------------------------------------- + -- ADDER TREE + --------------------------------------------------------------- + -- The adder tree summarizes the outputs of all multipliers. + u_adder_tree : entity common_lib.common_adder_tree(str) + generic map ( + g_representation => "SIGNED", + g_pipeline => g_fil_ppf_pipeline.adder_stage, + g_nof_inputs => g_fil_ppf.nof_taps, + g_dat_w => c_prod_w, + g_sum_w => c_sum_w + ) + port map ( + clk => clk, + in_dat => prod_vec, + sum => adder_out + ); + + u_requantize_addeer_output : entity common_lib.common_requantize + generic map ( + g_representation => "SIGNED", + g_lsb_w => c_ppf_lsb_w, + g_lsb_round => TRUE, + g_lsb_round_clip => FALSE, + g_msb_clip => FALSE, + g_msb_clip_symmetric => FALSE, + g_pipeline_remove_lsb => g_fil_ppf_pipeline.requant_remove_lsb, + g_pipeline_remove_msb => g_fil_ppf_pipeline.requant_remove_msb, + g_in_dat_w => c_sum_w, + g_out_dat_w => g_fil_ppf.out_dat_w + ) + port map ( + clk => clk, + clken => '1', + in_dat => adder_out, + out_dat => requant_out, + out_ovr => open + ); + + result <= RESIZE_SVEC(requant_out, result'LENGTH); + +end rtl; + diff --git a/libraries/dsp/filter/src/vhdl/fil_ppf_wide.vhd b/libraries/dsp/filter/src/vhdl/fil_ppf_wide.vhd new file mode 100644 index 0000000000000000000000000000000000000000..e547e97cd40912f6eb95b196c360e578ce335a02 --- /dev/null +++ b/libraries/dsp/filter/src/vhdl/fil_ppf_wide.vhd @@ -0,0 +1,187 @@ +------------------------------------------------------------------------------- +-- +-- 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: Performing a poly phase prefilter function on (multiple) wideband data stream. +-- +-- +-- Description: The poly phase prefilter function is applied on multiple inputs. +-- The incoming data must be divided over the inputs as shown in +-- the following example where the wideband factor is 4 (4 inputs). +-- +-- Stream input 0 : t0, t4, t8, t12, t16... +-- Stream input 1 : t1, t5, t9, t13, t17... +-- Stream input 2 : t2, t6, t10, t14, t18... +-- Stream input 3 : t3, t7, t11, t15, t19... +-- +-- Every input stream will be filtered by a single channel poly +-- phase prefilter unit. +-- It is also possible to offer multiple wideband input streams. Those +-- input streams will share the filtercoefficients. For a +-- system with wb_factor=4 and nof_streams=2 the following stream +-- inputs should be offered (s0t0 means stream 0, timestamp 0): +-- +-- Stream input 0 : s0t0, s0t4, s0t8 , s0t12, s0t16... +-- Stream input 1 : s1t0, s1t4, s1t8 , s1t12, s1t16... +-- Stream input 2 : s0t1, s0t5, s0t9 , s0t13, s0t17... +-- Stream input 3 : s1t1, s1t5, s1t9 , s1t13, s1t17... +-- Stream input 4 : s0t2, s0t6, s0t10, s0t14, s0t18... +-- Stream input 5 : s1t2, s1t6, s1t10, s1t14, s1t18... +-- Stream input 6 : s0t3, s0t7, s0t11, s0t15, s0t19... +-- Stream input 7 : s1t3, s1t7, s1t11, s1t15, s1t19... + +-- +-- Remarks: . +-- + +library IEEE, common_lib; +use IEEE.std_logic_1164.ALL; +use IEEE.numeric_std.ALL; +use common_lib.common_pkg.ALL; +use common_lib.common_mem_pkg.ALL; +use work.fil_pkg.ALL; + +entity fil_ppf_wide is + generic ( + g_fil_ppf : t_fil_ppf := c_fil_ppf; + g_fil_ppf_pipeline : t_fil_ppf_pipeline := c_fil_ppf_pipeline; + g_file_index_arr : t_nat_natural_arr := array_init(0, 128, 1); -- default use the instance index as file index 0, 1, 2, 3, 4 ... + g_coefs_file_prefix : string := "../../data/coef" -- Relative path to the mif files that contain the initial data for the coefficients memories + ); -- The sequence number and ".mif"-extension are added within the entity. + port ( + dp_clk : in std_logic; + dp_rst : in std_logic; + mm_clk : in std_logic; + mm_rst : in std_logic; + ram_coefs_mosi : in t_mem_mosi; + ram_coefs_miso : out t_mem_miso := c_mem_miso_rst; + in_dat_arr : in t_fil_slv_arr(g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 downto 0); + in_val : in std_logic; + out_dat_arr : out t_fil_slv_arr(g_fil_ppf.nof_streams*g_fil_ppf.wb_factor-1 downto 0); + out_val : out std_logic + ); +end fil_ppf_wide; + +architecture rtl of fil_ppf_wide is + + type t_fil_ppf_arr is array(integer range <> ) of t_fil_ppf; -- An array of t_fil_ppf's generics. + type t_nat_natural_arr2 is array(integer range <> ) of t_nat_natural_arr(127 downto 0); -- An array of arrays, used to point to the right .mif files for the coefficients + type t_out_arr is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.out_dat_w -1 downto 0); + type t_in_arr is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.in_dat_w -1 downto 0); + + ---------------------------------------------------------- + -- This function creates an array of t_fil_ppf generics + -- for the single channel poly phase filters that are + -- used to compose the multichannel(wideband) poly phase + -- filter. The array is based on the content of the g_fil_ppf + -- generic that belongs to the fil_ppf_w entity. + -- Only the nof_bands is modified. + ---------------------------------------------------------- + function func_create_generics_for_ppfs(input: t_fil_ppf) return t_fil_ppf_arr is + variable v_nof_bands : natural := input.nof_bands/input.wb_factor; -- The nof_bands for the single channel poly phase filters + variable v_return : t_fil_ppf_arr(input.wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values + begin + for I in 0 to input.wb_factor-1 loop + v_return(I).nof_bands := v_nof_bands; -- The new number of bands + end loop; + return v_return; + end; + + ---------------------------------------------------------- + -- Function that divids the input file index array into + -- "wb_factor" new file index arrays. + ---------------------------------------------------------- + function func_create_file_index_array(input: t_nat_natural_arr; wb_factor: natural; nof_taps: natural) return t_nat_natural_arr2 is + variable v_return : t_nat_natural_arr2(wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values + begin + for I in 0 to wb_factor-1 loop + for J in 0 to nof_taps-1 loop + v_return(I)(J) := input(I*nof_taps+J); + end loop; + end loop; + return v_return; + end; + + constant c_fil_ppf_arr : t_fil_ppf_arr(g_fil_ppf.wb_factor-1 downto 0) := func_create_generics_for_ppfs(g_fil_ppf); + constant c_file_index_arr2 : t_nat_natural_arr2(g_fil_ppf.wb_factor-1 downto 0) := func_create_file_index_array(g_file_index_arr, g_fil_ppf.wb_factor, g_fil_ppf.nof_taps); + + constant c_mem_addr_w : natural := ceil_log2(g_fil_ppf.nof_bands * g_fil_ppf.nof_taps / g_fil_ppf.wb_factor); + + signal ram_coefs_mosi_arr : t_mem_mosi_arr(g_fil_ppf.wb_factor-1 downto 0); + signal ram_coefs_miso_arr : t_mem_miso_arr(g_fil_ppf.wb_factor-1 downto 0) := (others => c_mem_miso_rst); + signal out_val_i : std_logic_vector(g_fil_ppf.wb_factor-1 downto 0); + signal out_arr_i : t_out_arr(g_fil_ppf.wb_factor-1 downto 0); + signal in_dat_vect_arr : t_in_arr(g_fil_ppf.wb_factor-1 downto 0); + +begin + --------------------------------------------------------------- + -- COMBINE MEMORY MAPPED INTERFACES + --------------------------------------------------------------- + -- Combine the internal array of mm interfaces for the coefficents + -- memory to one array that is connected to the port of the fil_ppf_w + u_mem_mux_coef : entity common_lib.common_mem_mux + generic map ( + g_nof_mosi => g_fil_ppf.wb_factor, + g_mult_addr_w => c_mem_addr_w + ) + port map ( + mosi => ram_coefs_mosi, + miso => ram_coefs_miso, + mosi_arr => ram_coefs_mosi_arr, + miso_arr => ram_coefs_miso_arr + ); + + gen_in_vect_wb : for I in 0 to g_fil_ppf.wb_factor-1 generate + gen_in_vect_streams : for J in 0 to g_fil_ppf.nof_streams-1 generate + --in_dat_vect_arr(I)((J+1)*g_fil_ppf.in_dat_w-1 downto J*g_fil_ppf.in_dat_w) <= in_dat_arr(J*g_fil_ppf.wb_factor+I)(g_fil_ppf.in_dat_w-1 downto 0); + in_dat_vect_arr(I)((J+1)*g_fil_ppf.in_dat_w-1 downto J*g_fil_ppf.in_dat_w) <= in_dat_arr(I*g_fil_ppf.nof_streams+J)(g_fil_ppf.in_dat_w-1 downto 0); + end generate; + end generate; + + --------------------------------------------------------------- + -- INSTANTIATE MULTIPLE SINGLE CHANNEL POLY PHASE FILTERS + --------------------------------------------------------------- + gen_ppf_singles : for I in 0 to g_fil_ppf.wb_factor-1 generate + u_single_filter : entity work.fil_ppf_single + generic map ( + g_fil_ppf => c_fil_ppf_arr(I), + g_fil_ppf_pipeline => g_fil_ppf_pipeline, + g_file_index_arr => c_file_index_arr2(I), + 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_coefs_mosi_arr(I), + ram_coefs_miso => ram_coefs_miso_arr(I), + in_dat => in_dat_vect_arr(I), + in_val => in_val, + out_dat => out_arr_i(I), + out_val => out_val_i(I) + ); + gen_in_vect_streams : for J in 0 to g_fil_ppf.nof_streams-1 generate + out_dat_arr(I*g_fil_ppf.nof_streams+J) <= RESIZE_SVEC(out_arr_i(I)((J+1)*g_fil_ppf.out_dat_w-1 downto J*g_fil_ppf.out_dat_w), out_dat_arr(I)'LENGTH); + end generate; + end generate; + + out_val <= out_val_i(0); + +end rtl;