Inside a constraint block, there is NO implied order of how the variable values will be solved. The SystemVerilog constraint solver is free to choose the variables to randomize first.
Let us look at an example below. The intention is to randomize “addrType” first, and then randomize “addr” value per “addrType”. However, the constraint solver can randomize “addr” first, followed by “addrType”.
typedef enum {LOW, MID, HIGH} addr_t;
class myAddrBus {
rand bit[7:0] addr;
rand addr_t addrType;
constraint addr_range {
if (addrType == LOW) addr inside {[0:63]};
else if (addrType == MID) addr inside {[64:127]};
else if (addrType == HIGH) addr inside {[128:255]};
// equivalently, the use of implication operators is the same as using if-else
// (addrType == LOW) -> addr inside {[0:63]};
// (addrType == MID) -> addr inside {[64:127]};
// (addrType == HIGH) -> addr inside {[128:255]};
}
}
To dictate the constraint solver order, one can declare a random property as “randc” instead of “rand”. The constraint solver randomizes “randc” before “rand” properties. For example, we can declare “addrType” as “randc” and “addr” as “rand”.
However, there are subtle differences between “randc” and “rand”: “randc” exhausts all values before repeating any value, while “rand” can repeat without exhausting all possible values. (Think of “randc” as picking a card from a deck of cards, while “rand” as rolling a dice).
A better approach is to use “solve-before” construct to set solving order for the same type of random properties. Using the same example above:
class myAddrBus {
rand bit[7:0] addr;
rand addr_t addrType;
constraint addr_range {
if (addrType == LOW) addr inside {[0:63]};
else if (addrType == MID) addr inside {[64:127]};
else if (addrType == HIGH) addr inside {[128:255]};
solve addrType before addr;
}
}
Note, “solve-before” construct cannot force “rand” to be randomized before “randc” properties.

Leave a comment