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

Subversion Repositories fpu

[/] [fpu/] [trunk/] [test_bench/] [test_top.v] - Blame information for rev 11

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 rudi
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  FPU                                                        ////
4
////  Floating Point Unit (Single precision)                     ////
5
////                                                             ////
6
////  TEST BENCH                                                 ////
7
////                                                             ////
8
////  Author: Rudolf Usselmann                                   ////
9
////          rudi@asics.ws                                      ////
10
////                                                             ////
11
/////////////////////////////////////////////////////////////////////
12
////                                                             ////
13
//// Copyright (C) 2000 Rudolf Usselmann                         ////
14
////                    rudi@asics.ws                            ////
15
////                                                             ////
16
//// This source file may be used and distributed without        ////
17
//// restriction provided that this copyright statement is not   ////
18
//// removed from the file and that any derivative work contains ////
19
//// the original copyright notice and the associated disclaimer.////
20
////                                                             ////
21
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
22
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
23
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
24
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
25
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
26
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
27
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
28
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
29
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
30
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
31
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
32
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
33
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
34
////                                                             ////
35
/////////////////////////////////////////////////////////////////////
36
 
37
 
38
`timescale 1ns / 100ps
39
 
40
module test;
41
 
42
reg             clk;
43
reg     [31:0]   opa;
44
reg     [31:0]   opb;
45
wire    [31:0]   sum;
46
wire            inf, snan, qnan;
47
wire            div_by_zero;
48
 
49
reg     [31:0]   exp, exp1, exp2, exp3, exp4;
50
reg     [31:0]   opa1, opa2, opa3, opa4;
51
reg     [31:0]   opb1, opb2, opb3, opb4;
52
reg     [2:0]    fpu_op, fpu_op1, fpu_op2, fpu_op3, fpu_op4, fpu_op5;
53
reg     [3:0]    rmode, rmode1, rmode2, rmode3, rmode4, rmode5;
54
reg             start, s1, s2, s3, s4;
55 5 rudi
reg     [115:0]  tmem[0:500000];
56
reg     [115:0]  tmp;
57
reg     [7:0]    oper;
58 2 rudi
reg     [7:0]    exc, exc1, exc2, exc3, exc4;
59
integer         i;
60
wire            ine;
61
reg             match;
62
wire            overflow, underflow;
63
wire            zero;
64
reg             exc_err;
65
reg             m0, m1, m2;
66
reg     [1:0]    fpu_rmode;
67
reg     [3:0]    test_rmode;
68
reg     [4:0]    test_sel;
69
reg             fp_fasu;
70
reg             fp_mul;
71
reg             fp_div;
72
reg             fp_combo;
73 5 rudi
reg             fp_i2f;
74
reg             fp_f2i;
75 2 rudi
reg             test_exc;
76
reg             show_prog;
77
event           error_event;
78
 
79
integer         error, vcount;
80
 
81
always #50 clk = ~clk;
82
 
83
initial
84
   begin
85
        $display ("\n\nFloating Point Unit Version 1.5\n\n");
86
        clk = 0;
87
        start = 0;
88
        s1 = 0;
89
        s2 = 0;
90
        s3 = 0;
91
        s4 = 0;
92
        error = 0;
93
        vcount = 0;
94
 
95
        show_prog = 0;
96 5 rudi
 
97
        fp_combo = 0;
98
        fp_fasu  = 0;
99
        fp_mul   = 0;
100
        fp_div   = 0;
101
        fp_i2f   = 1;
102
        fp_f2i   = 1;
103
 
104
        test_exc = 1;
105
        test_sel   = 5'b01111;
106
        test_rmode = 4'b1111;
107
 
108
        //test_sel   = 5'b00110;
109
        //test_rmode = 4'b01110;
110
 
111 2 rudi
        fp_combo = 1;
112
        fp_fasu  = 1;
113
        fp_mul   = 1;
114
        fp_div   = 1;
115 5 rudi
        fp_i2f   = 1;
116
        fp_f2i   = 1;
117 2 rudi
 
118
        test_sel   = 5'b11111;
119
        test_rmode = 4'b1111;
120
 
121
        @(posedge clk);
122
 
123
`include "test_bench/sel_test.vh"
124
 
125
        repeat (4)      @(posedge clk);
126
        $display("\n\n");
127
 
128
        $display("\n\nAll test Done !\n\n");
129
        $display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
130
 
131
        $finish;
132
   end
133
 
134
 
135
task run_test;
136
begin
137
        @(posedge clk);
138
        #1;
139
        opa = 32'hx;
140
        opb = 32'hx;
141
        fpu_rmode = 2'hx;
142 5 rudi
        fpu_op = 3'hx;
143 2 rudi
 
144
        repeat(4) @(posedge clk);
145
        #1;
146
 
147
        oper = 1;
148
        i=0;
149
        while( |oper == 1'b1 )
150
           begin
151
 
152
                @(posedge clk);
153
                #1;
154
                start = 1;
155
                tmp   = tmem[i];
156 5 rudi
                rmode = tmp[115:112];
157
                exc   = tmp[111:104];
158
                oper  = tmp[103:96];
159 2 rudi
                opa   = tmp[95:64];
160
                opb   = tmp[63:32];
161
                exp   = tmp[31:00];
162
 
163
                // FPU rounding mode
164
                //  0:  float_round_nearest_even
165
                //  1:  float_round_down
166
                //  2:  float_round_up
167
                //  3:  float_round_to_zero
168
 
169
                case(rmode)
170
                  0: fpu_rmode = 0;
171
                  1: fpu_rmode = 3;
172
                  2: fpu_rmode = 2;
173
                  3: fpu_rmode = 1;
174
                  default: fpu_rmode=2'hx;
175
                endcase
176
 
177
                // oper fpu operation
178
                //   1   add
179
                //   2   sub
180
                //   4   mul
181
                //   8   div
182 5 rudi
                //   ...
183 2 rudi
 
184
                case(oper)
185 5 rudi
                   8'b00000001: fpu_op=3'b000;  // Add
186
                   8'b00000010: fpu_op=3'b001;  // Sub
187
                   8'b00000100: fpu_op=3'b010;  // Mul
188
                   8'b00001000: fpu_op=3'b011;  // Div
189
                   8'b00010000: fpu_op=3'b100;  // i2f
190
                   8'b00100000: fpu_op=3'b101;  // f2i
191
                   8'b01000000: fpu_op=3'b110;  // rem
192 2 rudi
                   default: fpu_op=3'bx;
193
                endcase
194
 
195
                if(show_prog)   $write("Vector: %d\015",i);
196
 
197
                //if(oper==1)   $write("+");
198
                //else
199
                //if(oper==2)   $write("-");
200
                //else
201
                //if(oper==4)   $write("*");
202
                //else
203
                //if(oper==8)   $write("/");
204
                //else          $write("Unknown Operation (%d)",oper);
205
 
206
                i= i+1;
207
           end
208
        start = 0;
209
 
210
        @(posedge clk);
211
        #1;
212
        opa = 32'hx;
213
        opb = 32'hx;
214
        fpu_rmode = 2'hx;
215
        fpu_op = 2'hx;
216
 
217
        repeat(4) @(posedge clk);
218
        #1;
219
 
220
        for(i=0;i<500000;i=i+1)          // Clear Memory
221
           tmem[i] = 112'hxxxxxxxxxxxxxxxxx;
222
 
223
   end
224
endtask
225
 
226
always @(posedge clk)
227
   begin
228
        s1 <= #1 start;
229
        s2 <= #1 s1;
230
        s3 <= #1 s2;
231
        s4 <= #1 s3;
232
        exp1 <= #1 exp;
233
        exp2 <= #1 exp1;
234
        exp3 <= #1 exp2;
235
        exp4 <= #1 exp3;
236
        opa1 <= #1 opa;
237
        opa2 <= #1 opa1;
238
        opa3 <= #1 opa2;
239
        opa4 <= #1 opa3;
240
        opb1 <= #1 opb;
241
        opb2 <= #1 opb1;
242
        opb3 <= #1 opb2;
243
        opb4 <= #1 opb3;
244
        fpu_op1 <= #1 fpu_op;
245
        fpu_op2 <= #1 fpu_op1;
246
        fpu_op3 <= #1 fpu_op2;
247
        fpu_op4 <= #1 fpu_op3;
248
        fpu_op5 <= #1 fpu_op4;
249
        rmode1 <= #1 rmode;
250
        rmode2 <= #1 rmode1;
251
        rmode3 <= #1 rmode2;
252
        rmode4 <= #1 rmode3;
253
        rmode5 <= #1 rmode4;
254
        exc1 <= #1 exc;
255
        exc2 <= #1 exc1;
256
        exc3 <= #1 exc2;
257
        exc4 <= #1 exc3;
258
 
259
        #3;
260
 
261
        //      Floating Point Exceptions ( exc4 )
262
        //      -------------------------
263
        //      float_flag_invalid   =  1,
264
        //      float_flag_divbyzero =  4,
265
        //      float_flag_overflow  =  8,
266
        //      float_flag_underflow = 16,
267
        //      float_flag_inexact   = 32
268
 
269
        exc_err=0;
270
 
271
        if(test_exc)
272
           begin
273
 
274
                if(div_by_zero !== exc4[2])
275
                   begin
276
                        exc_err=1;
277
                        $display("\nERROR: DIV_BY_ZERO Exception: Expected: %h, Got %h\n",exc4[2],div_by_zero);
278
                   end
279
 
280 5 rudi
 
281 2 rudi
                if(ine !== exc4[5])
282
                   begin
283
                        exc_err=1;
284
                        $display("\nERROR: INE Exception: Expected: %h, Got %h\n",exc4[5],ine);
285
                   end
286
 
287
                if(overflow !== exc4[3])
288
                   begin
289
                        exc_err=1;
290
                        $display("\nERROR: Overflow Exception Expected: %h, Got %h\n",exc4[3],overflow);
291
                   end
292
 
293
 
294
                if(underflow !== exc4[4])
295
                   begin
296
                        exc_err=1;
297
                        $display("\nERROR: Underflow Exception Expected: %h, Got %h\n",exc4[4],underflow);
298
                   end
299
 
300
 
301
                if(zero !== !(|sum[30:0]))
302
                   begin
303
                        exc_err=1;
304
                        $display("\nERROR: Zero Detection Failed. ZERO: %h, Sum: %h\n", zero, sum);
305
                   end
306
 
307
                if(inf !== ( (sum[30:23] == 8'hff) & ((|sum[22:0]) == 1'b0) ) )
308
                   begin
309
                        exc_err=1;
310
                        $display("\nERROR: INF Detection Failed. INF: %h, Sum: %h\n", inf, sum);
311
                   end
312
 
313 5 rudi
 
314
                if(qnan !== ( &sum[30:23]  & |sum[22:0] )  & !(fpu_op4==5)   )
315 2 rudi
                   begin
316
                        exc_err=1;
317
                        $display("\nERROR: QNAN Detection Failed. QNAN: %h, Sum: %h\n", qnan, sum);
318
                   end
319 5 rudi
 
320
 
321 2 rudi
                if(snan !== ( ( &opa4[30:23] & !opa4[22] & |opa4[21:0]) | ( &opb4[30:23] & !opb4[22] & |opb4[21:0]) ) )
322
                   begin
323
                        exc_err=1;
324
                        $display("\nERROR: SNAN Detection Failed. SNAN: %h, OpA: %h, OpB: %h\n", snan, opa4, opb4);
325
                   end
326
 
327
           end
328
 
329
 
330
        m0 = ( (|sum) !== 1'b1) & ( (|sum) !== 1'b0);           // result unknown (ERROR)
331 5 rudi
        //m0 = ( (|sum) === 1'bx) & 0;
332 2 rudi
        m1 = (exp4 === sum);                                    // results are equal
333
 
334
        // NAN   *** Ignore Fraction Detail ***
335
        m2 =    (sum[31] == exp4[31]) &
336
                (sum[30:23] == 8'hff)  & (exp4[30:23] == 8'hff) &
337
                (sum[22] == exp4[22]) &
338
                ( (|sum[22:0]) == 1'b1) & ((|exp4[22:0]) == 1'b1);
339
 
340
        match = m1 | m2;
341
 
342
        if( (exc_err | !match | m0) & s4 )
343
           begin
344
                -> error_event;
345
                #0.6;
346
                $display("\n%t: ERROR: output mismatch. Expected %h, Got %h (%h)", $time, exp4, sum, {opa4, opb4, exp4} );
347
                $write("opa:\t");       disp_fp(opa4);
348 5 rudi
                $display("opa:\t%h",opa4[30:0]);
349 2 rudi
                case(fpu_op4)
350
                   0: $display("\t+");
351
                   1: $display("\t-");
352
                   2: $display("\t*");
353
                   3: $display("\t/");
354
                   default: $display("\t Unknown Operation ");
355
                endcase
356
                $write("opb:\t");       disp_fp(opb4);
357
                $write("EXP:\t");       disp_fp(exp4);
358
                $write("GOT:\t");       disp_fp(sum);
359
 
360
$display("\nThis rmode: %h fpop: %h; Previous: rmode: %h fpop: %h; Next: rmode: %h fpop: %h\n",
361
rmode4, fpu_op4, rmode5, fpu_op5, rmode3, fpu_op3);
362
 
363
                $display("\n");
364
                error = error + 1;
365
           end
366
 
367
        if(s4)  vcount = vcount + 1;
368
 
369
        if(error > 10)
370
           begin
371
                @(posedge clk);
372
                $display("\n\nFound to many errors, aborting ...\n\n");
373
                $display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
374
                $finish;
375
           end
376
   end
377
 
378
 
379
fpu u0(clk, fpu_rmode, fpu_op, opa, opb, sum, inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero);
380
 
381
 
382
task disp_fp;
383
input [31:0]     fp;
384
 
385
reg     [63:0]   x;
386
reg     [7:0]    exp;
387
 
388
   begin
389
 
390
        exp = fp[30:23];
391
        if(exp==8'h7f)  $write("(%h %h ( 00 ) %h) ",fp[31], exp, fp[22:0]);
392
        else
393
        if(exp>8'h7f)   $write("(%h %h (+%d ) %h) ",fp[31], exp, exp-8'h7f, fp[22:0]);
394
        else            $write("(%h %h (-%d ) %h) ",fp[31], exp, 8'h7f-exp, fp[22:0]);
395
 
396
 
397
        x[51:0] = {fp[22:0], 29'h0};
398
        x[63] = fp[31];
399
        x[62] = fp[30];
400
        x[61:59] = {fp[29], fp[29], fp[29]};
401
        x[58:52] = fp[29:23];
402
 
403
        $display("\t%f",$bitstoreal(x));
404
   end
405
 
406
endtask
407
 
408
endmodule
409
 
410
 
411
 
412
 
413
 
414
 
415
 
416
 
417
 
418
 
419
 
420
 
421
 
422
 
423
 
424
 
425
 
426
 
427
 
428
 
429
 
430
 
431
 
432
 
433
 
434
 

powered by: WebSVN 2.1.0

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