A constraint_expression is any SystemVerilog expression or one of the constraint specific operators( -> (Implication) and dist). Functions are allowed to certain limitation. Operators which has side effects are not allowed like ++,--.
Set Membership
A set membership is a list of expressions or a range. This operator searches for the existences of the value in the specified expression or range and returns 1 if it is existing.
EXAMPLE: class set_mem;
randinteger Var;
constraint range { Var inside {0,1,[50:60],[90:100]}; }
functionvoid post_randomize();
$write("%0d__",Var);
endfunction endclass
program set_mem_p_47;
set_mem obj=new();
initial repeat(10)
void'(obj.randomize());
endprogram
RESULTS:
50__57__60__93__100__94__90__1__54__100__
If you want to define a range which is outside the set, use negation.
EXAMPLE: class set_mem;
randbit [0:2] Var;
constraint range { !( Var inside {0,1,5,6});}
functionvoid post_randomize();
$write("%0d__",Var);
endfunction endclass
program set_mem_p_48;
set_mem obj=new();
initial repeat(10)
void'(obj.randomize());
endprogram
RESULTS:
7__4__4__4__7__2__2__3__2__7__
Engineers often mistaken that set membership operator is used only in constraint block. It can also be used in other scopes also.
class set_mem;
randbit [0:2] Var;
endclass
program set_mem_p_48;
set_mem obj=new();
integer repet = 0;
initial begin obj.Var = 1;
repeat(10)
begin void'(obj.randomize());
while ( obj.Var inside {[1:5]})
begin $display("Var = %0d",obj.Var);
break;
end end end endprogram RESULTS:
# Var = 4 # Var = 5 # Var = 1 # Var = 1 # Var = 2 # Var = 2
NOTE: X and Z are allowed in set membership operator, but not in constraint block, inside {....} is a statement which returns 0,1 or X .
Expressions are allowed in value set of inside operator.
If an expression in the list is an array then just use the array name in the constraint block. Elements are traversed by descending into the array until reaching a singular value.
int array [$] = '{3,4,5};
if ( ex inside {1, 2, array} )
Weighted Distribution
There are two types of distribution operators.
The := operator assigns the specified weight to the item or, if the item is a range, to every value in the range.
The :/ operator assigns the specified weight to the item or, if the item is a range, to the range as a whole. If there are n values in the range, the weight of each value is range_weight / n.
Var dist { 10 := 1; 20 := 2 ; 30 := 2 }
The probability of Var is equal to 10,20 and 30 is in the ratio of 1,2,2 respectively.
Var dist { 10 := 1; 20 := 2 ; [30:32] := 2 }
The probability of Var is equal to 10,20,30,31 and 32 is in the ratio of 1,2,2,2,2 respectively.
If you use the := operator each element weitht of the range has the assigned weight.
If you want to weight for the whole group,use :/ and the weight is equally distributed for each element in that group.
Var dist { 10 := 1; 20 := 2 ; [30:32] :/ 2 }
The probability of Var is equal to 10,20,30,31,32 is in the ration of 1,2,2/3,2/3,2/3 respectively.
To demonstrate the distribution property,hear is an example.
EXAMPLE: class Dist;
randinteger Var;
constraint range { Var dist { [0:1] := 50 , [2:7] := 50 }; }
endclass
Both the results show, how may times each value occured.
NOTE: If no weight is specified for items,the default weight is 1. Weight 0 is also allowed.
NOTE: Variable declared as randc are not allowed int dist.
If there are constraints on some expressions that cause the distribution weights on these expressions to be not satisfiable, implementations are only required to satisfy the non dist constraints. Use dist only on a one variable in a set of constraint expression variable.
In the following example, Even though probability of Var2 is equal to 0 to 1 is in ratio of 50, 50 to satisfy other constraints, the dist is ignored.
Calling a new(), resets the distrubution algorithem. If new() is called to creat an object when ever randomized is called,the dist algorithm restarts and the distribution may not be what is expected.
EXAMPLE: class Dist;
randinteger Var;
constraint range { Var dist { [0:1] := 50 , [2:7] := 50 }; }
endclass
program Dist_p_52;
Dist obj;
integer count_0_1 ,count_2_7 ;
The distribution is not followed if the variable is declared as randc as distribution may require repetition and randc doesnot allow. In the below example try changing the weights in distribution function, you will get always same results otherwise compilation error.
EXAMPLE: class Dist;
randcbyte Var;
constraint range { Var dist { [0:1] := 50 , [2:7] := 50 }; }
endclass
program Dist_p_52;
Dist obj;
integer count_0_1 ,count_2_7 ;
To constraint enumerated values using dist, if they are less number, give weights individually. If you want to give weights to enumerated values in groups, then give a continues group. As enumeration is represented in integer, the discontinuation in the declaration may not result properly.
EXAMPLE: program enums_53;
typedefenum {V_SMALL,SMALL,MEDIUM,LARGE,V_LARGE} size_e;
class dist_c;
rand size_e size_d;
constraint size_dist{size_d dist {[V_SMALL:MEDIUM] :/40,[LARGE:V_LARGE] :/ 60}; }
endclass
initialbegin dist_c obj;
obj=new;
for (int i=0; i<=10; i++)
begin obj.randomize();
$display (" size_d = %0s ", obj.size_d);
end end endprogram
Implication
Implication operator can be used to declare conditional relation. The syntax is expression -> constraint set. If the expression is true,then the constraint solver should satisfy the constraint set. If the expression is false then the random numbers generated are unconstrainted by constraint set. The boolean equivalent of a -> b is (!a || b).
randbit a;
randbit [3:0] b;
constraint c { (a == 0) -> (b == 1); }
a is one and b is 4 bit, So there are total of 32 solutions. But due to constraint c (when ever a is 0 b should be 1) 15 solutions are removed. So probability of a = 0 is 1/(32-15) = 1/17. If u observe the following program results count_0/count_1 approximately equal to 1/17.
EXAMPLE: class impli;
randbit a;
randbit [3:0] b;
constraint c { (a == 0) -> (b == 1); }
endclass
program impli_p_54;
impli obj;
integer count_0 ,count_1 ;
initial begin obj=new();
count_0 = 0;count_1 = 0;
for(int i=0; i< 10000; i++)
begin if( obj.randomize())
if( obj.a == 0 ) count_0 ++;
else count_1 ++;
end $display(" count_0 = %0d;count_1 = %0d; ",count_0 ,count_1);
end endprogram
RESULTS:
# count_0 = 571;count_1 = 9429;
If..Else
Just like implication, if...else style constraints are bidirectional.Above example applies hear too.
EXAMPLE: class if_else;
randbit a;
randbit [3:0] b;
constraint c { if(a == 0) (b == 1); }
endclass
program if_else_p_55;
if_else obj;
integer count_0 ,count_1 ;
initial begin obj=new();
count_0 = 0;count_1 = 0;
for(int i=0; i< 10000; i++)
begin obj = new();
if( obj.randomize())
begin if( obj.a == 0 ) count_0 ++;
elseif( obj.a == 1 ) count_1 ++;
end end $display(" count_0 = %0d;count_1 = %0d;",count_0 ,count_1);
end endprogram