Testbench Code
`timescale 1ns/1ps
module tb_dff_async_reset;
// 1) Inputs
reg CLK, RST, D;
// 2) Outputs
wire Q;
// 3) Expected outputs (prefixed "expected_")
reg expected_Q;
// 4) Mismatch
wire mismatch;
// DUT
dff_async_reset dut(.CLK(CLK), .RST(RST), .D(D), .Q(Q));
// Scoreboard: mirror DUT behavior exactly
always @(posedge CLK or posedge RST) begin
if (RST) expected_Q <= 1'b0;
else expected_Q <= D;
end
assign mismatch = (Q !== expected_Q);
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-unit period)
initial begin
CLK = 1'b0;
forever #5 CLK = ~CLK;
end
// VCD: only Inputs -> Outputs -> Expected -> mismatch; start at #0
initial begin
$dumpfile("tb_dff_async_reset.vcd");
$dumpvars(0,
tb_dff_async_reset.CLK,
tb_dff_async_reset.RST,
tb_dff_async_reset.D,
tb_dff_async_reset.Q,
tb_dff_async_reset.expected_Q,
tb_dff_async_reset.mismatch
);
$dumpon;
end
task log_case;
begin
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] CLK=%b RST=%b D=%b Q=%b expected_Q=%b t=%0t",
CLK, RST, D, Q, expected_Q, $time);
end
if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
end
endtask
// Assert reset asynchronously at any time
task async_assert_reset;
begin
RST = 1'b0; #1; // ensure a clean 0->1 edge
RST = 1'b1; // async clear
#1; // allow propagation
log_case();
end
endtask
// Deassert reset; Q should hold 0 until the next posedge CLK
task async_release_reset;
begin
RST = 1'b0;
#1;
log_case();
end
endtask
// Drive data on negedge, then check after next posedge
task capture_cycle;
input d_val;
begin
@(negedge CLK);
D = d_val;
@(posedge CLK);
#1;
log_case();
end
endtask
initial begin
// Start with unknown expected like real silicon; first reset will define it
D = 1'b0; RST = 1'b0; expected_Q = 1'bx;
@(negedge CLK);
// Basic async reset behavior and captures
async_assert_reset();
async_release_reset();
capture_cycle(1'b1);
capture_cycle(1'b0);
// Reset during different clock phases and around edges
@(negedge CLK); async_assert_reset();
capture_cycle(1'b1); // clock edge while reset asserted -> Q stays 0
async_release_reset();
capture_cycle(1'b1);
@(posedge CLK); #1; async_assert_reset(); // assert near/after edge
async_release_reset();
capture_cycle(1'b0);
// Randomized sequences
for (i=0; i<6; i=i+1) begin
if ($random) async_assert_reset();
if ($random) async_release_reset();
capture_cycle($random);
end
// 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