Generate the array of unique values without using random and constraints

In short: When you need an array of distinct values in a mixed order but do not need full randomness, you can skip constraints. Fill the array with known distinct values, such as the index itself, then call the built in shuffle() method to rearrange them. The result has no repeats and a random order, and it solves instantly because there is no constraint solver involved. The catch is that the set of values is fixed; only the order is random.

The constraint solver is powerful but not free. For a set of distinct values where you only care about order, a fill and shuffle is far cheaper and just as correct. It is a handy trick for quick tests and large arrays.

A simple way to picture it

Think of numbered raffle tickets. You print tickets 1 through 10, so they are already all different. Then you drop them in a bag and shake it. When you draw them out, the order is random but you still have exactly tickets 1 through 10 with no repeats. Filling the array is printing the tickets; shuffle() is shaking the bag.

The fill and shuffle method

Fill each element with its index, or any formula that gives distinct values, then call shuffle() on the array. The values stay distinct and the order becomes random.

module tb;
  int data[10];
  initial begin
    foreach (data[i])
      data[i] = i;        // 0,1,2,...,9  all distinct
    data.shuffle();       // mix the order, keep the set
    $display("data = %p", data);
  end
endmodule

After shuffle() the array still holds 0 through 9, but in a mixed order such as 3, 7, 0, 9, 1, and so on. No value repeats because the fill made them distinct to begin with.

Using a formula for the values

The fill does not have to be the plain index. Any formula that gives distinct results works, such as squares or a base plus offset for addresses. Here the array holds ten distinct even numbers, shuffled.

module tb;
  int addr[8];
  initial begin
    foreach (addr[i])
      addr[i] = 32'h1000 + (i * 4);   // distinct word addresses
    addr.shuffle();
    $display("addr = %p", addr);
  end
endmodule

Expected output, in plain words

The first example prints the numbers 0 through 9 in a mixed order, with each value appearing exactly once. The second prints eight distinct word addresses starting from 0x1000 and spaced by 4, again in a mixed order. The set of values is fixed; only the order changes from run to run.

Note: these outputs describe what the code is written to produce from a read of the IEEE 1800 LRM. The order depends on the seed, so it differs each run. Confirm on your own simulator or EDA Playground.

shuffle vs the unique constraint

These two solve related but different problems. The unique constraint gives a fully random set of distinct values chosen by the solver. Fill and shuffle gives a fixed set in a random order, with no solver cost. Pick based on whether the values themselves need to be random or just their order.

PointFill + shuffleunique constraint
ValuesFixed set you chooseRandom set the solver picks
OrderRandomRandom
Solver costNoneUses the constraint solver
SpeedVery fastSlower for large or tight sets
Best forDistinct values, order mattersFully random distinct values

When to use fill and shuffle

  • You need distinct values and only the order must be random.
  • You want speed on a large array without the solver cost.
  • The value set is known, such as a fixed list of addresses or IDs.
  • You are writing a quick test and do not need constrained randomness.

Common mistakes to avoid

  • Expecting random values, not just order: the set is fixed by your fill; only the order changes.
  • A fill that repeats: if your formula produces duplicates, shuffle will not remove them. Make the fill distinct first.
  • Using it when you need constraints: if the values must satisfy rules or ranges, use a rand array with a unique constraint instead.
  • Assuming shuffle sorts: it mixes the order; it does not sort.

The fully random alternative

When the values themselves must be random, not just their order, use a rand array with a unique constraint. We cover that in our guide on how to generate an array of unique random values.

For more randomization control, see randomize vs std::randomize and rand_mode and constraint_mode. More is in our SystemVerilog tutorials.

Frequently asked questions

How do I make a unique array without random and constraints?

Fill each element with a distinct value such as its index, then call the built in shuffle() method on the array. The values stay distinct and the order becomes random, with no constraint solver cost.

What does the shuffle() method do?

shuffle() rearranges the elements of an array into a random order in place. It does not add or remove values, so a distinct set stays distinct.

Is fill and shuffle fully random?

No. The set of values is fixed by how you fill the array; only the order is random. For random values, use a rand array with a unique constraint.

When should I use shuffle instead of a unique constraint?

Use shuffle when you need distinct values and only the order must be random, when you want speed on a large array, or when the value set is already known.

What if my fill formula produces duplicates?

shuffle will not remove duplicates; it only mixes the order. Make sure the fill produces distinct values first, for example by using the index or a spaced formula.

Does shuffle sort the array?

No. shuffle mixes the order randomly. If you need the values sorted, sort the array separately after filling it.

Similar Posts