This is the problem from my last interview as following:
Q. (Constrained randomization) Consider the lottery rules on this page
The Following are my code link to EDA playground:
Test Bench:
module tb;
initial begin
Pick p = new();
p.randomize();
$display("\nPicked result:");
for (int i=0; i<`NUM_JACKPOT; i++)
$write("%0d ", p.jackpot_result[i]);
$write("\n");
end
endmodule
Design Code:
`define NUM_JACKPOT 6
class Lottery;
randc int six_jackpot_nums[`NUM_JACKPOT];
constraint rand_jackpot {
foreach (six_jackpot_nums[i])
six_jackpot_nums[i] inside {[1:49]};
}
endclass
class Pick;
randc int six_jackpot_nums[`NUM_JACKPOT];
randc int jackpot_result [`NUM_JACKPOT];
int award_2nd_hi = `NUM_JACKPOT -1;
function pre_randomize();
Lottery l = new();
l.randomize();
$display("Jackpot bingo:");
for (int i=0; i<`NUM_JACKPOT; i++) begin
six_jackpot_nums[i] = l.six_jackpot_nums[i];
$write("%0d ", l.six_jackpot_nums[i]);
end
endfunction
constraint pick_jackpot{
foreach (jackpot_result[i])
jackpot_result[i] inside {[1:49]};
award_2nd_hi == (match(jackpot_result[0])+match(jackpot_result[1])+match(jackpot_result[2])+match(jackpot_result[3])+match(jackpot_result[4])+match(jackpot_result[5]));
}
function int match(int v);
int tmp[$];
tmp = six_jackpot_nums.find(x) with (x == v);
if(tmp.size != 0) return 1;
return 0;
endfunction
endclass
For the current status, I can successfully create the Six Number Jackpot. Yet, as I creating the 2nd highest pair of numbers, I got the conflict. Please advice.
Result:
xmsim: *W,RNDOCS: These constraints contribute to the set of conflicting constraints:
award_2nd_hi == (match(jackpot_result[0])+match(jackpot_result[1])+match(jackpot_result[2])+match(jackpot_result[3])+match(jackpot_result[4])+match(jackpot_result[5])); (./design.sv,31)
xmsim: *W,RNDOCS: These variables contribute to the set of conflicting constraints:
Var_Name Type Status Current_Value Source
-----------------------------------------------------------------------------------------------------
award_2nd_hi (S32) STATE VAR 5 (0x5) ./design.sv ; line 16
jackpot_result[0] (S32) SOLVED EARLY 32 (0x20) ./design.sv ; line 15
jackpot_result[1] (S32) SOLVED EARLY 47 (0x2f) ./design.sv ; line 15
jackpot_result[2] (S32) SOLVED EARLY 21 (0x15) ./design.sv ; line 15
jackpot_result[3] (S32) SOLVED EARLY 40 (0x28) ./design.sv ; line 15
jackpot_result[4] (S32) SOLVED EARLY 1 (0x1) ./design.sv ; line 15
jackpot_result[5] (S32) SOLVED EARLY 27 (0x1b) ./design.sv ; line 15
match( .v( jackpot_result[0] ) ) (S32) SOLVED EARLY 0 (0x0) ./design.sv ; line 31
match( .v( jackpot_result[1] ) ) (S32) SOLVED EARLY 1 (0x1) ./design.sv ; line 31
match( .v( jackpot_result[2] ) ) (S32) SOLVED EARLY 0 (0x0) ./design.sv ; line 31
match( .v( jackpot_result[3] ) ) (S32) SOLVED EARLY 0 (0x0) ./design.sv ; line 31
match( .v( jackpot_result[4] ) ) (S32) SOLVED EARLY 0 (0x0) ./design.sv ; line 31
match( .v( jackpot_result[5] ) ) (S32) SOLVED EARLY 0 (0x0) ./design.sv ; line 31
Jackpot bingo:
31 49 43 24 47 8
Picked result:
0 0 0 0 0 0
Here is a simpler approach which avoids all the warnings (and errors on other simulators). Randomly generate the set of 6 winners. Also, randomly pick one of the winners to be replaced with a losing number. Using post_randomize
, create the set of losers, then randomly pick one of them and replace one of the winners.
`define NUM_JACKPOT 6
class Lottery;
rand int six_jackpot_nums[`NUM_JACKPOT];
int jackpot_result [`NUM_JACKPOT];
int losers [$];
rand int unsigned idx;
function void post_randomize;
for (int i=1; i<50; i++) begin
if (!(i inside {six_jackpot_nums})) losers.push_back(i);
end
losers.shuffle();
for (int i=0; i<`NUM_JACKPOT; i++) begin
jackpot_result[i] = (i == idx) ? losers[0] : six_jackpot_nums[i];
end
endfunction
constraint rand_jackpot {
unique {six_jackpot_nums};
foreach (six_jackpot_nums[i]) six_jackpot_nums[i] inside {[1:49]};
idx inside {[1:`NUM_JACKPOT]};
}
endclass
module tb;
Lottery lot;
initial begin
lot = new();
void'(lot.randomize());
$display("\nPicked result:");
for (int i=0; i<`NUM_JACKPOT; i++) $write("%0d ", lot.six_jackpot_nums[i]);
$display("\nJackpot bingo:");
for (int i=0; i<`NUM_JACKPOT; i++) $write("%0d ", lot.jackpot_result [i]);
$display;
end
endmodule
Example output:
Picked result:
48 4 46 3 17 16
Jackpot bingo:
48 4 21 3 17 16
Here, 46 is replaced by 21.
To address the randc
issue noted in another answer, use the unique
constraint keyword.