SystemVerilog Constraint-Based Questions and Answers
SystemVerilog Constraint-Based Questions and Answers
Answers
Question 1: Restrict a random variable to a specific range
Problem: How can you constrain a random integer to lie between 0 and 100 inclusive?
class RangeExample;
rand int x;
// Constrain x to the range [0, 100]
constraint c_range { x inside {[0:100]}; }
endclass
Explanation: SystemVerilog constraints declare legal values for rand variables 1 . In the example, x
inside {[0:100]} restricts x to the range 0–100 on every randomization. The inside syntax
specifies an inclusive range or set of values for the variable.
class BitPattern;
rand bit [3:0] nibble;
// Ensure MSB is 1
constraint c_msb { nibble[3] == 1; }
endclass
Explanation: Constraints can directly reference bits of a vector. Here, nibble[3] == 1 forces the MSB of
nibble to be 1 (making its value between 8 and 15). This uses a straightforward hard constraint on the bit
value.
class CountOnes;
rand bit [7:0] data;
// Constrain exactly 3 ones in data
1
constraint c_count { $countones(data) == 3; }
endclass
Explanation: SystemVerilog provides the built-in $countones() function to count the number of 1-bits.
The constraint $countones(data) == 3 forces exactly three bits of data to be 1 2 . This is a
convenient way to enforce a fixed population count in a vector.
class UniqueArray;
rand byte arr [5];
// Ensure all array elements are unique
constraint c_unique { unique {arr}; }
endclass
Explanation: In SystemVerilog 2012 and later, the unique constraint ensures all elements differ. The
syntax unique {arr} means every element of arr must have a unique value. For example,
std::randomize(arr) with { unique {arr}; }; assigns 5 distinct values to arr 3 .
class AlignedAddress;
rand bit [31:0] addr;
// Constrain addr to [0x2000..0x4000] and 4-byte aligned
constraint c_align {
addr inside {[32'h2000:32'h4000]};
addr % 4 == 0;
}
endclass
Explanation: The constraint addr inside {[32'h2000:32'h4000]} restricts the address range, and
addr % 4 == 0 enforces a 4-byte alignment. For example, ChipVerify shows addr inside
{[32'h2000:32'h4000]}; addr % 4 == 0; as a solution to this problem 4 . The modulo condition
ensures addr is a multiple of 4.
2
class Implication;
rand bit a;
rand bit [1:0] b;
// If a is 1 then b must be 3
constraint c_impl { a -> (b == 2'b11); }
endclass
Explanation: The implication operator -> is used to express if-then logic. a -> (b == 2'b11) means if
a is true (1), then b must equal 2'b11 (which is 3). ChipVerify provides a similar example:
constraint c_ab { a -> b == 3'h3; } forces b to 3 whenever a is 1 5 .
class ForeachStatic;
rand bit [3:0] arr [5];
// Constrain arr[i] == i for i = 0..4
constraint c_each { foreach (arr[i]) arr[i] == i; }
endclass
Explanation: The foreach construct lets you iterate over array elements within a constraint. In this
example, foreach (arr[i]) arr[i] == i; sets each element of arr to its index value 6 .
ChipVerify illustrates this: constraint c_array { foreach (array[i]) array[i] == i; } assigns
array[i] = i for all i 6 .
class ForeachDynamic;
rand int darray []; // dynamic array with unknown size
// Specify size and element constraints
constraint c_size { darray.size() == 5; }
constraint c_each { foreach (darray[i]) darray[i] == i; }
function new(); darray = new[5]; endfunction
endclass
Explanation: For dynamic arrays, you must first set the size (either by assignment or a constraint) before
randomization. In the example, darray = new[5]; sets the array length. Then constraint c_each
3
{ foreach (darray[i]) darray[i] == i; } constrains each element. ChipVerify shows a similar
pattern: they set darray = new[5]; , then use foreach to constrain elements 7 .
class SoftConstraint;
rand bit [3:0] data;
// The 'soft' keyword makes this constraint lower priority
constraint c_soft { soft data >= 4; data <= 12; }
endclass
Explanation: By default, constraints are “hard” and must be satisfied. Declaring a constraint with soft
gives the solver flexibility to violate it if other constraints demand it. In this example, soft data >= 4;
prefers data to be ≥ 4, but an overriding inline constraint (e.g. data == 2 ) can still succeed by
breaking the soft constraint. ChipVerify notes that a soft constraint can be overridden: for instance, soft
data >= 4; in a constraint allows an inline constraint data == 2; to set data to 2 8 .
class SolveBeforeExample;
rand int a, b;
// Enforce solve order: a is solved before b
constraint c_order {
solve a before b;
b == a + 1;
}
endclass
Explanation: The solve A before B; directive tells the solver to choose A first, then solve constraints
on B . This can change the distribution of correlated solutions. In the example, b == a + 1 is the
relation, and solve a before b; ensures a is chosen freely before determining b . As shown in
documentation, solve a before b; makes a independent and then computes b 9 .
Sources: These examples follow standard SystemVerilog constraint syntax and practices 1 6 8 3 4
5 2 9 . Each code snippet uses rand and constraint to enforce the stated properties, illustrating
4
1 SystemVerilog Constraints
https://www.chipverify.com/systemverilog/systemverilog-constraints
3 system verilog - Systemverilog unique array values during randomizatoin - Stack Overflow
https://stackoverflow.com/questions/38360372/systemverilog-unique-array-values-during-randomizatoin