HomeSystemVerilog VerificationDay 8
DAY 8 · OOP PHASE

SystemVerilog Inheritance & Polymorphism — extends, virtual, override

By EcrioniX · Updated Jun 13, 2026

Day 7 taught you classes and objects. Now unlock the true power of OOP: inheritance and polymorphism. Create a hierarchy of related classes where common behavior lives in a base class, specialized behavior lives in derived classes, and a single base class reference can point to any derived type, calling the correct method automatically.

What is inheritance?

Inheritance allows a derived class to extend a base class using extends. The derived class inherits all properties and methods and can add new ones, override methods, or call the base version with super.

Inheritance syntax

class derived_class extends base_class;
  // Inherits all properties and methods
  // Can add new properties and methods
  // Can override virtual methods from base
endclass

What is polymorphism and virtual methods?

Polymorphism means "many forms". A single base class reference can point to objects of different derived types. When you call a method, the correct version (based on the actual object, not the reference type) executes. This requires the method to be virtual in the base class.

class transaction;
  virtual function void do_transaction();
    $display("Base: generic transaction");
  endfunction
endclass

class read_transaction extends transaction;
  virtual function void do_transaction();
    override;
    $display("Derived: reading from address");
  endfunction
endclass

transaction tr = new read_transaction();
tr.do_transaction();  // Calls derived version!
                      // Output: "Derived: reading from address"

Without virtual: static dispatch (usually wrong)

If the base method is not virtual, the base version is always called:

transaction tr = new read_transaction();
tr.do_transaction();  // Calls BASE version — wrong!
                      // Output: "Base: generic transaction"

Override and super keywords

Mark overridden methods with override (optional but recommended). Use super.method() to call the parent version. This is useful when extending rather than replacing base behavior:

class derived extends base;
  virtual function void setup();
    override;
    super.setup();           // Call base version first
    $display("Derived setup complete");
  endfunction

  function new();
    super.new();  // Call base constructor
  endfunction
endclass

Complete example: transaction hierarchy

transaction_hierarchy.sv
class transaction;
  rand logic [15:0] addr;
  rand logic [7:0]  data;
  logic valid;

  function new();
    addr=0; data=0; valid=0;
  endfunction

  virtual function void do_transaction();
    $display("Generic TX: addr=%h data=%h", addr, data);
  endfunction

  virtual function void display();
    $display("  addr=%h data=%h valid=%b", addr, data, valid);
  endfunction
endclass

class read_transaction extends transaction;
  logic [7:0] read_data;

  function new();
    super.new();
    read_data=0;
  endfunction

  virtual function void do_transaction();
    override;
    $display("READ TX: addr=%h", addr);
  endfunction

  virtual function void display();
    override;
    super.display();
    $display("  + read_data=%h", read_data);
  endfunction
endclass

class write_transaction extends transaction;
  logic [3:0] byte_enable;

  function new();
    super.new();
    byte_enable=4'b1111;
  endfunction

  virtual function void do_transaction();
    override;
    $display("WRITE TX: addr=%h data=%h be=%b", addr, data, byte_enable);
  endfunction

  virtual function void display();
    override;
    super.display();
    $display("  + byte_enable=%b", byte_enable);
  endfunction
endclass

module transaction_demo;
  initial begin
    // Create objects
    read_transaction rd = new();
    write_transaction wr = new();

    rd.addr=16'h1000;
    wr.addr=16'h2000; wr.data=8'hAA;

    // Store in queue of base class handles
    transaction q[$];
    q.push_back(rd);
    q.push_back(wr);

    // Polymorphic calls — each calls its own version
    foreach (q[i]) begin
      q[i].do_transaction();
      q[i].display();
    end

    $finish;
  end
endmodule

Why inheritance and polymorphism matter for testbenches

Day 8 takeaways

Frequently Asked Questions

What is inheritance in SystemVerilog?

Inheritance allows a derived class to extend a base class. The derived class inherits all properties and methods from the base and can add new ones or override existing ones to customize behavior.

What is polymorphism?

Polymorphism allows a base class reference to point to derived objects. Virtual methods ensure the correct derived version is called, not the base version, based on the actual object type.

What does virtual do?

Virtual enables dynamic dispatch: the method called is determined by the actual object type at runtime, not the reference type. Without virtual, the base version is always called (static dispatch).

How do I call parent methods?

Use super.method() to call the parent class version. For constructors: super.new(). This is useful when the derived class wants to extend rather than replace the base behavior.

Previous
← Day 7: Classes & Objects

← Full course roadmap