The super keyword is used from within a sub-class to refer to properties and methods of the base class. It's mandatory to use super to reach a base class's own version of a property or method, once the sub-class has overridden it with its own version of the same name.
7 min read | Intermediate Level
What You'll Learn
- What
superrefers to, and exactly when you're required to use it - Why
superonly works inside a class that actually extends another - How
super.method_name()reaches the base class's own version of an overridden method - How this ties into the constructor-chaining pattern from SystemVerilog Class Constructor
super Requires an Actual Inheritance Relationship
super can only be used within a class scope that actually derives from a base class. The code below has a compile error, because extPacket is missing the extends keyword — it isn't really a child of Packet at all, despite the name:
class Packet;
int addr;
function display ();
$display ("[Base] addr=0x%0h", addr);
endfunction
endclass
class extPacket; // "extends" keyword missing -> not a child class
function new ();
super.new ();
endfunction
endclass
module tb;
Packet p;
extPacket ep;
initial begin
ep = new();
p = new();
p.display();
end
endmodule
Output
super.new ();
|
ncvlog: *E,CLSSPX (testbench.sv,12|8): 'super' can only be used within a class scope that derives from a base class.
Adding extends Packet fixes this:
class extPacket extends Packet; // extPacket is a child class of Packet
function new ();
super.new ();
endfunction
endclass
Output
ncsim> run [Base] addr=0x0 ncsim: *W,RNQUIE: Simulation is complete.
The output here comes from p.display() — a plain Packet object, unrelated to extPacket. This example only demonstrates that the compile error is gone; extPacket itself isn't actually exercised yet. The next section puts it to real use.
Quick Check
Q: If extPacket kept super.new() inside its constructor but the extends Packet clause were removed again, would that be a compile-time or a run-time error?
Show Answer
Compile-time — exactly like the first example. super requires an actual inheritance relationship to exist at all, and that's checked when the code is compiled, not when it runs.
Accessing an Overridden Base Method With super
Here, extPacket's own display() calls Packet's version explicitly with super.display(), before adding its own line:
class Packet;
int addr;
function display ();
$display ("[Base] addr=0x%0h", addr);
endfunction
endclass
class extPacket extends Packet;
function display();
super.display(); // Call base class display method
$display ("[Child] addr=0x%0h", addr);
endfunction
function new ();
super.new ();
endfunction
endclass
module tb;
Packet p;
extPacket ep;
initial begin
ep = new();
p = new();
ep.display();
end
endmodule
Output
ncsim> run [Base] addr=0x0 [Child] addr=0x0 ncsim: *W,RNQUIE: Simulation is complete.
ep.display() now runs both lines — the base class's own output first (via super.display()), followed by the child's own line. Without super, extPacket's override would have completely replaced Packet's behavior instead of building on it.
Quick Check
Q: If extPacket's display() didn't call super.display() at all, what would ep.display() print?
Show Answer
Just [Child] addr=0x0 — only the child's own line. super.display() is what explicitly pulls in the base class's output; without it, an override runs only its own statements.
Where Is This Used?
UVM component phase methods follow exactly this pattern — an overridden run_phase(phase) or build_phase(phase) commonly calls super.run_phase(phase) or super.build_phase(phase) at the very start, ensuring the base class's own setup still happens before the derived class's additional logic runs, rather than silently skipping it.
Common Beginner Mistakes
Mistake #1: Using super in a class that doesn't actually extend anything
As the first example shows, this is a compile-time error, not a warning. Why? super only has meaning relative to an actual base class — a missing extends clause (even with a name that looks like it implies inheritance, like extPacket) means there's simply nothing for super to refer to.
Mistake #2: Using super for a method the child never actually overrides
If a child class doesn't redefine a method at all, calling it unqualified already reaches the base class's version — no super needed. Why? super is specifically for reaching the base class's version of something the child has overridden with its own version of the same name; using it elsewhere is unnecessary, though not harmful.
Mistake #3: Assuming super automatically chains through every ancestor
super.method_name() only calls exactly what's written at that one level — it isn't an automatic "run everything from every ancestor" mechanism. Why? If a three-level inheritance chain needs every level's behavior to run, each level's own override has to explicitly call super.method_name() itself; skip one level's call, and the chain stops there.
Practice Exercise
Challenge: Extend the Chain One More Level
Add a third class, extPacket2, extending extPacket, with its own display() that calls super.display() first, then prints its own line. What does calling display() on an extPacket2 object print?
Hint
Each level's super.display() call reaches exactly one level up — work out what each level in the chain actually calls before combining them.
Solution
class extPacket2 extends extPacket;
function new ();
super.new ();
endfunction
function display ();
super.display ();
$display ("[Grandchild] addr=0x%0h", addr);
endfunction
endclass
module tb;
extPacket2 gc;
initial begin
gc = new ();
gc.display ();
end
endmodule
This prints three lines: [Base] addr=0x0, then [Child] addr=0x0, then [Grandchild] addr=0x0 — extPacket2's super.display() reaches extPacket's override, which itself calls super.display() to reach Packet's original version, chaining all the way back.
Summary
In this tutorial, you learned:
superrefers to the base class from within a sub-class, and is required to reach a base class's version of a property or method the sub-class has overriddensuperonly works inside a class that genuinely extends another — using it anywhere else is a compile-time errorsuper.method_name()calls exactly the base class's own version of that method, letting an override extend behavior instead of fully replacing itsuperdoesn't automatically chain through every level of a multi-level inheritance hierarchy — each level needs its own explicit call for the chain to continue