1 |
2 |
danv |
-------------------------------------------------------------------------------
|
2 |
|
|
--
|
3 |
3 |
danv |
-- Copyright 2020
|
4 |
2 |
danv |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
|
5 |
|
|
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
6 |
3 |
danv |
--
|
7 |
|
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
|
|
-- you may not use this file except in compliance with the License.
|
9 |
|
|
-- You may obtain a copy of the License at
|
10 |
|
|
--
|
11 |
|
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
12 |
|
|
--
|
13 |
|
|
-- Unless required by applicable law or agreed to in writing, software
|
14 |
|
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
|
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
|
|
-- See the License for the specific language governing permissions and
|
17 |
|
|
-- limitations under the License.
|
18 |
2 |
danv |
--
|
19 |
|
|
-------------------------------------------------------------------------------
|
20 |
|
|
--
|
21 |
|
|
-- Purpose: Test bench for the pipelined radix-2 FFT.
|
22 |
|
|
--
|
23 |
|
|
-- The testbech uses a blockgenerator to generate data for
|
24 |
|
|
-- the input of the parallel FFT.
|
25 |
|
|
-- The output of the FFT is stored in a databuffer.
|
26 |
|
|
-- Both the block generator and databuffer are controlled
|
27 |
|
|
-- via a mm interface.
|
28 |
|
|
-- Use this testbench in conjunction with ../python/tc_mmf_fft_r2_pipe.py
|
29 |
|
|
--
|
30 |
|
|
-- Usage:
|
31 |
|
|
-- > run -all
|
32 |
|
|
-- > Run python script in separate terminal: "python tc_mmf_fft_r2_pipe.py --unb 0 --bn 0 --sim"
|
33 |
|
|
-- > Check the results of the python script.
|
34 |
|
|
-- > Stop the simulation manually in Modelsim by pressing the stop-button.
|
35 |
|
|
|
36 |
7 |
danv |
LIBRARY IEEE, common_pkg_lib, astron_mm_lib, astron_diagnostics_lib, dp_pkg_lib, astron_r2sdf_fft_lib;
|
37 |
2 |
danv |
USE IEEE.std_logic_1164.ALL;
|
38 |
|
|
USE IEEE.numeric_std.ALL;
|
39 |
|
|
USE common_pkg_lib.common_pkg.ALL;
|
40 |
|
|
USE common_lib.common_mem_pkg.ALL;
|
41 |
|
|
USE common_pkg_lib.common_str_pkg.ALL;
|
42 |
|
|
USE common_pkg_lib.tb_common_pkg.ALL;
|
43 |
|
|
USE common_lib.tb_common_mem_pkg.ALL;
|
44 |
5 |
danv |
USE astron_mm_lib.mm_file_unb_pkg.ALL;
|
45 |
|
|
USE astron_mm_lib.mm_file_pkg.ALL;
|
46 |
2 |
danv |
USE dp_pkg_lib.dp_stream_pkg.ALL;
|
47 |
5 |
danv |
USE astron_r2sdf_fft_lib.rTwoSDFPkg.all;
|
48 |
2 |
danv |
USE work.fft_pkg.all;
|
49 |
|
|
|
50 |
|
|
ENTITY tb_mmf_fft_r2_pipe IS
|
51 |
|
|
GENERIC(
|
52 |
|
|
g_fft : t_fft := (true, false, false, 1, 1, 0, 64, 8, 14, 0, c_dsp_mult_w, 2, true, 56, 2)
|
53 |
|
|
-- type t_rtwo_fft is record
|
54 |
|
|
-- use_reorder : boolean; -- = false for bit-reversed output, true for normal output
|
55 |
|
|
-- 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
|
56 |
|
|
-- use_separate : boolean; -- = false for complex input, true for two real inputs
|
57 |
|
|
-- nof_chan : natural; -- = default 0, defines the number of channels (=time-multiplexed input signals): nof channels = 2**nof_chan
|
58 |
|
|
-- wb_factor : natural; -- = default 1, wideband factor
|
59 |
|
|
-- twiddle_offset : natural; -- = default 0, twiddle offset for PFT sections in a wideband FFT
|
60 |
|
|
-- nof_points : natural; -- = 1024, N point FFT
|
61 |
|
|
-- in_dat_w : natural; -- = 8, number of input bits
|
62 |
|
|
-- out_dat_w : natural; -- = 13, number of output bits: in_dat_w + natural((ceil_log2(nof_points))/2 + 2)
|
63 |
|
|
-- out_gain_w : natural; -- = 0, output gain factor applied after the last stage output, before requantization to out_dat_w
|
64 |
|
|
-- stage_dat_w : natural; -- = 18, data width used between the stages(= DSP multiplier-width)
|
65 |
|
|
-- guard_w : natural; -- = 2, Guard used to avoid overflow in FFT stage.
|
66 |
|
|
-- guard_enable : boolean; -- = true when input needs guarding, false when input requires no guarding but scaling must be skipped at the last stage(s) (used in wb fft)
|
67 |
|
|
-- stat_data_w : positive; -- = 56
|
68 |
|
|
-- stat_data_sz : positive; -- = 2
|
69 |
|
|
-- end record;
|
70 |
|
|
);
|
71 |
|
|
END tb_mmf_fft_r2_pipe;
|
72 |
|
|
|
73 |
|
|
ARCHITECTURE tb OF tb_mmf_fft_r2_pipe IS
|
74 |
|
|
|
75 |
|
|
CONSTANT c_sim : BOOLEAN := TRUE;
|
76 |
|
|
|
77 |
|
|
----------------------------------------------------------------------------
|
78 |
|
|
-- Clocks and resets
|
79 |
|
|
----------------------------------------------------------------------------
|
80 |
|
|
CONSTANT c_mm_clk_period : TIME := 1 ns;
|
81 |
|
|
CONSTANT c_dp_clk_period : TIME := 5 ns;
|
82 |
|
|
CONSTANT c_dp_pps_period : NATURAL := 64;
|
83 |
|
|
|
84 |
|
|
SIGNAL dp_pps : STD_LOGIC;
|
85 |
|
|
|
86 |
|
|
SIGNAL mm_rst : STD_LOGIC;
|
87 |
|
|
SIGNAL mm_clk : STD_LOGIC := '0';
|
88 |
|
|
|
89 |
|
|
SIGNAL dp_rst : STD_LOGIC;
|
90 |
|
|
SIGNAL dp_clk : STD_LOGIC := '0';
|
91 |
|
|
|
92 |
|
|
----------------------------------------------------------------------------
|
93 |
|
|
-- MM buses
|
94 |
|
|
----------------------------------------------------------------------------
|
95 |
|
|
SIGNAL reg_diag_bg_mosi : t_mem_mosi;
|
96 |
|
|
SIGNAL reg_diag_bg_miso : t_mem_miso;
|
97 |
|
|
|
98 |
|
|
SIGNAL ram_diag_bg_mosi : t_mem_mosi;
|
99 |
|
|
SIGNAL ram_diag_bg_miso : t_mem_miso;
|
100 |
|
|
|
101 |
|
|
SIGNAL ram_ss_ss_wide_mosi : t_mem_mosi;
|
102 |
|
|
SIGNAL ram_ss_ss_wide_miso : t_mem_miso;
|
103 |
|
|
|
104 |
|
|
SIGNAL ram_diag_data_buf_re_mosi : t_mem_mosi;
|
105 |
|
|
SIGNAL ram_diag_data_buf_re_miso : t_mem_miso;
|
106 |
|
|
|
107 |
|
|
SIGNAL reg_diag_data_buf_re_mosi : t_mem_mosi;
|
108 |
|
|
SIGNAL reg_diag_data_buf_re_miso : t_mem_miso;
|
109 |
|
|
|
110 |
|
|
SIGNAL ram_diag_data_buf_im_mosi : t_mem_mosi;
|
111 |
|
|
SIGNAL ram_diag_data_buf_im_miso : t_mem_miso;
|
112 |
|
|
|
113 |
|
|
SIGNAL reg_diag_data_buf_im_mosi : t_mem_mosi;
|
114 |
|
|
SIGNAL reg_diag_data_buf_im_miso : t_mem_miso;
|
115 |
|
|
|
116 |
|
|
CONSTANT c_nof_channels : NATURAL := 2**g_fft.nof_chan;
|
117 |
|
|
CONSTANT c_nof_streams : POSITIVE := g_fft.wb_factor;
|
118 |
|
|
CONSTANT c_nof_integration : NATURAL := 8;
|
119 |
|
|
CONSTANT c_bg_block_len : NATURAL := g_fft.nof_points*c_nof_integration*c_nof_channels;
|
120 |
|
|
|
121 |
|
|
CONSTANT c_bg_buf_adr_w : NATURAL := ceil_log2(c_bg_block_len);
|
122 |
|
|
CONSTANT c_bg_data_file_index_arr : t_nat_natural_arr := array_init(0, 16, 1);
|
123 |
|
|
CONSTANT c_bg_data_file_prefix : STRING := "UNUSED";
|
124 |
|
|
|
125 |
|
|
SIGNAL bg_siso_arr : t_dp_siso_arr(0 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
|
126 |
|
|
SIGNAL bg_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0);
|
127 |
|
|
|
128 |
|
|
SIGNAL ss_out_sosi_re_arr : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
|
129 |
|
|
SIGNAL ss_out_sosi_im_arr : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
|
130 |
|
|
|
131 |
|
|
SIGNAL in_re : STD_LOGIC_VECTOR(g_fft.in_dat_w-1 DOWNTO 0);
|
132 |
|
|
SIGNAL in_im : STD_LOGIC_VECTOR(g_fft.in_dat_w-1 DOWNTO 0);
|
133 |
|
|
SIGNAL in_val : STD_LOGIC := '0';
|
134 |
|
|
|
135 |
|
|
SIGNAL out_re : STD_LOGIC_VECTOR(g_fft.out_dat_w-1 DOWNTO 0);
|
136 |
|
|
SIGNAL out_im : STD_LOGIC_VECTOR(g_fft.out_dat_w-1 DOWNTO 0);
|
137 |
|
|
SIGNAL out_val : STD_LOGIC := '0';
|
138 |
|
|
|
139 |
|
|
BEGIN
|
140 |
|
|
|
141 |
|
|
----------------------------------------------------------------------------
|
142 |
|
|
-- Clock and reset generation
|
143 |
|
|
----------------------------------------------------------------------------
|
144 |
|
|
mm_clk <= NOT mm_clk AFTER c_mm_clk_period/2;
|
145 |
|
|
mm_rst <= '1', '0' AFTER c_mm_clk_period*5;
|
146 |
|
|
|
147 |
|
|
dp_clk <= NOT dp_clk AFTER c_dp_clk_period/2;
|
148 |
|
|
dp_rst <= '1', '0' AFTER c_dp_clk_period*5;
|
149 |
|
|
|
150 |
|
|
------------------------------------------------------------------------------
|
151 |
|
|
-- External PPS
|
152 |
|
|
------------------------------------------------------------------------------
|
153 |
|
|
proc_common_gen_pulse(1, c_dp_pps_period, '1', dp_clk, dp_pps);
|
154 |
|
|
|
155 |
|
|
----------------------------------------------------------------------------
|
156 |
|
|
-- Procedure that polls a sim control file that can be used to e.g. get
|
157 |
|
|
-- the simulation time in ns
|
158 |
|
|
----------------------------------------------------------------------------
|
159 |
|
|
mmf_poll_sim_ctrl_file(c_mmf_unb_file_path & "sim.ctrl", c_mmf_unb_file_path & "sim.stat");
|
160 |
|
|
|
161 |
|
|
----------------------------------------------------------------------------
|
162 |
|
|
-- MM buses
|
163 |
|
|
----------------------------------------------------------------------------
|
164 |
|
|
u_mm_file_reg_diag_bg : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "BN") & "REG_DIAG_BG")
|
165 |
|
|
PORT MAP(mm_rst, mm_clk, reg_diag_bg_mosi, reg_diag_bg_miso);
|
166 |
|
|
|
167 |
|
|
u_mm_file_ram_diag_bg : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "BN") & "RAM_DIAG_BG")
|
168 |
|
|
PORT MAP(mm_rst, mm_clk, ram_diag_bg_mosi, ram_diag_bg_miso);
|
169 |
|
|
|
170 |
|
|
u_mm_file_ram_diag_data_buf_re : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "BN") & "RAM_DIAG_DATA_BUFFER_REAL")
|
171 |
|
|
PORT MAP(mm_rst, mm_clk, ram_diag_data_buf_re_mosi, ram_diag_data_buf_re_miso);
|
172 |
|
|
|
173 |
|
|
u_mm_file_reg_diag_data_buf_re : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "BN") & "REG_DIAG_DATA_BUFFER_REAL")
|
174 |
|
|
PORT MAP(mm_rst, mm_clk, reg_diag_data_buf_re_mosi, reg_diag_data_buf_re_miso);
|
175 |
|
|
|
176 |
|
|
u_mm_file_ram_diag_data_buf_im : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "BN") & "RAM_DIAG_DATA_BUFFER_IMAG")
|
177 |
|
|
PORT MAP(mm_rst, mm_clk, ram_diag_data_buf_im_mosi, ram_diag_data_buf_im_miso);
|
178 |
|
|
|
179 |
|
|
u_mm_file_reg_diag_data_buf_im : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "BN") & "REG_DIAG_DATA_BUFFER_IMAG")
|
180 |
|
|
PORT MAP(mm_rst, mm_clk, reg_diag_data_buf_im_mosi, reg_diag_data_buf_im_miso);
|
181 |
|
|
|
182 |
|
|
----------------------------------------------------------------------------
|
183 |
|
|
-- Source: block generator
|
184 |
|
|
----------------------------------------------------------------------------
|
185 |
5 |
danv |
u_bg : ENTITY astron_diagnostics_lib.mms_diag_block_gen
|
186 |
2 |
danv |
GENERIC MAP(
|
187 |
|
|
g_nof_output_streams => c_nof_streams,
|
188 |
|
|
g_buf_dat_w => c_nof_complex*g_fft.in_dat_w,
|
189 |
|
|
g_buf_addr_w => c_bg_buf_adr_w, -- Waveform buffer size 2**g_buf_addr_w nof samples
|
190 |
|
|
g_file_index_arr => c_bg_data_file_index_arr,
|
191 |
|
|
g_file_name_prefix => c_bg_data_file_prefix
|
192 |
|
|
)
|
193 |
|
|
PORT MAP(
|
194 |
|
|
-- System
|
195 |
|
|
mm_rst => mm_rst,
|
196 |
|
|
mm_clk => mm_clk,
|
197 |
|
|
dp_rst => dp_rst,
|
198 |
|
|
dp_clk => dp_clk,
|
199 |
|
|
en_sync => dp_pps,
|
200 |
|
|
-- MM interface
|
201 |
|
|
reg_bg_ctrl_mosi => reg_diag_bg_mosi,
|
202 |
|
|
reg_bg_ctrl_miso => reg_diag_bg_miso,
|
203 |
|
|
ram_bg_data_mosi => ram_diag_bg_mosi,
|
204 |
|
|
ram_bg_data_miso => ram_diag_bg_miso,
|
205 |
|
|
-- ST interface
|
206 |
|
|
out_siso_arr => bg_siso_arr,
|
207 |
|
|
out_sosi_arr => bg_sosi_arr
|
208 |
|
|
);
|
209 |
|
|
|
210 |
|
|
in_re <= bg_sosi_arr(0).re(g_fft.in_dat_w-1 DOWNTO 0);
|
211 |
|
|
in_im <= bg_sosi_arr(0).im(g_fft.in_dat_w-1 DOWNTO 0);
|
212 |
|
|
in_val <= bg_sosi_arr(0).valid;
|
213 |
|
|
|
214 |
|
|
-- DUT = Device Under Test
|
215 |
|
|
u_dut : ENTITY work.fft_r2_pipe
|
216 |
|
|
GENERIC MAP(
|
217 |
|
|
g_fft => g_fft -- generics for the FFT
|
218 |
|
|
)
|
219 |
|
|
port map(
|
220 |
|
|
clk => dp_clk,
|
221 |
|
|
rst => dp_rst,
|
222 |
|
|
in_re => in_re,
|
223 |
|
|
in_im => in_im,
|
224 |
|
|
in_val => in_val,
|
225 |
|
|
out_re => out_re,
|
226 |
|
|
out_im => out_im,
|
227 |
|
|
out_val => out_val
|
228 |
|
|
);
|
229 |
|
|
|
230 |
|
|
ss_out_sosi_re_arr(0).data <= RESIZE_SVEC(out_re, ss_out_sosi_re_arr(0).data'LENGTH);
|
231 |
|
|
ss_out_sosi_re_arr(0).valid <= out_val;
|
232 |
|
|
ss_out_sosi_re_arr(0).sync <= out_val;
|
233 |
|
|
|
234 |
|
|
ss_out_sosi_im_arr(0).data <= RESIZE_SVEC(out_im, ss_out_sosi_im_arr(0).data'LENGTH);
|
235 |
|
|
ss_out_sosi_im_arr(0).valid <= out_val;
|
236 |
|
|
ss_out_sosi_im_arr(0).sync <= out_val;
|
237 |
|
|
|
238 |
|
|
|
239 |
|
|
----------------------------------------------------------------------------
|
240 |
|
|
-- Sink: data buffer real
|
241 |
|
|
----------------------------------------------------------------------------
|
242 |
5 |
danv |
u_data_buf_re : ENTITY astron_diagnostics_lib.mms_diag_data_buffer
|
243 |
2 |
danv |
GENERIC MAP (
|
244 |
|
|
g_nof_streams => c_nof_streams,
|
245 |
|
|
g_data_w => g_fft.out_dat_w,
|
246 |
|
|
g_buf_nof_data => c_bg_block_len,
|
247 |
|
|
g_buf_use_sync => FALSE
|
248 |
|
|
)
|
249 |
|
|
PORT MAP (
|
250 |
|
|
-- System
|
251 |
|
|
mm_rst => mm_rst,
|
252 |
|
|
mm_clk => mm_clk,
|
253 |
|
|
dp_rst => dp_rst,
|
254 |
|
|
dp_clk => dp_clk,
|
255 |
|
|
|
256 |
|
|
-- MM interface
|
257 |
|
|
ram_data_buf_mosi => ram_diag_data_buf_re_mosi,
|
258 |
|
|
ram_data_buf_miso => ram_diag_data_buf_re_miso,
|
259 |
|
|
|
260 |
|
|
reg_data_buf_mosi => reg_diag_data_buf_re_mosi,
|
261 |
|
|
reg_data_buf_miso => reg_diag_data_buf_re_miso,
|
262 |
|
|
|
263 |
|
|
-- ST interface
|
264 |
|
|
in_sync => ss_out_sosi_re_arr(0).sync,
|
265 |
|
|
in_sosi_arr => ss_out_sosi_re_arr
|
266 |
|
|
);
|
267 |
|
|
|
268 |
|
|
----------------------------------------------------------------------------
|
269 |
|
|
-- Sink: data buffer imag
|
270 |
|
|
----------------------------------------------------------------------------
|
271 |
5 |
danv |
u_data_buf_im : ENTITY astron_diagnostics_lib.mms_diag_data_buffer
|
272 |
2 |
danv |
GENERIC MAP (
|
273 |
|
|
g_nof_streams => c_nof_streams,
|
274 |
|
|
g_data_w => g_fft.out_dat_w,
|
275 |
|
|
g_buf_nof_data => c_bg_block_len,
|
276 |
|
|
g_buf_use_sync => FALSE
|
277 |
|
|
)
|
278 |
|
|
PORT MAP (
|
279 |
|
|
-- System
|
280 |
|
|
mm_rst => mm_rst,
|
281 |
|
|
mm_clk => mm_clk,
|
282 |
|
|
dp_rst => dp_rst,
|
283 |
|
|
dp_clk => dp_clk,
|
284 |
|
|
|
285 |
|
|
-- MM interface
|
286 |
|
|
ram_data_buf_mosi => ram_diag_data_buf_im_mosi,
|
287 |
|
|
ram_data_buf_miso => ram_diag_data_buf_im_miso,
|
288 |
|
|
|
289 |
|
|
reg_data_buf_mosi => reg_diag_data_buf_im_mosi,
|
290 |
|
|
reg_data_buf_miso => reg_diag_data_buf_im_miso,
|
291 |
|
|
|
292 |
|
|
-- ST interface
|
293 |
|
|
in_sync => ss_out_sosi_im_arr(0).sync,
|
294 |
|
|
in_sosi_arr => ss_out_sosi_im_arr
|
295 |
|
|
);
|
296 |
|
|
|
297 |
|
|
END tb;
|