🧩 Advanced OOP in SystemVerilog: Aggregation, Inheritance, and More#
This section dives deeper into advanced OOP features in SystemVerilog, including aggregation, inheritance, constructor chaining, multilayer inheritance, data hiding, and parameterized classes. These concepts help build powerful and reusable testbench architectures.
1️⃣ Aggregation#
Aggregation is a way to build complex classes by composing them from other classes. It represents a “has-a” relationship.
Example:
class Address;
string city;
endclass
class Person;
Address addr; // Aggregation: Person has an Address
function new();
addr = new();
endfunction
endclass
In this example, Person
has an Address
object as a property. Aggregation helps build modular, hierarchical designs.
2️⃣ Inheritance#
Inheritance allows a class (child) to acquire the properties and methods of another class (parent). Use the extends
keyword.
Example:
class Packet;
bit [7:0] header;
endclass
class DataPacket extends Packet;
bit [31:0] payload;
endclass
Here, DataPacket
inherits header
from Packet
.
3️⃣ Inheritance and Constructors#
When using inheritance, constructors in the parent class do not automatically get called in the child class. To call the parent’s constructor, use super.new()
.
Example:
class Packet;
function new();
$display("Packet constructor");
endfunction
endclass
class DataPacket extends Packet;
function new();
super.new(); // Calls Packet’s constructor
$display("DataPacket constructor");
endfunction
endclass
Always call super.new()
first to ensure the parent class is properly initialized.
4️⃣ Multilayer Inheritance#
SystemVerilog supports multilayer (multiple levels) of inheritance. A class can inherit from a parent class, and then another class can inherit from that child class.
Example:
class Packet;
bit [7:0] header;
endclass
class DataPacket extends Packet;
bit [31:0] payload;
endclass
class EncryptedPacket extends DataPacket;
bit [127:0] encryptionKey;
endclass
This allows building complex hierarchies of functionality.
5️⃣ Data Hiding and Encapsulation#
Data hiding ensures that internal data is protected from unintended access. Use local
or protected
visibility keywords.
local
: Accessible only within the same class.protected
: Accessible within the class and its subclasses.
Example:
class Packet;
local bit [7:0] secret;
protected bit [7:0] protectedData;
function void setSecret(bit [7:0] s);
secret = s;
endfunction
endclass
This approach supports encapsulation, where data and behavior are bundled together with controlled access.
6️⃣ Parameterized Classes#
SystemVerilog allows parameterized classes to create reusable, type-safe structures. This helps avoid type mismatches at runtime.
Example:
class Queue #(type T=int);
T data[$]; // dynamic array of type T
function void push(T item);
data.push_back(item);
endfunction
function T pop();
return data.pop_front();
endfunction
endclass
Queue #(bit [7:0]) byteQueue = new();
Queue #(string) stringQueue = new();
Parameterized classes make it easier to build generic verification components.
📖 Conclusion#
These advanced OOP concepts in SystemVerilog empower engineers to create modular, reusable, and scalable verification environments. Mastering these techniques is essential for building high-quality testbenches.
// Aggregation: Address class
class Address;
string city;
string street;
function new(string cityName = "Unknown", string streetName = "Main St.");
city = cityName;
street = streetName;
endfunction
function void display();
$display("[Address] City: %s, Street: %s", city, street);
endfunction
endclass
// Base class: Packet
class Packet;
local bit [7:0] secret; // Data hiding: local
protected bit [7:0] protectedData; // Data hiding: protected
function new();
$display("[Packet] Constructor called.");
endfunction
function void setSecret(bit [7:0] s);
secret = s;
endfunction
function void showSecret();
$display("[Packet] Secret = %0h", secret);
endfunction
endclass
// Inheritance: DataPacket extends Packet
class DataPacket extends Packet;
bit [31:0] payload;
function new();
super.new(); // Calls Packet constructor
$display("[DataPacket] Constructor called.");
endfunction
endclass
// Multilayer Inheritance: EncryptedPacket extends DataPacket
class EncryptedPacket extends DataPacket;
bit [127:0] encryptionKey;
function new();
super.new(); // Calls DataPacket constructor
$display("[EncryptedPacket] Constructor called.");
endfunction
endclass
// Parameterized Class: Generic Queue
class Queue #(type T=int);
T data[$]; // dynamic array of type T
function void push(T item);
data.push_back(item);
endfunction
function T pop();
return data.pop_front();
endfunction
function void display();
foreach (data[i])
$display("[Queue] data[%0d] = %0s", i, data[i]);
endfunction
endclass
// Aggregation: Person class
class Person;
Address addr; // Person has an Address (aggregation)
function new(string cityName, string streetName);
addr = new(cityName, streetName);
$display("[Person] Constructor called.");
endfunction
function void display();
addr.display();
endfunction
endclass
// Testbench module
module tb_advanced_oop_demo;
Person p;
EncryptedPacket epkt;
Queue #(bit [7:0]) byteQueue;
Queue #(string) stringQueue;
initial begin
// Demonstrate Aggregation
p = new("Istanbul", "Nispetiye St.");
p.display();
// Demonstrate Inheritance & Constructor Chaining
epkt = new();
epkt.setSecret(8'hAB);
epkt.showSecret();
epkt.encryptionKey = 128'hDEADBEEFDEADBEEFDEADBEEFDEADBEEF;
$display("[EncryptedPacket] Key = %h", epkt.encryptionKey);
// Demonstrate Parameterized Class
byteQueue = new();
byteQueue.push(8'hAA);
byteQueue.push(8'hBB);
byteQueue.display();
stringQueue = new();
stringQueue.push("Hello");
stringQueue.push("World");
stringQueue.display();
#10 $finish;
end
endmodule