Consider that a class already has well-written constraints, and there's a need to randomize the class variables with a different set of constraints, decided by the user. Using the with construct, you can declare inline constraints at the point randomize() is called. These additional constraints are considered alongside the object's original constraints by the solver — not instead of them.

10 min read | Intermediate Level

What You'll Learn

  • What an inline constraint is, and why it's applied on top of a class's existing constraints rather than replacing them
  • What happens when an inline constraint and an existing class constraint are genuinely incompatible
  • Why inline constraints can never override an existing constraint, only add to it
  • When constraint_mode() is the right tool instead, if a constraint actually needs to be replaced rather than added to

Basic Inline Constraint


class Item;
  rand bit [7:0] id;
  
  constraint c_id { id < 25; }
  
endclass

module tb;
  
  initial begin
    Item itm = new ();
    itm.randomize() with { id == 10; }; 		// In-line constraint using with construct
    $display ("Item Id = %0d", itm.id);
  end
endmodule

The inline constraint has been applied here, and the randomized id is 10:

Output
run -all;
# KERNEL: Item Id = 10
# KERNEL: Simulation has finished. There are no more test vectors to simulate.

This works because id == 10 and id < 25 are both true at once — the solver has no trouble satisfying both simultaneously.

Quick Check

Q: Would itm.randomize() with { id == 30; }; succeed against this same class?

Show Answer

No. Even though 30 is a perfectly legal 8-bit value on its own, it violates c_id's id < 25 requirement — an inline constraint still has to coexist with everything the class already declares, not just be valid in isolation.

When Inline and Class Constraints Conflict

If the original constraint fixes id to a single value, and the inline constraint asks for something incompatible, randomization fails:


class Item;
  rand bit [7:0] id;
  
  constraint c_id { id == 25; }
endclass

module tb;
  initial begin
    Item itm = new ();
    if (! itm.randomize() with { id < 10; })
    	$display ("Randomization failed");
    $display ("Item Id = %0d", itm.id);
  end
endmodule

Output

Output
ncsim> run
    if (! itm.randomize() with { id < 10; })
                      |
ncsim: *W,SVRNDF (./testbench.sv,10|22): The randomize method call failed.
Observed simulation time : 0 FS + 0
ncsim: *W,RNDOCS: These constraints contribute to the set of conflicting constraints:

  constraint c_id { id == 25; }; (./testbench.sv,4)
    if (! itm.randomize() with { id < 10; }) (./testbench.sv,10)
ncsim: *W,RNDOCS: These variables contribute to the set of conflicting constraints:

rand variables:
       id [./testbench.sv, 2]

Randomization failed
Item Id = 0
ncsim: *W,RNQUIE: Simulation is complete.

id can't simultaneously equal exactly 25 and be less than 10 — the solver correctly reports failure, and id is left at its stale default value, 0, rather than any value that actually satisfied either constraint.

The same failure happens even when both sides try to pin id to specific, individually valid values:


...
if (! itm.randomize() with { id == 10; })
...

Output

Output
ncsim> run
    if (! itm.randomize() with { id == 10; })
                      |
ncsim: *W,SVRNDF (./testbench.sv,10|22): The randomize method call failed.
Observed simulation time : 0 FS + 0
ncsim: *W,RNDOCS: These constraints contribute to the set of conflicting constraints:

  constraint c_id { id == 25; }; (./testbench.sv,4)
    if (! itm.randomize() with { id == 10; }) (./testbench.sv,10)
ncsim: *W,RNDOCS: These variables contribute to the set of conflicting constraints:

rand variables:
       id [./testbench.sv, 2]

Randomization failed
Item Id = 0
ncsim: *W,RNQUIE: Simulation is complete.

Even though id == 10 would be a perfectly legal value all on its own, c_id still requires exactly 25 — and a variable can't equal two different specific values at the same time.

Quick Check

Q: If c_id were changed to id inside {20, 25, 30}; (a set of 3 legal values) and the inline constraint were id == 25;, would this succeed?

Show Answer

Yes. 25 is one of the values c_id already permits, so both constraints agree — there's no conflict, since id = 25 genuinely satisfies both requirements at once.

Inline Constraints Add To, Never Replace

The takeaway from both failing examples: constraints provided inline don't override the class's original constraints — they're considered alongside them by the solver, as an addition, not a replacement. If a class constraint is genuinely incompatible with what a specific test needs, an inline constraint can never fix that on its own; the original constraint has to be disabled first, using constraint_mode():


// If a test genuinely needs to REPLACE c_id rather than add to it:
itm.c_id.constraint_mode(0);              // disable the original constraint first
itm.randomize() with { id < 10; };        // now this alone governs id
itm.c_id.constraint_mode(1);              // re-enable it afterward, if needed

Where Is This Used?

Inline constraints are commonly used in individual test cases to steer a shared, reusable transaction class toward one specific scenario, without writing an entirely new subclass just for that test. As this article shows, that only works cleanly when the desired value is still compatible with the class's own built-in rules — a genuinely incompatible override needs constraint_mode() instead.

Common Beginner Mistakes

Mistake #1: Assuming an inline constraint can override an existing class constraint

As both conflict examples show, it can't — it only adds to what's already there. Why? A genuinely incompatible inline value doesn't replace the class's rule; it just makes the overall constraint set impossible to satisfy, and the whole call fails.

Mistake #2: Not checking randomize()'s return value with an inline constraint

The same general risk applies here as anywhere else, but it's easy to underestimate with inline constraints specifically. Why? It's simple to write an inline value that looks perfectly reasonable on its own while forgetting about a class constraint declared elsewhere that quietly conflicts with it.

Mistake #3: Assuming a failed randomize() leaves an obviously invalid value

As both examples show, id lands on 0 after the failure — not some clearly-invalid sentinel value that would be easy to notice. Why? Zero can easily look like a legitimate value if you're not specifically checking the return value, making a silent failure even easier to miss.

Mistake #4: Reaching for an inline constraint to disable a rule entirely

An inline constraint can't turn off an existing class constraint — only constraint_mode(0) can. Why? If the actual goal is to bypass a rule completely for one test, rather than add a compatible extra condition, inline constraints are the wrong tool for that specific job.

Practice Exercise

Challenge: Predict Two Inline Calls

Given constraint c_range { val inside {[10:20]}; }, predict whether each of these inline calls succeeds: randomize() with { val == 15; } and randomize() with { val == 25; }.

Hint

Check each inline value against c_range's own allowed range — the inline constraint still has to coexist with it, not just be a reasonable value on its own.

Solution

val == 15 succeeds — 15 falls within [10:20], so both constraints agree. val == 25 fails — 25 is outside c_range's allowed window, so no value can satisfy both requirements at once, and the call returns 0 with val left at its stale prior value.

Summary

In this tutorial, you learned:

  • An inline constraint, added via randomize() with { ... }, is considered alongside a class's existing constraints, not instead of them
  • If the inline constraint and an existing class constraint can't both be true at once, randomize() fails and returns 0
  • A failed randomization leaves the variable at its stale prior value — not a distinctly invalid one, making the return value the only reliable way to detect the failure
  • Inline constraints can never override or disable an existing class constraint — that requires constraint_mode(0) instead
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5