summaryrefslogtreecommitdiff
path: root/lab_2/SRC/tb.sv
blob: 00daa958e9ef0c19116fd447c0dc7aca0fb8fe46 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Contains the FAIL_UNLESS_EQUAL macro.
`include "macro.svh"

module tb;
  parameter FULL_TEST = 0;

  // [Step 1] Wildcard import the typedef_pkg package.
  import typedef_pkg::*;

  // [Step 2] Declare signals. The operation, operand_a, operand_b, and result signals must use the
  // data types from the typedef_pkg package. Initialize the clk signal with a value of 1'b0.

  logic clk = 1'b0;
  logic op_start;
  operation_t operation;
  operand_t operand_a;
  operand_t operand_b;
  result_t result;

  // [Step 3] Instantiate the DUV module. The module is declared as

  /*
        module duv
        (
            input logic clk,

            input logic op_start,
            input operation_t operation,
            input operand_t operand_a,
            input operand_t operand_b,

            output result_t result
        );
    */

  duv ALU0 (
      .clk,
      .op_start,
      .operation,
      .operand_a,
      .operand_b,
      .result
  );

  // [Step 4] Always block to generate the clock.

  always #1ns clk = ~clk;

  // [Step 5] Test the DUV using an initial block. Be sure to initialize all DUV input variables, and use the
  // $finish system task to halt simulation at the end of the test.

  initial begin
    automatic result_t expected_result;
    automatic int test_count = 0;

    // Initialise all inputs
    op_start  = 1'b0;
    operation = ADD;
    operand_a = 8'h00;
    operand_b = 8'h00;

    // Wait for initial setup and reset
    repeat (3) @(posedge clk);

    // Exhaustively test all combinations
    for (int op = 0; op < 4; op++) begin
      for (int a = 0; a < (FULL_TEST ? 256 : 16); a++) begin
        for (int b = 0; b < (FULL_TEST ? 256 : 16); b++) begin
          // Set up inputs and calculate expected result first
          operation = operation_t'(op);
          operand_a = a[7:0];
          operand_b = b[7:0];

          // Calculate expected result before starting operation
          case (operation)
            ADD:  expected_result = (operand_a + operand_b) & 16'h01FF;  // ADD
            MULT: expected_result = operand_a * operand_b;  // MULT
            OR:   expected_result = (operand_a | operand_b) & 16'h00FF;  // OR
            AND:  expected_result = (operand_a & operand_b) & 16'h00FF;  // AND
          endcase

          // Start the operation
          op_start = 1'b1;

          // Wait for rising edge to latch inputs
          @(posedge clk);

          op_start = 1'b0;

          // Wait 2 more clock cycles for result
          @(posedge clk);
          @(posedge clk);

          // Compare only relevant bits based on operation
          case (operation)
            ADD:
            `FAIL_UNLESS_EQUAL(expected_result, result & 16'h01FF, $sformatf(
                               "ADD a=%0d b=%0d", operand_a, operand_b))
            MULT:
            `FAIL_UNLESS_EQUAL(expected_result, result, $sformatf(
                               "MULT a=%0d b=%0d", operand_a, operand_b))
            OR:
            `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf(
                               "OR a=%0d b=%0d", operand_a, operand_b))
            AND:
            `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf(
                               "AND a=%0d b=%0d", operand_a, operand_b))
          endcase

          test_count += 1;
        end
      end
    end

    $display("All tests passed! Total tests: %0d", test_count);
    $display("Finished Successfully!");
    $finish;
  end  // Initial end
endmodule : tb