// Contains the FAIL_UNLESS_EQUAL and RND_CHECK macros. `include "macro.svh" module testbench; // [Step 1] Declare signals that connect to DUV. Intialize the clk signal with a value of 1'b0. import typedef_pkg::*; 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] Declare the scoreboard that holds the operation, operand_a, operand_b, and results values. typedef struct { operation_t operation; logic [7:0] operand_a; logic [7:0] operand_b; logic [15:0] result; } scoreboard_t; // [Step 3] Instantiate the DUV module. duv ALU0 ( .clk(clk), .op_start(op_start), .operation(operation), .operand_a(operand_a), .operand_b(operand_b), .result(result) ); // [Step 4] Always block to generate the clock. always #1ns clk = ~clk; // [Step 5] Implement the check task to check the scoreboard. task check(input scoreboard_t sb); automatic logic [15:0] expected_result; case (sb.operation) ADD: begin expected_result = (sb.operand_a + sb.operand_b) & 16'h01FF; `FAIL_UNLESS_EQUAL(expected_result, sb.result & 16'h01FF, $sformatf( "ADD a=%0d b=%0d", sb.operand_a, sb.operand_b)) end MULT: begin expected_result = sb.operand_a * sb.operand_b; `FAIL_UNLESS_EQUAL(expected_result, sb.result, $sformatf( "MULT a=%0d b=%0d", sb.operand_a, sb.operand_b)) end OR: begin expected_result = (sb.operand_a | sb.operand_b) & 16'h00FF; `FAIL_UNLESS_EQUAL(expected_result, sb.result & 16'h00FF, $sformatf( "OR a=%0d b=%0d", sb.operand_a, sb.operand_b)) end AND: begin expected_result = (sb.operand_a & sb.operand_b) & 16'h00FF; `FAIL_UNLESS_EQUAL(expected_result, sb.result & 16'h00FF, $sformatf( "AND a=%0d b=%0d", sb.operand_a, sb.operand_b)) end endcase endtask // [Step 6] 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 scoreboard_t sb; automatic int test_count = 0; automatic logic [1:0] rnd_op; automatic logic [7:0] rnd_a; automatic logic [7:0] rnd_b; // Initialise all inputs op_start = 1'b0; operation = ADD; operand_a = 8'h00; operand_b = 8'h00; // Wait for initial setup repeat (3) @(posedge clk); // Randomised test loop repeat (100) begin `RND_CHECK(std::randomize(rnd_op, rnd_a, rnd_b)) // Log inputs to scoreboard sb.operation = operation_t'(rnd_op); sb.operand_a = rnd_a; sb.operand_b = rnd_b; // Drive DUV inputs and execute operation operation = rnd_op; operand_a = rnd_a; operand_b = rnd_b; op_start = 1'b1; @(posedge clk); op_start = 1'b0; // Wait exactly two clock cycles for result @(posedge clk); @(posedge clk); sb.result = result; check(sb); test_count += 1; end $display("All tests passed! Total tests: %0d", test_count); $display("Finished Successfully!"); $finish; end //:initial endmodule : testbench