Testbench Code
`timescale 1ns/1ps
module tb_dff_posedge;
// 1) Inputs
reg CLK, D;
// 2) Outputs
wire Q;
// 3) Expected outputs (prefixed "expected_")
reg expected_Q;
// 4) Mismatch (HIGH when outputs != expected)
wire mismatch;
// DUT
dff_posedge dut(.CLK(CLK), .D(D), .Q(Q));
// Scoreboard: sample expected the same way as the DUT
always @(posedge CLK) expected_Q <= D;
// 4-state compare (case-inequality)
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;
integer i, j;
// Free-running clock (10 time units period)
initial begin
CLK = 1'b0;
forever #5 CLK = ~CLK;
end
// VCD — start at #0; dump only requested signals in order
initial begin
$dumpfile("tb_dff_posedge.vcd");
// Order: Inputs -> Outputs -> Expected -> mismatch
$dumpvars(0,
tb_dff_posedge.CLK,
tb_dff_posedge.D,
tb_dff_posedge.Q,
tb_dff_posedge.expected_Q,
tb_dff_posedge.mismatch
);
$dumpon;
end
// Drive D on negedge, check after the next posedge
task drive_and_check;
input [127:0] tc_name;
input d_val;
begin
@(negedge CLK);
D = d_val; // meet setup
@(posedge CLK); // capture edge for DUT and expected
#1; // allow propagation
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)
$display("[FAIL] %0s D@edge=%b Q=%b expected_Q=%b t=%0t",
tc_name, D, Q, expected_Q, $time);
end
if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
end
endtask
// Between-edge data changes (Q must hold)
task change_between_edges;
input d_val;
begin
@(negedge CLK);
D = d_val;
end
endtask
// Compact edge table (2 rows)
task print_edge_table;
integer d;
begin
$display(" D | EXP_Q_after_↑CLK");
$display("---------------------");
for (d=0; d<2; d=d+1)
$display(" %0d | %0d", d[0], d[0]);
end
endtask
initial begin
// Explicitly start with unknown expected to match real flop power-up
D = 1'b0;
expected_Q = 1'bx;
// Give one edge to establish a known state
@(posedge CLK); #1;
// Directed
drive_and_check("cap_0", 1'b0);
change_between_edges(1'b1);
drive_and_check("cap_1", 1'b1);
change_between_edges(1'b0);
drive_and_check("cap_0_again", 1'b0);
// Two-step sequences
for (i=0; i<2; i=i+1) begin
drive_and_check("prev_edge", i[0]);
for (j=0; j<2; j=j+1)
drive_and_check("next_edge", j[0]);
end
// Randomized sequences
for (i=0; i<10; i=i+1) begin
change_between_edges($random);
drive_and_check("cap_rand", $random);
end
// Edge table
print_edge_table();
// 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