In SystemVerilog, static variables play a significant role in class and function behavior. Normally, each class instance holds its own copy of the internal variables. However, when a variable is declared as static, it is shared across all instances of the class. This tutorial will explain SystemVerilog static variables in functions, comparing static and non-static variables through examples.
Introduction to Class Variables in SystemVerilog
In SystemVerilog, each class instance typically has its own copy of internal variables. Here is an example of a basic class definition with internal variables:
class Packet;
bit [15:0] addr;
bit [7:0] data;
function new (bit [15:0] ad, bit [7:0] d);
addr = ad;
data = d;
$display ("addr=0x%0h data=0x%0h", addr, data);
endfunction
endclass
module tb;
initial begin
Packet p1, p2, p3;
p1 = new(16'hdead, 8'h12);
p2 = new(16'hface, 8'hab);
p3 = new(16'hcafe, 8'hfc);
end
endmodule
In this example, each object (p1
, p2
, and p3
) has its own instance of addr
and data
. Here’s the simulation output:
Simulation Log:
addr=0xdead data=0x12
addr=0xface data=0xab
addr=0xcafe data=0xfc
Simulation complete.
Static Variables in SystemVerilog Classes
When you declare a variable as static in a class, it is shared across all instances of that class. Static variables exist only once, regardless of the number of objects created. Let’s modify the previous example to include static and non-static counters.
class Packet;
bit [15:0] addr;
bit [7:0] data;
static int static_ctr = 0; // Static counter
int ctr = 0; // Non-static counter
function new (bit [15:0] ad, bit [7:0] d);
addr = ad;
data = d;
static_ctr++; // Increment static counter
ctr++; // Increment non-static counter
$display ("static_ctr=%0d ctr=%0d addr=0x%0h data=0x%0h", static_ctr, ctr, addr, data);
endfunction
endclass
module tb;
initial begin
Packet p1, p2, p3;
p1 = new(16'hdead, 8'h12);
p2 = new(16'hface, 8'hab);
p3 = new(16'hcafe, 8'hfc);
end
endmodule
Explanation:
- The
static_ctr
is shared across all class instances, and it increments each time a new object is created. - The
ctr
variable is unique to each object, so it starts at 1 for every instance.
Simulation Log:
static_ctr=1 ctr=1 addr=0xdead data=0x12
static_ctr=2 ctr=1 addr=0xface data=0xab
static_ctr=3 ctr=1 addr=0xcafe data=0xfc
Simulation complete.
Notice that the static_ctr
increments with each object creation and becomes 3 after creating all three objects. In contrast, ctr
remains 1 for every object.
Practical Uses of Static Variables
Declaring variables as static can be very useful, especially when you want to track values across all instances of a class. For example, you might want to know the total number of objects created.
Static Methods in SystemVerilog
Static methods in SystemVerilog follow similar behavior. They can be called without creating an instance of the class. However, static methods cannot access non-static members of the class, but they can access other static properties or call other static methods.
Here’s an example:
class Packet;
static int ctr = 0; // Static counter
function new ();
ctr++; // Increment counter on each creation
endfunction
static function get_pkt_ctr ();
$display ("ctr=%0d", ctr); // Display the static counter value
endfunction
endclass
module tb;
Packet pkt[6];
initial begin
for (int i = 0; i < $size(pkt); i++) begin
pkt[i] = new; // Create new objects
end
Packet::get_pkt_ctr(); // Static method call using :: operator
pkt[5].get_pkt_ctr(); // Instance method call
end
endmodule
Simulation Log:
ctr=6
ctr=6
Simulation complete.
Attempting to Access Non-Static Variables from Static Methods
A static method cannot access non-static members of the class. If you try to access a non-static variable inside a static method, you’ll encounter a compilation error.
Here’s an example that will fail:
class Packet;
static int ctr = 0;
bit [1:0] mode; // Non-static member
function new ();
ctr++;
endfunction
static function get_pkt_ctr ();
$display ("ctr=%0d mode=%0d", ctr, mode); // Compilation error: cannot access 'mode' from static method
endfunction
endclass
Simulation Log:
Error: A static class method cannot access non-static class members.
Conclusion
SystemVerilog static variables and functions are powerful tools for managing data that should be shared across all instances of a class or for tracking information without the need for creating instances. Static variables persist across function calls, and static methods can be called without creating objects. However, static methods cannot access non-static variables, which is important to keep in mind when designing classes.
By understanding these concepts, you can write more efficient and flexible SystemVerilog code for your simulations and hardware design.