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