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

Subversion Repositories astron_filter

[/] [astron_filter/] [trunk/] [fil_ppf_wide.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
-------------------------------------------------------------------------------
2
--
3
-- Copyright (C) 2012
4
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6
--
7
-- This program is free software: you can redistribute it and/or modify
8
-- it under the terms of the GNU General Public License as published by
9
-- the Free Software Foundation, either version 3 of the License, or
10
-- (at your option) any later version.
11
--
12
-- This program is distributed in the hope that it will be useful,
13
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
-- GNU General Public License for more details.
16
--
17
-- You should have received a copy of the GNU General Public License
18
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
--
20
-------------------------------------------------------------------------------
21
-- Purpose: Performing a poly phase prefilter (PPF) function on one or more
22
--          wideband data stream.
23
--
24
-- Description:
25
--   The poly phase prefilter function is applied on multiple inputs. In
26
--   array notation:
27
--
28
--               parallel                 serial             type
29
--   in_dat_arr  [wb_factor][nof_streams] [t][nof_channels]  int
30
--   out_dat_arr [wb_factor][nof_streams] [t][nof_channels]  int
31
-- 
32
--   If g_big_endian_wb_*=true then the time t to wb_factor P mapping for the
33
--   fil_ppf_wide is t[0,1,2,3] = P[3,2,1,0], else when it is false then the
34
--   mapping is t[3,2,1,0] = P[3,2,1,0]. The mapping can be selected
35
--   independently for the in_dat_arr and the out_dat_arr.
36
--
37
--   The incoming data must be divided over the inputs as shown in the
38
--   following example for nof_streams=1 and wb_factor is 4. The array
39
--   index I runs from [wb_factor*nof_streams-1:0].
40
--
41
--     array   wb     stream   time index when g_big_endian_wb_*=true)
42
--     index   index  index 
43
--       I       P      S      t
44
--       3       3      0    : 0, 4,  8, 12, 16, ...
45
--       2       2      0    : 1, 5,  9, 13, 17, ...
46
--       1       1      0    : 2, 6, 10, 14, 18, ...
47
--       0       0      0    : 3, 7, 11, 15, 19, ...
48
--                             ^
49
--                             big endian
50
--              
51
--   Every array input will be filtered by a fil_ppf_single instance. It is
52
--   also possible to offer multiple wideband input streams. Those wide
53
--   band input streams will share the filter coefficients. For a system with
54
--   nof_streams=2 and wb_factor=4 the array inputs become:
55
--
56
--     array   wb     stream   time index when g_big_endian_wb_*=true)
57
--     index   index  index  
58
--       I       P      S      t
59
--       7       3      1    : 0, 4, 8,  12, 16, ...
60
--       6       3      0    : 0, 4, 8,  12, 16, ...
61
--       5       2      1    : 1, 5, 9,  13, 17, ...
62
--       4       2      0    : 1, 5, 9,  13, 17, ...
63
--       3       1      1    : 2, 6, 10, 14, 18, ...
64
--       2       1      0    : 2, 6, 10, 14, 18, ...
65
--       1       0      1    : 3, 7, 11, 15, 19, ...
66
--       0       0      0    : 3, 7, 11, 15, 19, ...
67
--                             ^
68
--                             big endian
69
--
70
--   Note that I, P and S all increment in the same direction and t increments 
71
--   in the opposite direction of P. This is the g_big_endian_wb_in=true and
72
--   g_big_endian_wb_out=true format for the in_dat_arr and out_dat_arr.
73
--
74
--   If g_big_endian_wb_in=false and g_big_endian_wb_out=false for little endian
75
--   format, then the time t increments in the same direction as P, for both
76
--   in_dat_arr and out_dat_arr, so then I, P and S all increment in the same
77
--   direction:
78
--
79
--     array   wb     stream   time index when g_big_endian_wb_*=false
80
--     index   index  index  
81
--       I       P      S      t
82
--       7       3      1    : 3, 7, 11, 15, 19, ...
83
--       6       3      0    : 3, 7, 11, 15, 19, ...
84
--       5       2      1    : 2, 6, 10, 14, 18, ...
85
--       4       2      0    : 2, 6, 10, 14, 18, ...
86
--       3       1      1    : 1, 5, 9,  13, 17, ...
87
--       2       1      0    : 1, 5, 9,  13, 17, ...
88
--       1       0      1    : 0, 4, 8,  12, 16, ...
89
--       0       0      0    : 0, 4, 8,  12, 16, ...
90
--                             ^
91
--                             little endian
92
--
93
--   The FIR coefficients must always be provided as for little endian wb input,
94
--   independent of g_big_endian_wb_in, because internally this fil_ppf_wide
95
--   adjusts the streams_in_arr to little endian wb input when needed.
96
--
97
--   With wb_factor > 1 and nof_streams > 1 the streams in in_dat_arr and
98
--   out_dat_arr are looped first and then the wb_factor is looped. This
99
--   fits with the fact that all streams for a certain wb_index use the same
100
--   filter coeffcients and may thus ease routing. The alternative would be
101
--   to group the data per stream and loop over the wb_factor first and then
102
--   over these wide band streams. This may ease the routing of the further
103
--   data processing per wide band stream. One may instante one fil_ppf_wide
104
--   for all streams (all using the same set of coefficients) or multiple
105
--   fil_ppf_wide instances for all streams (each with their own set of
106
--   coefficients).
107
--
108
-- Remarks:
109
-- . See also description tb_fil_ppf_single.vhd for more info.
110
--              
111
library IEEE, common_pkg_lib, astron_ram_lib, astron_mm_lib;
112
use IEEE.std_logic_1164.ALL;
113
use IEEE.numeric_std.ALL;
114
use common_pkg_lib.common_pkg.ALL;
115
use astron_ram_lib.common_ram_pkg.ALL;
116
use work.fil_pkg.ALL;
117
 
118
entity fil_ppf_wide is
119
  generic (
120
    g_big_endian_wb_in  : boolean            := false;
121
    g_big_endian_wb_out : boolean            := false;
122
    g_fil_ppf           : t_fil_ppf          := c_fil_ppf;
123
    g_fil_ppf_pipeline  : t_fil_ppf_pipeline := c_fil_ppf_pipeline;
124
    g_coefs_file_prefix : string             := "../../data/coef"  -- Relative path to the mif files that contain the FIR the coefficients
125
                                                                   -- The sequence number and ".mif"-extension are added within the entity.
126
  );
127
  port (
128
    dp_clk         : in  std_logic;
129
    dp_rst         : in  std_logic;
130
    mm_clk         : in  std_logic;
131
    mm_rst         : in  std_logic;
132
    ram_coefs_mosi : in  t_mem_mosi;
133
    ram_coefs_miso : out t_mem_miso := c_mem_miso_rst;
134
    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
135
    in_val         : in  std_logic;
136
    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
137
    out_val        : out std_logic
138
  );
139
end fil_ppf_wide;
140
 
141
architecture rtl of fil_ppf_wide is
142
 
143
  constant c_nof_mif_files   : natural := g_fil_ppf.wb_factor * g_fil_ppf.nof_taps;
144
  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 ...
145
 
146
  type t_fil_ppf_arr      is array(integer range <> ) of t_fil_ppf;                       -- An array of t_fil_ppf's generics.                                                                              
147
  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
148
 
149
  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);
150
  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);
151
 
152
  ----------------------------------------------------------
153
  -- This function creates an array of t_fil_ppf generics 
154
  -- for the single channel poly phase filters that are 
155
  -- used to compose the multichannel(wideband) poly phase
156
  -- filter. The array is based on the content of the g_fil_ppf
157
  -- generic that belongs to the fil_ppf_w entity. 
158
  -- Only the nof_bands is modified. 
159
  ----------------------------------------------------------
160
  function func_create_generics_for_ppfs(input: t_fil_ppf) return t_fil_ppf_arr is
161
    variable v_nof_bands : natural := input.nof_bands/input.wb_factor;                     -- The nof_bands for the single channel poly phase filters
162
    variable v_return    : t_fil_ppf_arr(input.wb_factor-1 downto 0) := (others => input); -- Variable that holds the return values
163
  begin
164
    for P in 0 to input.wb_factor-1 loop
165
      v_return(P).nof_bands := v_nof_bands;     -- The new number of bands
166
    end loop;
167
    return v_return;
168
  end;
169
 
170
  ----------------------------------------------------------
171
  -- Function that divides the input file index array into 
172
  -- "wb_factor" new file index arrays. 
173
  ----------------------------------------------------------
174
  function func_create_file_index_array(input: t_nat_natural_arr; wb_factor: natural; nof_taps: natural) return t_nat_natural_arr2 is
175
    variable v_return : t_nat_natural_arr2(wb_factor-1 downto 0);    -- Variable that holds the return values
176
  begin
177
    for P in 0 to wb_factor-1 loop
178
      for T in 0 to nof_taps-1 loop
179
        v_return(P)(T) := input(P*nof_taps+T);
180
      end loop;
181
    end loop;
182
    return v_return;
183
  end;
184
 
185
  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);
186
  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);
187
 
188
  constant c_mem_addr_w      : natural := ceil_log2(g_fil_ppf.nof_bands * g_fil_ppf.nof_taps / g_fil_ppf.wb_factor);
189
 
190
  signal ram_coefs_mosi_arr  : t_mem_mosi_arr(g_fil_ppf.wb_factor-1 downto 0);
191
  signal ram_coefs_miso_arr  : t_mem_miso_arr(g_fil_ppf.wb_factor-1 downto 0) := (others => c_mem_miso_rst);
192
 
193
  signal streams_in_arr      : t_streams_in_arr( g_fil_ppf.wb_factor-1 downto 0);
194
  signal streams_out_arr     : t_streams_out_arr(g_fil_ppf.wb_factor-1 downto 0);
195
  signal streams_out_val_arr : std_logic_vector( g_fil_ppf.wb_factor-1 downto 0);
196
 
197
begin
198
  ---------------------------------------------------------------
199
  -- COMBINE MEMORY MAPPED INTERFACES
200
  ---------------------------------------------------------------
201
  -- Combine the internal array of mm interfaces for the coefficents 
202
  -- memory to one array that is connected to the port of the fil_ppf_w
203
  u_mem_mux_coef : entity astron_mm_lib.common_mem_mux
204
  generic map (
205
    g_nof_mosi    => g_fil_ppf.wb_factor,
206
    g_mult_addr_w => c_mem_addr_w
207
  )
208
  port map (
209
    mosi     => ram_coefs_mosi,
210
    miso     => ram_coefs_miso,
211
    mosi_arr => ram_coefs_mosi_arr,
212
    miso_arr => ram_coefs_miso_arr
213
  );
214
 
215
  p_wire_input : process(in_dat_arr)
216
    variable vP : natural;
217
  begin
218
    for P in 0 to g_fil_ppf.wb_factor-1 loop
219
      if g_big_endian_wb_in=true then
220
        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
221
      else
222
        vP := P;                        -- keep input little endian time [0,1,2,3] to P [0,1,2,3] index mapping 
223
      end if;
224
      for S in 0 to g_fil_ppf.nof_streams-1 loop
225
        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);
226
      end loop;
227
    end loop;
228
  end process;
229
 
230
  ---------------------------------------------------------------
231
  -- INSTANTIATE MULTIPLE SINGLE CHANNEL POLY PHASE FILTERS
232
  ---------------------------------------------------------------
233
  gen_fil_ppf_singles : for P in 0 to g_fil_ppf.wb_factor-1 generate
234
    u_fil_ppf_single : entity work.fil_ppf_single
235
    generic map (
236
      g_fil_ppf           => c_fil_ppf_arr(P),
237
      g_fil_ppf_pipeline  => g_fil_ppf_pipeline,
238
      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
239
      g_coefs_file_prefix => g_coefs_file_prefix
240
    )
241
    port map (
242
      dp_clk         => dp_clk,
243
      dp_rst         => dp_rst,
244
      mm_clk         => mm_clk,
245
      mm_rst         => mm_rst,
246
      ram_coefs_mosi => ram_coefs_mosi_arr(P),
247
      ram_coefs_miso => ram_coefs_miso_arr(P),
248
      in_dat         => streams_in_arr(P),
249
      in_val         => in_val,
250
      out_dat        => streams_out_arr(P),
251
      out_val        => streams_out_val_arr(P)
252
    );
253
  end generate;
254
 
255
  p_wire_output : process(streams_out_arr)
256
    variable vP : natural;
257
  begin
258
    for P in 0 to g_fil_ppf.wb_factor-1 loop
259
      if g_big_endian_wb_out=true then
260
        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
261
      else
262
        vP := P;                        -- keep internal little endian for output little endian time [0,1,2,3] to P [0,1,2,3] index mapping 
263
      end if;
264
      for S in 0 to g_fil_ppf.nof_streams-1 loop
265
        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));
266
      end loop;
267
    end loop;
268
  end process;
269
 
270
  out_val <= streams_out_val_arr(0);
271
 
272
end rtl;

powered by: WebSVN 2.1.0

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