SystemVerilog provides the support to use foreach
loop inside a constraint so that arrays can be constrained.
The foreach
construct iterates over the elements of an array and its argument is an identifier that represents a single entity in the array.
Click here to refresh loops in SystemVerilog !
Example
The code shown below declares a static array called array with size 5. This array can hold 5 elements where each element can be accessed using an index from 0 to 4.
The constraint uses foreach
loop to iterate over all the elements and assign the value of each element to that of its index.
class ABC;
rand bit[3:0] array [5];
// This constraint will iterate through each of the 5 elements
// in an array and set each element to the value of its
// particular index
constraint c_array { foreach (array[i]) {
array[i] == i;
}
}
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("array = %p", abc.array);
end
endmodule
The output given below shows that each element of the array was assigned to a value equal to that of its index.
ncsim> run
array = '{'h0, 'h1, 'h2, 'h3, 'h4}
ncsim: *W,RNQUIE: Simulation is complete.
Dynamic Arrays/Queues
Dynamic arrays and queues do not have a size at the time of declaration and hence the foreach
loop cannot be directly used. Therefore, the array's size has to be either assigned directly or constrained as part of the set of constraints.
Example
class ABC;
rand bit[3:0] darray []; // Dynamic array -> size unknown
rand bit[3:0] queue [$]; // Queue -> size unknown
// Assign size for the queue if not already known
constraint c_qsize { queue.size() == 5; }
// Constrain each element of both the arrays
constraint c_array { foreach (darray[i])
darray[i] == i;
foreach (queue[i])
queue[i] == i + 1;
}
// Size of an array can be assigned using a constraint like
// we have done for the queue, but let's assign the size before
// calling randomization
function new ();
darray = new[5]; // Assign size of dynamic array
endfunction
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("array = %p
queue = %p", abc.darray, abc.queue);
end
endmodule
ncsim> run array = '{'h0, 'h1, 'h2, 'h3, 'h4} queue = '{'h1, 'h2, 'h3, 'h4, 'h5} ncsim: *W,RNQUIE: Simulation is complete.
Multidimensional Arrays
SystemVerilog constraints are powerful enough to be applied on multidimensional arrays as well. In the following example we have a multidimensional static array with a packed structure.

Here we attempt to assign the pattern 0xF0F0F to each element of the multidimensional array.
class ABC;
rand bit[4:0][3:0] md_array [2][5]; // Multidimansional Arrays
constraint c_md_array {
foreach (md_array[i]) {
foreach (md_array[i][j]) {
foreach (md_array[i][j][k]) {
if (k %2 == 0)
md_array[i][j][k] == 'hF;
else
md_array[i][j][k] == 0;
}
}
}
}
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("md_array = %p", abc.md_array);
end
endmodule
ncsim> run md_array = '{'{'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f}, '{'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f}} ncsim: *W,RNQUIE: Simulation is complete.
Multidimensional Dynamic Arrays
Constraining a multi-dimensional dynamic array is a little more tricky and may not be supported by all simulators. In the example shown below, the size of X or Y elements of the 2D array md_array is not known.
class ABC;
rand bit[3:0] md_array [][]; // Multidimansional Arrays with unknown size
constraint c_md_array {
// First assign the size of the first dimension of md_array
md_array.size() == 2;
// Then for each sub-array in the first dimension do the following:
foreach (md_array[i]) {
// Randomize size of the sub-array to a value within the range
md_array[i].size() inside {[1:5]};
// Iterate over the second dimension
foreach (md_array[i][j]) {
// Assign constraints for values to the second dimension
md_array[i][j] inside {[1:10]};
}
}
}
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("md_array = %p", abc.md_array);
end
endmodule
ncsim> run
md_array = '{'{'h9, 'h6, 'h7, 'h9, 'h1}, '{'h5, 'h9, 'h4, 'h2}}
ncsim: *W,RNQUIE: Simulation is complete.
Array Reduction Iterative Constraint
This is another pretty useful construct and technique supported in SystemVerilog.
Array reduction methods can produce a single value from an unpacked array of integral values. This can be used within a constraint to allow the expression to be considered during randomization.
For example, consider that an array of N elements have to be randomized such that the sum of all elements equal some value. An array reduction operator can be used with the with
clause such that it iterates over each element of the array and include it in the constraint solver.
class ABC;
rand bit[3:0] array [5];
// Intrepreted as int'(array[0]) + int'(array[1]) + .. + int'(array[4]) == 20;
constraint c_sum { array.sum() with (int'(item)) == 20; }
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("array = %p", abc.array);
end
endmodule
ncsim> run array = '{'h4, 'h2, 'h2, 'h4, 'h8} ncsim: *W,RNQUIE: Simulation is complete.