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

Subversion Repositories astron_multiplier

[/] [astron_multiplier/] [trunk/] [tb_common_mult.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 danv
-------------------------------------------------------------------------------
2
--
3
-- Copyright (C) 2009
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
-- Purpose: Tb for common_mult architectures
23
-- Description:
24
--   The tb is self verifying.
25
-- Usage:
26
--   > as 10
27
--   > run -all
28
 
29
LIBRARY IEEE, common_pkg_lib, common_components_lib;
30
USE IEEE.std_logic_1164.ALL;
31
USE IEEE.numeric_std.ALL;
32
--USE technology_lib.technology_select_pkg.ALL;
33
USE common_pkg_lib.common_pkg.ALL;
34
USE common_pkg_lib.tb_common_pkg.ALL;
35
 
36
 
37
ENTITY tb_common_mult IS
38
  GENERIC (
39
    g_in_dat_w         : NATURAL := 7;
40
    g_out_dat_w        : NATURAL := 11;  -- = 2*g_in_dat_w, or smaller to truncate MSbits, or larger to extend MSbits
41
    g_nof_mult         : NATURAL := 2;
42
    g_pipeline_input   : NATURAL := 1;
43
    g_pipeline_product : NATURAL := 1;
44
    g_pipeline_output  : NATURAL := 1
45
  );
46
END tb_common_mult;
47
 
48
ARCHITECTURE tb OF tb_common_mult IS
49
 
50
  CONSTANT clk_period    : TIME := 10 ns;
51
  CONSTANT c_pipeline    : NATURAL := g_pipeline_input + g_pipeline_product + g_pipeline_output;
52
  CONSTANT c_nof_mult    : NATURAL := 2;  -- fixed
53
 
54
  CONSTANT c_max_p       : INTEGER :=  2**(g_in_dat_w-1)-1;
55
  CONSTANT c_min         : INTEGER := -c_max_p;
56
  CONSTANT c_max_n       : INTEGER := -2**(g_in_dat_w-1);
57
 
58
  CONSTANT c_technology  : NATURAL := 0;
59
 
60
  FUNCTION func_sresult(in_a, in_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
61
    CONSTANT c_res_w  : NATURAL := 2*g_in_dat_w;  -- use sufficiently large result width
62
    VARIABLE v_a      : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
63
    VARIABLE v_b      : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
64
    VARIABLE v_result : SIGNED(c_res_w-1 DOWNTO 0);
65
  BEGIN
66
    -- Calculate expected result
67
    v_a      := RESIZE_SVEC(in_a, g_in_dat_w);
68
    v_b      := RESIZE_SVEC(in_b, g_in_dat_w);
69
    v_result := RESIZE_NUM(SIGNED(v_a)*SIGNED(v_b), c_res_w);
70
    RETURN RESIZE_SVEC(STD_LOGIC_VECTOR(v_result), g_out_dat_w);  -- Truncate MSbits or sign extend MSBits
71
  END;
72
 
73
  FUNCTION func_uresult(in_a, in_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
74
    CONSTANT c_res_w  : NATURAL := 2*g_in_dat_w;  -- use sufficiently large result width
75
    VARIABLE v_a      : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
76
    VARIABLE v_b      : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
77
    VARIABLE v_result : UNSIGNED(c_res_w-1 DOWNTO 0);
78
  BEGIN
79
    -- Calculate expected result
80
    v_a      := RESIZE_UVEC(in_a, g_in_dat_w);
81
    v_b      := RESIZE_UVEC(in_b, g_in_dat_w);
82
    v_result := RESIZE_NUM(UNSIGNED(v_a)*UNSIGNED(v_b), c_res_w);
83
    RETURN RESIZE_UVEC(STD_LOGIC_VECTOR(v_result), g_out_dat_w);  -- Truncate MSbits or zero extend MSBits
84
  END;
85
 
86
  SIGNAL rst                  : STD_LOGIC;
87
  SIGNAL clk                  : STD_LOGIC := '0';
88
  SIGNAL tb_end               : STD_LOGIC := '0';
89
 
90
  -- Input signals
91
  SIGNAL in_a                 : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
92
  SIGNAL in_b                 : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
93
  SIGNAL in_a_p               : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
94
  SIGNAL in_b_p               : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
95
 
96
  -- Product signals
97
  SIGNAL sresult_expected     : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);  -- pipelined expected result
98
  SIGNAL sresult_rtl          : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
99
  SIGNAL sresult_ip           : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
100
  SIGNAL uresult_expected     : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);  -- pipelined expected result
101
  SIGNAL uresult_rtl          : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
102
  SIGNAL uresult_ip           : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
103
 
104
  -- auxiliary signals
105
  SIGNAL in_a_arr             : STD_LOGIC_VECTOR(g_nof_mult*g_in_dat_w-1 DOWNTO 0);
106
  SIGNAL in_b_arr             : STD_LOGIC_VECTOR(g_nof_mult*g_in_dat_w-1 DOWNTO 0);
107
  SIGNAL out_sresult          : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);  -- combinatorial expected result
108
  SIGNAL out_uresult          : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);  -- combinatorial expected result
109
  SIGNAL sresult_arr_expected : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0);
110
  SIGNAL uresult_arr_expected : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0);
111
  SIGNAL sresult_arr_rtl      : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0);
112
  SIGNAL uresult_arr_rtl      : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0);
113
  SIGNAL sresult_arr_ip       : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0);
114
  SIGNAL uresult_arr_ip       : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0);
115
 
116
BEGIN
117
 
118
  clk  <= NOT clk OR tb_end AFTER clk_period/2;
119
 
120
  -- run 1 us
121
  p_in_stimuli : PROCESS
122
  BEGIN
123
    rst <= '1';
124
    in_a <= TO_SVEC(0, g_in_dat_w);
125
    in_b <= TO_SVEC(0, g_in_dat_w);
126
    proc_common_wait_some_cycles(clk, 10);
127
    rst <= '0';
128
    proc_common_wait_some_cycles(clk, 10);
129
 
130
    -- Some special combinations
131
    in_a <= TO_SVEC(2, g_in_dat_w);
132
    in_b <= TO_SVEC(3, g_in_dat_w);
133
    WAIT UNTIL rising_edge(clk);
134
    in_a <= TO_SVEC(c_max_p, g_in_dat_w);  -- p*p = pp
135
    in_b <= TO_SVEC(c_max_p, g_in_dat_w);
136
    WAIT UNTIL rising_edge(clk);
137
    in_a <= TO_SVEC(c_max_n, g_in_dat_w);  -- -p*-p = pp
138
    in_b <= TO_SVEC(c_max_n, g_in_dat_w);
139
    WAIT UNTIL rising_edge(clk);
140
    in_a <= TO_SVEC(c_max_p, g_in_dat_w);  -- p*-p =  = -pp
141
    in_b <= TO_SVEC(c_max_n, g_in_dat_w);
142
    WAIT UNTIL rising_edge(clk);
143
    in_a <= TO_SVEC(c_max_p, g_in_dat_w);  -- p*(-p-1) = -pp - p
144
    in_b <= TO_SVEC(c_min, g_in_dat_w);
145
    WAIT UNTIL rising_edge(clk);
146
    in_a <= TO_SVEC(c_max_n, g_in_dat_w);  -- -p*(-p-1) = pp + p
147
    in_b <= TO_SVEC(c_min, g_in_dat_w);
148
    WAIT UNTIL rising_edge(clk);
149
 
150
    proc_common_wait_some_cycles(clk, 50);
151
 
152
    -- All combinations
153
    FOR I IN -2**(g_in_dat_w-1) TO 2**(g_in_dat_w-1)-1 LOOP
154
      FOR J IN -2**(g_in_dat_w-1) TO 2**(g_in_dat_w-1)-1 LOOP
155
        in_a <= TO_SVEC(I, g_in_dat_w);
156
        in_b <= TO_SVEC(J, g_in_dat_w);
157
        WAIT UNTIL rising_edge(clk);
158
      END LOOP;
159
    END LOOP;
160
 
161
    proc_common_wait_some_cycles(clk, 50);
162
    tb_end <= '1';
163
    WAIT;
164
  END PROCESS;
165
 
166
  -- pipeline inputs to ease comparison in the Wave window
167
  u_in_a_pipeline : ENTITY common_components_lib.common_pipeline
168
  GENERIC MAP (
169
    g_representation => "SIGNED",
170
    g_pipeline       => c_pipeline,
171
    g_reset_value    => 0,
172
    g_in_dat_w       => g_in_dat_w,
173
    g_out_dat_w      => g_in_dat_w
174
  )
175
  PORT MAP (
176
    rst     => rst,
177
    clk     => clk,
178
    clken   => '1',
179
    in_dat  => in_a,
180
    out_dat => in_a_p
181
  );
182
 
183
  u_in_b_pipeline : ENTITY common_components_lib.common_pipeline
184
  GENERIC MAP (
185
    g_representation => "SIGNED",
186
    g_pipeline       => c_pipeline,
187
    g_reset_value    => 0,
188
    g_in_dat_w       => g_in_dat_w,
189
    g_out_dat_w      => g_in_dat_w
190
  )
191
  PORT MAP (
192
    rst     => rst,
193
    clk     => clk,
194
    clken   => '1',
195
    in_dat  => in_b,
196
    out_dat => in_b_p
197
  );
198
 
199
  gen_wires : FOR I IN 0 TO g_nof_mult-1 GENERATE
200
    -- use same input for all multipliers
201
    in_a_arr((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= in_a;
202
    in_b_arr((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= in_b;
203
    -- calculate expected output only for one multiplier
204
    out_sresult <= func_sresult(in_a, in_b);
205
    out_uresult <= func_uresult(in_a, in_b);
206
    -- copy the expected result for all multipliers
207
    sresult_arr_expected((I+1)*g_out_dat_w-1 DOWNTO I*g_out_dat_w) <= sresult_expected;
208
    uresult_arr_expected((I+1)*g_out_dat_w-1 DOWNTO I*g_out_dat_w) <= uresult_expected;
209
  END GENERATE;
210
 
211
  -- use mult(0) to observe result in Wave window
212
  sresult_rtl <= sresult_arr_rtl(g_out_dat_w-1 DOWNTO 0);
213
  uresult_rtl <= uresult_arr_rtl(g_out_dat_w-1 DOWNTO 0);
214
  sresult_ip  <= sresult_arr_ip(g_out_dat_w-1 DOWNTO 0);
215
  uresult_ip  <= uresult_arr_ip(g_out_dat_w-1 DOWNTO 0);
216
 
217
  u_sresult : ENTITY common_components_lib.common_pipeline
218
  GENERIC MAP (
219
    g_representation => "SIGNED",
220
    g_pipeline       => c_pipeline,
221
    g_reset_value    => 0,
222
    g_in_dat_w       => g_out_dat_w,
223
    g_out_dat_w      => g_out_dat_w
224
  )
225
  PORT MAP (
226
    rst     => rst,
227
    clk     => clk,
228
    clken   => '1',
229
    in_dat  => out_sresult,
230
    out_dat => sresult_expected
231
  );
232
 
233
  u_uresult : ENTITY common_components_lib.common_pipeline
234
  GENERIC MAP (
235
    g_representation => "UNSIGNED",
236
    g_pipeline       => c_pipeline,
237
    g_reset_value    => 0,
238
    g_in_dat_w       => g_out_dat_w,
239
    g_out_dat_w      => g_out_dat_w
240
  )
241
  PORT MAP (
242
    rst     => rst,
243
    clk     => clk,
244
    clken   => '1',
245
    in_dat  => out_uresult,
246
    out_dat => uresult_expected
247
  );
248
 
249
  u_sdut_rtl : ENTITY work.common_mult
250
  GENERIC MAP (
251
    g_technology       => c_technology,
252
    g_variant          => "RTL",
253
    g_in_a_w           => g_in_dat_w,
254
    g_in_b_w           => g_in_dat_w,
255
    g_out_p_w          => g_out_dat_w,
256
    g_nof_mult         => g_nof_mult,
257
    g_pipeline_input   => g_pipeline_input,
258
    g_pipeline_product => g_pipeline_product,
259
    g_pipeline_output  => g_pipeline_output,
260
    g_representation   => "SIGNED"
261
  )
262
  PORT MAP (
263
    rst     => '0',
264
    clk     => clk,
265
    clken   => '1',
266
    in_a    => in_a_arr,
267
    in_b    => in_b_arr,
268
    out_p   => sresult_arr_rtl
269
  );
270
 
271
  u_udut_rtl : ENTITY work.common_mult
272
  GENERIC MAP (
273
    g_technology       => c_technology,
274
    g_variant          => "RTL",
275
    g_in_a_w           => g_in_dat_w,
276
    g_in_b_w           => g_in_dat_w,
277
    g_out_p_w          => g_out_dat_w,
278
    g_nof_mult         => g_nof_mult,
279
    g_pipeline_input   => g_pipeline_input,
280
    g_pipeline_product => g_pipeline_product,
281
    g_pipeline_output  => g_pipeline_output,
282
    g_representation   => "UNSIGNED"
283
  )
284
  PORT MAP (
285
    rst     => '0',
286
    clk     => clk,
287
    clken   => '1',
288
    in_a    => in_a_arr,
289
    in_b    => in_b_arr,
290
    out_p   => uresult_arr_rtl
291
  );
292
 
293
  u_sdut_ip : ENTITY work.common_mult
294
  GENERIC MAP (
295
    g_technology       => c_technology,
296
    g_variant          => "IP",
297
    g_in_a_w           => g_in_dat_w,
298
    g_in_b_w           => g_in_dat_w,
299
    g_out_p_w          => g_out_dat_w,
300
    g_nof_mult         => g_nof_mult,
301
    g_pipeline_input   => g_pipeline_input,
302
    g_pipeline_product => g_pipeline_product,
303
    g_pipeline_output  => g_pipeline_output,
304
    g_representation   => "SIGNED"
305
  )
306
  PORT MAP (
307
    rst     => '0',
308
    clk     => clk,
309
    clken   => '1',
310
    in_a    => in_a_arr,
311
    in_b    => in_b_arr,
312
    out_p   => sresult_arr_ip
313
  );
314
 
315
  u_udut_ip : ENTITY work.common_mult
316
  GENERIC MAP (
317
    g_technology       => c_technology,
318
    g_variant          => "IP",
319
    g_in_a_w           => g_in_dat_w,
320
    g_in_b_w           => g_in_dat_w,
321
    g_out_p_w          => g_out_dat_w,
322
    g_nof_mult         => g_nof_mult,
323
    g_pipeline_input   => g_pipeline_input,
324
    g_pipeline_product => g_pipeline_product,
325
    g_pipeline_output  => g_pipeline_output,
326
    g_representation   => "UNSIGNED"
327
  )
328
  PORT MAP (
329
    rst     => '0',
330
    clk     => clk,
331
    clken   => '1',
332
    in_a    => in_a_arr,
333
    in_b    => in_b_arr,
334
    out_p   => uresult_arr_ip
335
  );
336
 
337
  p_verify : PROCESS(rst, clk)
338
  BEGIN
339
    IF rst='0' THEN
340
      IF rising_edge(clk) THEN
341
        -- verify all multipliers in parallel
342
        ASSERT sresult_arr_rtl = sresult_arr_expected REPORT "Error: wrong Signed RTL result" SEVERITY ERROR;
343
        ASSERT uresult_arr_rtl = uresult_arr_expected REPORT "Error: wrong Unsigned RTL result" SEVERITY ERROR;
344
        ASSERT sresult_arr_ip  = sresult_arr_expected REPORT "Error: wrong Signed IP result" SEVERITY ERROR;
345
        ASSERT uresult_arr_ip  = uresult_arr_expected REPORT "Error: wrong Unsigned IP result" SEVERITY ERROR;
346
      END IF;
347
    END IF;
348
  END PROCESS;
349
 
350
END tb;

powered by: WebSVN 2.1.0

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