When developing SystemVerilog code, writing a generic class that can be instantiated in multiple ways can save you a lot of time. By using parameterized classes, you can avoid rewriting code for different array sizes or data types. This approach allows you to define one class that can be used with different types of data or sizes without repeating code. In this article, we will explore how to use SystemVerilog parameterized classes effectively.
What Are SystemVerilog Parameterized Classes?
A parameterized class in SystemVerilog allows you to create a class that is flexible and can be customized during instantiation. Parameters in SystemVerilog are like constants within the class, and they can have default values. However, you can override these default values when you instantiate the class.
The basic syntax to declare a parameterized class looks like this:
class <class_name> #( <parameter_list> );
For example, a parameterized class can be declared with the following syntax:
class Trans #(addr = 32);
Overriding Class Parameters During Instantiation
You can easily override class parameters when you create an instance of the class. Here’s how it works:
Trans #(.addr(16)) obj;
In this case, the addr
parameter is set to 16
when the class Trans
is instantiated. This allows for great flexibility in your design.
Example of a Parameterized Class: Array Size
Let’s take a look at an example where a class is parameterized by size. The size
parameter can be changed during class instantiation, making the class adaptable to different scenarios.
class Something #(int size = 8);
bit [size-1:0] out;
endclass
In this example, the Something
class has a parameter size
with a default value of 8. The size of the out
variable is based on the value of this parameter.
Instantiating the Class with Different Parameters
You can override the default parameter values during instantiation like this:
module tb;
// Override default value of size
Something #(16) sth1; // size = 16
Something #(.size(8)) sth2; // size = 8
typedef Something #(4) td_nibble; // Define an alias with size = 4
td_nibble nibble;
initial begin
// Instantiate class objects
sth1 = new;
sth2 = new;
nibble = new;
// Print the size of the "out" variable
$display("sth1.out = %0d bits", $bits(sth1.out));
$display("sth2.out = %0d bits", $bits(sth2.out));
$display("nibble.out = %0d bits", $bits(nibble.out));
end
endmodule
Simulation Log:
When you run the simulation, the output will show the size of the out
variable for each instantiation:
sth1.out = 16 bits
sth2.out = 8 bits
nibble.out = 4 bits
This demonstrates how you can change the size dynamically at the time of instantiation using parameters.
Example of Parameterized Classes with Data Types
You can also parameterize the data type of a class. This allows you to specify different data types for different instances of the class. Let’s look at an example where the data type is parameterized.
class Stack #(type T = int);
T item;
function T add_a(T a);
return item + a;
endfunction
endclass
In this example, T
is a parameter that has a default value of int
. You can override this parameter to use different data types when instantiating the class.
Instantiating Classes with Different Data Types
You can instantiate the Stack
class with different data types:
module tb;
Stack st; // item is of type int by default
Stack #(bit[3:0]) bs; // item is a 4-bit vector
Stack #(real) rs; // item is of type real
initial begin
st = new;
bs = new;
rs = new;
// Assign different values and perform operations
st.item = -456;
$display("st.item = %0d", st.add_a(10));
bs.item = 8'hA1;
$display("bs.item = %0d", bs.add_a(10));
rs.item = 3.14;
$display("rs.item = %0.2f", rs.add_a(10));
end
endmodule
Simulation Log:
When you run the simulation, the output will reflect the different data types for each class instance:
st.item = -446
bs.item = 11
rs.item = 13.14
As you can see, the data type of item
affects the output of the add_a
function.
Key Takeaways
- Parameterized classes in SystemVerilog allow you to create flexible and reusable code by defining parameters that can be customized during instantiation.
- You can parameterize the size of variables and the data types in a class.
- This approach allows you to avoid redundant code and makes your classes adaptable to different use cases.
- You can override parameters during instantiation to suit specific requirements for size, data type, or other characteristics.
Conclusion
By using SystemVerilog parameterized classes, you can make your code more flexible and reusable. Parameterized classes allow you to customize array sizes, data types, and other features without rewriting code. This method is a great way to write clean, maintainable, and efficient SystemVerilog code.
Comparison of Default and Custom Parameterized Classes
Parameter | Default Value | Custom Value | Example Usage |
---|---|---|---|
Size | 8 | 16 | Something #(16) sth1; |
Data Type (T) | int | bit[3:0] | Stack #(bit[3:0]) bs; |
This table summarizes how default and custom parameter values affect the class behavior.