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

Subversion Repositories astron_filter

[/] [astron_filter/] [trunk/] [fil_ppf_single.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 multiple datastreams.
22
--
23
-- Description:
24
--   The poly phase prefilter (PPF) function is based on a taps memory, a
25
--   coefficients memory, a filter and a control unit.
26
--
27
--   The control unit writes the incoming data to the taps memory, along with
28
--   the historical tap data. It also drives the read addresses for both the
29
--   taps- and the coefficients memory. The output of the taps memory and the
30
--   coefficients memory are connected to the input of the filter unit that
31
--   peforms the actual filter function(multiply and accumulate). The prefilter
32
--   support multiple streams that share the same filter coefficients. The
33
--   filter coefficients can be written and read via the MM interface. 
34
--
35
--   The PPF introduces a data valid latency of 1 tap, so nof_bands samples.
36
--   The nof_bands = nof_points of the FFT that gets the PPF output.
37
--
38
--   The following example shows the working for the poly phase prefilter
39
--   where nof_bands=4 and nof_taps=2. The total number of coefficients is 8.
40
--   For the given input stream all the multiplications and additions are
41
--   given that are required to generate the given output stream. Note that
42
--   every input sample is used nof_taps=2 times.
43
--                  
44
--   Time:                t0 t1 ....
45
--   Incoming datastream: a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2 c3 ....
46
--   Outgoing datastream:             A0 A1 A2 A3 B0 B1 B2 B3 C0 C1 C2 C3 ....
47
--
48
--              A0 = coef0*a0 + coef1*b0
49
--              A1 = coef2*a1 + coef3*b1
50
--              A2 = coef4*a2 + coef5*b2
51
--              A3 = coef6*a3 + coef7*b3
52
--
53
--              B0 = coef0*b0 + coef1*c0
54
--              B1 = coef2*b1 + coef3*c1
55
--              B2 = coef4*b2 + coef5*c2
56
--              B3 = coef6*b3 + coef7*c3
57
--
58
--              C0 = coef0*c0 + coef1*d0
59
--              C1 = coef2*c1 + coef3*d1
60
--              C2 = coef4*c2 + coef5*d2
61
--              C3 = coef6*c3 + coef7*d3
62
--
63
-- Remarks:
64
-- .  See also description tb_fil_ppf_single.vhd for more info.
65
--
66
library IEEE, common_pkg_lib, astron_ram_lib, astron_mm_lib;
67
use IEEE.std_logic_1164.ALL;
68
use IEEE.numeric_std.ALL;
69
use common_pkg_lib.common_pkg.ALL;
70
use astron_ram_lib.common_ram_pkg.ALL;
71
use work.fil_pkg.ALL;
72
 
73
entity fil_ppf_single is
74
  generic (
75
    g_fil_ppf           : t_fil_ppf          := c_fil_ppf;
76
    g_fil_ppf_pipeline  : t_fil_ppf_pipeline := c_fil_ppf_pipeline;
77
    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 ...
78
    g_coefs_file_prefix : string             := "hex/coef"       -- Relative path to the mif files that contain the initial data for the coefficients memories 
79
  );                                                                   -- The sequence number and ".mif"-extension are added within the entity.
80
  port (
81
    dp_clk         : in  std_logic;
82
    dp_rst         : in  std_logic;
83
    mm_clk         : in  std_logic;
84
    mm_rst         : in  std_logic;
85
    ram_coefs_mosi : in  t_mem_mosi;
86
    ram_coefs_miso : out t_mem_miso := c_mem_miso_rst;
87
    in_dat         : in  std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.in_dat_w-1 downto 0);
88
    in_val         : in  std_logic;
89
    out_dat        : out std_logic_vector(g_fil_ppf.nof_streams*g_fil_ppf.out_dat_w-1 downto 0);
90
    out_val        : out std_logic
91
  );
92
end fil_ppf_single;
93
 
94
architecture rtl of fil_ppf_single is
95
 
96
  constant c_coefs_postfix   : string := ".mif";
97
  constant c_taps_mem_addr_w : natural := ceil_log2(g_fil_ppf.nof_bands * (2**g_fil_ppf.nof_chan));
98
  constant c_coef_mem_addr_w : natural := ceil_log2(g_fil_ppf.nof_bands);
99
  constant c_taps_mem_delay  : natural := g_fil_ppf_pipeline.mem_delay;
100
  constant c_coef_mem_delay  : natural := g_fil_ppf_pipeline.mem_delay;
101
  constant c_taps_mem_data_w : natural := g_fil_ppf.in_dat_w*g_fil_ppf.nof_taps;
102
  constant c_coef_mem_data_w : natural := g_fil_ppf.coef_dat_w;
103
 
104
  constant c_taps_mem : t_c_mem := (latency   => c_taps_mem_delay,
105
                                    adr_w     => c_taps_mem_addr_w,
106
                                    dat_w     => c_taps_mem_data_w,
107
                                    nof_dat   => g_fil_ppf.nof_bands * (2**g_fil_ppf.nof_chan),
108
                                    init_sl   => '0');  -- use '0' instead of 'X' to avoid RTL RAM simulation warnings due to read before write
109
 
110
  constant c_coef_mem : t_c_mem := (latency   => c_coef_mem_delay,
111
                                    adr_w     => c_coef_mem_addr_w,
112
                                    dat_w     => c_coef_mem_data_w,
113
                                    nof_dat   => g_fil_ppf.nof_bands,
114
                                    init_sl   => '0');  -- use '0' instead of 'X' to avoid RTL RAM simulation warnings due to read before write
115
 
116
  signal ram_coefs_mosi_arr : t_mem_mosi_arr(g_fil_ppf.nof_taps-1 downto 0);
117
  signal ram_coefs_miso_arr : t_mem_miso_arr(g_fil_ppf.nof_taps-1 downto 0) := (others => c_mem_miso_rst);
118
  signal taps_wren          : std_logic;
119
  signal taps_rdaddr        : std_logic_vector(c_taps_mem_addr_w-1 downto 0);
120
  signal taps_wraddr        : std_logic_vector(c_taps_mem_addr_w-1 downto 0);
121
  signal taps_mem_out_vec   : std_logic_vector(c_taps_mem_data_w*g_fil_ppf.nof_streams-1 downto 0);
122
  signal taps_mem_in_vec    : std_logic_vector(c_taps_mem_data_w*g_fil_ppf.nof_streams-1 downto 0);
123
  signal coef_rdaddr        : std_logic_vector(c_coef_mem_addr_w-1 downto 0);
124
  signal coef_vec           : std_logic_vector(c_coef_mem_data_w*g_fil_ppf.nof_taps-1 downto 0);
125
 
126
begin
127
 
128
  ---------------------------------------------------------------
129
  -- MEMORY FOR THE HISTORICAL TAP DATA
130
  ---------------------------------------------------------------
131
  gen_taps_mems : for I in 0 to g_fil_ppf.nof_streams-1 generate
132
    u_taps_mem : entity astron_ram_lib.common_ram_r_w
133
    generic map (
134
      g_ram       => c_taps_mem,
135
      g_init_file => "UNUSED"     -- assume block RAM gets initialized to '0' by default in simulation
136
    )
137
    port map (
138
      rst       => dp_rst,
139
      clk       => dp_clk,
140
      wr_en     => taps_wren,
141
      wr_adr    => taps_wraddr,
142
      wr_dat    => taps_mem_in_vec((I+1)*c_taps_mem_data_w-1 downto I*c_taps_mem_data_w),
143
      rd_en     => '1',
144
      rd_adr    => taps_rdaddr,
145
      rd_dat    => taps_mem_out_vec((I+1)*c_taps_mem_data_w-1 downto I*c_taps_mem_data_w),
146
      rd_val    => open
147
    );
148
  end generate;
149
  ---------------------------------------------------------------
150
  -- COMBINE MEMORY MAPPED INTERFACES
151
  ---------------------------------------------------------------
152
  -- Combine the internal array of mm interfaces for the coefficents 
153
  -- memory to one array that is connected to the port of the fil_ppf
154
  u_mem_mux_coef : entity astron_mm_lib.common_mem_mux
155
  generic map (
156
    g_nof_mosi    => g_fil_ppf.nof_taps,
157
    g_mult_addr_w => c_coef_mem_addr_w
158
  )
159
  port map (
160
    mosi     => ram_coefs_mosi,
161
    miso     => ram_coefs_miso,
162
    mosi_arr => ram_coefs_mosi_arr,
163
    miso_arr => ram_coefs_miso_arr
164
  );
165
 
166
  ---------------------------------------------------------------
167
  -- GENERATE THE COEFFICIENT MEMORIES
168
  ---------------------------------------------------------------
169
  -- For every tap a unique memory is instantiated that holds
170
  -- the corresponding coefficients for all the bands. 
171
  gen_coef_mems : for I in 0 to g_fil_ppf.nof_taps-1 generate
172
    u_coef_mem : entity astron_ram_lib.common_ram_crw_crw
173
    generic map (
174
      g_ram        => c_coef_mem,
175
      -- Sequence number and ".hex" extensie are added to the relative path in case a ram file is provided.                                                          
176
      g_init_file  => sel_a_b(g_coefs_file_prefix = "UNUSED", g_coefs_file_prefix, g_coefs_file_prefix & "_" & NATURAL'IMAGE(g_file_index_arr(I)) & c_coefs_postfix)
177
    )
178
    port map (
179
      -- MM side
180
      rst_a     => mm_rst,
181
      clk_a     => mm_clk,
182
      wr_en_a   => ram_coefs_mosi_arr(I).wr,
183
      wr_dat_a  => ram_coefs_mosi_arr(I).wrdata(g_fil_ppf.coef_dat_w-1 downto 0),
184
      adr_a     => ram_coefs_mosi_arr(I).address(c_coef_mem.adr_w-1 downto 0),
185
      rd_en_a   => ram_coefs_mosi_arr(I).rd,
186
      rd_dat_a  => ram_coefs_miso_arr(I).rddata(g_fil_ppf.coef_dat_w-1 downto 0),
187
      rd_val_a  => ram_coefs_miso_arr(I).rdval,
188
      -- Datapath side
189
      rst_b     => dp_rst,
190
      clk_b     => dp_clk,
191
      wr_en_b   => '0',
192
      wr_dat_b  => (others =>'0'),
193
      adr_b     => coef_rdaddr,
194
      rd_en_b   => '1',
195
      rd_dat_b  => coef_vec((I+1)*c_coef_mem_data_w-1 downto I*c_coef_mem_data_w),
196
      rd_val_b  => open
197
    );
198
  end generate;
199
 
200
  -- Address the coefficients, taking into account the nof_chan. The coefficients will only be
201
  -- updated if all 2**nof_chan time-multiples signals are processed. 
202
  coef_rdaddr <= taps_rdaddr(c_taps_mem_addr_w-1 downto (c_taps_mem_addr_w - c_coef_mem_addr_w));
203
 
204
  ---------------------------------------------------------------
205
  -- FILTER CONTROL UNIT
206
  ---------------------------------------------------------------
207
  -- The control unit receives the input data and writes it to 
208
  -- the tap memory, along with the historical tap data. 
209
  -- It also controls the reading of the coefficients memory.
210
  u_fil_ctrl : entity work.fil_ppf_ctrl
211
  generic map (
212
    g_fil_ppf_pipeline => g_fil_ppf_pipeline,
213
    g_fil_ppf          => g_fil_ppf
214
  )
215
  port map (
216
    clk          => dp_clk,
217
    rst          => dp_rst,
218
    in_dat       => in_dat,
219
    in_val       => in_val,
220
    taps_rdaddr  => taps_rdaddr,
221
    taps_wraddr  => taps_wraddr,
222
    taps_wren    => taps_wren,
223
    taps_in_vec  => taps_mem_out_vec,
224
    taps_out_vec => taps_mem_in_vec,
225
    out_val      => out_val
226
  );
227
 
228
  ---------------------------------------------------------------
229
  -- FILTER UNIT
230
  ---------------------------------------------------------------
231
  -- The actual filter unit that performs the filter operations: 
232
  -- multiplications and additions.
233
  gen_filter_units : for I in 0 to g_fil_ppf.nof_streams-1 generate
234
    u_filter : entity work.fil_ppf_filter
235
    generic map (
236
      g_fil_ppf_pipeline => g_fil_ppf_pipeline,
237
      g_fil_ppf          => g_fil_ppf
238
    )
239
    port map (
240
      clk       => dp_clk,
241
      rst       => dp_rst,
242
      taps      => taps_mem_out_vec((I+1)*c_taps_mem_data_w-1 downto I*c_taps_mem_data_w),
243
      coefs     => coef_vec,
244
      result    => out_dat((I+1)*g_fil_ppf.out_dat_w-1 downto I*g_fil_ppf.out_dat_w)
245
    );
246
  end generate;
247
 
248
end rtl;

powered by: WebSVN 2.1.0

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