Reset testing has two halves. Directed sequences prove each known scenario works: reset at time zero, reset in the middle of a transfer, reset while the downstream stalls, and back-to-back resets. Randomised reset timing then probes the windows between those scenarios by moving reset at unpredictable moments while traffic flows.
Sequence | What it proves |
|---|---|
Reset at time zero | The baseline: every register reaches its reset value and the first transaction works. |
Reset mid-transfer | In-flight data is dropped safely and later transfers are intact. |
Reset while stalled | A full buffer or a held handshake survives reset without hanging the link. |
Back-to-back resets | A second reset during recovery does not wedge the control logic. |
Staggered release | Each domain stays quiet until all its dependencies are out of reset. |
Fixed reset times always hit the same windows. A pseudo-random generator with a fixed seed varies the idle gaps between transfers and the cycle on which reset lands, so repeated runs with different seeds sweep different windows while every run stays reproducible. The example below uses an 8-bit LFSR for the gaps and keeps the reset itself directed, so the test stays readable: random spacing, deliberate reset.
A one-entry valid/ready buffer must survive a reset asserted while it holds a word with the sink stalled. Words 0 and 1 pass normally, word 2 is accepted then destroyed by the reset, and words 3 and 4 must arrive intact and in order. The sink also fails the test if the output is ever valid while reset is asserted.
`timescale 1ns/1ps
// One-entry valid/ready buffer with asynchronous reset: the unit under test.
module xfer_buf (
input logic clk,
input logic rst_n,
input logic s_valid,
output logic s_ready,
input logic [7:0] s_data,
output logic m_valid,
input logic m_ready,
output logic [7:0] m_data
);
logic full_q;
logic [7:0] data_q;
assign s_ready = ~full_q & rst_n; // not ready while in reset: a source holding valid must see no accept
assign m_valid = full_q;
assign m_data = data_q;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
full_q <= 1'b0;
data_q <= 8'h00;
end else if (s_valid && s_ready) begin
full_q <= 1'b1;
data_q <= s_data;
end else if (m_valid && m_ready) begin
full_q <= 1'b0;
end
end
endmodule
How to read the result: the PASS line means word 2 was dropped by the reset while words 0, 1, 3 and 4 arrived in order, and the output never showed valid during reset. Every wait is a fixed cycle count backed by a watchdog timeout, so the test terminates deterministically on any simulator. Change the seed to sweep different gap patterns; the expected word list never changes because the reset itself stays directed.
The review checks that the directed set covers every reset in the intent and that random-reset runs actually move reset while traffic flows, with seeds recorded so failures reproduce. A random-reset test that never asserts reset, or that only resets an idle design, fails review no matter how many cycles it runs.
Because a reset that lands while the buffer holds a word is allowed to destroy that word: reset clears state. The contract is safe outputs during reset and intact later words, both of which the test checks.
Random gaps sweep different timing windows reproducibly, while a directed reset keeps the expected word list fixed and the failure diagnosis simple. Fully random reset times come later, once the directed contract passes.