In SystemVerilog, just like static variables in a class, constraints can also be declared as static. A static constraint is shared across all instances of a class. This article will help you understand how static constraints work, how they differ from non-static constraints, and how to use them effectively in your code.

What Are Static Constraints?

Static constraints in SystemVerilog are constraints that are applied across all instances of a class. This means that when you turn a static constraint on or off, it affects every instance of that class. The main advantage of using static constraints is that they allow you to control constraints globally across multiple class instances.

When using the constraint_mode() method, static constraints behave differently compared to non-static ones. Non-static constraints are specific to each instance, while static constraints are shared across all instances of a class.

Syntax for Static Constraints

To declare a static constraint, simply use the static keyword before the constraint definition, like this:

class [class_name];
    ...
    static constraint [constraint_name] [definition];
endclass

Non-Static Constraints: The Default Behavior

By default, constraints in SystemVerilog are non-static. This means each instance of a class gets its own copy of the constraint. Here’s an example showing two non-static constraints that apply to a class:

class ABC;
    rand bit [3:0] a;

    // Non-static constraints
    constraint c1 { a > 5; }
    constraint c2 { a < 12; }
endclass

module tb;
    initial begin
        ABC obj1 = new;
        ABC obj2 = new;
        for (int i = 0; i < 5; i++) begin
            obj1.randomize();
            obj2.randomize();
            $display ("obj1.a = %0d, obj2.a = %0d", obj1.a, obj2.a);
        end
    end
endmodule

Explanation:

  • Both obj1 and obj2 will have their variables a constrained between 5 and 12 because both objects have the same non-static constraints.
  • Even though random values are generated, the constraints still enforce the limits.

Simulation Output:

obj1.a = 9, obj2.a = 6
obj1.a = 7, obj2.a = 11
obj1.a = 6, obj2.a = 6
obj1.a = 9, obj2.a = 11
obj1.a = 6, obj2.a = 9
ncsim: *W,RNQUIE: Simulation is complete.

Static Constraints: When You Want Global Control

Static constraints, on the other hand, apply globally to all instances of a class. Let’s see how static constraints behave differently from non-static ones.

Turning Off Non-Static Constraints

Let’s turn off a non-static constraint using the constraint_mode() method and compare the behavior:

class ABC;
    rand bit [3:0] a;

    // Non-static constraint c1, static constraint c2
    constraint c1 { a > 5; }
    static constraint c2 { a < 12; }
endclass

module tb;
    initial begin
        ABC obj1 = new;
        ABC obj2 = new;

        // Turn off non-static constraint
        obj1.c1.constraint_mode(0);

        for (int i = 0; i < 5; i++) begin
            obj1.randomize();
            obj2.randomize();
            $display ("obj1.a = %0d, obj2.a = %0d", obj1.a, obj2.a);
        end
    end
endmodule

Explanation:

  • Here, c1 is turned off for obj1, meaning obj1 is no longer constrained by a > 5. However, c2, which is static, still applies.
  • For obj2, both constraints are still active.

Simulation Output:

obj1.a = 3, obj2.a = 6
obj1.a = 7, obj2.a = 11
obj1.a = 6, obj2.a = 6
obj1.a = 9, obj2.a = 11
obj1.a = 6, obj2.a = 9
ncsim: *W,RNQUIE: Simulation is complete.

As expected, when the non-static constraint c1 is turned off, obj1 can take values outside the range a > 5, while obj2 remains constrained by both c1 and c2.

Turning Off Static Constraints

Now let’s turn off the static constraint c2 and observe how both obj1 and obj2 are affected:

class ABC;
    rand bit [3:0] a;

    // Non-static constraint c1, static constraint c2
    constraint c1 { a > 5; }
    static constraint c2 { a < 12; }
endclass

module tb;
    initial begin
        ABC obj1 = new;
        ABC obj2 = new;

        // Turn off static constraint
        obj1.c2.constraint_mode(0);

        for (int i = 0; i < 5; i++) begin
            obj1.randomize();
            obj2.randomize();
            $display ("obj1.a = %0d, obj2.a = %0d", obj1.a, obj2.a);
        end
    end
endmodule

Explanation:

  • When the static constraint c2 is turned off, both obj1 and obj2 are affected because static constraints apply to all instances of a class.
  • Both objects can now take values outside the range a < 12.

Simulation Output:

obj1.a = 15, obj2.a = 12
obj1.a = 9, obj2.a = 15
obj1.a = 14, obj2.a = 6
obj1.a = 11, obj2.a = 11
obj1.a = 12, obj2.a = 11
ncsim: *W,RNQUIE: Simulation is complete.

Summary of Differences Between Static and Non-Static Constraints

Constraint TypeEffect on InstancesApplies to All Instances
Non-StaticAffects only the instance that calls the constraintNo
StaticAffects all instances of the classYes

Restrictions for Using Static Constraints

  • randc variables are not allowed with static constraints because they are always solved first.
  • Integral values are required for the variables that are constrained.
  • There should not be circular dependencies (e.g., solve a before b combined with solve b before a).

Conclusion

Static constraints are powerful tools in SystemVerilog, allowing you to control constraints globally across multiple class instances. By using the static keyword, you can manage your constraints more efficiently. Understanding how to toggle these constraints using methods like constraint_mode() can help you create more flexible and controlled simulations.

Scroll to Top