One of the most common questions UVM beginners (and even experienced engineers!) struggle with is:
“Why is my simulation ending early?”
“Why is my test stuck forever?”
In most cases, the answer lies in phase objections.
Why Do We Need Phase Objections in UVM?
UVM is phase-driven. Every component goes through a sequence of predefined phases such as:
- build
- connect
- run
- reset
- main
- shutdown
- report
Among these, runtime phases (like run_phase, main_phase, etc.) execute concurrently across all components.
The problem is UVM does not know automatically when your stimulus, sequences, or checks are complete. That’s where objections come in.
Objections tell the UVM scheduler: “Hey, I am still doing something important. Don’t end this phase yet.”
What Is a Phase Objection?
A phase objection is a mechanism used to:
- Hold a phase alive while some activity is still running
- End the phase only when all activities are done
There are two key operations:
- raise_objection()
- drop_objection()
Phase Raise Objection
When a component calls raise_objection():
- It informs UVM that this phase should not finish yet
- The objection count for that phase increases
Syntax
phase.raise_objection(this);
You typically raise an objection when:
- A sequence starts
- A stimulus generation begins
- You start driving transactions
- You begin monitoring/checking critical behavior
Phase Drop Objection
When a component calls drop_objection():
- It tells UVM that this component has finished its work
- The objection count decreases
When all objections are dropped, UVM ends the phase and moves to the next one.
Syntax
phase.drop_objection(this);
Example:
Now let’s look at a realistic run_phase example.
class my_test extends uvm_test;
`uvm_component_utils(my_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info("TEST", "Starting stimulus", UVM_MEDIUM)
#100ns; // Stimulus execution
`uvm_info("TEST", "Stimulus completed", UVM_MEDIUM)
phase.drop_objection(this);
endtask
endclass
What Happens Here?
- raise_objection() prevents run_phase from ending
- Stimulus runs for 100 ns
- drop_objection() signals completion
- If no other component has an active objection → run_phase ends
What If You Forget to Raise an Objection?
task run_phase(uvm_phase phase);
#100ns;
endtask
Result:
- Simulation may end at time 0
- Your stimulus may never execute
- You’ll see confusing results
Note: Always raise objections for time-consuming activities.
What If You Forget to Drop an Objection?
task run_phase(uvm_phase phase);
phase.raise_objection(this);
#100ns;
// drop_objection missing
endtask
Result:
- Simulation never ends
- Test appears “hung”
- You may need to manually kill simulation
Note: Every raise must have a matching drop.
Objections Across Multiple Components
In a real testbench:
- Test
- Sequences
- Drivers
- Monitors
…can all raise objections.
UVM internally keeps a global objection count.
Phase Ends Only When:
Total objections == 0
Using Objections in Sequences
You can also raise objections inside sequences:
task body();
starting_phase.raise_objection(this);
// sequence operations
repeat(10) begin
send_item();
end
starting_phase.drop_objection(this);
endtask
This is very useful when:
- Sequences control test duration
- Multiple sequences run in parallel
Best Practices
- Always pair raise_objection() and drop_objection()
- Raise objections only in runtime phases
- Prefer raising objections at higher-level components (test/sequence)
- Avoid unnecessary objections in every small component
Real-World Analogy
Think of a conference call
- Each speaker joining says: “I’m still here” → raise_objection
- When a speaker leaves: “I’m done” → drop_objection
- The call ends only when everyone leaves
“If Still confused, Chat with VLSI AI or discuss in VLSI Community”