In SystemVerilog, constructors are special methods used to create and initialize objects of a class. A constructor helps in setting the initial values of class variables when an object is instantiated.

What is a Class Constructors in SystemVerilog?

A constructor is a function inside a class that automatically runs when an object of that class is created. Unlike some languages like C/C++, which require manual memory management, SystemVerilog handles memory and object creation efficiently, with automatic garbage collection.

Simple Example of a SystemVerilog Class Constructors

Let’s explore a simple example of using a constructor in a class.

// Define a class called "Packet" with a 32-bit address variable
// Initialize "addr" to 32'hfade_cafe in the constructor
class Packet;
  bit [31:0] addr;

  function new ();
    addr = 32'hfade_cafe;  // Initialize the address
  endfunction
endclass

module tb;

  // Create a class handle called "pkt" and instantiate the class object
  initial begin
    // The constructor new() is automatically called during object instantiation
    Packet pkt = new;

    // Display the value of addr
    // Since the constructor was called, addr should be 32'hfade_cafe
    $display ("addr=0x%0h", pkt.addr);
  end
endmodule

Simulation Log

ncsim> run
addr=0xfadecafe
ncsim: *W,RNQUIE: Simulation is complete.

In this example, when we instantiate the object pkt from the Packet class, the constructor new() is called automatically. This constructor initializes the addr variable to 32'hfade_cafe.

If the constructor is not defined explicitly, SystemVerilog provides an implicit constructor that initializes the class variables to default values. For instance, without a constructor, addr would default to zero.

Implicit Constructor Example

// Define a class with a variable called "addr"
// No explicit constructor is defined
class Packet;
  bit [31:0] addr;
endclass

module tb;
  initial begin
    // The implicit constructor is called here
    Packet pkt = new;
    $display ("addr=0x%0h", pkt.addr);  // addr will be 0 by default
  end
endmodule

Simulation Log

ncsim> run
addr=0x0
ncsim: *W,RNQUIE: Simulation is complete.

Inheritance and Constructors in SystemVerilog

In SystemVerilog, constructors are inherited in derived classes. When a derived class object is created, the base class constructor is automatically called before the derived class constructor.

Example with Base and Derived Classes

// Base class with a data member and a constructor
class baseClass;
  bit [15:0] data;

  function new ();
    data = 16'hface;  // Initialize data
  endfunction
endclass

// Derived class with additional members and a constructor
class subClass extends baseClass;
  bit [3:0] id;
  bit [2:0] mode = 3;

  function new (int val = 2);
    super.new ();  // Call the base class constructor
    id = val;      // Initialize id with the passed value
  endfunction
endclass

module tb;
  initial begin
    // Create two handles for the subclass
    subClass sc1, sc2;

    // Instantiate the subclass and display values
    sc1 = new ();
    $display ("data=0x%0h id=%0d mode=%0d", sc1.data, sc1.id, sc1.mode);

    // Pass a value to the constructor
    sc2 = new (4);
    $display ("data=0x%0h id=%0d mode=%0d", sc2.data, sc2.id, sc2.mode);
  end
endmodule

Simulation Log

ncsim> run
data=0xface id=2 mode=3
data=0xface id=4 mode=3
ncsim: *W,RNQUIE: Simulation is complete.

Here, the constructor of the derived class (subClass) first calls the constructor of the base class (baseClass) using the super.new() keyword. After that, the derived class’s variables are initialized.

Restrictions on Constructors

In SystemVerilog, certain types of constructors are not allowed. For instance, constructors cannot be declared as virtual or static. Let’s see an example of an invalid constructor:

class ABC;
  string fruit;

  // Invalid constructor declaration (virtual is not allowed)
  virtual function new ();
    fruit = "Apple";
  endfunction
endclass

module tb;
  initial begin
    ABC abc = new ();
    $display ("fruit = %s", abc.fruit);
  end
endmodule

Simulation Log

ncvlog: *E,BADQAL (testbench.sv,6|21): Lifetime or qualifier(s) 'virtual' not allowed before function new declaration.

Constructor in Derived Classes and Base Class Objects

You can instantiate an object of a derived class and assign it to a base class handle. Here’s an example:

class C;
endclass

class D extends C;
endclass

module tb;
  initial begin
    // Assign the derived class object to a base class handle
    C c = D::new;
  end
endmodule

This approach achieves the same effect as the following code:

module tb;
  initial begin
    D d = new;  // Instantiate a derived class object
    C c = d;    // Assign it to a base class handle
  end
endmodule

Conclusion

SystemVerilog class constructors provide an easy and efficient way to create and initialize objects. By using constructors, you ensure that your objects are initialized with the correct values as soon as they are instantiated. Understanding how constructors work, including how inheritance affects constructors, will make your SystemVerilog designs much more effective.

Scroll to Top