SystemVerilog constraints are pretty amazing ! Lets see one use case where constraints are used to generate two queues of random sizes with unique values. Let us assume total number of elements in each queue should be less than or equal to 10.
Consider that both queues are part of a class called ABC. The first logical thing would be to decide the size of each queue which can be maintained in two separate variables that can be randomized. The constraints on these variables ensure that the total number of elements in each queue meets the requirement.
class ABC; int l_q[$]; int l_q2[$]; rand int l_q_size; rand int l_q2_size; constraint c_size { l_q_size inside {[1:9]}; l_q2_size inside {[1:10]}; (l_q_size + l_q2_size) <= 10; l_q2_size >= 1; solve l_q_size before l_q2_size; } endclass module tb; initial begin ABC abc = new; abc.randomize(); $display ("l_q_size=%0d l_q2_size=%0d", abc.l_q_size, abc.l_q2_size); for (int i = 0; i < abc.l_q_size; i++) begin int l_num; std::randomize(l_num) with { l_num inside {[1:10]}; !(l_num inside {abc.l_q}); }; abc.l_q.push_back(l_num); end for (int i = 0; i < abc.l_q2_size; i++) begin int l_num; std::randomize(l_num) with { l_num inside {[1:10]}; !(l_num inside {abc.l_q2, abc.l_q}); }; abc.l_q2.push_back(l_num); end $display("l_q=%p", abc.l_q); $display("l_q2=%p", abc.l_q2); end endmodule
The class instance abc is randomized to decide on the size for each queue. That many number of elements can be randomized and pushed into the queue using a simple for
loop. For each iteration, a local variable is randomized using the scope randomizer with inline constraints. These constraints ensure that unique elements are pushed into the queue and each element falls within the valid range.
In a similar way, the second for
loop pushes a new set of elements into the second queue. Note that the inline constraint has also considered l_q or the first queue to keep elements unique between the two queues.
This is the fastest way to generate two queues with unique data.
class ABC; rand int l_q[$]; rand int l_q2[$]; constraint c_q { l_q.size() inside {[1:10]}; foreach (l_q[i]) { l_q[i] inside {[1:10]}; unique {l_q}; } } constraint c_q2 { l_q.size() + l_q2.size() inside {[1:10]}; foreach (l_q2[i]) { l_q2[i] inside {[1:10]}; unique {l_q, l_q2}; } } endclass module tb; initial begin ABC abc = new; abc.randomize(); $display("l_q=%p", abc.l_q); $display("l_q2=%p", abc.l_q2); end endmodule
This could be your next interview question !