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

Subversion Repositories ecpu_alu

[/] [ecpu_alu/] [trunk/] [alu/] [systemc/] [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%d] S:%s[%b] B:%h[u%d] = Y:%h [u%d]  expected %h [u%d] -- 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 randomit($time)
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 (systemc_clk);
53
 
54
  // ALU test vector record
55
  parameter DWIDTH  = 8;
56
  parameter OPWIDTH = 4;
57
 
58
  input                        systemc_clk      ;
59
  wire clk;
60
  // ALU access regs
61
  reg           [DWIDTH-1:0 ]    A        /*verilator public*/;
62
  reg           [DWIDTH-1:0 ]    B        /*verilator public*/;
63
  reg           [OPWIDTH-1:0]    S        ;
64
  wire signed [DWIDTH-1:0 ]    Y       ;
65
  reg                                        CLR      ;
66
 
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
 
103
 test_vector #(DWIDTH, OPWIDTH) this_record ();
104
 test_vector #(DWIDTH, OPWIDTH) this_record_reg ();
105
  test_vector #(DWIDTH, OPWIDTH) next_record ();
106
 
107
  initial
108
  begin
109
                opcode_list[`cADD_AB  ] =   "add";
110
                opcode_list[`cINC_A   ] =  "inca";
111
                opcode_list[`cINC_B   ] =  "incb";
112
                opcode_list[`cSUB_AB  ] =   "sub";
113
                opcode_list[`cCMP_AB  ] =   "cmp";
114
                opcode_list[`cASL_AbyB] =   "asl";
115
                opcode_list[`cASR_AbyB] =   "asr";
116
 
117
                opcode_list[`cCLR     ] =   "clr";
118
                opcode_list[`cDEC_A   ] =  "deca";
119
                opcode_list[`cDEC_B   ] =  "decb";
120
                opcode_list[`cMUL_AB  ] =   "mul";
121
                opcode_list[`cCPL_A   ] =  "cpla";
122
    opcode_list[`cAND_AB  ] =   "and";
123
    opcode_list[`cOR_AB   ] =    "or";
124
    opcode_list[`cXOR_AB  ] =   "xor";
125
    opcode_list[`cCPL_B   ] =  "cplb";
126
 
127
  end
128
 
129
        // instantiate ALU
130
        alu #(DWIDTH, OPWIDTH) alu_inst0  (
131
                                                                    A                   ,
132
                                                                    B                   ,
133
                                                                    S                   ,
134
                                                                    Y                   ,
135
                                                                    CLR         ,
136
                                                                    clk         ,
137
                                                                    C                   ,
138
                                                                    V                   ,
139
                                                                    Z
140
                                                                  );
141
 
142
        // apply clock stimulus
143
        //clock_stim    :       process
144
  //initial
145
        //begin
146
        //      clk     = 1'b0;
147
  //  forever #100 clk = ~clk;
148
        //end
149
  assign clk = ~systemc_clk;
150
  initial   $display ("START OF VERILOG");
151
  always @(clk)
152
  begin
153
    //`ifdef DEBUG_TB
154
    $display("Time has reached [%0t] ",$time);
155
    //`endif
156
  end
157
  always @(systemc_clk)
158
  begin
159
    //`ifdef DEBUG_TB
160
    $display("SYSTEMC_CLK Time has reached [%0t] ",$time);
161
    //`endif
162
  end
163
 
164
  initial errors_found = 0;
165
 
166
  // end test
167
  always @(posedge clk or posedge finished)
168
  begin
169
    if (finished)
170
    begin
171
      if (errors_found > 0)
172
        $display("Test FAILED with %d ERRORs [%0t] ", errors_found, $time);
173
      else
174
        $display("Test PASSED ");
175
 
176
      // close files  and finish
177
      $finish;
178
    end
179
  end
180
 
181
 
182
                // apply_test_vectors
183
          initial
184
                begin
185
            #1;
186
                                          //file                infile  :       text is in "alu_test.txt";
187
            `ifdef RANDOM
188
                                            random_count = `RANDOM;
189
            `else
190
              random_count = 10;
191
            `endif
192
                                                finished  = 1'b0;
193
                                                count       =    0;
194
 
195
                                                CLR           = 1'b1;
196
 
197
                                                started   = 1'b0;
198
            $display ("Generating %0d random inputs", random_count);
199
          end
200
 
201
                                                always @(negedge clk)
202
            begin
203
 
204
              count = count + 1;
205
 
206
              // verify outputs are as expected
207
 
208
             // `ifdef DEBUG_ALU_TB
209
             // `endif
210
 
211
                random_number = `DOLLAR_RANDOM                   ;
212
                `ifdef FORCE_A
213
                  aa    = `FORCE_A                        ;
214
                `else
215
                  aa    = random_number                   ;
216
                `endif
217
 
218
                random_number = `DOLLAR_RANDOM                   ;
219
                `ifdef FORCE_B
220
                  bb    = `FORCE_B                        ;
221
                `else
222
                  bb    = random_number                   ;
223
                `endif
224
 
225
                random_number = `DOLLAR_RANDOM                   ;
226
                `ifdef FORCE_OPCODE
227
                  ss    = `FORCE_OPCODE                   ;
228
                `else
229
                  ss    = get_random_opcode(random_number);
230
                `endif
231
 
232
                random_number = `DOLLAR_RANDOM                   ;
233
                `ifdef FORCE_CLR
234
                  clrc  = `FORCE_CLR                      ;
235
                `else
236
                  clrc  = 0                   ;
237
                `endif
238
 
239
                random_count = random_count - 1;
240
 
241
              if (count == 1)
242
                $display("**** Start of Test ****");
243
              //$display("[%0t ps] A=%h B=%h SS=%s clrc=%b rand=%d", $time, aa, bb, ss, clrc, random_number);
244
              //$display("%b %b %s %b", aa, bb, ss, clrc);
245
              `ifdef DEBUG_ALU_TB
246
 
247
                $stop;
248
              `endif
249
 
250
                                                        // wait for falling edge of CLK
251
                                                        `ifndef verilator
252
                @(negedge clk);
253
               `endif
254
 
255
              `ifdef DEBUG_ALU_TB
256
                $display("**** stage2 of Test ****");
257
                $stop;
258
              `endif
259
                                                        // wait for half of half a period
260
              `ifndef verilator
261
                                                          #(`CLK_HALF_PERIOD / 2);
262
              `endif
263
 
264
 
265
                                                        // apply stimulus to inputs
266
              `ifdef DEBUG_ALU_TB
267
                $display("**** stage3 of Test ****");
268
                $stop;
269
              `endif
270
                                                        A         =     aa                ;
271
                                                        B         =     bb                ;
272
                                                        S         =     string2opcode(ss) ;
273
                                                        CLR     =       clrc              ;
274
 
275
              `ifdef DEBUG_ALU_TB
276
                $display("**** stage4 of Test ****");
277
                $stop;
278
              `endif
279
                                                        // store stimulus for use when verifying outputs
280
                                                        //if (last_ss == "clr")
281
              //begin
282
                                                        //      next_record.A   = `ZERO;
283
                                                        //      next_record.B   = `ZERO;
284
              //end
285
                                                        //else
286
              //begin
287
                                                                next_record.A   = aa;
288
                                                                next_record.B   = bb;
289
                                                        //end
290
 
291
              next_record.S     = ss;
292
 
293
                                                        // wait for rising edge of clock when data 
294
                                                        // should be loaded from registers into ALU
295
                                                        `ifndef verilator
296
                @(posedge clk);
297
              `endif
298
 
299
                                                        // set local 'started' flag so verification can
300
                                                        // start
301
                                                        // grace period of 2 clock cycles for ALU to read
302
                                                        // first set of data
303
 
304
              `ifdef DEBUG_ALU_TB
305
                $stop;
306
              `endif
307
 
308
              if (!CLR && !started)
309
              begin
310
                                                        `ifndef verilator
311
                @(posedge clk);
312
                                                                @(posedge clk);
313
              `endif
314
                                                                if (count > 3)
315
                  started = 1'b1;
316
                                                        end
317
 
318
              if (random_count <= 0)
319
                finished = 1'b1;
320
                                                end // while $feof
321
 
322
          function integer randomit ;
323
          input integer t;
324
          begin
325
            randomit = $c("vsc->randomit()");
326
          end
327
          endfunction
328
                                                // end test
329
                                                //finished = 1'b1;
330
 
331
                                        //end // process apply_test_vectors
332
 
333
                reg signed  [DWIDTH-1:0] result   ;
334
          reg         [DWIDTH-1:0] result_u ;
335
          reg         [DWIDTH-1:0] op1      ;
336
          reg         [DWIDTH-1:0] op2      ;
337
 
338
 
339
          reg check_here;
340
          initial check_here = 1'b0;
341
          // verify_test
342
          always @(negedge clk)
343
                                        begin
344
                                                // wait a little more after results appear
345
            `ifndef verilator
346
                                                  #(`CLK_HALF_PERIOD/2);
347
            `endif
348
 
349
                                                // get expected record
350
                                                this_record_reg.A <= next_record.A;
351
            this_record_reg.B <= next_record.B;
352
            this_record_reg.S <= next_record.S;
353
            this_record_reg.Y <= next_record.Y;
354
 
355
                                                this_record.A <= this_record_reg.A;
356
            this_record.B <= this_record_reg.B;
357
            this_record.S <= this_record_reg.S;
358
            this_record.Y <= this_record_reg.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
 
425
  // function to return the opcode as a std_logic_vector
426
  // from the given string
427
  function      [OPWIDTH-1:0] string2opcode;
428
  input [8*OPWIDTH-1:0] s;
429
  reg   [8*OPWIDTH:1] t;
430
        reg [OPWIDTH-1:0]        opcode;
431
        begin
432
 
433
 
434
                if                  (s == opcode_list[`cADD_AB   ]) opcode = `cADD_AB   ;
435
                else if         (s == opcode_list[`cINC_A    ]) opcode = `cINC_A    ;
436
                else if         (s == opcode_list[`cINC_B    ]) opcode = `cINC_B    ;
437
                else if         (s == opcode_list[`cSUB_AB   ]) opcode = `cSUB_AB   ;
438
                else if         (s == opcode_list[`cCMP_AB   ]) opcode = `cCMP_AB   ;
439
                else if         (s == opcode_list[`cASL_AbyB ]) opcode = `cASL_AbyB ;
440
                else if         (s == opcode_list[`cASR_AbyB ]) opcode = `cASR_AbyB ;
441
                else if         (s == opcode_list[`cCLR      ]) opcode = `cCLR      ;
442
                else if         (s == opcode_list[`cDEC_A    ]) opcode = `cDEC_A    ;
443
                else if         (s == opcode_list[`cDEC_B    ]) opcode = `cDEC_B    ;
444
                else if         (s == opcode_list[`cMUL_AB   ]) opcode = `cMUL_AB   ;
445
                else if         (s == opcode_list[`cCPL_A    ]) opcode = `cCPL_A    ;
446
                else if         (s == opcode_list[`cAND_AB   ]) opcode = `cAND_AB   ;
447
                else if         (s == opcode_list[`cOR_AB    ]) opcode = `cOR_AB    ;
448
                else if         (s == opcode_list[`cXOR_AB   ]) opcode = `cXOR_AB   ;
449
                else if         (s == opcode_list[`cCPL_B    ]) opcode = `cCPL_B    ;
450
 
451
                string2opcode = opcode;
452
  end
453
        endfunction
454
 
455
 
456
  function [8*OPWIDTH:1] get_random_opcode;
457
  input integer myseed;
458
  integer tmp;
459
  begin
460
    `ifndef verilator
461
      tmp = `DOLLAR_RANDOM(myseed);
462
    `else
463
      tmp = `DOLLAR_RANDOM;
464
    `endif
465
    get_random_opcode = opcode_list[({tmp} % 11)];
466
  end
467
  endfunction
468
 
469
  function [DWIDTH-1:0] bas ;
470
  input [DWIDTH-1:0]    a1          ;
471
  input [DWIDTH-1:0]    shift_size  ;
472
  input                 direction   ;
473
  reg   [DWIDTH-1:0]    tmp         ;
474
  integer               tmp2        ;
475
  begin
476
    tmp = a1;
477
    tmp2 = shift_size[2:0];
478
    while (tmp2 > 0)
479
    begin
480
      if (direction)
481
        tmp = {tmp[0], tmp[DWIDTH-1:1]};
482
      else
483
        tmp = {tmp[DWIDTH-2:0], tmp[DWIDTH-1]};
484
      tmp2 = tmp2 - 1;
485
    end
486
    bas = tmp;
487
  end
488
  endfunction
489
 
490
  `ifndef NO_WAVES
491
    initial
492
    begin
493
      `ifndef verilator
494
      $dumpfile("alu_tb.vcd");
495
      $dumpvars;
496
      `endif
497
    end
498
  `endif
499
 
500
`ifdef verilator
501
 
502
 `systemc_header
503
#include "verilog_sc.h" // Header for contained object
504
 `systemc_interface
505
   verilog_sc* vsc;     // Pointer to object we are embedding
506
 `systemc_ctor
507
   vsc = new verilog_sc();      // Construct contained object
508
 `systemc_dtor
509
   delete vsc;  // Destruct contained object
510
 `verilog
511
 
512
`endif
513
 
514
endmodule
515
 

powered by: WebSVN 2.1.0

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