Welcome ! This website will help YOU (recent graduates/professionals) learn verification languages like SystemVerilog and UVM. Register for free and access more content !

Now let's take a look at some of the common ways of writing constraint expressions inside a constraint block.

Simple expressions

Note that there can be only one relational operator < <= > >= in an expression.

 
  class MyClass;
    rand bit [7:0] min, typ, max;
 
    // Valid expression
    constraint my_range { 0 < min;
                          typ < max;
                          typ > min; 
                          max < 128; }
 
    // Use of multiple operators in a single expression is not allowed
    constraint my_error { 0 < min < typ < max < 128; }
 
    // This will set min to 16 and randomize all others
    constraint my_min {  min == 16; }
 
    // This will set max to a random value greater than or equal to 64
    constraint my_max {  max >= 64; }
  endclass
 

You cannot make assignments inside a constraint block as it only contains expressions. Instead you have to use an equivalence operator == as shown for the constraint named my_min in the example above where min will get a value of 16 and all other variables will be randomized. This is one way of fixing a particular value to a variable even if the solver attempts to randomize it.

 
  constraint my_min { min == temp.low * 9/5 + 32; }
 

You can also use a little more complex expression like the one shown above where min represents a variable to store Fahrenheit and low is a variable within the class object temp that holds temperature in Celsius.

Example
 
  class myClass;
      rand bit [3:0] min, typ, max;
      rand bit [3:0] fixed;
 
      constraint my_range { 3 < min;
                            typ < max;
                            typ > min;
                            max < 14; }
 
      constraint c_fixed { fixed == 5; }
 
      function string display ();
        return $sformatf ("min=%0d typ=%0d max=%0d fixed=%d", min, typ, max, fixed);
      endfunction
 
  endclass
 
    module tb;
       initial begin
          for (int i = 0; i < 10; i++) begin
             myClass cls = new ();
             cls.randomize();
             $display ("itr=%0d %s", i, cls.display());
          end
       end
    endmodule
 

Note that fixed variable is fixed to the value 5 while other variables have been randomized with values that meet all constraints.

run -all;
# KERNEL: itr=0 min=7 typ=9 max=12 fixed= 5
# KERNEL: itr=1 min=4 typ=9 max=12 fixed= 5
# KERNEL: itr=2 min=7 typ=10 max=13 fixed= 5
# KERNEL: itr=3 min=4 typ=6 max=11 fixed= 5
# KERNEL: itr=4 min=8 typ=12 max=13 fixed= 5
# KERNEL: itr=5 min=5 typ=6 max=13 fixed= 5
# KERNEL: itr=6 min=6 typ=9 max=13 fixed= 5
# KERNEL: itr=7 min=10 typ=12 max=13 fixed= 5
# KERNEL: itr=8 min=5 typ=11 max=13 fixed= 5
# KERNEL: itr=9 min=6 typ=9 max=11 fixed= 5
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
exit


inside operator

You can specify a lower and an upper limit as an alternative to the expression shown below using an inside operator.

 
  constraint my_range { typ > 32;
                        typ < 256; }
 
  // typ >= 32 and typ <= 256 
  constraint new_range { typ inside {[32:256]}; } 
 
  // Choose from the following values
  constraint spec_range { type inside {32, 64, 128}; }
 

Note that an inside construct includes both lower and upper limits. SystemVerilog gathers all the values and chooses between the values with equal probability unless there are other constraints on the variable.



Inverted inside operator

If you want any value outside a specific range, an inverted constraint can be written as follows. This will produce a random value from 0 to 31 since typ is an 8-bit variable and the upper limit already covers the maximum value it can hold.

 
  rand bit [2:0] typ;
  constraint inv_range { ! (typ inside {[3:6]}); }
 

Note that repeated randomization gave all values except the ones that fall within the range 3 through 6.

run -all;
# KERNEL: itr=0 typ=7
# KERNEL: itr=1 typ=0
# KERNEL: itr=2 typ=7
# KERNEL: itr=3 typ=0
# KERNEL: itr=4 typ=0
# KERNEL: itr=5 typ=0
# KERNEL: itr=6 typ=7
# KERNEL: itr=7 typ=1
# KERNEL: itr=8 typ=1
# KERNEL: itr=9 typ=7
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
exit


Weighted distributions

The dist operator allows you to create weighted distributions so that some values are chosen more often than others. The := operator specifies that the weight is the same for every specified value in the range while the :/ operator specifies that the weight is to be equally divided between all the values.

:= operator

 
  rand bit [2:0] typ;
  constraint dist1   {  typ dist { 0:=20, [1:5]:=50, 6:=40, 7:=10}; }
 

In dist1, the weight of 0 is 20, 6 is 40, and 7 is 10 while 1 through 5 is 50, for a total of 320. Hence the probability of choosing 0 is 20/320 and the probability of choosing a value between 1 and 5 is 50/320. Let's look at a simple example.

 
  class myClass;
    rand bit [2:0] typ;
    constraint dist1   {  typ dist { 0:=20, [1:5]:=50, 6:=40, 7:=10}; }
  endclass
 
  module tb;
    initial begin
      for (int i = 0; i < 10; i++) begin
        myClass cls = new ();
        cls.randomize();
        $display ("itr=%0d typ=%0d", i, cls.typ);
      end
    end
  endmodule
 

In the log shown below, note that 1 through 5 has appeared more than 0, 6 or 7 because they have a higher weight and are chosen more often.

run -all;
# KERNEL: itr=0 typ=5
# KERNEL: itr=1 typ=1
# KERNEL: itr=2 typ=6
# KERNEL: itr=3 typ=3
# KERNEL: itr=4 typ=2
# KERNEL: itr=5 typ=3
# KERNEL: itr=6 typ=0
# KERNEL: itr=7 typ=5
# KERNEL: itr=8 typ=1
# KERNEL: itr=9 typ=4
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
exit
:/ operator

 
  rand bit [2:0] typ;
  constraint dist2    {  typ dist { 0:/20, [1:5]:=50, 6:/10, 7:/20}; } 
 

In dist2, the weight of 0 is 20, 6 is 10 and 7 is 20 while 1 through 5 share a total weight of 50, thus have 10 each. Hence the probability of choosing 0 is 20/100, and the probability of choosing a value between 1 and 5 is 10/100. Let's look at a simple example.

 
  class myClass;
    rand bit [2:0] typ;
    constraint dist2   {  typ dist { 0:/20, [1:5]:/50, 6:/40, 7:/10}; }
  endclass
 
  module tb;
    initial begin
      for (int i = 0; i < 10; i++) begin
        myClass cls = new ();
        cls.randomize();
        $display ("itr=%0d typ=%0d", i, cls.typ);
      end
    end
  endmodule
 

In the log shown below, note that 6 has appeared more than the others because it has the highest weight.

run -all;
# KERNEL: itr=0 typ=5
# KERNEL: itr=1 typ=6
# KERNEL: itr=2 typ=4
# KERNEL: itr=3 typ=6
# KERNEL: itr=4 typ=6
# KERNEL: itr=5 typ=4
# KERNEL: itr=6 typ=2
# KERNEL: itr=7 typ=3
# KERNEL: itr=8 typ=4
# KERNEL: itr=9 typ=6
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
exit


Bidirectional constraints

Constraint blocks are not executed from top to bottom like procedural code, but are all active at the same time. Let's see this with another example.

 
  class myClass;
    rand bit [3:0] val;
    constraint  c1 { val > 3;
                     val < 12; }
 
    constraint  c2  {val >= 10; }
  endclass
 
  module tb;
    initial begin
      for (int i = 0; i < 10; i++) begin
        myClass cls = new ();
        cls.randomize();
        $display ("itr=%0d typ=%0d", i, cls.val);
      end
    end
  endmodule  
 

Note that constraints c1 and c2 limits the values to 10 and 11.

run -all;
# KERNEL: itr=0 typ=11
# KERNEL: itr=1 typ=11
# KERNEL: itr=2 typ=11
# KERNEL: itr=3 typ=10
# KERNEL: itr=4 typ=11
# KERNEL: itr=5 typ=10
# KERNEL: itr=6 typ=10
# KERNEL: itr=7 typ=10
# KERNEL: itr=8 typ=10
# KERNEL: itr=9 typ=10
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
exit

Was this article helpful ?

We use cookies to personalize content and ads, to provide social media features and to analyze our traffic. You consent to our cookies if you continue to use our website. To find out more about the cookies we use and how to delete them, see our privacy policy.

  I accept cookies from this site.
Agree
EU Cookie Directive plugin by www.channeldigital.co.uk