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.

Scroll to Top