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

Subversion Repositories astron_wb_fft

[/] [astron_wb_fft/] [trunk/] [fft_r2_wide.vhd] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
--------------------------------------------------------------------------------
2
-- Author: Harm Jan Pepping : HJP at astron.nl: April 2012
3
--------------------------------------------------------------------------------
4
--
5
-- Copyright (C) 2012
6
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
7
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
8
--
9
-- This program is free software: you can redistribute it and/or modify
10
-- it under the terms of the GNU General Public License as published by
11
-- the Free Software Foundation, either version 3 of the License, or
12
-- (at your option) any later version.
13
--
14
-- This program is distributed in the hope that it will be useful,
15
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
16
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
-- GNU General Public License for more details.
18
--
19
-- You should have received a copy of the GNU General Public License
20
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
--
22
--------------------------------------------------------------------------------
23
-- Purpose: The fft_r2_wide unit performs a complex FFT that is partly pipelined 
24
--          and partly parallel. 
25
--
26
-- Description:
27
--  The fft_r2_wide supports:
28
--
29
--  * Complex input
30
--    For complex input use_separate = false.
31
--
32
--    When use_reorder=true then the output bins of the FFT are re-ordered to 
33
--    undo the bit-reversed (or bit-flipped) default radix 2 FFT output order.
34
--    The fft_r2_wide then outputs first 0 Hz and the positive frequencies
35
--    and then the negative frequencies. The use_reorder is performed at both
36
--    the pipelined stage and the parallel stage.
37
--
38
--    When use_fft_shift=true then the fft_r2_wide then outputs the frequency
39
--    bins in incrementing order, so first the negative frequencies, then 0 Hz
40
--    and then the positive frequencies.
41
--    When use_fft_shift = true then also use_reorder must be true.
42
--
43
--  * Two real inputs:
44
--    When use_separate=true then the fft_r2_wide can be used to process two
45
--    real streams. The first real stream (A) presented on the real input, the
46
--    second real stream (B) presented on the imaginary input. The separation
47
--    unit outputs the spectrum of A and B in an alternating way.
48
--    When use_separate = true then also use_reorder must be true.
49
--    When use_separate = true then the use_fft_shift must be false, because
50
--    fft_shift() only applies to spectra for complex input.
51
--
52
-- Remarks:
53
-- . This fft_r2_wide also support wb_factor = 1 (= only a fft_r2_pipe
54
--   instance) or wb_factor = g_fft.nof_points (= only a fft_r2_par instance).
55
--   Care must be taken to properly account for guard_w and out_gain_w,
56
--   therefore it is best to simply use a structural approach that generates
57
--   seperate instances for each case:
58
--   . wb_factor = 1                                  --> pipe
59
--   . wb_factor > 1 AND wb_factor < g_fft.nof_points --> wide
60
--   . wb_factor = g_fft.nof_points                   --> par
61
-- . This fft_r2_wide uses the use_reorder in the pipeline FFT, in the parallel
62
--   FFT and also has reorder memory in the fft_sepa_wide instance. The reorder
63
--   memories in the FFTs can maybe be saved by using only the reorder memory
64
--   in the fft_sepa_wide instance. This would require changing the indexing in
65
--   fft_sepa_wide instance.
66
-- . The reorder memory in the pipeline FFT, parallel FFT and in the
67
--   fft_sepa_wide could make reuse of a reorder component from the reorder
68
--   library instead of using a dedicated local solution.
69
 
70
library ieee, common_pkg_lib, common_components_lib, common_requantize_lib, rTwoSDF_lib;
71
use IEEE.std_logic_1164.all;
72
use common_pkg_lib.common_pkg.all;
73
use rTwoSDF_lib.rTwoSDFPkg.all;
74
use work.fft_pkg.all;
75
 
76
entity fft_r2_wide is
77
  generic (
78
    g_fft          : t_fft := c_fft;                   -- generics for the FFT
79
    g_pft_pipeline : t_fft_pipeline := c_fft_pipeline; -- For the pipelined part, from rTwoSDF_lib.rTwoSDFPkg
80
    g_fft_pipeline : t_fft_pipeline := c_fft_pipeline  -- For the parallel part, from rTwoSDF_lib.rTwoSDFPkg
81
  );
82
  port (
83
    clk        : in  std_logic;
84
    rst        : in  std_logic := '0';
85
    in_re_arr  : in  t_fft_slv_arr(g_fft.wb_factor-1 downto 0); -- = time samples t3, t2, t1, t0
86
    in_im_arr  : in  t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
87
    in_val     : in  std_logic := '1';
88
    out_re_arr : out t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
89
    out_im_arr : out t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
90
    out_val    : out std_logic
91
  );
92
end entity fft_r2_wide;
93
 
94
architecture rtl of fft_r2_wide is
95
 
96
  type t_fft_arr is array(integer range <> ) of t_fft;  -- An array of t_fft's generics. 
97
 
98
  ----------------------------------------------------------
99
  -- This function creates an array of t_fft generics 
100
  -- for the pipelined fft's of the first stage.The array is 
101
  -- based on the g_fft generic that belongs to the 
102
  -- fft_r2_wide entity. 
103
  -- Most imortant in the settings are twiddle_offset and 
104
  -- the nof_points.
105
  ----------------------------------------------------------
106
  function func_create_generic_for_pipe_fft(input : t_fft) return t_fft_arr is
107
    variable v_nof_points : natural := input.nof_points/input.wb_factor;                 -- The nof_points for the pipelined fft stages
108
    variable v_return     : t_fft_arr(input.wb_factor-1 downto 0) := (others => input);  -- Variable that holds the return values
109
  begin
110
    for I in 0 to input.wb_factor-1 loop
111
      v_return(I).use_reorder    := input.use_reorder; -- Pass on use_reorder
112
      v_return(I).use_fft_shift  := false;             -- FFT shift function is forced to false
113
      v_return(I).use_separate   := false;             -- Separate function is forced to false. 
114
      v_return(I).twiddle_offset := I;                 -- Twiddle offset is set to the order number of the pipelined fft. 
115
      v_return(I).nof_points     := v_nof_points;      -- Set the nof points 
116
      v_return(I).in_dat_w       := input.stage_dat_w; -- Set the input width  
117
      v_return(I).out_dat_w      := input.stage_dat_w; -- Set the output width. 
118
      v_return(I).out_gain_w     := 0;                 -- Output gain is forced to 0
119
      v_return(I).guard_w        := 0;                 -- Set the guard_w to 0 to enable scaling at every stage. 
120
      v_return(I).guard_enable   := false;             -- No input guard. 
121
    end loop;
122
    return v_return;
123
  end;
124
 
125
  ----------------------------------------------------------
126
  -- This function creates t_fft generic for the 
127
  -- parallel fft stage, based on the g_fft generic that 
128
  -- belongs to the fft_r2_wide entity. 
129
  ----------------------------------------------------------
130
  function func_create_generic_for_par_fft(input : t_fft) return t_fft is
131
    variable v_return         : t_fft   := input;  -- Variable that holds the return value
132
  begin
133
      v_return.use_reorder    := input.use_reorder;    -- Pass on use_reorder
134
      v_return.use_fft_shift  := input.use_fft_shift;  -- Pass on use_fft_shift
135
      v_return.use_separate   := false;                -- Separate function is forced to false, because it is handled outside the parallel fft
136
      v_return.twiddle_offset := 0;                    -- Twiddle offset is forced to 0, which is also the input.twiddle_offset default
137
      v_return.nof_points     := input.wb_factor;      -- Set the number of points to wb_factor
138
      v_return.in_dat_w       := input.stage_dat_w;    -- Specify the input width
139
      v_return.out_dat_w      := input.stage_dat_w;    -- Output width 
140
      v_return.out_gain_w     := 0;                    -- Output gain is forced to 0, because it is handled outside the parallel fft
141
      v_return.guard_w        := input.guard_w;        -- Set the guard_w here to skip the scaling on the last stages
142
      v_return.guard_enable   := false;                -- No input guard. 
143
    return v_return;
144
  end;
145
 
146
  constant c_pipeline_remove_lsb : natural := 0;
147
 
148
  constant c_fft_r2_pipe_arr  : t_fft_arr(g_fft.wb_factor-1 downto 0) := func_create_generic_for_pipe_fft(g_fft);
149
  constant c_fft_r2_par       : t_fft                                 := func_create_generic_for_par_fft(g_fft);
150
 
151
  constant c_in_scale_w       : natural := g_fft.stage_dat_w - g_fft.in_dat_w - sel_a_b(g_fft.guard_enable, g_fft.guard_w, 0);
152
 
153
  constant c_out_scale_w      : integer := c_fft_r2_par.out_dat_w - g_fft.out_dat_w - g_fft.out_gain_w;  -- Estimate number of LSBs to throw away when > 0 or insert when < 0
154
 
155
  signal in_fft_pipe_re_arr   : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
156
  signal in_fft_pipe_im_arr   : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
157
 
158
  signal out_fft_pipe_re_arr  : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
159
  signal out_fft_pipe_im_arr  : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
160
 
161
  signal in_fft_par_re_arr    : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
162
  signal in_fft_par_im_arr    : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
163
 
164
  signal fft_pipe_out_re      : std_logic_vector(g_fft.out_dat_w-1 downto 0);
165
  signal fft_pipe_out_im      : std_logic_vector(g_fft.out_dat_w-1 downto 0);
166
 
167
  signal fft_out_re_arr       : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
168
  signal fft_out_im_arr       : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
169
  signal fft_out_val          : std_logic;
170
 
171
  signal sep_out_re_arr       : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
172
  signal sep_out_im_arr       : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
173
  signal sep_out_val          : std_logic;
174
 
175
  signal int_val              : std_logic_vector(g_fft.wb_factor-1 downto 0);
176
 
177
  signal out_cplx             : std_logic_vector(c_nof_complex*g_fft.stage_dat_w-1 downto 0);
178
  signal in_cplx              : std_logic_vector(c_nof_complex*g_fft.stage_dat_w-1 downto 0);
179
 
180
begin
181
 
182
  -- Default to fft_r2_pipe when g_fft.wb_factor=1
183
  gen_fft_r2_pipe : if g_fft.wb_factor=1 generate
184
    u_fft_r2_pipe : entity work.fft_r2_pipe
185
    generic map (
186
      g_fft      => g_fft,
187
      g_pipeline => g_pft_pipeline
188
    )
189
    port map (
190
      clk        => clk,
191
      rst        => rst,
192
      in_re      => in_re_arr(0)(g_fft.in_dat_w-1 downto 0),
193
      in_im      => in_im_arr(0)(g_fft.in_dat_w-1 downto 0),
194
      in_val     => in_val,
195
      out_re     => fft_pipe_out_re,
196
      out_im     => fft_pipe_out_im,
197
      out_val    => out_val
198
    );
199
 
200
    out_re_arr(0) <= resize_fft_svec(fft_pipe_out_re);
201
    out_im_arr(0) <= resize_fft_svec(fft_pipe_out_im);
202
  end generate;
203
 
204
  -- Default to fft_r2_par when g_fft.wb_factor=g_fft.nof_points
205
  gen_fft_r2_par : if g_fft.wb_factor=g_fft.nof_points generate
206
    u_fft_r2_par : entity work.fft_r2_par
207
    generic map (
208
      g_fft      => g_fft,
209
      g_pipeline => g_fft_pipeline
210
    )
211
    port map (
212
      clk        => clk,
213
      rst        => rst,
214
      in_re_arr  => in_re_arr,
215
      in_im_arr  => in_im_arr,
216
      in_val     => in_val,
217
      out_re_arr => out_re_arr,
218
      out_im_arr => out_im_arr,
219
      out_val    => out_val
220
    );
221
  end generate;
222
 
223
  -- Create wideband FFT as combinination of g_fft.wb_factor instances of fft_r2_pipe with one instance of fft_r2_par
224
  gen_fft_r2_wide : if g_fft.wb_factor>1 and g_fft.wb_factor<g_fft.nof_points generate
225
 
226
    ---------------------------------------------------------------
227
    -- PIPELINED FFT STAGE
228
    ---------------------------------------------------------------
229
 
230
    -- Inputs are prepared/scaled for the pipelined ffts
231
    gen_fft_pipe_inputs : for I in 0 to g_fft.wb_factor-1 generate
232
      in_fft_pipe_re_arr(I) <= scale_and_resize_svec(in_re_arr(I), c_in_scale_w, c_fft_slv_w);
233
      in_fft_pipe_im_arr(I) <= scale_and_resize_svec(in_im_arr(I), c_in_scale_w, c_fft_slv_w);
234
    end generate;
235
 
236
    -- The first stage of the wideband fft consist of the generation of g_fft.wb_factor
237
    -- pipelined fft's. These pipelines fft's operate in parallel.   
238
    gen_pipelined_ffts : for I in g_fft.wb_factor-1 downto 0 generate
239
      u_pft : entity work.fft_r2_pipe
240
      generic map (
241
        g_fft      => c_fft_r2_pipe_arr(I),   -- generics for the pipelined FFTs
242
        g_pipeline => g_pft_pipeline          -- pipeline generics for the pipelined FFTs
243
      )
244
      port map (
245
        clk       => clk,
246
        rst       => rst,
247
        in_re     => in_fft_pipe_re_arr(I)(c_fft_r2_pipe_arr(I).in_dat_w-1 downto 0),
248
        in_im     => in_fft_pipe_im_arr(I)(c_fft_r2_pipe_arr(I).in_dat_w-1 downto 0),
249
        in_val    => in_val,
250
        out_re    => out_fft_pipe_re_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0),
251
        out_im    => out_fft_pipe_im_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0),
252
        out_val   => int_val(I)
253
      );
254
    end generate;
255
 
256
 
257
    ---------------------------------------------------------------
258
    -- PARALLEL FFT STAGE
259
    ---------------------------------------------------------------
260
 
261
    -- Create input for parallel FFT
262
    gen_inputs_for_par : for I in g_fft.wb_factor-1 downto 0 generate
263
      in_fft_par_re_arr(I) <= resize_fft_svec(out_fft_pipe_re_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0));
264
      in_fft_par_im_arr(I) <= resize_fft_svec(out_fft_pipe_im_arr(I)(c_fft_r2_pipe_arr(I).out_dat_w-1 downto 0));
265
    end generate;
266
 
267
    -- The g_fft.wb_factor outputs of the pipelined fft's are offered
268
    -- to the input of a single parallel FFT. 
269
    u_fft : entity work.fft_r2_par
270
    generic map (
271
      g_fft      => c_fft_r2_par,           -- generics for the FFT
272
      g_pipeline => g_fft_pipeline          -- pipeline generics for the parallel FFT
273
    )
274
    port map (
275
      clk        => clk,
276
      rst        => rst,
277
      in_re_arr  => in_fft_par_re_arr,
278
      in_im_arr  => in_fft_par_im_arr,
279
      in_val     => int_val(0),
280
      out_re_arr => fft_out_re_arr,
281
      out_im_arr => fft_out_im_arr,
282
      out_val    => fft_out_val
283
    );
284
 
285
    ---------------------------------------------------------------
286
    -- OPTIONAL: SEPARATION STAGE
287
    ---------------------------------------------------------------
288
    -- When the separate functionality is required:
289
    gen_separate : if g_fft.use_separate generate
290
      u_separator : entity work.fft_sepa_wide
291
      generic map (
292
        g_fft      => g_fft
293
      )
294
      port map (
295
        clk        => clk,
296
        rst        => rst,
297
        in_re_arr  => fft_out_re_arr,
298
        in_im_arr  => fft_out_im_arr,
299
        in_val     => fft_out_val,
300
        out_re_arr => sep_out_re_arr,
301
        out_im_arr => sep_out_im_arr,
302
        out_val    => sep_out_val
303
      );
304
    end generate;
305
 
306
     -- In case no separtion is required, the output of the parallel fft is used. 
307
    no_separate : if g_fft.use_separate=false generate
308
      sep_out_re_arr <= fft_out_re_arr;
309
      sep_out_im_arr <= fft_out_im_arr;
310
      sep_out_val    <= fft_out_val;
311
    end generate;
312
 
313
    ---------------------------------------------------------------
314
    -- OUTPUT QUANTIZER
315
    ---------------------------------------------------------------
316
    gen_output_requantizers : for I in g_fft.wb_factor-1 downto 0 generate
317
      u_requantize_output_re : entity common_requantize_lib.common_requantize
318
      generic map (
319
        g_representation      => "SIGNED",
320
        g_lsb_w               => c_out_scale_w,
321
        g_lsb_round           => TRUE,
322
        g_lsb_round_clip      => FALSE,
323
        g_msb_clip            => FALSE,
324
        g_msb_clip_symmetric  => FALSE,
325
        g_pipeline_remove_lsb => c_pipeline_remove_lsb,
326
        g_pipeline_remove_msb => 0,
327
        g_in_dat_w            => g_fft.stage_dat_w,
328
        g_out_dat_w           => g_fft.out_dat_w
329
      )
330
      port map (
331
        clk        => clk,
332
        in_dat     => sep_out_re_arr(I),
333
        out_dat    => out_re_arr(I),
334
        out_ovr    => open
335
      );
336
 
337
      u_requantize_output_im : entity common_requantize_lib.common_requantize
338
      generic map (
339
        g_representation      => "SIGNED",
340
        g_lsb_w               => c_out_scale_w,
341
        g_lsb_round           => TRUE,
342
        g_lsb_round_clip      => FALSE,
343
        g_msb_clip            => FALSE,
344
        g_msb_clip_symmetric  => FALSE,
345
        g_pipeline_remove_lsb => c_pipeline_remove_lsb,
346
        g_pipeline_remove_msb => 0,
347
        g_in_dat_w            => g_fft.stage_dat_w,
348
        g_out_dat_w           => g_fft.out_dat_w
349
      )
350
      port map (
351
        clk        => clk,
352
        in_dat     => sep_out_im_arr(I),
353
        out_dat    => out_im_arr(I),
354
        out_ovr    => open
355
      );
356
    end generate;
357
 
358
    u_out_val : entity common_components_lib.common_pipeline_sl
359
    generic map (
360
      g_pipeline => c_pipeline_remove_lsb
361
    )
362
    port map (
363
      rst     => rst,
364
      clk     => clk,
365
      in_dat  => sep_out_val,
366
      out_dat => out_val
367
    );
368
 
369
  end generate;
370
end rtl;

powered by: WebSVN 2.1.0

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