Implication and If else in constraints

Implication Constraints (-> Operator)

The implication operator (->) is used to define conditional constraints. It ensures that when a specific condition is true, another condition or constraint must hold. The implication operator works like an if-then statement but in constraint form.

Syntax:

constraint constraint_name {
    condition -> consequence;
}
  • condition: A Boolean expression that acts as a trigger.
  • consequence: A constraint that must be satisfied if the condition is true.

If the condition is false, the solver ignores the consequence, and the randomization continues without enforcing it.

Example 1: Basic Implication Constraint

Let’s consider a scenario where if a packet is marked as high state, its size must be greater than or equal to 200.

class Packet;
  string state; 
  rand int size;

  // Constraint: If state is high, size must be at least 200
    constraint priority_size {
      (state == "high") -> size >= 200;
      size inside {[64:1000]}; // Valid range for size
    }
endclass

module tb;
    initial begin
        Packet pkt = new();
        pkt.state = "high";

      repeat (3) begin
            if (pkt.randomize()) begin
              $display("state: %0s, Size: %0d", pkt.state, pkt.size);
            end else begin
                $error("Randomization failed!");
            end
        end
    end
endmodule

Output:

state: high, Size: 653
state: high, Size: 765
state: high, Size: 345

If-Else Constraints in SystemVerilog

SystemVerilog also supports if-else constraints, which behave similarly to traditional if-else statements but are written inside a constraint block. These allow you to apply different constraints based on conditions dynamically.

Syntax:

constraint constraint_name {
    if (condition) {
        // Constraint when condition is true
    } else {
        // Constraint when condition is false
    }
}

Example 2: Using If-Else in Constraints

Let’s constrain a variable speed based on whether the packet type is control or data.

class Packet;
    rand bit is_control; // 1: control packet, 0: data packet
    rand int speed;

    // Constraint: Speed depends on packet type
    constraint speed_constraint {
        if (is_control) {
          speed inside {[10:90]}; // Speed range for control packets
        } else {
            speed inside {[100:1000]}; // Speed range for data packets
        }
    }
endclass

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

      repeat (10) begin
            if (pkt.randomize()) begin
              $display("is_control: %0d, Packet Type: %s, Speed: %0d", 
                         pkt.is_control, pkt.is_control ? "Control" : "Data", pkt.speed);
            end else begin
                $error("Randomization failed!");
            end
        end
    end
endmodule

Explanation:

  1. If-Else Logic: The constraint applies different speed ranges depending on is_control:
    • If is_control is 1 (control packet), the speed must be between [10:90].
    • Otherwise, the speed must be between [100:1000].
  2. Randomization: The solver applies the appropriate constraint based on the value of is_control.

Output:

is_control: 0, Packet Type:    Data, Speed: 742
is_control: 1, Packet Type: Control, Speed: 73
is_control: 1, Packet Type: Control, Speed: 73
is_control: 1, Packet Type: Control, Speed: 10
is_control: 0, Packet Type:    Data, Speed: 516
is_control: 0, Packet Type:    Data, Speed: 708
is_control: 0, Packet Type:    Data, Speed: 837
is_control: 1, Packet Type: Control, Speed: 69
is_control: 0, Packet Type:    Data, Speed: 485
is_control: 1, Packet Type: Control, Speed: 58