Part 2 · Phases & Lifecycle · Intermediate

Reset, Configure, Main, Shutdown: The Four Groups

What belongs in each runtime group, canonical code for each phase, cross-agent coordination guarantees, and common misplacements.

RESET group: safe starting state

The reset group ensures every agent drives its interface to a safe idle state and waits for reset deassertion before any configuration or traffic begins.

systemverilog
class apb_driver extends uvm_driver #(apb_item);
  task reset_phase(uvm_phase phase);
    phase.raise_objection(this, "APB idle during reset");
    vif.psel    <= 0;
    vif.penable <= 0;
    vif.pwrite  <= 0;
    vif.paddr   <= '0;
    vif.pwdata  <= '0;
    @(negedge vif.preset_n);   // wait for reset assert
    @(posedge vif.preset_n);   // wait for reset release
    phase.drop_objection(this, "APB reset released");
  endtask
endclass
diagram
[PHASE][RUN] reset group coordination

  Agent A reset_phase: drive idle, wait reset release ──► drop
  Agent B reset_phase: drive idle, wait reset release ──► drop
  Agent C reset_phase: drive idle, wait reset release ──► drop
       │
       ▼ ALL drops  reset group done  configure group begins
  • reset_phase: drive safe idle, wait for reset deassertion.

  • post_reset_phase: optional settle delay after reset release.

  • All agents must drop reset objections before configure begins.


CONFIGURE group: DUT programming

The configure group is the natural home for register programming — typically via RAL frontdoor sequences:

systemverilog
class env extends uvm_env;
  ral_block_my_dut regmodel;

  task configure_phase(uvm_phase phase);
    reg_cfg_seq cfg_seq;
    phase.raise_objection(this, "register configuration");
    cfg_seq = reg_cfg_seq::type_id::create("cfg_seq");
    cfg_seq.regmodel = regmodel;
    cfg_seq.start(reg_adapter_sequencer);
    phase.drop_objection(this, "register configuration done");
  endtask
endclass
diagram
[PHASE][RUN] configure group flow

  pre_configure:  verify clocks/reset stable, check prerequisites
  configure:      RAL frontdoor writes, mode register setup
  post_configure: wait N cycles for config to propagate

  guarantee: NO main traffic until ALL agents finish configure group
  • configure_phase pairs naturally with UVM RAL frontdoor access.

  • post_configure_phase: add pipeline settle cycles if DUT needs them.

  • Never start stimulus in configure_phase — that belongs in main_phase.


MAIN group: primary stimulus

main_phase holds the bulk of verification activity — sequence execution, traffic generation, and active checking:

systemverilog
class axi_driver extends uvm_driver #(axi_item);
  task main_phase(uvm_phase phase);
    axi_item req;
    phase.raise_objection(this, "AXI main traffic");
    forever begin
      seq_item_port.get_next_item(req);
      drive_axi(req);
      seq_item_port.item_done();
    end
    // real drivers drop via controlled stop, not unreachable code
  endtask
endclass

class my_test extends uvm_test;
  task main_phase(uvm_phase phase);
    fork super.main_phase(phase); join_none
    phase.raise_objection(this, "main virtual sequence");
    main_vseq.start(env.v_sqr);
    phase.drop_objection(this, "main vseq done");
  endtask
endclass
diagram
[RUN][PHASE] main group activity map

  TEST:       raise  start virtual sequence  drop
  DRIVER:     raise  forever get/drive loop (drop on stop)
  MONITOR:    sample bus (typically no objection — passive)
  SCOREBOARD: compare queue (typically no objection — passive)
  COVERAGE:   sample coverage (passive)
  • Test raises/drops for sequence duration; driver raises for its service loop.

  • Passive components (monitor, coverage) usually don't raise objections.

  • post_main_phase: stop accepting new sequences, signal wind-down.


SHUTDOWN group: graceful drain

The shutdown group ensures in-flight transactions complete before the runtime schedule ends and cleanup phases begin:

systemverilog
class axi_driver extends uvm_driver #(axi_item);
  uvm_event stop_ev;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    stop_ev = uvm_event_pool::get_global("stop_ev");
  endfunction

  task shutdown_phase(uvm_phase phase);
    phase.raise_objection(this, "draining AXI");
    stop_ev.trigger();                    // tell main_phase loop to stop accepting
    wait_for_inflight_complete();         // wait for outstanding bursts
    drive_idle();                         // return bus to safe state
    phase.drop_objection(this, "AXI drained");
  endtask
endclass
diagram
[PHASE][RUN] shutdown sequence

  post_main:     stop accepting new sequences/items
  pre_shutdown:  signal agents to wind down
  shutdown:      drain in-flight, drive idle
  post_shutdown: final settle cycles
       │
       ▼ ALL drops  runtime schedule complete  extract_phase

Key takeaways

  • RESET: idle interfaces + wait reset release — all agents coordinated.

  • CONFIGURE: RAL/register programming — no traffic until all agents done.

  • MAIN: primary stimulus — test owns sequence duration objection.

  • SHUTDOWN: drain in-flight transactions — graceful stop before cleanup.

Common pitfalls

  • Stimulus in configure_phase — breaks 'config before traffic' guarantee.

  • Reset handling in run_phase while other agents use reset_phase — desync.

  • Skipping shutdown group — in-flight transactions lost at phase kill.

  • Driver forever loop in main_phase without stop mechanism — can't drain.