Randomly distribute ones in a n bit vector

How can I effectively disitribute ones in a n bit vector so that its cross sum matches a given value by using Systemverilog randomization constraints?

My current solution is:

int temp_value,
    temp_array[$];
bit [n-1:0] vector;
int cross_sum;

vector = {{n}{1'b0}};

for(int i = 0; i < cross_sum; i++)
begin
  void'(randomize(temp_value) with {temp_value inside {[0:n-1]} && !(temp_value inside {temp_array});});
  temp_array.push_back(temp_value);
  vector[temp_value] = 'b1;
end

This solution is too slow in simulation for n=2^14.

Is cross_sum is also random type or fixed. ??
till now i understand that you want to put ones in random position in vector. That number of number of ones should not be greater than cross sum . please correct me if I am wrong .

Hi

May be this code help you .

int unsigned cross_sum ;
rand int [n-1:0] vector ;
rand int unsigned enble_1[$] ;

constraint enble_size_sum { enble_1.size == n ; enble_1.sum == cross_sum ;}
constraint enble_values { foreach(enble_1[i]) enble_1[i] inside[0:1] ; }
constraint vector_1 {foreach(vector[i]) { vector[i] == enble_1[i] ; } }

You can use either

void'( randomize(vector) with { $countones(vector) == cross_sum } );

or

bit temp_array[n];
bit [n-1:0] vector;
int cross_sum;

  void'(randomize(temp_array) with { (temp_array.sum(b) with (int'(b)) == cross_sum); } );
  vector = type(vector)'(temp_array);

In reply to dave_59:

Unfortunately this solution seems not to work on the Cadence Incisive Simulator (tried on version 12.20.009 and 13.10.003). It seems that the simulator get stuck in an infinite loop.

In reply to Chandra Bhushan Singh:

Cross_sum is a fixed value. I need the number of ones in vector to be equal to cross_sum.

How about this code? It seems not slow even when n is a big value.


parameter n = 16384;
int temp_value;
int temp_array[$];
bit [n-1:0] vector;
int cross_sum;
initial begin
    vector = {{n}{1'b0}};
    cross_sum = $urandom_range(1,n);
    $display(" cross_sum: %0d",cross_sum);
    for(int i = 0; i < n; i++)
    begin
        temp_array.push_back(i);
    end
    temp_array.shuffle;
    for(int i =0;i<cross_sum;i++)begin
        vector[temp_array[i]] = 1'b1;
    end
    $display("vector: %b",vector);
end

I think Dave’s code works well for constraints. If you want to do it procedurally:

Compare the following code:
bit [n-1:0] pattern;

for(int i =0; i<N ; i++) // N= number of ones in array
begin
patern[i] =1’b1;
end
pattern.shuffle();

In reply to sebastian.schmutz:

Hi,
Here my two cents.
I find the solution provided in other thread important to be mentioned. That solution is in my opinion longer but quite more efficient than leaving the count function in the constraint solver.

That solution is about creating a vector of indices that you can shuffle, and then randomize the number of index you want to take from that vector to insert the ones. Take in mind that this doesn´t require any constraint and it doesn´t force the solver with try and error but just plain loops.

Here i present an example function where you can configure the max number of ones inside 3 vectors of 32,32 and 128bits respectively and that will be concatenated in one single vector.


    function logic[BLK_AIRQC_NUM_IRQS-1:0] randomize_irq(int max_int_ones=15,int max_ext_ones=15,int max_sgi_ones=20);
        automatic logic [BLK_AIRQC_NUM_IRQS-1:0] all_irqs_after_randomization=0;
        automatic int  irqs_128index_arr[BLK_AIRQC_NUM_IRQ_INT_G];
        automatic int  irqs_32index_arr[BLK_AIRQC_NUM_IRQ_EXT_G];
        automatic logic [BLK_AIRQC_NUM_IRQ_INT_G-1:0] int_irqs=0;        
        automatic logic [BLK_AIRQC_NUM_IRQ_EXT_G-1:0] ext_irqs=0;        
        automatic logic [BLK_AIRQC_NUM_IRQ_SGI_G-1:0] sgi_irqs=0;
        automatic int random_number_of_ones;
        //allirqs= (MSB) sgi , ext , int (LSB)
        //Initialization of indices
        foreach(irqs_32index_arr[i]) begin
            irqs_32index_arr[i]=i;//put indices on each element value
        end
        foreach(irqs_128index_arr[i]) begin
            irqs_128index_arr[i]=i;//put indices on each element value
        end
        //end of initialization
        //////////////////////
        
        irqs_32index_arr.shuffle;//randomize the order of the array or indices        
        assert(std::randomize() with {random_number_of_ones dist  {['h1:max_ext_ones]:=100, 0:=0,['h0:32]:=50};});            
        for (int unsigned i=0; i<random_number_of_ones; i++) begin//now use the n first indices to put ones
            ext_irqs[irqs_32index_arr[i]]=1;//put ones for IRQs using the index from the shuffled vector            
        end
        irqs_32index_arr.shuffle;//randomize the order of the array or indices
        assert(std::randomize(random_number_of_ones) with {random_number_of_ones dist  {['h1:max_sgi_ones]:=100, 0:=0,['h0:32]:=50};});
        for (int unsigned i=0; i<random_number_of_ones; i++) begin
            sgi_irqs[irqs_32index_arr[i]]=1;//put ones for IRQs using the index from the shuffled vector            
        end
        irqs_128index_arr.shuffle;//randomize the order of the array or indices
        assert(std::randomize(random_number_of_ones) with {random_number_of_ones dist  {['h1:max_int_ones]:=100, 0:=0,['h0:128]:=30};});
        for (int unsigned i=0; i<random_number_of_ones; i++) begin
            int_irqs[irqs_128index_arr[i]]=1;//put ones for IRQs using the index from the shuffled vector            
        end
        all_irqs_after_randomization = {sgi_irqs, ext_irqs, int_irqs};
        return all_irqs_after_randomization;        
    endfunction


I hope it helps
Jonathan