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

Subversion Repositories astron_filter

[/] [astron_filter/] [trunk/] [fil_ppf_wide.vhd] - Rev 2

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--
-- 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 (PPF) function on one or more
--          wideband data stream.
--
-- Description:
--   The poly phase prefilter function is applied on multiple inputs. In
--   array notation:
--
--               parallel                 serial             type
--   in_dat_arr  [wb_factor][nof_streams] [t][nof_channels]  int
--   out_dat_arr [wb_factor][nof_streams] [t][nof_channels]  int
-- 
--   If g_big_endian_wb_*=true then the time t to wb_factor P mapping for the
--   fil_ppf_wide is t[0,1,2,3] = P[3,2,1,0], else when it is false then the
--   mapping is t[3,2,1,0] = P[3,2,1,0]. The mapping can be selected
--   independently for the in_dat_arr and the out_dat_arr.
--
--   The incoming data must be divided over the inputs as shown in the
--   following example for nof_streams=1 and wb_factor is 4. The array
--   index I runs from [wb_factor*nof_streams-1:0].
--
--     array   wb     stream   time index when g_big_endian_wb_*=true)
--     index   index  index 
--       I       P      S      t
--       3       3      0    : 0, 4,  8, 12, 16, ...
--       2       2      0    : 1, 5,  9, 13, 17, ...
--       1       1      0    : 2, 6, 10, 14, 18, ...
--       0       0      0    : 3, 7, 11, 15, 19, ...
--                             ^
--                             big endian
--              
--   Every array input will be filtered by a fil_ppf_single instance. It is
--   also possible to offer multiple wideband input streams. Those wide
--   band input streams will share the filter coefficients. For a system with
--   nof_streams=2 and wb_factor=4 the array inputs become:
--
--     array   wb     stream   time index when g_big_endian_wb_*=true)
--     index   index  index  
--       I       P      S      t
--       7       3      1    : 0, 4, 8,  12, 16, ...
--       6       3      0    : 0, 4, 8,  12, 16, ...
--       5       2      1    : 1, 5, 9,  13, 17, ...
--       4       2      0    : 1, 5, 9,  13, 17, ...
--       3       1      1    : 2, 6, 10, 14, 18, ...
--       2       1      0    : 2, 6, 10, 14, 18, ...
--       1       0      1    : 3, 7, 11, 15, 19, ...
--       0       0      0    : 3, 7, 11, 15, 19, ...
--                             ^
--                             big endian
--
--   Note that I, P and S all increment in the same direction and t increments 
--   in the opposite direction of P. This is the g_big_endian_wb_in=true and
--   g_big_endian_wb_out=true format for the in_dat_arr and out_dat_arr.
--
--   If g_big_endian_wb_in=false and g_big_endian_wb_out=false for little endian
--   format, then the time t increments in the same direction as P, for both
--   in_dat_arr and out_dat_arr, so then I, P and S all increment in the same
--   direction:
--
--     array   wb     stream   time index when g_big_endian_wb_*=false
--     index   index  index  
--       I       P      S      t
--       7       3      1    : 3, 7, 11, 15, 19, ...
--       6       3      0    : 3, 7, 11, 15, 19, ...
--       5       2      1    : 2, 6, 10, 14, 18, ...
--       4       2      0    : 2, 6, 10, 14, 18, ...
--       3       1      1    : 1, 5, 9,  13, 17, ...
--       2       1      0    : 1, 5, 9,  13, 17, ...
--       1       0      1    : 0, 4, 8,  12, 16, ...
--       0       0      0    : 0, 4, 8,  12, 16, ...
--                             ^
--                             little endian
--
--   The FIR coefficients must always be provided as for little endian wb input,
--   independent of g_big_endian_wb_in, because internally this fil_ppf_wide
--   adjusts the streams_in_arr to little endian wb input when needed.
--
--   With wb_factor > 1 and nof_streams > 1 the streams in in_dat_arr and
--   out_dat_arr are looped first and then the wb_factor is looped. This
--   fits with the fact that all streams for a certain wb_index use the same
--   filter coeffcients and may thus ease routing. The alternative would be
--   to group the data per stream and loop over the wb_factor first and then
--   over these wide band streams. This may ease the routing of the further
--   data processing per wide band stream. One may instante one fil_ppf_wide
--   for all streams (all using the same set of coefficients) or multiple
--   fil_ppf_wide instances for all streams (each with their own set of
--   coefficients).
--
-- Remarks:
-- . See also description tb_fil_ppf_single.vhd for more info.
--              
library IEEE, common_pkg_lib, astron_ram_lib, astron_mm_lib;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
use common_pkg_lib.common_pkg.ALL; 
use astron_ram_lib.common_ram_pkg.ALL;  
use work.fil_pkg.ALL;
 
entity fil_ppf_wide is
  generic (
    g_big_endian_wb_in  : boolean            := false;
    g_big_endian_wb_out : boolean            := false;
    g_fil_ppf           : t_fil_ppf          := c_fil_ppf;    
    g_fil_ppf_pipeline  : t_fil_ppf_pipeline := c_fil_ppf_pipeline; 
    g_coefs_file_prefix : string             := "../../data/coef"  -- Relative path to the mif files that contain the FIR the coefficients
                                                                   -- 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.wb_factor*g_fil_ppf.nof_streams-1 downto 0);  -- = t_slv_32_arr fits g_fil_ppf.in_dat_w <= 32
    in_val         : in  std_logic;  
    out_dat_arr    : out t_fil_slv_arr(g_fil_ppf.wb_factor*g_fil_ppf.nof_streams-1 downto 0);  -- = t_slv_32_arr fits g_fil_ppf.out_dat_w <= 32
    out_val        : out std_logic
  ); 
end fil_ppf_wide;
 
architecture rtl of fil_ppf_wide is   
 
  constant c_nof_mif_files   : natural := g_fil_ppf.wb_factor * g_fil_ppf.nof_taps;
  constant c_file_index_arr  : t_nat_natural_arr := array_init(0, c_nof_mif_files, 1);  -- use the instance index as file index 0, 1, 2, 3, 4 ...
 
  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(g_fil_ppf.nof_taps-1 downto 0); -- An array of arrays, used to point to the right .mif files for the coefficients
 
  type t_streams_in_arr   is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.in_dat_w  -1 downto 0);
  type t_streams_out_arr  is array(integer range <> ) of std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.out_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 P in 0 to input.wb_factor-1 loop
      v_return(P).nof_bands := v_nof_bands;     -- The new number of bands
    end loop;                               
    return v_return; 
  end;
 
  ----------------------------------------------------------
  -- Function that divides 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);    -- Variable that holds the return values
  begin
    for P in 0 to wb_factor-1 loop
      for T in 0 to nof_taps-1 loop
        v_return(P)(T) := input(P*nof_taps+T);
      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(c_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 streams_in_arr      : t_streams_in_arr( g_fil_ppf.wb_factor-1 downto 0);
  signal streams_out_arr     : t_streams_out_arr(g_fil_ppf.wb_factor-1 downto 0);
  signal streams_out_val_arr : std_logic_vector( 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 astron_mm_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
  );
 
  p_wire_input : process(in_dat_arr)
    variable vP : natural;
  begin
    for P in 0 to g_fil_ppf.wb_factor-1 loop
      if g_big_endian_wb_in=true then
        vP := g_fil_ppf.wb_factor-1-P;  -- convert input big endian time [0,1,2,3] to P [3,2,1,0] index mapping to internal little endian
      else
        vP := P;                        -- keep input little endian time [0,1,2,3] to P [0,1,2,3] index mapping 
      end if;
      for S in 0 to g_fil_ppf.nof_streams-1 loop
        streams_in_arr(vP)((S+1)*g_fil_ppf.in_dat_w-1 downto S*g_fil_ppf.in_dat_w) <= in_dat_arr(P*g_fil_ppf.nof_streams+S)(g_fil_ppf.in_dat_w-1 downto 0);
      end loop;
    end loop;
  end process;
 
  ---------------------------------------------------------------
  -- INSTANTIATE MULTIPLE SINGLE CHANNEL POLY PHASE FILTERS
  ---------------------------------------------------------------
  gen_fil_ppf_singles : for P in 0 to g_fil_ppf.wb_factor-1 generate
    u_fil_ppf_single : entity work.fil_ppf_single 
    generic map (
      g_fil_ppf           => c_fil_ppf_arr(P),
      g_fil_ppf_pipeline  => g_fil_ppf_pipeline,
      g_file_index_arr    => c_file_index_arr2(P),  -- use (g_fil_ppf.wb_factor-1 - P) to try impact of reversed WB FIR coefficients
      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(P), 
      ram_coefs_miso => ram_coefs_miso_arr(P), 
      in_dat         => streams_in_arr(P),
      in_val         => in_val,
      out_dat        => streams_out_arr(P),
      out_val        => streams_out_val_arr(P)
    ); 
  end generate;  
 
  p_wire_output : process(streams_out_arr)
    variable vP : natural;
  begin
    for P in 0 to g_fil_ppf.wb_factor-1 loop
      if g_big_endian_wb_out=true then
        vP := g_fil_ppf.wb_factor-1-P;  -- convert internal little endian to output big endian time [0,1,2,3] to P [3,2,1,0] index mapping
      else
        vP := P;                        -- keep internal little endian for output little endian time [0,1,2,3] to P [0,1,2,3] index mapping 
      end if;
      for S in 0 to g_fil_ppf.nof_streams-1 loop
        out_dat_arr(vP*g_fil_ppf.nof_streams+S) <= RESIZE_SVEC_32(streams_out_arr(P)((S+1)*g_fil_ppf.out_dat_w-1 downto S*g_fil_ppf.out_dat_w));
      end loop;
    end loop;
  end process;
 
  out_val <= streams_out_val_arr(0);                             
 
end rtl;
 

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.