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_pipe.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
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
-- Purpose: Test bench for fft_r2_pipe.vhd using file data
21
--
22
-- Usage:
23
--   The g_data_file with input and expected output data is created by the
24
--   Matlab script:
25
--
26
--     $RADIOHDL/applications/apertif/matlab/run_pfft.m
27
--
28
--   yields:
29
--
30
--   . g_data_file_*: run_pfft_m_<signal type>_8b_128points_16b.dat
31
--
32
--   First verified use_separate=true with a sinusoid for debugging, because
33
--   this yields an impulse in the spectrum. Then used impulse to verify the
34
--   dual of the sinusoid, because it yields sinusoids in the spectrum. Then
35
--   use chirp of sinusoid and chirp of impulse to increase the test coverage
36
--   of the FFT, while still having reconizable input and output results.
37
--   Finally use noise to even further increase the test coverage. In fact
38
--   for regression tests the noise stimuli are sufficient, but not suitable
39
--   for debugging.
40
--
41
--   The g_data_file_* contains input data and expected FFT output data
42
--   Two real input data files A and B used when g_fft.use_separate = true:
43
--     g_data_file_a           = real input data via A and expected output data for 1 stream, or zeros when UNUSED
44
--     g_data_file_b           = real input data via B and expected output data for 1 stream, or zeros when UNUSED
45
--     g_data_file_a_nof_lines = number of lines with input data that is available in the g_data_file_a
46
--     g_data_file_b_nof_lines = number of lines with input data that is available in the g_data_file_b
47
 
48
--   One complex input data file C used when g_fft.use_separate = false:
49
--     g_data_file_c           = complex input data and expected output data for 1 stream, or zeros when UNUSED
50
--     g_data_file_c_nof_lines = number of lines with input data that is available in the g_data_file_c
51
--   
52
--     g_data_file_nof_lines   = number of lines with input data to read and simulate,
53
--                               must be <= g_data_file_*_nof_lines and choose multiple of g_fft.nof_points
54
-- 
55
--   Then verify nof_chan>0.
56
--
57
--   Then verify g_enable_in_val_gaps=false to check the in_val flow control.
58
--
59
--   Then verify complex input using use_separate=false with a phasor. First
60
--   with use_reorder and then without.
61
--
62
--   For the fft_r2_pipe wb_factor=1 effectively, because the pipelined FFT
63
--   is serial for the entire g_fft.nof_points input time samples. More serial
64
--   then that is not possible.
65
--
66
--   Preserve the various tb options in the tb_tb multi-tb that will serve as
67
--   the regression test.
68
--   
69
--   The g_ppf parameters nof points, in_dat_w and out_dat_w must match the
70
--   settings in the data file.
71
--
72
--   The dat file that is created by Matlab first need to be copied manually
73
--   to these local directories.
74
--   The modelsim_copy_files key in the hdllib.cfg will copy these files to the
75
--   build directory from where they are loaded by Modelsim.
76
--
77
--   > run -all
78
--   > testbench is selftesting.
79
--   > observe the *_scope signals as radix decimal, format analogue format
80
--     signals in the Wave window
81
--
82 5 danv
library ieee, common_pkg_lib, astron_r2sdf_fft_lib, astron_ram_lib, astron_mm_lib;
83 2 danv
use IEEE.std_logic_1164.all;
84
use IEEE.numeric_std.all;
85
use IEEE.std_logic_textio.all;
86
use std.textio.all;
87
use common_pkg_lib.common_pkg.all;
88 5 danv
use astron_ram_lib.common_ram_pkg.ALL;
89 2 danv
use common_pkg_lib.common_lfsr_sequences_pkg.ALL;
90
use common_pkg_lib.tb_common_pkg.all;
91 5 danv
use astron_mm_lib.tb_common_mem_pkg.ALL;
92
use astron_r2sdf_fft_lib.rTwoSDFPkg.all;
93 2 danv
use work.fft_pkg.all;
94
use work.tb_fft_pkg.all;
95
 
96
entity tb_fft_r2_pipe is
97
  generic(
98
    -- DUT generics
99
    --g_fft : t_fft := ( true, false,  true, 0, 1, 0, 128, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- two real inputs A and B
100
    g_fft : t_fft := ( true, false,  true, 0, 1, 0,  32, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- two real inputs A and B
101
    --g_fft : t_fft := ( true, false, false, 0, 1, 0,  64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- complex input reordered
102
    --g_fft : t_fft := (false, false, false, 0, 1, 0,  64, 8, 16, 0, c_dsp_mult_w, 2, true, 56, 2);         -- complex input flipped
103
    --  type t_rtwo_fft is record
104
    --    use_reorder    : boolean;  -- = false for bit-reversed output, true for normal output
105
    --    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
106
    --    use_separate   : boolean;  -- = false for complex input, true for two real inputs
107
    --    nof_chan       : natural;  -- = default 0, defines the number of channels (=time-multiplexed input signals): nof channels = 2**nof_chan         
108
    --    wb_factor      : natural;  -- = default 1, wideband factor
109
    --    twiddle_offset : natural;  -- = default 0, twiddle offset for PFT sections in a wideband FFT
110
    --    nof_points     : natural;  -- = 1024, N point FFT
111
    --    in_dat_w       : natural;  -- = 8, number of input bits
112
    --    out_dat_w      : natural;  -- = 13, number of output bits, bit growth: in_dat_w + natural((ceil_log2(nof_points))/2 + 2)  
113
    --    out_gain_w     : natural;  -- = 0, output gain factor applied after the last stage output, before requantization to out_dat_w
114
    --    stage_dat_w    : natural;  -- = 18, data width used between the stages(= DSP multiplier-width)
115
    --    guard_w        : natural;  -- = 2,  Guard used to avoid overflow in FFT stage. 
116
    --    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)
117
    --    stat_data_w    : positive; -- = 56 (= 18b+18b)+log2(781250)
118
    --    stat_data_sz   : positive; -- = 2 (complex re and im)
119
    --  end record;
120
    --
121
    -- TB generics
122
    g_diff_margin           : integer := 2;  -- maximum difference between HDL output and expected output (> 0 to allow minor rounding differences)
123
 
124
    -- Two real input data files A and B used when g_fft.use_separate = true
125
    -- * 128 points = 64 subbands
126
    --g_data_file_a           : string := "data/run_pfft_m_sinusoid_chirp_8b_128points_16b.dat";
127
    --g_data_file_a_nof_lines : natural := 25600;
128
    --g_data_file_b           : string := "UNUSED";
129
    --g_data_file_b_nof_lines : natural := 0;
130
 
131
    -- * 32 points = 16 subbands
132
    g_data_file_a           : string := "data/run_pfft_m_sinusoid_chirp_8b_32points_16b.dat";
133
    g_data_file_a_nof_lines : natural := 6400;
134
    --g_data_file_a           : string := "data/run_pfft_m_sinusoid_8b_32points_16b.dat";
135
    --g_data_file_a_nof_lines : natural := 160;
136
 
137
    --g_data_file_b           : string := "data/run_pfft_m_impulse_chirp_8b_32points_16b.dat";
138
    --g_data_file_b_nof_lines : natural := 6400;
139
    g_data_file_b           : string := "UNUSED";
140
    g_data_file_b_nof_lines : natural := 0;
141
 
142
    -- One complex input data file C used when g_fft.use_separate = false
143
    --g_data_file_c           : string := "data/run_pfft_complex_m_phasor_chirp_8b_64points_16b.dat";
144
    --g_data_file_c_nof_lines : natural := 12800;
145
    g_data_file_c           : string := "data/run_pfft_complex_m_phasor_8b_64points_16b.dat";
146
    g_data_file_c_nof_lines : natural := 320;
147
 
148
    g_data_file_nof_lines   : natural := 6400;
149
    g_enable_in_val_gaps    : boolean := FALSE   -- when false then in_val flow control active continuously, else with random inactive gaps
150
  );
151
end entity tb_fft_r2_pipe;
152
 
153
architecture tb of tb_fft_r2_pipe is
154
 
155
  constant c_clk_period            : time := 10 ns;
156
 
157
  constant c_in_complex            : boolean := not g_fft.use_separate;
158
  constant c_fft_r2_check          : boolean := fft_r2_parameter_asserts(g_fft);
159
 
160
  constant c_nof_channels          : natural := 2**g_fft.nof_chan;
161
  constant c_nof_data_per_block    : natural := g_fft.nof_points * c_nof_channels;
162
  constant c_nof_valid_per_block   : natural := c_nof_data_per_block;  -- wb_factor=1
163
 
164
  constant c_rnd_factor            : natural := sel_a_b(g_enable_in_val_gaps, 3, 1);
165
  constant c_dut_block_latency     : natural := 3;
166
  constant c_dut_clk_latency       : natural := c_nof_valid_per_block * c_dut_block_latency * c_rnd_factor;  -- worst case
167
 
168
  -- input/output data width
169
  constant c_in_dat_w              : natural := g_fft.in_dat_w;
170
  constant c_out_dat_w             : natural := g_fft.out_dat_w;
171
 
172
  -- Data file access
173
  constant c_nof_lines_header        : natural := 2;
174
  constant c_nof_lines_a_wg_dat      : natural := g_data_file_a_nof_lines;                    -- Real input A via in_re, one value per line
175
  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)
176
  constant c_nof_lines_a_pfft_header : natural := c_nof_lines_header + c_nof_lines_a_wg_dat;
177
  constant c_nof_lines_b_wg_dat      : natural := g_data_file_b_nof_lines;                    -- Real input B via in_im, one value per line
178
  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)
179
  constant c_nof_lines_b_pfft_header : natural := c_nof_lines_header + c_nof_lines_b_wg_dat;
180
  constant c_nof_lines_c_wg_dat      : natural := g_data_file_c_nof_lines;                    -- Complex input, two values per line (re, im)
181
  constant c_nof_lines_c_pfft_dat    : natural := g_data_file_c_nof_lines;                    -- Full spectrum, two values per line (re, im)
182
  constant c_nof_lines_c_pfft_header : natural := c_nof_lines_header + c_nof_lines_c_wg_dat;
183
 
184
  -- signal definitions
185
  signal tb_end                 : std_logic := '0';
186
  signal tb_end_almost          : std_logic := '0';
187
  signal clk                    : std_logic := '0';
188
  signal rst                    : std_logic := '0';
189
  signal random                 : std_logic_vector(15 DOWNTO 0) := (OTHERS=>'0');  -- use different lengths to have different random sequences
190
 
191
  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)
192
  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)
193
  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)
194
 
195
  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)
196
  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
197
  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
198
  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)
199
  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
200
  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
201
  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)
202
  signal expected_data_c_re_arr : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- full spectrum, re
203
  signal expected_data_c_im_arr : t_integer_arr(0 to g_data_file_nof_lines-1) := (OTHERS=>0);                -- full spectrum, im  
204
 
205
  signal t_blk                  : integer := 0;  -- block time counter
206
 
207
  -- Input
208
  signal in_dat_a               : std_logic_vector(c_in_dat_w-1 downto 0);
209
  signal in_dat_a_scope         : integer;
210
  signal in_dat_b               : std_logic_vector(c_in_dat_w-1 downto 0);
211
  signal in_dat_b_scope         : integer;
212
  signal in_channel             : natural;
213
  signal in_val                 : std_logic:= '0';
214
  signal in_val_cnt             : natural := 0;
215
  signal in_blk_val             : std_logic;
216
  signal in_blk_val_cnt         : natural := 0;
217
  signal in_gap                 : std_logic := '0';
218
 
219
  -- Output control
220
  signal out_val_cnt            : natural := 0;
221
  signal out_val                : std_logic:= '0';  -- for complex(A,B)
222
  signal out_val_a              : std_logic:= '0';  -- for real A
223
  signal out_val_b              : std_logic:= '0';  -- for real B
224
  signal out_bin_cnt            : natural := 0;
225
  signal out_bin                : natural;
226
  signal out_channel            : natural;
227
  signal out_blk_val            : std_logic;
228
  signal out_blk_val_cnt        : natural := 0;
229
 
230
  -- Output data
231
  signal out_re                 : std_logic_vector(c_out_dat_w-1 downto 0);
232
  signal out_im                 : std_logic_vector(c_out_dat_w-1 downto 0);
233
 
234
  -- Output data for complex input data
235
  signal out_re_c_scope         : integer := 0;
236
  signal exp_re_c_scope         : integer := 0;
237
  signal out_im_c_scope         : integer := 0;
238
  signal exp_im_c_scope         : integer := 0;
239
 
240
  signal diff_re_c_scope        : integer := 0;
241
  signal diff_im_c_scope        : integer := 0;
242
 
243
  -- register control signals to account for clk register in output scope signals
244
  signal reg_out_val_a          : std_logic;
245
  signal reg_out_val_b          : std_logic;
246
  signal reg_out_val            : std_logic;
247
  signal reg_out_channel        : natural := 0;
248
  signal reg_out_bin_cnt        : natural := 0;
249
  signal reg_out_bin            : natural;
250
 
251
  -- Output data two real input data A and B
252
  signal out_re_a_scope         : integer := 0;
253
  signal exp_re_a_scope         : integer := 0;
254
  signal out_im_a_scope         : integer := 0;
255
  signal exp_im_a_scope         : integer := 0;
256
 
257
  signal out_re_b_scope         : integer := 0;
258
  signal exp_re_b_scope         : integer := 0;
259
  signal out_im_b_scope         : integer := 0;
260
  signal exp_im_b_scope         : integer := 0;
261
 
262
  signal diff_re_a_scope        : integer := 0;
263
  signal diff_im_a_scope        : integer := 0;
264
  signal diff_re_b_scope        : integer := 0;
265
  signal diff_im_b_scope        : integer := 0;
266
 
267
begin
268
 
269
  clk <= (not clk) or tb_end after c_clk_period/2;
270
  rst <= '1', '0' after c_clk_period*7;
271
  random <= func_common_random(random) WHEN rising_edge(clk);
272
  in_gap <= random(random'HIGH) WHEN g_enable_in_val_gaps=TRUE ELSE '0';
273
 
274
  ---------------------------------------------------------------
275
  -- DATA INPUT
276
  ---------------------------------------------------------------
277
  p_input_stimuli : process
278
    variable vP : natural;
279
  begin
280
    -- read input data from file
281
    if c_in_complex then
282
      proc_common_read_integer_file(g_data_file_c, c_nof_lines_header, g_data_file_nof_lines, c_nof_complex, input_data_c_arr);
283
    else
284
      proc_common_read_integer_file(g_data_file_a, c_nof_lines_header, g_data_file_nof_lines, 1, input_data_a_arr);
285
      proc_common_read_integer_file(g_data_file_b, c_nof_lines_header, g_data_file_nof_lines, 1, input_data_b_arr);
286
    end if;
287
    wait for 1 ns;
288
    in_dat_a <= (others=>'0');
289
    in_dat_b <= (others=>'0');
290
    in_val <= '0';
291
    proc_common_wait_until_low(clk, rst);         -- Wait until reset has finished
292
    proc_common_wait_some_cycles(clk, 10);        -- Wait an additional amount of cycles
293
 
294
    -- apply stimuli
295
    for I in 0 to g_data_file_nof_lines-1 loop  -- serial
296
      for K in 0 to c_nof_channels-1 loop  -- serial
297
        if c_in_complex then
298
          in_dat_a <= TO_SVEC(input_data_c_arr(2*I), c_in_dat_w);
299
          in_dat_b <= TO_SVEC(input_data_c_arr(2*I+1), c_in_dat_w);
300
        else
301
          in_dat_a <= TO_SVEC(input_data_a_arr(I), c_in_dat_w);
302
          in_dat_b <= TO_SVEC(input_data_b_arr(I), c_in_dat_w);
303
        end if;
304
        in_channel <= K;
305
        in_val <= '1';
306
        proc_common_wait_some_cycles(clk, 1);
307
        if in_gap='1' then
308
          in_val <= '0';
309
          proc_common_wait_some_cycles(clk, 1);
310
        end if;
311
      end loop;
312
    end loop;
313
 
314
    -- Wait until done
315
    in_val <= '0';
316
    proc_common_wait_some_cycles(clk, c_dut_clk_latency);  -- wait for at least latency of 2 FFT block
317
    tb_end_almost <= '1';
318
    proc_common_wait_some_cycles(clk, 100);
319
    tb_end <= '1';
320
    wait;
321
  end process;
322
 
323
  ---------------------------------------------------------------
324
  -- DUT = Device Under Test
325
  ---------------------------------------------------------------
326
  u_dut : entity work.fft_r2_pipe
327
  generic map (
328
    g_fft      => g_fft
329
  )
330
  port map (
331
    clk      => clk,
332
    rst      => rst,
333
    in_re    => in_dat_a,
334
    in_im    => in_dat_b,
335
    in_val   => in_val,
336
    out_re   => out_re,
337
    out_im   => out_im,
338
    out_val  => out_val
339
  );
340
 
341
  -- Separate output
342
  in_val_cnt  <= in_val_cnt+1  when rising_edge(clk) and in_val='1'  else in_val_cnt;
343
  out_val_cnt <= out_val_cnt+1 when rising_edge(clk) and out_val='1' else out_val_cnt;
344
 
345
  proc_fft_out_control(1, g_fft.nof_points, c_nof_channels, g_fft.use_reorder, g_fft.use_fft_shift, g_fft.use_separate,
346
                       out_val_cnt, out_val, out_val_a, out_val_b, out_channel, out_bin, out_bin_cnt);
347
 
348
  -- Block count t_blk for c_nof_channels>=1 channels per block
349
  in_blk_val  <= '1' when in_val='1'  and (in_val_cnt  mod c_nof_channels)=0 else '0';
350
  out_blk_val <= '1' when out_val='1' and (out_val_cnt mod c_nof_channels)=0 else '0';
351
  in_blk_val_cnt  <= in_val_cnt/c_nof_channels;
352
  out_blk_val_cnt <= out_val_cnt/c_nof_channels;
353
 
354
  t_blk <= t_blk+1 when rising_edge(clk) and in_blk_val='1' and in_blk_val_cnt > 0 and (in_blk_val_cnt MOD c_nof_valid_per_block = 0);
355
 
356
  ---------------------------------------------------------------
357
  -- VERIFY OUTPUT
358
  ---------------------------------------------------------------
359
  p_verify_out_val_cnt : process
360
  begin
361
    -- Wait until tb_end_almost
362
    proc_common_wait_until_high(clk, tb_end_almost);
363
    assert in_val_cnt > 0 report "Test did not run, no valid input data"  severity error;
364
    -- The PFFT has a memory of 1 block, independent of use_reorder and use_separate, but without the
365
    -- reorder buffer it outputs 1 sample more, because that is immediately available in a new block.
366
    -- Ensure g_data_file_nof_lines is multiple of g_fft.nof_points.
367
    if g_fft.use_reorder=true then
368
      assert out_val_cnt = in_val_cnt-c_nof_valid_per_block                report "Unexpected number of valid output data" severity error;
369
    else
370
      assert out_val_cnt = in_val_cnt-c_nof_valid_per_block+c_nof_channels report "Unexpected number of valid output data" severity error;
371
    end if;
372
    wait;
373
  end process;
374
 
375
  p_expected_output : process
376
  begin
377
    -- read expected output data from file
378
    if c_in_complex then
379
      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);
380
      wait for 1 ns;
381
      for I in 0 to g_data_file_nof_lines-1 loop
382
        expected_data_c_re_arr(I) <= expected_data_c_arr(2*I);
383
        expected_data_c_im_arr(I) <= expected_data_c_arr(2*I+1);
384
      end loop;
385
    else
386
      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);
387
      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);
388
      wait for 1 ns;
389
      for I in 0 to g_data_file_nof_lines/c_nof_complex-1 loop
390
        expected_data_a_re_arr(I) <= expected_data_a_arr(2*I);
391
        expected_data_a_im_arr(I) <= expected_data_a_arr(2*I+1);
392
        expected_data_b_re_arr(I) <= expected_data_b_arr(2*I);
393
        expected_data_b_im_arr(I) <= expected_data_b_arr(2*I+1);
394
      end loop;
395
    end if;
396
    wait;
397
  end process;
398
 
399
  -- p_verify_output
400
  gen_verify_two_real : if not c_in_complex generate
401
    assert diff_re_a_scope >= -g_diff_margin and diff_re_a_scope <= g_diff_margin report "Output data A real error" severity error;
402
    assert diff_im_a_scope >= -g_diff_margin and diff_im_a_scope <= g_diff_margin report "Output data A imag error" severity error;
403
    assert diff_re_b_scope >= -g_diff_margin and diff_re_b_scope <= g_diff_margin report "Output data B real error" severity error;
404
    assert diff_im_b_scope >= -g_diff_margin and diff_im_b_scope <= g_diff_margin report "Output data B imag error" severity error;
405
  end generate;
406
  gen_verify_complex : if c_in_complex generate
407
    assert diff_re_c_scope >= -g_diff_margin and diff_re_c_scope <= g_diff_margin report "Output data C real error" severity error;
408
    assert diff_im_c_scope >= -g_diff_margin and diff_im_c_scope <= g_diff_margin report "Output data C imag error" severity error;
409
  end generate;
410
 
411
  ---------------------------------------------------------------
412
  -- DATA SCOPES
413
  ---------------------------------------------------------------
414
  in_dat_a_scope <= TO_SINT(in_dat_a);
415
  in_dat_b_scope <= TO_SINT(in_dat_b);
416
 
417
  -- clk diff to avoid combinatorial glitches when selecting the data with out_val_a,b, out_val
418
  reg_out_val_a   <= out_val_a   when rising_edge(clk);
419
  reg_out_val_b   <= out_val_b   when rising_edge(clk);
420
  reg_out_val     <= out_val     when rising_edge(clk);
421
  reg_out_channel <= out_channel when rising_edge(clk);
422
  reg_out_bin_cnt <= out_bin_cnt when rising_edge(clk);
423
  reg_out_bin     <= out_bin     when rising_edge(clk);
424
 
425
  -- clk diff to avoid combinatorial glitches
426
  out_re_a_scope <= TO_SINT(out_re) when rising_edge(clk) and out_val_a='1';
427
  out_im_a_scope <= TO_SINT(out_im) when rising_edge(clk) and out_val_a='1';
428
  out_re_b_scope <= TO_SINT(out_re) when rising_edge(clk) and out_val_b='1';
429
  out_im_b_scope <= TO_SINT(out_im) when rising_edge(clk) and out_val_b='1';
430
  out_re_c_scope <= TO_SINT(out_re) when rising_edge(clk) and out_val='1';
431
  out_im_c_scope <= TO_SINT(out_im) when rising_edge(clk) and out_val='1';
432
 
433
  exp_re_a_scope <= expected_data_a_re_arr(out_bin_cnt) when rising_edge(clk) and out_val_a='1';
434
  exp_im_a_scope <= expected_data_a_im_arr(out_bin_cnt) when rising_edge(clk) and out_val_a='1';
435
  exp_re_b_scope <= expected_data_b_re_arr(out_bin_cnt) when rising_edge(clk) and out_val_b='1';
436
  exp_im_b_scope <= expected_data_b_im_arr(out_bin_cnt) when rising_edge(clk) and out_val_b='1';
437
  exp_re_c_scope <= expected_data_c_re_arr(out_bin_cnt) when rising_edge(clk) and out_val='1';
438
  exp_im_c_scope <= expected_data_c_im_arr(out_bin_cnt) when rising_edge(clk) and out_val='1';
439
 
440
  diff_re_a_scope <= exp_re_a_scope - out_re_a_scope;
441
  diff_im_a_scope <= exp_im_a_scope - out_im_a_scope;
442
  diff_re_b_scope <= exp_re_b_scope - out_re_b_scope;
443
  diff_im_b_scope <= exp_im_b_scope - out_im_b_scope;
444
  diff_re_c_scope <= exp_re_c_scope - out_re_c_scope;
445
  diff_im_c_scope <= exp_im_c_scope - out_im_c_scope;
446
 
447
end tb;

powered by: WebSVN 2.1.0

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