Testbench Code
`timescale 1ns/1ps
module tb_d_latch;
// 1) Inputs
reg EN, D;
// 2) Outputs
wire Q;
// 3) Expected outputs (prefixed "expected_")
reg expected_Q;
// 4) Mismatch (HIGH when outputs != expected)
wire mismatch;
// DUT
d_latch dut(.EN(EN), .D(D), .Q(Q));
// 4-state compare
assign mismatch = (Q !== expected_Q);
// Counters / limits
integer TOTAL_TEST_CASES = 0;
integer TOTAL_PASSED_TEST_CASES = 0;
integer TOTAL_FAILED_TEST_CASES = 0;
integer VCD_MAX_CASES = 32;
integer ERROR_MAX_CASES = 32;
// Loop indices
integer i, j;
// VCD — start at #0; dump only requested signals in order
initial begin
$dumpfile("tb_d_latch.vcd");
$dumpvars(0,
tb_d_latch.EN,
tb_d_latch.D,
tb_d_latch.Q,
tb_d_latch.expected_Q,
tb_d_latch.mismatch
);
$dumpon; // begin dumping at time 0
end
// Golden next-state function
function next_q;
input en_val, d_val, cur_q;
begin
if (en_val) next_q = d_val;
else next_q = cur_q; // hold
end
endfunction
// Named testcase runner
task apply_and_check;
input [127:0] tc_name;
input en_val, d_val;
reg nxt;
begin
EN = en_val;
D = d_val;
nxt = next_q(en_val, d_val, expected_Q);
expected_Q = nxt;
#1; // allow settle
TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
if (!mismatch) begin
TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
end else begin
TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
if (TOTAL_FAILED_TEST_CASES <= ERROR_MAX_CASES) begin
$display("[FAIL] %0s EN=%b D=%b Q=%b expected_Q=%b t=%0t",
tc_name, EN, D, Q, expected_Q, $time);
end
end
if (TOTAL_TEST_CASES == VCD_MAX_CASES)
$dumpoff; // limit VCD to first 32 cases
end
endtask
// Compact truth table from current state
task print_truth_table;
reg curQ, nxt;
integer e, d;
begin
curQ = expected_Q;
$display("Truth table (from current state Q=%b):", curQ);
$display(" EN D | EXP_Q");
$display("--------------");
for (e=0; e<2; e=e+1) begin
for (d=0; d<2; d=d+1) begin
nxt = next_q(e[0], d[0], curQ);
$display(" %0d %0d | %0d", e, d, nxt);
end
end
end
endtask
initial begin
// Establish a known value at t=0 by enabling and driving D=0
EN = 1'b1; D = 1'b0; expected_Q = 1'b0; #1;
// Directed tests (meaningful names)
apply_and_check("track_low" , 1'b1, 1'b0); // Q=0
apply_and_check("track_high" , 1'b1, 1'b1); // Q=1
apply_and_check("hold_ignore_low" , 1'b0, 1'b0); // hold 1
apply_and_check("hold_ignore_high" , 1'b0, 1'b1); // hold 1
apply_and_check("re_enable_to_low" , 1'b1, 1'b0); // Q=0
apply_and_check("hold_again" , 1'b0, 1'b1); // hold 0
apply_and_check("glitch_filter_demo", 1'b0, 1'b0); // still hold 0
// Exhaustive two-step transitions over {EN,D} (4 -> 4)
for (i=0; i<4; i=i+1) begin
apply_and_check("prev_vec", i[1], i[0]);
for (j=0; j<4; j=j+1)
apply_and_check("next_vec", j[1], j[0]);
end
// Random stress
for (i=0; i<100; i=i+1)
apply_and_check("rand", $random, $random);
// Truth table (small input space)
print_truth_table();
// Final summary
$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