The short answer: UVM runs every component through the same phases. The function phases build (top-down), connect, end_of_elaboration and start_of_simulation set the testbench up in zero time; run_phase is a task that runs in all components in parallel and consumes simulation time; extract, check, report and final collect and report results. The run phase ends when every raised objection has been dropped, so tests raise an objection before starting stimulus and drop it when they’re done.
Phases are how UVM keeps hundreds of components in step without them calling each other directly. Objections are how it knows when to stop. Most “my test ends at time zero” and “my test never ends” problems come down to these two ideas.
- The phases
- What goes in each phase
- Objections
- Drain time: letting the last transaction finish
- Run-time sub-phases
- Common phase mistakes
Table of Contents
Part 1: The phases

Part 2: What goes in each phase
| Phase | Type | What I put there |
|---|---|---|
| build_phase | function, top-down | Get configuration, create child components |
| connect_phase | function, bottom-up | Connect ports and exports, assign virtual interfaces |
| end_of_elaboration_phase | function | Print the topology, sanity checks |
| start_of_simulation_phase | function | Print configuration, set verbosity |
| run_phase | task, parallel | Drive, monitor, run sequences |
| extract_phase | function | Pull final data from models and scoreboards |
| check_phase | function | End-of-test checks, e.g. no expected items left |
| report_phase | function | Print the summary and pass/fail |
| final_phase | function | Close files, last cleanup |
build is top-down because a parent must exist (and set configuration) before its children are created. Most others are bottom-up.
Part 3: Objections
task run_phase(uvm_phase phase);
my_seq seq = my_seq::type_id::create("seq");
phase.raise_objection(this, "running main sequence");
seq.start(env.agt.sqr);
phase.drop_objection(this, "main sequence done");
endtask
- The run phase ends when the objection count returns to zero.
- If nobody raises an objection, run_phase ends at time zero and nothing happens.
- If someone never drops one, the test runs until the global timeout.
- Raise objections in tests and sequences (things that know when the work is done), not in drivers and monitors that run forever.
Part 4: Drain time: letting the last transaction finish
function void end_of_elaboration_phase(uvm_phase phase);
uvm_phase run = phase.find_by_name("run");
run.phase_done.set_drain_time(this, 200ns);
endfunction
After the last objection drops, the drain time lets in-flight transactions reach the scoreboard before the phase ends. An alternative is for the scoreboard to hold its own objection while it still has expected items.
Part 5: Run-time sub-phases
Alongside run_phase, UVM defines parallel sub-phases: reset, configure, main and shutdown (each with pre_ and post_ versions). They can help structure a test, but many teams avoid them because jumping between phases is hard to debug. I use run_phase plus sequences to order reset, configuration and traffic explicitly.
Part 6: Common phase mistakes
- Creating components outside build_phase, or with new() instead of the factory.
- Using connections in build_phase before the other side exists.
- Forgetting super.build_phase(phase) in classes that rely on automatic configuration.
- Putting time-consuming code in a function phase (it won’t compile) or forgetting to raise an objection in run_phase.
- Checking results in run_phase instead of check_phase, so in-flight items cause false failures.
Practise this on VLSI Forge
I built VLSI Forge so you can write RTL in your browser, run it on a real simulator and check every signal in the waveform. Free, nothing to install.
Design Verification problems · Daily challenge
Previous in my UVM series: Drivers, monitors and agents. Next: The UVM factory.
FAQ
What are the UVM phases?
build, connect, end_of_elaboration, start_of_simulation, run (with optional sub-phases), extract, check, report and final.
Why is build_phase top-down?
Parents must exist and set configuration before their children are created and read it.
What is an objection in UVM?
A counter that keeps a time-consuming phase alive. The phase ends when every raised objection has been dropped.
Why does my UVM test end at time zero?
Nothing raised an objection in run_phase, so UVM saw no reason to keep the phase running.
