Testbench Code
`timescale 1ns/1ps
module tb_sub4_2c;
// 1) Inputs
reg [3:0] a, b;
// 2) DUT outputs
wire [3:0] diff;
wire bout;
// 3) Expected (purely combinational, width-safe)
wire [4:0] golden = {1'b0, a} + {1'b0, ~b} + 5'b00001; // a + (~b) + 1
wire [3:0] exp_diff = golden[3:0];
wire exp_bout = ~golden[4]; // borrow = NOT carry
// 4) Single mismatch flag (treat X/Z as mismatches)
wire mismatch = ({diff, bout} !== {exp_diff, exp_bout});
// Accounting
integer TOTAL_TEST_CASES = 0;
integer TOTAL_PASSED_TEST_CASES = 0;
integer TOTAL_FAILED_TEST_CASES = 0;
// Limits
integer VCD_MAX_CASES = 32; // normal printed rows
integer ERROR_MAX_CASES = 32; // error printed rows
integer printed_rows = 0;
integer printed_errors = 0;
// DUT (pick dataflow or structural)
sub4_2c dut(.a(a), .b(b), .diff(diff), .bout(bout));
// sub4_2c_struct dut(.a(a), .b(b), .diff(diff), .bout(bout));
// VCD dump
initial begin
$dumpfile("tb_sub4_2c.vcd");
$dumpvars(0,
tb_sub4_2c.a, tb_sub4_2c.b,
tb_sub4_2c.diff, tb_sub4_2c.bout,
tb_sub4_2c.exp_diff, tb_sub4_2c.exp_bout,
tb_sub4_2c.mismatch
);
$dumpon;
end
// Header + init
initial begin
a = 0; b = 0;
$display(" a b | diff bout | exp_diff exp_bout | mismatch");
$display("-----------------------------------------------------");
end
// Apply + check (drive -> wait -> read combinational mismatch)
task apply_and_check;
input [3:0] ta, tb_;
begin
a = ta; b = tb_;
#1; // settle
TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
if (!mismatch) begin
TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
if (printed_rows < VCD_MAX_CASES) begin
$display("0x%1h 0x%1h | 0x%1h %0d | 0x%1h %0d | %0d",
a, b, diff, bout, exp_diff, exp_bout, mismatch);
printed_rows = printed_rows + 1;
end
end else begin
TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
if (printed_errors < ERROR_MAX_CASES) begin
$display("ERR: a=0x%1h b=0x%1h => diff=0x%1h bout=%0d (exp diff=0x%1h bout=%0d)",
a, b, diff, bout, exp_diff, exp_bout);
printed_errors = printed_errors + 1;
end
end
// Optional: stop VCD after cap of total vectors
if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
end
endtask
integer ia, ib;
initial begin
// Directed: equal, underflow/borrow, boundaries
apply_and_check(4'h0, 4'h0); // 0 - 0
apply_and_check(4'hF, 4'h0); // no borrow
apply_and_check(4'h0, 4'hF); // borrow
apply_and_check(4'h8, 4'h7); // near MSB boundary
apply_and_check(4'h7, 4'h8); // borrow near MSB boundary
apply_and_check(4'hA, 4'hA); // equal
// Compact sweep (keeps prints/VCD readable)
for (ia = 0; ia < 16; ia = ia + 1)
for (ib = 0; ib < 16; ib = ib + 1)
apply_and_check(ia[3:0], ib[3:0]);
// A few randoms
repeat (16) apply_and_check($random, $random);
// 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