🔍 Introduction#
A UVM Sequence is a fundamental building block for generating stimulus in a testbench. Starting a sequence and controlling its flow is key to writing flexible and reusable testbenches. This page explains the uvm_do
macro and alternative ways to start a sequence, including where to raise objections and how to manually implement the steps that uvm_do
performs behind the scenes.
🚀 Sequence Starting Methods#
1️⃣ Using uvm_do
Macro#
The most common and convenient way in UVM:
`uvm_do(seq_item)
This macro effectively does:
- Calls
create()
to instantiate the sequence item. - Calls
randomize()
to apply constraints (if any). - Calls
start_item()
to begin the transaction. - Calls
finish_item()
to finalize it.
👉 In other words, uvm_do
creates and sends the item in a single line.
2️⃣ Manual Sequence Starting (Step-by-Step)#
If you don’t want to use uvm_do
or need finer control, you can manually write the steps:
my_item item;
item = my_item::type_id::create("item");
// Randomization (add constraints if needed)
if (!item.randomize())
`uvm_error("MY_SEQ", "Randomization failed")
// Start the item
start_item(item);
// (Optional) Fill in the fields manually
item.data = 8'hFF;
// Finish the item
finish_item(item);
This is especially useful when you want to set certain fields manually or apply custom constraints.
3️⃣ Starting a Sequence via Sequencer#
You can also start a sequence by explicitly calling start()
on the sequencer:
my_sequence seq;
seq = my_sequence::type_id::create("seq");
seq.start(my_sequencer);
This approach is typically used for nested sequences or more complex flows.
🛠️ Using uvm_send
#
The uvm_send
macro is used to send single sequence items inside a sequence:
`uvm_send(item)
Behind the scenes, this does:
start_item(item)
- (optional randomization or manual field setting)
finish_item(item)
all in one step.
📌 Objection Usage#
In UVM, it’s common to raise an objection to prevent the simulation from ending while a sequence is running. Typically done in:
start_of_simulation_phase
run_phase
main_phase
Example:
phase.raise_objection(this, "My sequence started");
...
phase.drop_objection(this, "My sequence completed");
💡 Note: You can raise objections inside the sequence itself or inside the test. This controls when the simulation ends.
🎯 When to Use Each Method?#
Method | When to Use |
---|---|
uvm_do | Simple stimulus flows, rapid development |
Manual (Step-by-Step) | When you need manual field assignment or apply special constraints |
Sequencer start() | Nested sequences or complex control |
uvm_send | Quick send of single items |
📝 Conclusion#
UVM Sequence starting methods add flexibility and control to your verification environment. Macros like uvm_do
are great for rapid development, while manual methods provide more customization. Choose the best method based on your testbench needs and flow control.