Testbench Code
`timescale 1ns/1ps
module tb_safe_div8;
// 1) Inputs
reg [7:0] dividend;
reg [7:0] divisor;
// 2) DUT outputs
wire [7:0] q;
wire [7:0] r;
wire div_by_zero;
// 3) Expected (prefixed expected_)
reg [7:0] expected_q;
reg [7:0] expected_r;
reg expected_div_by_zero;
// 4) Mismatch (HIGH on fail)
wire mismatch = (q !== expected_q) ||
(r !== expected_r) ||
(div_by_zero !== expected_div_by_zero);
// Counters
integer TOTAL_TEST_CASES = 0;
integer TOTAL_PASSED_TEST_CASES = 0;
integer TOTAL_FAILED_TEST_CASES = 0;
// VCD limit
integer VCD_MAX_CASES = 32;
// Randoms (Verilog-2005: declare at module scope)
integer seed;
integer i;
reg [7:0] rand_din, rand_div;
// DUT
safe_div8 dut(
.dividend(dividend), .divisor(divisor),
.q(q), .r(r), .div_by_zero(div_by_zero)
);
// ---------- Golden model (mirror DUT’s ternary semantics) ----------
task compute_expected;
input [7:0] din;
input [7:0] div;
begin
// Use the same ternary (+==) modeling so x/z propagate consistently
expected_div_by_zero = (div == 8'd0) ? 1'b1 : 1'b0;
expected_q = (div == 8'd0) ? 8'd0 : (din / div);
expected_r = (div == 8'd0) ? 8'd0 : (din % div);
end
endtask
// Apply + check (EXPECTED FIRST -> WAIT -> COMPARE)
task apply_and_check;
input [7:0] din;
input [7:0] div;
begin
dividend = din;
divisor = div;
compute_expected(din, div); // expected first
#1; // let DUT settle
TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
if (!mismatch) TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
else TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
$display(" %3d %3d | %3d %3d %1b | %3d %3d %1b | %0d",
dividend, divisor, q, r, div_by_zero,
expected_q, expected_r, expected_div_by_zero, mismatch);
if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
end
endtask
// VCD dump (Inputs -> Outputs -> Expected -> Mismatch)
initial begin
$dumpfile("tb_safe_div8.vcd");
$dumpvars(0,
tb_safe_div8.dividend, tb_safe_div8.divisor, // Inputs
tb_safe_div8.q, tb_safe_div8.r, tb_safe_div8.div_by_zero, // Outputs
tb_safe_div8.expected_q, tb_safe_div8.expected_r, // Expected
tb_safe_div8.expected_div_by_zero, // Expected
tb_safe_div8.mismatch // Mismatch
);
$dumpon; // start at #0
end
// Header + init + stimulus
initial begin
dividend = 8'd0; divisor = 8'd1;
expected_q = 8'd0; expected_r = 8'd0; expected_div_by_zero = 1'b0;
seed = 32'hA5A5_5AA5 ^ $time;
$display(" dividend divisor | q r dz | exp_q exp_r exp_dz | mismatch");
$display("----------------------------------------------------------------");
// Directed (≤ ~12 printed rows)
apply_and_check(8'd0, 8'd1); // 0/1
apply_and_check(8'd9, 8'd3); // exact
apply_and_check(8'd10, 8'd3); // remainder
apply_and_check(8'd255, 8'd255); // =1, r=0
apply_and_check(8'd200, 8'd250); // q=0, r=200
apply_and_check(8'd37, 8'd0); // divide-by-zero (guard)
apply_and_check(8'd255, 8'd2); // 127, r=1
// X/Z showcase (explicit unknowns)
apply_and_check(8'd127, 8'bzzzz_zzzz); // divisor all Z -> (==0) is x -> outputs x
apply_and_check(8'd247, 8'b0000_10x0); // divisor has X -> outputs x
// A few randoms (stay under 32 total)
for (i = 0; i < 6; i = i + 1) begin
rand_din = $random(seed);
rand_div = $random(seed);
if (rand_div == 8'd0) rand_div = 8'd1; // zero tested above
apply_and_check(rand_din, rand_div);
end
// Summary
$display("----------------------------------------------------------------");
$display("TOTAL_TEST_CASES=%0d", TOTAL_TEST_CASES);
$display("TOTAL_PASSED_TEST_CASES=%0d", TOTAL_PASSED_TEST_CASES);
$display("TOTAL_FAILED_TEST_CASES=%0d", TOTAL_FAILED_TEST_CASES);
$display("ALL_TEST_CASES_PASSED=%s",
(TOTAL_FAILED_TEST_CASES==0) ? "true" : "false");
#2 $finish;
end
endmodule