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

Subversion Repositories astron_wb_fft

[/] [astron_wb_fft/] [trunk/] [tb_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
-- Author: Eric Kooistra    : kooistra at astron.nl: july 2016
2
--------------------------------------------------------------------------------
3
--
4
-- Copyright (C) 2016
5
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
6
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
7
--
8
-- This program is free software: you can redistribute it and/or modify
9
-- it under the terms of the GNU General Public License as published by
10
-- the Free Software Foundation, either version 3 of the License, or
11
-- (at your option) any later version.
12
--
13
-- This program is distributed in the hope that it will be useful,
14
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
15
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
-- GNU General Public License for more details.
17
--
18
-- You should have received a copy of the GNU General Public License
19
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
--
21
--------------------------------------------------------------------------------
22
--
23
-- Purpose: Test bench for fft_r2_wide.vhd using file data
24
--
25
-- Usage:
26
--   This tb uses the same Matlab stimuli and expected results as
27
--   tb_fft_r2_pipe.vhd.
28
--
29
--   For the fft_r2_wide wb_factor > 1 and < nof_points, because it implements
30
--   a combination of fft_r2_pipe and fft_r2_par.
31
--   The fft_r2_wide does support use_reorder.
32
--   The fft_r2_wide does support use_separate.
33
--   The fft_r2_wide does support input flow control with invalid gaps in the
34
--   input.
35
--   The fft_r2_wide only supports nof_chan=0, because the concept of channels
36
--   is void when wb_factor > 0.
37
--
38
--   For more description see tb_fft_r2_pipe.vhd.
39
--
40
--   > run -all
41
--   > testbench is selftesting.
42
--   > observe the *_scope signals as radix decimal, format analogue format
43
--     signals in the Wave window
44
--
45
library ieee, common_pkg_lib, rTwoSDF_lib, common_ram_lib, mm_lib, other_lib;
46
use IEEE.std_logic_1164.all;
47
use IEEE.numeric_std.all;
48
use IEEE.std_logic_textio.all;
49
use std.textio.all;
50
use common_pkg_lib.common_pkg.all;
51
use common_ram_lib.common_ram_pkg.ALL;
52
use common_pkg_lib.common_lfsr_sequences_pkg.ALL;
53
use common_pkg_lib.tb_common_pkg.all;
54
use mm_lib.tb_common_mem_pkg.ALL;
55
use rTwoSDF_lib.rTwoSDFPkg.all;
56
use work.fft_pkg.all;
57
use work.tb_fft_pkg.all;
58
 
59
entity tb_fft_r2_wide is
60
  generic(
61
    -- DUT generics
62
    --g_fft : t_fft := ( true, false,  true, 0, 4, 0, 128, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- two real inputs A and B
63
    g_fft : t_fft := ( true, false,  true, 0, 4, 0,  32, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- two real inputs A and B
64
    --g_fft : t_fft := ( true, false, false, 0, 4, 0,  32, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- complex input reordered
65
    --g_fft : t_fft := (false, false, false, 0, 4, 0,  32, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- complex input flipped
66
    --  type t_rtwo_fft is record
67
    --    use_reorder    : boolean;  -- = false for bit-reversed output, true for normal output
68
    --    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
69
    --    use_separate   : boolean;  -- = false for complex input, true for two real inputs
70
    --    nof_chan       : natural;  -- = default 0, defines the number of channels (=time-multiplexed input signals): nof channels = 2**nof_chan         
71
    --    wb_factor      : natural;  -- = default 1, wideband factor
72
    --    twiddle_offset : natural;  -- = default 0, twiddle offset for PFT sections in a wideband FFT
73
    --    nof_points     : natural;  -- = 1024, N point FFT
74
    --    in_dat_w       : natural;  -- = 8, number of input bits
75
    --    out_dat_w      : natural;  -- = 13, number of output bits, bit growth: in_dat_w + natural((ceil_log2(nof_points))/2 + 2)  
76
    --    out_gain_w     : natural;  -- = 0, output gain factor applied after the last stage output, before requantization to out_dat_w
77
    --    stage_dat_w    : natural;  -- = 18, data width used between the stages(= DSP multiplier-width)
78
    --    guard_w        : natural;  -- = 2,  Guard used to avoid overflow in FFT stage. 
79
    --    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)
80
    --    stat_data_w    : positive; -- = 56 (= 18b+18b)+log2(781250)
81
    --    stat_data_sz   : positive; -- = 2 (complex re and im)
82
    --  end record;
83
    --
84
    -- TB generics
85
    g_diff_margin           : integer := 2;  -- maximum difference between HDL output and expected output (> 0 to allow minor rounding differences)
86
 
87
    -- Two real input data files A and B used when g_fft.use_separate = true
88
    -- * 128 points = 64 subbands
89
    --g_data_file_a           : string := "data/run_pfft_m_sinusoid_chirp_8b_128points_16b.dat";
90
    --g_data_file_a_nof_lines : natural := 25600;
91
    --g_data_file_b           : string := "UNUSED";
92
    --g_data_file_b_nof_lines : natural := 0;
93
 
94
    -- * 32 points = 16 subbands
95
    g_data_file_a           : string := "data/run_pfft_m_sinusoid_chirp_8b_32points_16b.dat";
96
    g_data_file_a_nof_lines : natural := 6400;
97
    --g_data_file_a           : string := "data/run_pfft_m_sinusoid_8b_32points_16b.dat";
98
    --g_data_file_a_nof_lines : natural := 160;
99
 
100
    --g_data_file_b           : string := "data/run_pfft_m_impulse_chirp_8b_32points_16b.dat";
101
    --g_data_file_b_nof_lines : natural := 6400;
102
    g_data_file_b           : string := "UNUSED";
103
    g_data_file_b_nof_lines : natural := 0;
104
 
105
    -- One complex input data file C used when g_fft.use_separate = false
106
    -- * 64 points = 64 channels
107
    --g_data_file_c           : string := "data/run_pfft_complex_m_phasor_chirp_8b_64points_16b.dat";
108
    --g_data_file_c_nof_lines : natural := 12800;
109
    --g_data_file_c           : string := "data/run_pfft_complex_m_phasor_8b_64points_16b.dat";
110
    --g_data_file_c_nof_lines : natural := 320;
111
    --g_data_file_c           : string := "data/run_pfft_complex_m_noise_8b_64points_16b.dat";
112
    --g_data_file_c_nof_lines : natural := 640;
113
 
114
    -- * 32 points = 32 channels
115
    g_data_file_c           : string := "data/run_pfft_complex_m_phasor_chirp_8b_32points_16b.dat";
116
    g_data_file_c_nof_lines : natural := 6400;
117
    --g_data_file_c           : string := "data/run_pfft_complex_m_phasor_8b_32points_16b.dat";
118
    --g_data_file_c_nof_lines : natural := 160;
119
    --g_data_file_c           : string := "data/run_pfft_complex_m_noise_8b_32points_16b.dat";
120
    --g_data_file_c_nof_lines : natural := 320;
121
 
122
    g_data_file_nof_lines   : natural := 6400;    -- actual number of lines with input data to simulate from the data files, must be <= g_data_file_*_nof_lines
123
    g_enable_in_val_gaps    : boolean := TRUE   -- when false then in_val flow control active continuously, else with random inactive gaps
124
  );
125
end entity tb_fft_r2_wide;
126
 
127
architecture tb of tb_fft_r2_wide is
128
 
129
  constant c_clk_period            : time := 10 ns;
130
  constant c_sclk_period           : time := c_clk_period / g_fft.wb_factor;
131
 
132
  constant c_in_complex            : boolean := not g_fft.use_separate;
133
  constant c_fft_r2_check          : boolean := fft_r2_parameter_asserts(g_fft);
134
 
135
  constant c_nof_channels          : natural := 1;  -- fixed g_fft.nof_chan=0, because the concept of channels is void when wb_factor > 1
136
  constant c_nof_data_per_block    : natural := g_fft.nof_points * c_nof_channels;
137
  constant c_nof_valid_per_block   : natural := c_nof_data_per_block / g_fft.wb_factor;
138
 
139
  constant c_rnd_factor            : natural := sel_a_b(g_enable_in_val_gaps, 3, 1);
140
  constant c_dut_block_latency     : natural := 4;
141
  constant c_dut_clk_latency       : natural := c_nof_valid_per_block * c_dut_block_latency * c_rnd_factor + 50;  -- worst case
142
 
143
  -- input/output data width
144
  constant c_in_dat_w              : natural := g_fft.in_dat_w;
145
  constant c_out_dat_w             : natural := g_fft.out_dat_w;
146
 
147
  -- Data file access (Header + WG data + PFFT data)
148
  constant c_nof_lines_header        : natural := 2;
149
  constant c_nof_lines_a_wg_dat      : natural := g_data_file_a_nof_lines;                    -- Real input A via in_re, one value per line
150
  constant c_nof_lines_a_wg_header   : natural := c_nof_lines_header;
151
  constant c_nof_lines_a_pfft_dat    : natural := g_data_file_a_nof_lines/c_nof_complex;      -- Half spectrum, two values per line (re, im)
152
  constant c_nof_lines_a_pfft_header : natural := c_nof_lines_header + c_nof_lines_a_wg_dat;
153
  constant c_nof_lines_b_wg_dat      : natural := g_data_file_b_nof_lines;                    -- Real input B via in_im, one value per line
154
  constant c_nof_lines_b_wg_header   : natural := c_nof_lines_header;
155
  constant c_nof_lines_b_pfft_dat    : natural := g_data_file_b_nof_lines/c_nof_complex;      -- Half spectrum, two values per line (re, im)
156
  constant c_nof_lines_b_pfft_header : natural := c_nof_lines_header + c_nof_lines_b_wg_dat;
157
  constant c_nof_lines_c_wg_dat      : natural := g_data_file_c_nof_lines;                    -- Complex input, two values per line (re, im)
158
  constant c_nof_lines_c_wg_header   : natural := c_nof_lines_header;
159
  constant c_nof_lines_c_pfft_dat    : natural := g_data_file_c_nof_lines;                    -- Full spectrum, two values per line (re, im)
160
  constant c_nof_lines_c_pfft_header : natural := c_nof_lines_header + c_nof_lines_c_wg_dat;
161
 
162
  -- signal definitions
163
  signal tb_end                 : std_logic := '0';
164
  signal tb_end_almost          : std_logic := '0';
165
  signal clk                    : std_logic := '0';
166
  signal sclk                   : std_logic := '0';
167
  signal rst                    : std_logic := '0';
168
  signal random                 : std_logic_vector(15 DOWNTO 0) := (OTHERS=>'0');  -- use different lengths to have different random sequences
169
 
170
  signal input_data_a_arr       : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- one value per line (A via re input)
171
  signal input_data_b_arr       : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- one value per line (B via im input)
172
  signal input_data_c_arr       : t_integer_arr(0 to g_data_file_nof_lines*c_nof_complex-1) := (OTHERS=>0);  -- two values per line (re, im)
173
 
174
  signal output_data_a_re_arr   : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, re
175
  signal output_data_a_im_arr   : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, im
176
  signal output_data_b_re_arr   : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, re
177
  signal output_data_b_im_arr   : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, im
178
  signal output_data_c_re_arr   : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- full spectrum, re
179
  signal output_data_c_im_arr   : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- full spectrum, im  
180
 
181
  signal expected_data_a_arr    : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- half spectrum, two values per line (re, im)
182
  signal expected_data_a_re_arr : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, re
183
  signal expected_data_a_im_arr : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, im
184
  signal expected_data_b_arr    : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- half spectrum, two values per line (re, im)
185
  signal expected_data_b_re_arr : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, re
186
  signal expected_data_b_im_arr : t_integer_arr(0 to g_data_file_nof_lines/c_nof_complex-1) := (OTHERS=>0);  -- half spectrum, im
187
  signal expected_data_c_arr    : t_integer_arr(0 to g_data_file_nof_lines*c_nof_complex-1) := (OTHERS=>0);  -- full spectrum, two values per line (re, im)
188
  signal expected_data_c_re_arr : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- full spectrum, re
189
  signal expected_data_c_im_arr : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- full spectrum, im  
190
 
191
  signal t_blk                  : integer := 0;  -- block time counter
192
 
193
  -- Input
194
  signal in_re_arr              : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
195
  signal in_im_arr              : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
196
  signal in_re_data             : std_logic_vector(g_fft.wb_factor*c_in_dat_w-1 DOWNTO 0);
197
  signal in_im_data             : std_logic_vector(g_fft.wb_factor*c_in_dat_w-1 DOWNTO 0);
198
  signal in_val                 : std_logic:= '0';
199
  signal in_val_cnt             : natural := 0;
200
  signal in_gap                 : std_logic := '0';
201
 
202
  -- Input in sclk domain  
203
  signal in_re_scope            : integer;
204
  signal in_im_scope            : integer;
205
  signal in_val_scope           : std_logic:= '0';
206
 
207
  -- Output
208
  signal out_re_arr             : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
209
  signal out_im_arr             : t_fft_slv_arr(g_fft.wb_factor-1 downto 0);
210
  signal out_re_data            : std_logic_vector(g_fft.wb_factor*c_out_dat_w-1 DOWNTO 0);
211
  signal out_im_data            : std_logic_vector(g_fft.wb_factor*c_out_dat_w-1 DOWNTO 0);
212
  signal out_val                : std_logic:= '0';  -- for parallel output
213
  signal out_val_cnt            : natural := 0;
214
 
215
  -- Output in sclk domain  
216
  signal out_re_scope           : integer := 0;
217
  signal out_im_scope           : integer := 0;
218
  signal out_val_a              : std_logic:= '0';  -- for real A
219
  signal out_val_b              : std_logic:= '0';  -- for real B
220
  signal out_val_c              : std_logic:= '0';  -- for complex(A,B)
221
  signal out_channel            : natural := 0;
222
  signal out_cnt                : natural := 0;
223
  signal out_bin_cnt            : natural := 0;
224
  signal out_bin                : natural;
225
 
226
  -- Output data for complex input data
227
  signal out_re_c_scope         : integer := 0;
228
  signal exp_re_c_scope         : integer := 0;
229
  signal out_im_c_scope         : integer := 0;
230
  signal exp_im_c_scope         : integer := 0;
231
  signal diff_re_c_scope        : integer := 0;
232
  signal diff_im_c_scope        : integer := 0;
233
 
234
  -- register control signals to account for sclk register in output scope signals
235
  signal reg_out_val_a          : std_logic;
236
  signal reg_out_val_b          : std_logic;
237
  signal reg_out_val_c          : std_logic;
238
  signal reg_out_channel        : natural := 0;
239
  signal reg_out_cnt            : natural := 0;
240
  signal reg_out_bin_cnt        : natural := 0;
241
  signal reg_out_bin            : natural;
242
 
243
  -- Output data two real input data A and B
244
  signal out_re_a_scope         : integer := 0;
245
  signal exp_re_a_scope         : integer := 0;
246
  signal out_im_a_scope         : integer := 0;
247
  signal exp_im_a_scope         : integer := 0;
248
  signal out_re_b_scope         : integer := 0;
249
  signal exp_re_b_scope         : integer := 0;
250
  signal out_im_b_scope         : integer := 0;
251
  signal exp_im_b_scope         : integer := 0;
252
  signal diff_re_a_scope        : integer := 0;
253
  signal diff_im_a_scope        : integer := 0;
254
  signal diff_re_b_scope        : integer := 0;
255
  signal diff_im_b_scope        : integer := 0;
256
 
257
begin
258
 
259
  sclk <= (not sclk) or tb_end after c_sclk_period/2;
260
  clk <= (not clk) or tb_end after c_clk_period/2;
261
  rst <= '1', '0' after c_clk_period*7;
262
  random <= func_common_random(random) WHEN rising_edge(clk);
263
  in_gap <= random(random'HIGH) WHEN g_enable_in_val_gaps=TRUE ELSE '0';
264
 
265
  ---------------------------------------------------------------
266
  -- DATA INPUT
267
  ---------------------------------------------------------------
268
  p_input_stimuli : process
269
  begin
270
    -- read input data from file
271
    if c_in_complex then
272
      proc_common_read_integer_file(g_data_file_c, c_nof_lines_c_wg_header, g_data_file_nof_lines, c_nof_complex, input_data_c_arr);
273
    else
274
      proc_common_read_integer_file(g_data_file_a, c_nof_lines_a_wg_header, g_data_file_nof_lines, 1, input_data_a_arr);
275
      proc_common_read_integer_file(g_data_file_b, c_nof_lines_b_wg_header, g_data_file_nof_lines, 1, input_data_b_arr);
276
    end if;
277
    wait for 1 ns;
278
    in_re_arr <= (others=>(others=>'0'));
279
    in_im_arr <= (others=>(others=>'0'));
280
    in_val <= '0';
281
    proc_common_wait_until_low(clk, rst);         -- Wait until reset has finished
282
    proc_common_wait_some_cycles(clk, 10);        -- Wait an additional amount of cycles
283
 
284
    -- apply stimuli
285
    for J in 0 to g_data_file_nof_lines/g_fft.wb_factor-1 loop  -- serial
286
      for I in 0 to g_fft.wb_factor-1 loop  -- parallel
287
        if c_in_complex then
288
          in_re_arr(I) <= to_fft_svec(input_data_c_arr(2*(J*g_fft.wb_factor+I)));
289
          in_im_arr(I) <= to_fft_svec(input_data_c_arr(2*(J*g_fft.wb_factor+I)+1));
290
        else
291
          in_re_arr(I) <= to_fft_svec(input_data_a_arr(J*g_fft.wb_factor+I));
292
          in_im_arr(I) <= to_fft_svec(input_data_b_arr(J*g_fft.wb_factor+I));
293
        end if;
294
      end loop;
295
      in_val <= '1';
296
      proc_common_wait_some_cycles(clk, 1);
297
      if in_gap='1' then
298
        in_val <= '0';
299
        proc_common_wait_some_cycles(clk, 1);
300
      end if;
301
    end loop;
302
 
303
    -- Wait until done
304
    in_val <= '0';
305
    proc_common_wait_some_cycles(clk, c_dut_clk_latency);  -- wait for DUT latency
306
    tb_end_almost <= '1';
307
    proc_common_wait_some_cycles(clk, 100);
308
    tb_end <= '1';
309
    wait;
310
  end process;
311
 
312
  ---------------------------------------------------------------
313
  -- DUT = Device Under Test
314
  ---------------------------------------------------------------
315
  u_dut : entity work.fft_r2_wide
316
  generic map(
317
    g_fft          => g_fft
318
  )
319
  port map(
320
    clk        => clk,
321
    rst        => rst,
322
    in_re_arr  => in_re_arr,
323
    in_im_arr  => in_im_arr,
324
    in_val     => in_val,
325
    out_re_arr => out_re_arr,
326
    out_im_arr => out_im_arr,
327
    out_val    => out_val
328
  );
329
 
330
  -- Data valid count
331
  in_val_cnt  <= in_val_cnt+1  when rising_edge(clk) and in_val='1'  else in_val_cnt;
332
  out_val_cnt <= out_val_cnt+1 when rising_edge(clk) and out_val='1' else out_val_cnt;
333
 
334
  -- Block count t_blk time axis
335
  t_blk <= in_val_cnt / (g_fft.nof_points /g_fft.wb_factor);
336
 
337
  -- Verify nof valid counts
338
  p_verify_out_val_cnt : process
339
  begin
340
    -- Wait until tb_end_almost
341
    proc_common_wait_until_high(clk, tb_end_almost);
342
    assert in_val_cnt > 0 report "Test did not run, no valid input data"  severity error;
343
    if g_fft.wb_factor=g_fft.nof_points then
344
      -- Parallel FFT 
345
      assert out_val_cnt = in_val_cnt report "Unexpected number of valid output data" severity error;
346
    else
347
      -- Wideband FFT 
348
      -- The PFFT has a memory of 1 block, independent of use_reorder and use_separate, but without the
349
      -- reorder buffer it outputs 1 sample more, because that is immediately available in a new block.
350
      -- Ensure g_data_file_nof_lines is multiple of g_fft.nof_points.
351
      if g_fft.use_reorder=true then
352
        assert out_val_cnt = in_val_cnt-c_nof_valid_per_block                report "Unexpected number of valid output data" severity error;
353
      else
354
        assert out_val_cnt = in_val_cnt-c_nof_valid_per_block+c_nof_channels report "Unexpected number of valid output data" severity error;
355
      end if;
356
    end if;
357
    wait;
358
  end process;
359
 
360
  ---------------------------------------------------------------
361
  -- DATA OUTPUT CONTROL IN SCLK DOMAIN
362
  ---------------------------------------------------------------
363
  out_cnt <= out_cnt + 1 when rising_edge(sclk) and out_val_c='1' else out_cnt;
364
 
365
  proc_fft_out_control(g_fft.wb_factor, g_fft.nof_points, c_nof_channels, g_fft.use_reorder, g_fft.use_fft_shift, g_fft.use_separate,
366
                       out_cnt, out_val_c, out_val_a, out_val_b, out_channel, out_bin, out_bin_cnt);
367
 
368
  -- clk diff to avoid combinatorial glitches when selecting the data with out_val_a,b,c
369
  reg_out_val_a   <= out_val_a   when rising_edge(sclk);
370
  reg_out_val_b   <= out_val_b   when rising_edge(sclk);
371
  reg_out_val_c   <= out_val_c   when rising_edge(sclk);
372
  reg_out_channel <= out_channel when rising_edge(sclk);
373
  reg_out_cnt     <= out_cnt     when rising_edge(sclk);
374
  reg_out_bin_cnt <= out_bin_cnt when rising_edge(sclk);
375
  reg_out_bin     <= out_bin     when rising_edge(sclk);
376
 
377
  out_re_a_scope <= out_re_scope when rising_edge(sclk) and out_val_a='1';
378
  out_im_a_scope <= out_im_scope when rising_edge(sclk) and out_val_a='1';
379
  out_re_b_scope <= out_re_scope when rising_edge(sclk) and out_val_b='1';
380
  out_im_b_scope <= out_im_scope when rising_edge(sclk) and out_val_b='1';
381
  out_re_c_scope <= out_re_scope when rising_edge(sclk) and out_val_c='1';
382
  out_im_c_scope <= out_im_scope when rising_edge(sclk) and out_val_c='1';
383
 
384
  exp_re_a_scope <= expected_data_a_re_arr(out_bin_cnt) when rising_edge(sclk) and out_val_a='1';
385
  exp_im_a_scope <= expected_data_a_im_arr(out_bin_cnt) when rising_edge(sclk) and out_val_a='1';
386
  exp_re_b_scope <= expected_data_b_re_arr(out_bin_cnt) when rising_edge(sclk) and out_val_b='1';
387
  exp_im_b_scope <= expected_data_b_im_arr(out_bin_cnt) when rising_edge(sclk) and out_val_b='1';
388
  exp_re_c_scope <= expected_data_c_re_arr(out_bin_cnt) when rising_edge(sclk) and out_val_c='1';
389
  exp_im_c_scope <= expected_data_c_im_arr(out_bin_cnt) when rising_edge(sclk) and out_val_c='1';
390
 
391
  diff_re_a_scope <= exp_re_a_scope - out_re_a_scope;
392
  diff_im_a_scope <= exp_im_a_scope - out_im_a_scope;
393
  diff_re_b_scope <= exp_re_b_scope - out_re_b_scope;
394
  diff_im_b_scope <= exp_im_b_scope - out_im_b_scope;
395
  diff_re_c_scope <= exp_re_c_scope - out_re_c_scope;
396
  diff_im_c_scope <= exp_im_c_scope - out_im_c_scope;
397
 
398
  ---------------------------------------------------------------
399
  -- VERIFY OUTPUT DATA
400
  ---------------------------------------------------------------
401
  -- p_verify_output
402
  gen_verify_two_real : if not c_in_complex generate
403
    assert diff_re_a_scope >= -g_diff_margin and diff_re_a_scope <= g_diff_margin report "Output data A real error" severity error;
404
    assert diff_im_a_scope >= -g_diff_margin and diff_im_a_scope <= g_diff_margin report "Output data A imag error" severity error;
405
    assert diff_re_b_scope >= -g_diff_margin and diff_re_b_scope <= g_diff_margin report "Output data B real error" severity error;
406
    assert diff_im_b_scope >= -g_diff_margin and diff_im_b_scope <= g_diff_margin report "Output data B imag error" severity error;
407
  end generate;
408
  gen_verify_complex : if c_in_complex generate
409
    assert diff_re_c_scope >= -g_diff_margin and diff_re_c_scope <= g_diff_margin report "Output data C real error" severity error;
410
    assert diff_im_c_scope >= -g_diff_margin and diff_im_c_scope <= g_diff_margin report "Output data C imag error" severity error;
411
  end generate;
412
 
413
  ---------------------------------------------------------------
414
  -- READ EXPECTED OUTPUT DATA FROM FILE
415
  ---------------------------------------------------------------
416
  p_expected_output : process
417
  begin
418
    if c_in_complex then
419
      proc_common_read_integer_file(g_data_file_c, c_nof_lines_c_pfft_header, g_data_file_nof_lines, c_nof_complex, expected_data_c_arr);
420
      wait for 1 ns;
421
      for I in 0 to g_data_file_nof_lines-1 loop
422
        expected_data_c_re_arr(I) <= expected_data_c_arr(2*I);
423
        expected_data_c_im_arr(I) <= expected_data_c_arr(2*I+1);
424
      end loop;
425
    else
426
      proc_common_read_integer_file(g_data_file_a, c_nof_lines_a_pfft_header, g_data_file_nof_lines/c_nof_complex, c_nof_complex, expected_data_a_arr);
427
      proc_common_read_integer_file(g_data_file_b, c_nof_lines_b_pfft_header, g_data_file_nof_lines/c_nof_complex, c_nof_complex, expected_data_b_arr);
428
      wait for 1 ns;
429
      for I in 0 to g_data_file_nof_lines/c_nof_complex-1 loop
430
        expected_data_a_re_arr(I) <= expected_data_a_arr(2*I);
431
        expected_data_a_im_arr(I) <= expected_data_a_arr(2*I+1);
432
        expected_data_b_re_arr(I) <= expected_data_b_arr(2*I);
433
        expected_data_b_im_arr(I) <= expected_data_b_arr(2*I+1);
434
      end loop;
435
    end if;
436
    wait;
437
  end process;
438
 
439
  ---------------------------------------------------------------
440
  -- INPUT AND OUTPUT DATA SCOPES
441
  ---------------------------------------------------------------
442
  p_data : process(in_re_arr, in_im_arr, out_re_arr, out_im_arr)
443
  begin
444
    for P in 0 to g_fft.wb_factor-1 loop
445
      in_re_data( (P+1)*c_in_dat_w-1 downto P*c_in_dat_w) <= in_re_arr( P)(c_in_dat_w-1 downto 0);
446
      in_im_data( (P+1)*c_in_dat_w-1 downto P*c_in_dat_w) <= in_im_arr( P)(c_in_dat_w-1 downto 0);
447
 
448
      out_re_data((P+1)*c_out_dat_w-1 downto P*c_out_dat_w) <= out_re_arr(P)(c_out_dat_w-1 downto 0);
449
      out_im_data((P+1)*c_out_dat_w-1 downto P*c_out_dat_w) <= out_im_arr(P)(c_out_dat_w-1 downto 0);
450
    end loop;
451
  end process;
452
 
453
  u_in_re_scope : entity other_lib.common_wideband_data_scope
454
  generic map (
455
    g_sim                 => TRUE,
456
    g_wideband_factor     => g_fft.wb_factor,  -- Wideband rate factor = 4 for dp_clk processing frequency is 200 MHz frequency and SCLK sample frequency Fs is 800 MHz
457
    g_wideband_big_endian => FALSE,            -- When true in_data[3:0] = sample[t0,t1,t2,t3], else when false : in_data[3:0] = sample[t3,t2,t1,t0]
458
    g_dat_w               => c_in_dat_w        -- Actual width of the data samples
459
  )
460
  port map (
461
    -- Sample clock
462
    SCLK      => sclk,  -- sample clk, use only for simulation purposes
463
 
464
    -- Streaming input data
465
    in_data   => in_re_data,
466
    in_val    => in_val,
467
 
468
    -- Scope output samples
469
    out_dat   => OPEN,
470
    out_int   => in_re_scope,
471
    out_val   => in_val_scope
472
  );
473
 
474
  u_in_im_scope : entity other_lib.common_wideband_data_scope
475
  generic map (
476
    g_sim                 => TRUE,
477
    g_wideband_factor     => g_fft.wb_factor,  -- Wideband rate factor = 4 for dp_clk processing frequency is 200 MHz frequency and SCLK sample frequency Fs is 800 MHz
478
    g_wideband_big_endian => FALSE,            -- When true in_data[3:0] = sample[t0,t1,t2,t3], else when false : in_data[3:0] = sample[t3,t2,t1,t0]
479
    g_dat_w               => c_in_dat_w        -- Actual width of the data samples
480
  )
481
  port map (
482
    -- Sample clock
483
    SCLK      => sclk,  -- sample clk, use only for simulation purposes
484
 
485
    -- Streaming input data
486
    in_data   => in_im_data,
487
    in_val    => in_val,
488
 
489
    -- Scope output samples
490
    out_dat   => OPEN,
491
    out_int   => in_im_scope,
492
    out_val   => open
493
  );
494
 
495
  u_out_re_scope : entity other_lib.common_wideband_data_scope
496
  generic map (
497
    g_sim                 => TRUE,
498
    g_wideband_factor     => g_fft.wb_factor,  -- Wideband rate factor = 4 for dp_clk processing frequency is 200 MHz frequency and SCLK sample frequency Fs is 800 MHz
499
    g_wideband_big_endian => FALSE,            -- When true in_data[3:0] = sample[t0,t1,t2,t3], else when false : in_data[3:0] = sample[t3,t2,t1,t0]
500
    g_dat_w               => c_out_dat_w       -- Actual width of the data samples
501
  )
502
  port map (
503
    -- Sample clock
504
    SCLK      => sclk,  -- sample clk, use only for simulation purposes
505
 
506
    -- Streaming input data
507
    in_data   => out_re_data,
508
    in_val    => out_val,
509
 
510
    -- Scope output samples
511
    out_dat   => OPEN,
512
    out_int   => out_re_scope,
513
    out_val   => out_val_c
514
  );
515
 
516
  u_out_im_scope : entity other_lib.common_wideband_data_scope
517
  generic map (
518
    g_sim                 => TRUE,
519
    g_wideband_factor     => g_fft.wb_factor,  -- Wideband rate factor = 4 for dp_clk processing frequency is 200 MHz frequency and SCLK sample frequency Fs is 800 MHz
520
    g_wideband_big_endian => FALSE,            -- When true in_data[3:0] = sample[t0,t1,t2,t3], else when false : in_data[3:0] = sample[t3,t2,t1,t0]
521
    g_dat_w               => c_out_dat_w       -- Actual width of the data samples
522
  )
523
  port map (
524
    -- Sample clock
525
    SCLK      => sclk,  -- sample clk, use only for simulation purposes
526
 
527
    -- Streaming input data
528
    in_data   => out_im_data,
529
    in_val    => out_val,
530
 
531
    -- Scope output samples
532
    out_dat   => OPEN,
533
    out_int   => out_im_scope,
534
    out_val   => open
535
  );
536
 
537
end tb;

powered by: WebSVN 2.1.0

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