01 · State and power
Mid-Test Reset Orchestration
Make every testbench component survive a warm, IP-level, or subsystem reset without hanging, comparing stale traffic, or corrupting its register model.
A reset observer ends the old comparison epoch, cancels traffic, clears interfaces and models, then releases stimulus only after the DUT advertises readiness.
observed transaction epoch = active scoreboard epoch → eligible for comparison
Why it matters
- Modern SoCs reset more than once at power-on. Warm resets, IP resets, and subsystem resets can occur while the rest of the chip remains live.
- A testbench that cannot recover from reset during traffic cannot verify high-availability or error-recovery behavior.
- Hardware clears registers and pipelines immediately, while software testbench objects preserve state until they are told what to discard, retain, or restart.
What is difficult
- A sequence can block forever waiting for a response that the reset erased.
- A scoreboard can retain pre-reset expected items and compare them against unrelated post-reset traffic.
- Reset scope is not always global. One agent may need to restart while unrelated interfaces continue running.
- UVM phase jumping requires every component and domain to move coherently, which is difficult to debug and scale across a large team.
Failure signatures
- A driver completes a stale handshake or leaves valid asserted across reset.
- A sequencer keeps requests that can no longer receive responses.
- Expected or actual queues leak across the reset boundary and create false mismatches.
- The RAL mirror retains pre-reset values even though hardware returned non-sticky fields to defaults.
- A DUT buffer fails to clear and releases old data after reset.
Two viable approaches—and their cost
UVM phase jumping
Force the UVM domain back to reset_phase so components reinitialize through standard phase callbacks.
- Uses the official UVM phase mechanism.
- Can coordinate component reinitialization through existing reset-phase code.
- Difficult to debug when only part of the environment jumps.
- Can deadlock when components or domains do not move together.
- Provides less granular control for an IP-only reset while other agents continue.
Centralized reset handler
Monitor reset as a dynamic sideband event and explicitly broadcast cleanup and restart work.
- Keeps reset behavior explicit and independent of the UVM phase controller.
- Can reset one agent or subsystem without disturbing unrelated traffic.
- Makes each component's flush, kill, preserve, and restart policy reviewable.
- Every stateful component needs a reset cleanup or recovery method.
- The environment must define ordering between aborting stimulus, flushing checks, and resetting mirrors.
Interview answer, built from the mechanism
- Treat reset as a dynamic event rather than a one-time phase. A dedicated reset handler detects the edge and tells every affected component what to do.
- Make the driver interruptible with fork-join_any so the reset watcher can abort a bus handshake immediately. Stop sequencer activity so no blocked request remains behind.
- Flush expected and actual scoreboard state that hardware discarded, and call the appropriate RAL reset type so the mirror matches hardware defaults while sticky state is preserved.
- Wait for reset release, perform any required reboot or initialization checks, and only then resume stimulus.
Component responsibility contract
| Component | Responsibility | Required change |
|---|---|---|
| Driver | Handshake abort | Wrap sequence-item driving and reset detection in fork-join_any. |
| Sequencer | Sequence kill | Call stop_sequences() to clear blocked and queued requests. |
| Scoreboard | Data flush | Clear expected and actual queues plus local counters and state machines. |
| RAL model | Mirror reset | Call the correct reg_model.reset() type to match hardware defaults. |
| Reset handler | Event ordering | Broadcast reset, coordinate cleanup, wait for release, and authorize restart. |
Implementation patterns
task mac_driver::run_phase(uvm_phase phase);
forever begin
wait (vif.rst_n === 1'b1);
fork
begin : drive_process
forever begin
seq_item_port.get_next_item(req);
drive_item(req);
seq_item_port.item_done();
end
end
begin : reset_watcher
@(negedge vif.rst_n);
uvm_report_info("DRV", "Reset detected: abort drive", UVM_LOW);
end
join_any
disable fork;
cleanup_signals();
end
endtask
task mac_driver::cleanup_signals();
vif.valid <= 1'b0;
vif.data <= 'z;
// The reset handler kills the sequence, so this path does not call item_done().
endtaskThe drive loop and reset watcher race. Reset wins immediately, disable fork removes stale drive activity, and the interface returns to an idle value before the next boot.
function void mac_scoreboard::flush();
exp_fifo.flush();
actual_fifo.flush();
m_expected_count = 0;
endfunction
task mac_env::run_phase(uvm_phase phase);
forever begin
@(negedge vif.rst_n);
agt.sqr.stop_sequences();
scb.flush();
reg_model.reset();
wait (vif.rst_n === 1'b1);
uvm_report_info("ENV", "Reset released: resume", UVM_LOW);
end
endtaskCleanup follows the hardware state transition: stop producers, discard predictions that no longer exist, synchronize the register mirror, then wait for reset release.
Stress recipe
- Fill request queues, response queues, pipelines, and DUT buffers before asserting reset.
- Assert reset during an active valid-ready handshake and confirm the driver drops valid without hanging.
- Exercise warm, IP-level, subsystem, and full reset scopes while unrelated agents remain active.
- Verify sticky registers retain their value while non-sticky fields and the RAL mirror return to the correct reset type.
- Restart traffic immediately after the allowed reboot window and reject any pre-reset data.
Follow-up questions
How do you verify registers that are sticky and are not cleared by a warm reset?
Model distinct RAL reset kinds. On a warm reset, call model.reset("WARM") so only non-sticky fields return to their warm-reset defaults while sticky mirrors retain their values.
What happens to the sequence that reset interrupted?
Usually the environment kills it. If the use case requires a resumable sequence, checkpoint its progress in a configuration object before termination and restart from that state after reset recovery.
How do you expose a DUT buffer that fails to clear on reset?
Run a dirty-reset test: fill every buffer with traffic, assert reset while state is maximally dirty, then check immediately after release that no pre-reset payload leaks out.
