Inline Constraints

SystemVerilog is widely used for functional verification, and its constraint-based randomization is a powerful feature that allows the generation of random values while meeting specific requirements. Constraints can be defined inside a class or applied inline when calling the randomize() method. Inline constraints provide flexibility for overriding or adding constraints temporarily without modifying the class itself.

This article explores inline constraints, their usage, scenarios involving conflicts, and how constraints from the class and inline constraints interact. We’ll use examples to illustrate these concepts.

Inline Constraints

Inline constraints are constraints written directly within the randomize() method call. They are used to override or supplement class-defined constraints temporarily, offering great flexibility during testing. Inline constraints can be written using with keyword.

Syntax:

obj.randomize() with { constraint_block };

Example: Basic Inline Constraint

class Packet;
    rand bit [7:0] addr;
endclass

module testbench;
    initial begin
        Packet pkt = new();

        // Randomize with inline constraint
        pkt.randomize() with { addr > 100 && addr < 200; };

        $display("Randomized address: %0d", pkt.addr);
    end
endmodule

In this example, the addr field is randomized such that its value lies between 101 and 199, as constrained by the inline block.

Output:

Randomized address: 103

Inline Constraints with Class Constraints

Inline constraints can be used alongside class constraints to refine or temporarily override them.

Example: Class and Inline Constraints

class Packet;
    rand bit [7:0] addr;

    // Class constraint
    constraint addr_range { addr >= 50 && addr <= 150; }
endclass

module testbench;
    initial begin
        Packet pkt = new();

        // Randomize with an inline constraint
        pkt.randomize() with { addr > 100; };

        $display("Randomized address: %0d", pkt.addr);
    end
endmodule

Explanation:

  • The class constraint ensures that addr is between 50 and 150.
  • The inline constraint further refines it to addr > 100.
  • The effective range for addr is now 101 to 150.

Output:

Randomized address: 141

Conflict with Inline Constraints

Conflicts arise when inline constraints contradict class constraints. SystemVerilog will detect the inconsistency and fail to randomize.

Example: Conflicting Constraints

class Packet;
    rand bit [7:0] addr;

    // Class constraint
    constraint addr_range { addr >= 50 && addr <= 150; }
endclass

module testbench;
    initial begin
        Packet pkt = new();

        // Attempt to randomize with conflicting constraints
        if (!pkt.randomize() with { addr < 40; }) begin
            $display("Randomization failed due to conflicting constraints.");
        end
    end
endmodule

Explanation:

  • The class constraint requires addr to be between 50 and 150.
  • The inline constraint specifies addr < 40, creating a conflict.
  • Randomization fails because no value satisfies both constraints.

Output:

Error-[CNST-CIF] Constraints inconsistency failure
testbench.sv, 15
  Constraints are inconsistent and cannot be solved.
  Please check the inconsistent constraints being printed above and rewrite 
  them.

Randomization failed due to conflicting constraints

Let’s take one more example for generating even numbers using inline constraints.

Example: Generate even no using inline constraints only

class Packet;
    rand bit [7:0] addr;
endclass

module testbench;
    initial begin
        Packet pkt = new();
      repeat (5) begin
        // Randomize with inline constraints only
        pkt.randomize() with { addr % 2 == 0; }; // Generate even addresses

        $display("Randomized even address: %0d", pkt.addr);
      end
    end
endmodule

In this example, the addr variable is constrained inline to be even, without needing a class constraint.

Output:

Randomized even address: 106
Randomized even address: 232
Randomized even address: 204
Randomized even address: 212
Randomized even address: 2

Best Practices for Using Inline Constraints

  1. Avoid Conflicts: Ensure that inline constraints do not contradict class constraints to prevent randomization failure.
  2. Use Inline Constraints Sparingly: Reserve inline constraints for temporary or case-specific scenarios. For reusable constraints, define them in the class.
  3. Leverage Constraints for Debugging: Use inline constraints to test specific edge cases during verification without altering the class.
  4. Combine Constraints Effectively: Use inline constraints to refine or specialize class constraints, ensuring they complement each other.