I would like to randomize an array of numbers with the following given constraints:

- all numbers are inside [1:7]
- array average is 4.882
- "triangular shaped" distribution around the array average. i.e. majority of the numbers (>90%) should be in the range [$floor(avg):$ceil(avg)] (=[4:5]), and then with lower probability the numbers {3,6}, and then with the least probability (~1%) the numbers {1,2,7}

I've tried the following code:

class credit_flow_data #(int size = 1000); int credit_prob; rand int credit_high_duration_arr[size]; longint credit_high_duration_arr_desired_sum; real credit_high_duration_desired_avg; real credit_low_duration_desired_avg; function new(int credit_prob, real credit_low_duration_desired_avg); this.credit_prob = credit_prob; this.credit_low_duration_desired_avg = credit_low_duration_desired_avg; calc_credit_high_duration_desired_avg(); this.credit_high_duration_arr_desired_sum = longint'(this.size*this.credit_high_duration_desired_avg); endfunction function void calc_credit_high_duration_desired_avg(); real credit_prob_normalized = real'(this.credit_prob)/100.0; if (credit_prob_normalized == 0 || credit_prob_normalized == 1) begin this.credit_high_duration_desired_avg = credit_prob_normalized; end else begin this.credit_high_duration_desired_avg = credit_prob_normalized/(1-credit_prob_normalized)*this.credit_low_duration_desired_avg; end $display("credit_high_duration_desired_avg = %0f", credit_high_duration_desired_avg); endfunction: calc_credit_high_duration_desired_avg constraint credit_high_duration_arr_c { if (this.credit_prob == 0 || this.credit_prob == 100) { foreach (credit_high_duration_arr[i]) { credit_high_duration_arr[i] == this.credit_prob/100; } } else { foreach (credit_high_duration_arr[i]) { credit_high_duration_arr[i] inside {[1:7]}; credit_high_duration_arr[i] dist {4:=950, 5:=950, [1:2]:/5, 3:=50, 6:=50, 7:=5}; } credit_high_duration_arr.sum() with (int'(item)) == credit_high_duration_arr_desired_sum; } } endclass module tb; credit_flow_data #(1000) data; int credit_prob; initial begin credit_prob = 83; data = new(credit_prob, 1); data.randomize(); for (int i=0; i<data.size; i++) begin $display("%0d", data.credit_high_duration_arr[i]); end end endmodule

The avg is as expected - 4.882, but oddly the probability of 7's is too high - 154/1000=15.4% !

In addition, most of the 7's are located at the end of the array (sequence of 7's), and it's less desired. I would like a more shuffled like behavior (i.e. the 7's should be spread throughout the array).

Any suggestions?

Other solutions to the problems also welcome :)