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
|
// Contains the FAIL_UNLESS_EQUAL macro.
`include "macro.svh"
/* [Step 2] Instantiate the DUV module. The module is declared as
module duv
(
input logic clk,
input logic op_start,
input logic [1:0] operation,
input logic [7:0] operand_a,
input logic [7:0] operand_b,
output logic [15:0] result
);
*/
module tb;
parameter FULL_TEST = 1;
// [Step 1] Declare signals. Intialize the clk signal with a value of 1'b0.
logic clk = 1'b0;
logic op_start;
logic [1:0] operation;
logic [7:0] operand_a;
logic [7:0] operand_b;
logic [15:0] result;
// [Step 2] Instantiate the DUV module. The module is declared as
duv ALU0 (
.clk,
.op_start,
.operation,
.operand_a,
.operand_b,
.result
);
// [Step 3] Always block to generate the clock.
always #1ns clk = ~clk;
// [Step 4] Test the DUV using an initial block. Be sure to initialize all DUV input variables, and use the $finish system task
initial begin
automatic logic [15:0] expected_result;
automatic int test_count = 0;
// Initialise all inputs
op_start = 1'b0;
operation = 2'b00;
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 = op[1:0];
operand_a = a[7:0];
operand_b = b[7:0];
// Calculate expected result before starting operation
case (operation)
2'b00: expected_result = (operand_a + operand_b) & 16'h01FF; // ADD
2'b01: expected_result = operand_a * operand_b; // MULT
2'b10: expected_result = (operand_a | operand_b) & 16'h00FF; // OR
2'b11: 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)
2'b00:
`FAIL_UNLESS_EQUAL(expected_result, result & 16'h01FF, $sformatf(
"ADD a=%0d b=%0d", operand_a, operand_b))
2'b01:
`FAIL_UNLESS_EQUAL(expected_result, result, $sformatf(
"MULT a=%0d b=%0d", operand_a, operand_b))
2'b10:
`FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf(
"OR a=%0d b=%0d", operand_a, operand_b))
2'b11:
`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
|