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

Subversion Repositories ecpu_alu

[/] [ecpu_alu/] [trunk/] [alu/] [tb/] [alu_tb.v] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 leonous
//
2
`timescale 1ns/1ps
3
 
4
// testbench clock half period                                  
5
`define                 CLK_HALF_PERIOD 10000
6
`define               ZERO                0
7
`define               ADD_VERSION
8
 
9
// Use the same defines from the controller
10
`include  "alu_controller.vh"
11
`ifdef DECIMAL_DISPLAY
12
  `define DISPLAY_FORMAT_SELECTED "[%0t ps] A:%d[u%d] S:%s[%b] B:%d[u%d] = Y:%d [u%d]  expected %d [u%d]"
13
`endif
14
`ifdef HEX_DISPLAY
15
  `define DISPLAY_FORMAT_SELECTED "[%0t ps] A:%h[u%h] S:%s[%b] B:%h[u%h] = Y:%h [u%h]  expected %h [u%h]"
16
`endif
17
`ifdef BINARY_DISPLAY
18
  `define DISPLAY_FORMAT_SELECTED "[%0t ps] A:%b[u%b] S:%s[%b] B:%b[u%b] = Y:%b [u%b]  expected %b [u%b]"
19
`endif
20
 
21
`ifndef DISPLAY_FORMAT_SELECTED
22
  `define DISPLAY_FORMAT_SELECTED "[%0t ps] A:%h[u%h] S:%s[%b] B:%h[u%h] = Y:%h [u%h]  expected %h [u%h]"
23
`endif
24
 
25
`define DISPLAY_FORMAT          `DISPLAY_FORMAT_SELECTED
26
`define DISPLAY_FORMAT_ERROR    {`DISPLAY_FORMAT_SELECTED, " -- ERROR Output Y is wrong"}
27
 
28
`ifndef verilator
29
  `define dollar_display_with_error $display(`DISPLAY_FORMAT_ERROR, $time, this_record.A, A_u, this_record.S, S,  this_record.B, B_u, Y, Y_u, result, result_u)
30
  `define dollar_display_no_error $display(`DISPLAY_FORMAT, $time, this_record.A, A_u, this_record.S, S,  this_record.B, B_u, Y, Y_u, result, result_u)
31
`else
32
  `define dollar_display_with_error $display("[%0t ps] A:%h[u%h] S:%s[%b] B:%h[u%h] = Y:%h [u%h]  expected %h [u%h] -- ERROR Output Y is wrong", $time, this_record.A, A_u, this_record.S, S,  this_record.B, B_u, Y, Y_u, result, result_u)
33
  `define dollar_display_no_error $display("[%0t ps] A:%h[u%h] S:%s[%b] B:%h[u%h] = Y:%h [u%h]  expected %h [u%h]", $time, this_record.A, A_u, this_record.S, S,  this_record.B, B_u, Y, Y_u, result, result_u)
34
`endif
35
 
36
`ifndef verilator
37
  `define DOLLAR_RANDOM $random
38
`else
39
  `define DOLLAR_RANDOM $c("srand")
40
`endif
41
module test_vector;
42
  parameter DWIDTH  = 8;
43
  parameter OPWIDTH = 4;
44
 
45
        reg signed [DWIDTH-1:0]    A     ; // ALU input operand 1
46
        reg signed [DWIDTH-1:0]    B     ; // ALU input operand 2
47
        reg [8*OPWIDTH-1:0] S    ; // ALU input opcode
48
        reg [DWIDTH-1:0]    Y    ; // ALU output
49
 
50
endmodule
51
 
52
module alu_tb;
53
 
54
  // ALU test vector record
55
  parameter DWIDTH  = 8;
56
  parameter OPWIDTH = 4;
57
 
58
 
59
  // ALU access regs
60
  reg           [DWIDTH-1:0 ]    A        ;
61
  reg           [DWIDTH-1:0 ]    B        ;
62
  reg           [OPWIDTH-1:0]    S        ;
63
  wire signed [DWIDTH-1:0 ]    Y       ;
64
  reg                                        CLR      ;
65
 
66
  reg                                        CLK      ;
67
  wire                                     C        ;
68
  wire                                     V        ;
69
  wire                                     Z        ;
70
 
71
  // keep a copy of the previous CLR
72
  reg                          last_CLR ;
73
 
74
  // unsigned local copies for the "recorded" copies for stimulus
75
  // 
76
  reg           [DWIDTH-1:0 ]    A_u      ;
77
  reg           [DWIDTH-1:0 ]    B_u      ;
78
  reg         [DWIDTH-1:0 ]    Y_u      ;
79
 
80
  // finished = '1' indicates end of test run
81
  reg                     finished        ;
82
 
83
  // used to synchronise verification with stimulus
84
  reg                             started                           ;
85
 
86
  integer                 infile , success       ;
87
  integer                 outfile                 ;
88
  integer                 count                   ;
89
 
90
  reg                           cc, vv, zz, clrc, space ;
91
  reg     [DWIDTH-1:0]    aa, bb, yy              ;
92
 
93
  reg     [8*OPWIDTH-1:0] ss, last_ss             ;
94
 
95
  reg                     random_mode             ;
96
  integer                 random_count            ;
97
  integer                 random_number           ;
98
 
99
  integer                 errors_found            ;
100
 
101
  reg [8*OPWIDTH:1]       opcode_list [0:15]      ;
102
  initial
103
  begin
104
                opcode_list[`cADD_AB  ] =   "add";
105
                opcode_list[`cINC_A   ] =  "inca";
106
                opcode_list[`cINC_B   ] =  "incb";
107
                opcode_list[`cSUB_AB  ] =   "sub";
108
                opcode_list[`cCMP_AB  ] =   "cmp";
109
                opcode_list[`cASL_AbyB] =   "asl";
110
                opcode_list[`cASR_AbyB] =   "asr";
111
                opcode_list[`cCLR     ] =   "clr";
112
                opcode_list[`cDEC_A   ] =  "deca";
113
                opcode_list[`cDEC_B   ] =  "decb";
114
                opcode_list[`cMUL_AB  ] =   "mul";
115
                opcode_list[`cCPL_A   ] =  "cpla";
116
    opcode_list[`cAND_AB  ] =   "and";
117
    opcode_list[`cOR_AB   ] =    "or";
118
    opcode_list[`cXOR_AB  ] =   "xor";
119
    opcode_list[`cCPL_B   ] =  "cplb";
120
 
121
  end
122
  initial
123
  begin
124
    `ifdef RANDOM
125
      random_count  = `RANDOM;
126
      random_mode   = 1'b1;
127
      $display ("Generating %0d random inputs", random_count);
128
    `else
129
      random_mode   = 1'b0;
130
      random_count = 0;
131
    `endif
132
  end
133
 
134
  //    records to store stimulus for verification
135
  test_vector #(DWIDTH, OPWIDTH) this_record ();
136
  test_vector #(DWIDTH, OPWIDTH) next_record ();
137
 
138
        // instantiate ALU
139
        alu #(DWIDTH, OPWIDTH) alu_inst0  (
140
                                                                    A                   ,
141
                                                                    B                   ,
142
                                                                    S                   ,
143
                                                                    Y                   ,
144
                                                                    CLR         ,
145
                                                                    CLK         ,
146
                                                                    C                   ,
147
                                                                    V                   ,
148
                                                                    Z
149
                                                                  );
150
 
151
        // apply clock stimulus
152
        //clock_stim    :       process
153
  initial
154
        begin
155
                CLK     = 1'b0;
156
    forever #(`CLK_HALF_PERIOD) CLK = ~CLK;
157
        end
158
 
159
  always @(CLK)
160
  begin
161
    `ifdef DEBUG_TB
162
    $display("Time has reached [%0t] ",$time);
163
    `endif
164
  end
165
 
166
  initial errors_found = 0;
167
 
168
  // end test
169
  always @(posedge CLK or posedge finished)
170
  begin
171
    if (finished)
172
    begin
173
      if (errors_found > 0)
174
        $display("Test FAILED with %d ERRORs [%0t] ", errors_found, $time);
175
      else
176
        $display("Test PASSED ");
177
 
178
      // close files  and finish
179
      $fclose(infile);
180
      $fclose(outfile);
181
      $finish;
182
    end
183
  end
184
 
185
 
186
 
187
                // apply_test_vectors
188
          initial
189
                begin
190
            #1;
191
                                          //file                infile  :       text is in "alu_test.txt";
192
                                          infile          = $fopen("alu_test.txt", "r");
193
 
194
 
195
                                                finished  = 1'b0;
196
                                                count       =    0;
197
 
198
                                                CLR           = 1'b1;
199
 
200
                                                started   = 1'b0;
201
 
202
 
203
                                                while ((!$feof(infile) && !random_mode) || (random_mode && random_count > 0))
204
            begin
205
 
206
              count = count + 1;
207
 
208
              // verify outputs are as expected
209
 
210
              `ifdef DEBUG_ALU_TB
211
                $display ("%t  %0d random inputs", $time, random_count);
212
              `endif
213
 
214
              if (random_mode)
215
              begin
216
                random_number = `DOLLAR_RANDOM                   ;
217
                `ifdef FORCE_A
218
                  aa    = `FORCE_A                        ;
219
                `else
220
                  aa    = random_number                   ;
221
                `endif
222
 
223
                random_number = `DOLLAR_RANDOM                   ;
224
                `ifdef FORCE_B
225
                  bb    = `FORCE_B                        ;
226
                `else
227
                  bb    = random_number                   ;
228
                `endif
229
 
230
                random_number = `DOLLAR_RANDOM                   ;
231
                `ifdef FORCE_OPCODE
232
                  ss    = `FORCE_OPCODE                   ;
233
                `else
234
                  ss    = get_random_opcode(random_number);
235
                `endif
236
 
237
                random_number = `DOLLAR_RANDOM                   ;
238
                `ifdef FORCE_CLR
239
                  clrc  = `FORCE_CLR                      ;
240
                `else
241
                  clrc  = random_number                   ;
242
                `endif
243
 
244
                random_count = random_count - 1;
245
              end
246
              else
247
              begin
248
                                                          success  = $fscanf(infile, "%b %b %s %b", aa, bb, ss, clrc);
249
                while (success == 0 && !$feof(infile))
250
                begin
251
                  success  = $fgetc(infile);
252
                  success  = $fscanf(infile, "%b %b %s %b", aa, bb, ss, clrc);
253
                end
254
              end
255
 
256
              if (count == 1)
257
                $display("**** Start of Test ****");
258
 
259
              //$display("%b %b %s %b", aa, bb, ss, clrc);
260
              `ifdef DEBUG_ALU_TB
261
 
262
                $stop;
263
              `endif
264
 
265
                                                        // wait for falling edge of CLK
266
                                                        `ifndef verilator
267
                @(negedge CLK);
268
               `endif
269
 
270
              `ifdef DEBUG_ALU_TB
271
                $display("**** stage2 of Test ****");
272
                $stop;
273
              `endif
274
                                                        // wait for half of half a period
275
              `ifndef verilator
276
                                                          #(`CLK_HALF_PERIOD / 2);
277
              `endif
278
 
279
 
280
                                                        // apply stimulus to inputs
281
              `ifdef DEBUG_ALU_TB
282
                $display("**** stage3 of Test ****");
283
                $stop;
284
              `endif
285
                                                        A         =     aa                ;
286
                                                        B         =     bb                ;
287
                                                        S         =     string2opcode(ss) ;
288
                                                        CLR     =       clrc              ;
289
 
290
              `ifdef DEBUG_ALU_TB
291
                $display("**** stage4 of Test ****");
292
                $stop;
293
              `endif
294
                                                        // store stimulus for use when verifying outputs
295
                                                        //if (last_ss == "clr")
296
              //begin
297
                                                        //      next_record.A   = `ZERO;
298
                                                        //      next_record.B   = `ZERO;
299
              //end
300
                                                        //else
301
              //begin
302
                                                                next_record.A   = aa;
303
                                                                next_record.B   = bb;
304
                                                        //end
305
 
306
              next_record.S     = ss;
307
 
308
                                                        // wait for rising edge of clock when data 
309
                                                        // should be loaded from registers into ALU
310
                                                        `ifndef verilator
311
                @(posedge CLK);
312
              `endif
313
 
314
                                                        // set local 'started' flag so verification can
315
                                                        // start
316
                                                        // grace period of 2 clock cycles for ALU to read
317
                                                        // first set of data
318
 
319
              `ifdef DEBUG_ALU_TB
320
                $stop;
321
              `endif
322
 
323
              if (!CLR && !started)
324
              begin
325
                                                        `ifndef verilator
326
                @(posedge CLK);
327
                                                                @(posedge CLK);
328
              `endif
329
                                                                started = 1'b1;
330
                                                        end
331
                                                end // while $feof
332
 
333
                                                // end test
334
                                                finished = 1'b1;
335
 
336
                                        end // process apply_test_vectors
337
 
338
                reg signed  [DWIDTH-1:0] result   ;
339
          reg         [DWIDTH-1:0] result_u ;
340
          reg         [DWIDTH-1:0] op1      ;
341
          reg         [DWIDTH-1:0] op2      ;
342
 
343
 
344
          reg check_here;
345
          initial check_here = 1'b0;
346
          // verify_test
347
          always @(posedge CLK)
348
                                        begin
349
                                                // wait a little more after results appear
350
            `ifndef verilator
351
                                                  #(`CLK_HALF_PERIOD/2);
352
            `endif
353
 
354
                                                // get expected record
355
                                                this_record.A <= next_record.A;
356
            this_record.B <= next_record.B;
357
            this_record.S <= next_record.S;
358
            this_record.Y <= next_record.Y;
359
 
360
                                                if (started && !CLR)
361
            begin
362
                                                        // convert string operands from this_record
363
                                                        // into std_logic_vectors
364
                                                        op1     = this_record.A;
365
                                                        op2     = this_record.B;
366
 
367
                                                        // depending on opcode command string...perform
368
                                                        // high level equivalent of ALU operation and store
369
                                                        // in 'result'
370
                                                        if            (this_record.S ==  opcode_list[`cADD_AB  ]  )  result = op1 + op2          ;
371
                                                        else if         (this_record.S ==  opcode_list[`cINC_A   ]  )  result = op1 + 1            ;
372
                                                        else if         (this_record.S ==  opcode_list[`cINC_B   ]  )  result = op2 + 1            ;
373
                                                        else if         (this_record.S ==  opcode_list[`cSUB_AB  ]  )  result = op1 - op2          ;
374
                                                        else if         (this_record.S ==  opcode_list[`cCMP_AB  ]  )  result = Y                  ;
375
                                                        else if         (this_record.S ==  opcode_list[`cASL_AbyB]  )  result = bas(op1, op2, 1'b0);
376
                                                        else if         (this_record.S ==  opcode_list[`cASR_AbyB]  )  result = bas(op1, op2, 1'b1);
377
                                                        else if         (this_record.S ==  opcode_list[`cCLR     ]  )  result = (op1==op2) ? 'd0: Y;
378
                                                        else if         (this_record.S ==  opcode_list[`cDEC_A   ]  )  result = op1 - 1            ;
379
                                                        else if         (this_record.S ==  opcode_list[`cDEC_B   ]  )  result = op2 - 1            ;
380
              else if   (this_record.S ==  opcode_list[`cMUL_AB  ]  )  result = Y                  ;
381
              else if   (this_record.S ==  opcode_list[`cCPL_A   ]  )  result = ~op1               ;
382
              else if   (this_record.S ==  opcode_list[`cAND_AB  ]  )  result = op1 & op2          ;
383
              else if   (this_record.S ==  opcode_list[`cOR_AB   ]  )  result = op1 | op2          ;
384
              else if   (this_record.S ==  opcode_list[`cXOR_AB  ]  )  result = op1 ^ op2          ;
385
              else if   (this_record.S ==  opcode_list[`cCPL_B   ]  )  result = ~op2               ;
386
 
387
 
388
                                                        // WORKAROUND for bug wher clr lasts for two cycles
389
              if (last_ss == "clr" || last_CLR)
390
                result = Y;
391
                                                        last_ss                   = this_record.S;
392
 
393
              // create signed and unsigned copies of
394
              // ALU output Y, stimulus values and the expected result
395
              A_u       = this_record.A ;
396
              B_u       = this_record.B ;
397
              Y_u       = Y             ;
398
              result_u  = result        ;
399
 
400
              check_here = ~ check_here; //  for debug
401
                                                        if( Y != result  || (&result === 1'bx) || (|result === 1'bz)
402
                  || (&Y === 1'bx) || (|Y === 1'bz))
403
              begin
404
                `dollar_display_with_error;
405
                errors_found = errors_found + 1;
406
              end
407
              else
408
                `dollar_display_no_error;
409
 
410
              `ifdef STOP_ON_ERROR
411
                if (errors_found > `STOP_ON_ERROR)
412
                begin
413
                  $display("Maximum error count of %d reached...Terminating simulation", errors_found);
414
                  $finish;
415
                end
416
              `endif
417
 
418
                                                end // end if (started and !CLR)
419
 
420
            last_CLR = CLR;
421
 
422
                                        end // process verify_test
423
 
424
    `ifdef CREATE_SIGNAL_LOG
425
      // open output file for writing
426
      initial outfile = $fopen("alu_test.out","w");
427
 
428
      // vector_stim_out 
429
      always @(posedge CLK )
430
      begin
431
        $fwrite (outfile, "A=%h B=%h S=%b Y=%h CLR=%b CLK=%b C=%b V=%b Z=%b\n", A,B,S,Y,CLR,CLK,C,V,Z);
432
      end
433
    `endif
434
 
435
 
436
  // function to return the opcode as a std_logic_vector
437
  // from the given string
438
  function      [OPWIDTH-1:0] string2opcode;
439
  input [8*OPWIDTH-1:0] s;
440
  reg   [8*OPWIDTH:1] t;
441
        reg [OPWIDTH-1:0]        opcode;
442
        begin
443
 
444
 
445
                if                  (s == opcode_list[`cADD_AB   ]) opcode = `cADD_AB   ;
446
                else if         (s == opcode_list[`cINC_A    ]) opcode = `cINC_A    ;
447
                else if         (s == opcode_list[`cINC_B    ]) opcode = `cINC_B    ;
448
                else if         (s == opcode_list[`cSUB_AB   ]) opcode = `cSUB_AB   ;
449
                else if         (s == opcode_list[`cCMP_AB   ]) opcode = `cCMP_AB   ;
450
                else if         (s == opcode_list[`cASL_AbyB ]) opcode = `cASL_AbyB ;
451
                else if         (s == opcode_list[`cASR_AbyB ]) opcode = `cASR_AbyB ;
452
                else if         (s == opcode_list[`cCLR      ]) opcode = `cCLR      ;
453
                else if         (s == opcode_list[`cDEC_A    ]) opcode = `cDEC_A    ;
454
                else if         (s == opcode_list[`cDEC_B    ]) opcode = `cDEC_B    ;
455
                else if         (s == opcode_list[`cMUL_AB   ]) opcode = `cMUL_AB   ;
456
                else if         (s == opcode_list[`cCPL_A    ]) opcode = `cCPL_A    ;
457
                else if         (s == opcode_list[`cAND_AB   ]) opcode = `cAND_AB   ;
458
                else if         (s == opcode_list[`cOR_AB    ]) opcode = `cOR_AB    ;
459
                else if         (s == opcode_list[`cXOR_AB   ]) opcode = `cXOR_AB   ;
460
                else if         (s == opcode_list[`cCPL_B    ]) opcode = `cCPL_B    ;
461
 
462
                string2opcode = opcode;
463
  end
464
        endfunction
465
 
466
 
467
  function [8*OPWIDTH:1] get_random_opcode;
468
  input integer myseed;
469
  integer tmp;
470
  begin
471
    `ifndef verilator
472
      tmp = `DOLLAR_RANDOM(myseed);
473
    `else
474
      tmp = $c("srand");
475
    `endif
476
    get_random_opcode = opcode_list[({tmp} % 11)];
477
  end
478
  endfunction
479
 
480
  function [DWIDTH-1:0] bas ;
481
  input [DWIDTH-1:0]    a1          ;
482
  input [DWIDTH-1:0]    shift_size  ;
483
  input                 direction   ;
484
  reg   [DWIDTH-1:0]    tmp         ;
485
  integer               tmp2        ;
486
  begin
487
    tmp = a1;
488
    tmp2 = shift_size[2:0];
489
    while (tmp2 > 0)
490
    begin
491
      if (direction)
492
        tmp = {tmp[0], tmp[DWIDTH-1:1]};
493
      else
494
        tmp = {tmp[DWIDTH-2:0], tmp[DWIDTH-1]};
495
      tmp2 = tmp2 - 1;
496
    end
497
    bas = tmp;
498
  end
499
  endfunction
500
 
501
  `ifndef NO_WAVES
502
    initial
503
    begin
504
      `ifndef verilator
505
      $dumpfile("alu_tb.vcd");
506
      $dumpvars;
507
      `endif
508
    end
509
  `endif
510
endmodule
511
 

powered by: WebSVN 2.1.0

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