Create() Vs new()
In short: In UVM you build objects and components with the factory call type_id::create() instead of the plain constructor new(). Both end up calling new(), but create() first asks the factory which class to build, so a single override line in a test can swap one class for another without editing the code that builds it. Use create() everywhere; keep new() only for the constructor definition itself.
When you first read UVM code you see two ways to make an object: the language keyword new(), and the longer my_type::type_id::create("name", this). They look like they do the same thing, and for a single run they often do. The difference shows up the moment you want one test to behave differently from another without touching shared code. This guide explains what each call really does, why the factory route matters, three worked examples, a side-by-side table, and the mistakes that quietly disable overrides.
A simple way to picture it
Think of ordering a taxi through an app instead of walking to one specific car. If you walk straight to a numbered car and get in, that is new(): you always get that exact car. If you open the app and ask for a ride, that is create(): the dispatcher decides which car turns up. Most days you get an ordinary car, but on a special day the dispatcher can send a different one, and you never change how you ask. The factory is that dispatcher, and the override is the note that tells it to send a different car today.
What new() does
new() is the plain SystemVerilog constructor. It builds one object of exactly the class you name, and nothing can change that at run time. It is the right tool inside a class to define how that class is constructed, and you still write a new() in every UVM class. What you avoid is calling it directly to build components and transactions, because a direct new() hard-codes the type.
// new() always builds exactly this class
bus_driver drv;
drv = new("drv", this); // hard-coded: always a bus_driver, no override possibleWhat create() does
create() is added to every class by the registration macro. It asks the factory, is there an override for this type or this instance path, and then calls new() on whatever the factory decides. In the common case with no override it returns exactly the class you asked for, so it behaves like new(). The payoff is that a test can register an override once and every create() for that type quietly returns the replacement.
// create() asks the factory first, then constructs
bus_driver drv;
drv = bus_driver::type_id::create("drv", this); // factory may return a subclass
// for an object (no parent), pass only a name
bus_item req;
req = bus_item::type_id::create("req");The registration macro is what makes create() exist
You do not get type_id or create() for free. The registration macro adds them: components use uvm_component_utils and objects such as sequences and sequence items use uvm_object_utils. Skip the macro and create() will not compile for that class, which is a common early error.
class bus_driver extends uvm_driver #(bus_item);
`uvm_component_utils(bus_driver) // gives bus_driver::type_id::create(...)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
class bus_item extends uvm_sequence_item;
`uvm_object_utils(bus_item) // gives bus_item::type_id::create(...)
function new(string name = "bus_item");
super.new(name);
endfunction
endclassWorked example: the override that create() enables
Here is the whole point in one example. The environment always builds its driver with create(). A normal test changes nothing. An error test registers a type override, and now the same environment builds an error-injecting driver instead, with no edit to the environment.
// environment: never edited, always uses create()
class bus_env extends uvm_env;
`uvm_component_utils(bus_env)
bus_driver drv;
function new(string n, uvm_component p); super.new(n,p); endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
drv = bus_driver::type_id::create("drv", this); // factory decides the real type
endfunction
endclass
// error test: one override line changes what create() returns
class error_test extends base_test;
`uvm_component_utils(error_test)
function new(string n, uvm_component p); super.new(n,p); endfunction
function void build_phase(uvm_phase phase);
bus_driver::type_id::set_type_override(error_driver::get_type());
super.build_phase(phase); // env now builds an error_driver
endfunction
endclassIf the environment had used drv = new("drv", this), the override would do nothing, because the factory never sees the request. That single detail is why the habit matters.
A second example: create() inside a sequence
The same rule applies to transactions. A sequence builds its items with create(), so a test can override the item type too, for example swapping a plain packet for a corner-case packet without rewriting the sequence.
task body();
bus_item req;
req = bus_item::type_id::create("req"); // an override can return a stress_item here
start_item(req);
assert(req.randomize());
finish_item(req);
endtaskcreate() versus new(), side by side
| Point | create() | new() |
|---|---|---|
| Who decides the type | The factory (can be overridden) | Fixed at compile time |
| Enables overrides | Yes | No |
| Needs the registration macro | Yes | No |
| Arguments for a component | name and parent | name and parent |
| Arguments for an object | name only | name only |
| Where you use it | Building components and transactions | Only the constructor definition itself |
| Behaviour with no override | Same result as new() | The only result |
When to use which
The rule is short. Use create() for every component and every transaction you build, so overrides stay available across the whole testbench. Write a new() in each class because the constructor still has to exist, and call new() directly only for plain data objects that are not part of the UVM factory, such as a simple helper class that never needs overriding. When in doubt, reach for create().
Common mistakes to avoid
- Building components with
new(), which hides the request from the factory so no override can apply. - Forgetting the registration macro, so
type_idandcreate()do not exist for that class. - Passing a parent to
create()for an object, or omitting it for a component; objects take a name only, components take a name and parent. - Setting a type override after
super.build_phase()has already built the component, so the original class is created first. - Assuming
create()is slow. The lookup happens once per object and is tiny next to the run phase.
Keep learning
This habit is what makes the UVM factory useful, so read the concept of the UVM factory for type, instance, and name overrides. See where create() is called throughout a real testbench in the UVM testbench architecture guide, and why the base classes are subclassed in inheritance in SystemVerilog. More topics live on the UVM category page, and this comparison is a frequent interview question.
Frequently asked questions
What is the main difference between create() and new()?
create() asks the UVM factory which class to build and then calls new() on it, so an override can substitute a different class. new() builds exactly the class you name with no chance of substitution. For a run with no override the result is the same, but only create() keeps overrides available.
Do I still need to write new() in my classes?
Yes. Every UVM class still defines a new() constructor, and create() calls it internally. What you avoid is calling new() directly to build components and transactions; use create() for that so the factory stays in the loop.
Why does my factory override do nothing?
The usual cause is building the component with new() instead of create(), so the factory never sees the request. Other causes are a missing registration macro or setting the override after super.build_phase() has already built the component.
How do the arguments differ between components and objects?
For a component you pass a name and a parent, such as create(“drv”, this). For an object such as a sequence item you pass only a name, such as create(“req”). Mixing these up is a common compile error.
Does create() work without the registration macro?
No. The uvm_component_utils or uvm_object_utils macro is what adds type_id and create() to the class. Without it the create() call will not compile for that type.
Is create() slower than new()?
Not in any way that matters. The factory lookup happens once when the object is built, which is a tiny cost next to the simulation time spent in the run phase. The flexibility is well worth it.






Hii , i am a verification trainee and i need some suggestions regarding verification so that i can be a better verification engineer
Hi Sewanjali,
Thanks, for visiting my blog posts. Can you please let me know what kind of guidance you actually seek? So I can try to guide you better.
Thank you