1 |
2 |
danv |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Author: Harm Jan Pepping : pepping at astron.nl: 2012
|
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 |
|
|
|
22 |
|
|
library ieee, common_pkg_lib;
|
23 |
|
|
use IEEE.std_logic_1164.all;
|
24 |
|
|
use common_pkg_lib.common_pkg.all;
|
25 |
|
|
|
26 |
|
|
package fft_pkg is
|
27 |
|
|
|
28 |
|
|
-- FFT parameters for pipelined FFT (fft_pipe), parallel FFT (fft_par) and wideband FFT (fft_wide)
|
29 |
|
|
type t_fft is record
|
30 |
|
|
use_reorder : boolean; -- = false for bit-reversed output, true for normal output
|
31 |
|
|
use_fft_shift : boolean; -- = false for [0, pos, neg] bin frequencies order, true for [neg, 0, pos] bin frequencies order in case of complex input
|
32 |
|
|
use_separate : boolean; -- = false for complex input, true for two real inputs
|
33 |
|
|
nof_chan : natural; -- = default 0, defines the number of channels (=time-multiplexed input signals): nof channels = 2**nof_chan
|
34 |
|
|
wb_factor : natural; -- = default 1, wideband factor
|
35 |
|
|
twiddle_offset : natural; -- = default 0, twiddle offset for PFT sections in a wideband FFT
|
36 |
|
|
nof_points : natural; -- = 1024, N point FFT
|
37 |
|
|
in_dat_w : natural; -- = 8, number of input bits
|
38 |
|
|
out_dat_w : natural; -- = 13, number of output bits
|
39 |
|
|
out_gain_w : natural; -- = 0, output gain factor applied after the last stage output, before requantization to out_dat_w
|
40 |
|
|
stage_dat_w : natural; -- = 18, data width used between the stages(= DSP multiplier-width)
|
41 |
|
|
guard_w : natural; -- = 2, guard used to avoid overflow in first FFT stage, compensated in last guard_w nof FFT stages.
|
42 |
|
|
-- on average the gain per stage is 2 so guard_w = 1, but the gain can be 1+sqrt(2) [Lyons section
|
43 |
|
|
-- 12.3.2], therefore use input guard_w = 2.
|
44 |
|
|
guard_enable : boolean; -- = true when input needs guarding, false when input requires no guarding but scaling must be
|
45 |
|
|
-- skipped at the last stage(s) compensate for input guard (used in wb fft with pipe fft section
|
46 |
|
|
-- doing the input guard and par fft section doing the output compensation)
|
47 |
|
|
stat_data_w : positive; -- = 56
|
48 |
|
|
stat_data_sz : positive; -- = 2
|
49 |
|
|
end record;
|
50 |
|
|
|
51 |
|
|
constant c_fft : t_fft := (true, false, true, 0, 4, 0, 1024, 8, 14, 0, c_dsp_mult_w, 2, true, 56, 2);
|
52 |
|
|
|
53 |
|
|
-- Check consistancy of the FFT parameters
|
54 |
|
|
function fft_r2_parameter_asserts(g_fft : t_fft) return boolean; -- the return value is void, because always true or abort due to failure
|
55 |
|
|
|
56 |
|
|
-- Definitions for fft slv array (an array can not have unconstraint elements, so choose sufficiently wide 32 bit slv elements)
|
57 |
|
|
subtype t_fft_slv_arr is t_slv_32_arr; -- use subtype to ease interfacing to existing types and to have central definition for rtwo components
|
58 |
|
|
constant c_fft_slv_w : natural := 32; -- match slv width of t_fft_slv_arr
|
59 |
|
|
function to_fft_svec(n : integer) return std_logic_vector; -- map to c_fft_slv_w wide slv, no need for to_rtwo_uvec, because natural is subtype of integer
|
60 |
|
|
function resize_fft_uvec(vec : std_logic_vector) return std_logic_vector; -- map to c_fft_slv_w wide slv
|
61 |
|
|
function resize_fft_svec(vec : std_logic_vector) return std_logic_vector; -- map to c_fft_slv_w wide slv
|
62 |
|
|
|
63 |
|
|
-- FFT shift swaps right and left half of bin axis to shift zero-frequency component to center of spectrum
|
64 |
|
|
function fft_shift(bin : std_logic_vector) return std_logic_vector;
|
65 |
|
|
function fft_shift(bin, w : natural) return natural;
|
66 |
|
|
|
67 |
|
|
end package fft_pkg;
|
68 |
|
|
|
69 |
|
|
package body fft_pkg is
|
70 |
|
|
|
71 |
|
|
function fft_r2_parameter_asserts(g_fft : t_fft) return boolean is
|
72 |
|
|
begin
|
73 |
|
|
-- nof_points
|
74 |
|
|
assert g_fft.nof_points=2**true_log2(g_fft.nof_points) report "fft_r2: nof_points must be a power of 2" severity failure;
|
75 |
|
|
-- wb_factor
|
76 |
|
|
assert g_fft.wb_factor=2**true_log2(g_fft.wb_factor) report "fft_r2: wb_factor must be a power of 2" severity failure;
|
77 |
|
|
-- use_reorder
|
78 |
|
|
if g_fft.use_reorder=false then
|
79 |
|
|
assert g_fft.use_separate=false report "fft_r2 : without use_reorder there cannot be use_separate for two real inputs" severity failure;
|
80 |
|
|
assert g_fft.use_fft_shift=false report "fft_r2 : without use_reorder there cannot be use_fft_shift for complex input" severity failure;
|
81 |
|
|
end if;
|
82 |
|
|
-- use_separate
|
83 |
|
|
if g_fft.use_separate=true then
|
84 |
|
|
assert g_fft.use_fft_shift=false report "fft_r2 : with use_separate there cannot be use_fft_shift for two real inputs" severity failure;
|
85 |
|
|
end if;
|
86 |
|
|
return true;
|
87 |
|
|
end;
|
88 |
|
|
|
89 |
|
|
function to_fft_svec(n : integer) return std_logic_vector is
|
90 |
|
|
begin
|
91 |
|
|
return RESIZE_SVEC(TO_SVEC(n, 32), c_fft_slv_w);
|
92 |
|
|
end;
|
93 |
|
|
|
94 |
|
|
function resize_fft_uvec(vec : std_logic_vector) return std_logic_vector is
|
95 |
|
|
begin
|
96 |
|
|
return RESIZE_UVEC(vec, c_fft_slv_w);
|
97 |
|
|
end;
|
98 |
|
|
|
99 |
|
|
function resize_fft_svec(vec : std_logic_vector) return std_logic_vector is
|
100 |
|
|
begin
|
101 |
|
|
return RESIZE_SVEC(vec, c_fft_slv_w);
|
102 |
|
|
end;
|
103 |
|
|
|
104 |
|
|
function fft_shift(bin : std_logic_vector) return std_logic_vector is
|
105 |
|
|
constant c_w : natural := bin'length;
|
106 |
|
|
variable v_bin : std_logic_vector(c_w-1 downto 0) := bin;
|
107 |
|
|
begin
|
108 |
|
|
return not v_bin(c_w-1) & v_bin(c_w-2 downto 0); -- invert MSbit for fft_shift
|
109 |
|
|
end;
|
110 |
|
|
|
111 |
|
|
function fft_shift(bin, w : natural) return natural is
|
112 |
|
|
begin
|
113 |
|
|
return TO_UINT(fft_shift(TO_UVEC(bin, w)));
|
114 |
|
|
end;
|
115 |
|
|
|
116 |
|
|
end fft_pkg;
|
117 |
|
|
|