Generate unique elements in an array

In reply to Reuben:
I don’t get a compiler error when I run this in Questa. I do get an assertion error when I run this because the randomization fails. That is because you are excluding 4 values which leaves only 12 possible values of a 4-bit number that could be unique. So you need to change your array declaration to arr[12].

This is about specifying the hard coded values in unique constrains as shown in below.

class nibbleset;
rand bit [3:0] nibbles[10];
const rand bit [3:0] excludes = {0,15};
rand bit[3:0] excluded;
constraint uniq {unique {nibbles, excludes,7};}
//constraint uniq {unique {nibbles, excludes,excluded};}
constraint exclusion { excluded==1; }
endclass

We are seeing the error as shown in below for the above code snippet(uncommitted line ).

Error-[CSTR-NET] Non-equivalent type
customer_test.sv, 18

If I replace the value 7 with an identifier(excluded) the test case is passing.

The following blog was mentioning about the hard coded values in the unique constraints is allowed .

Is this valid to mention the hardcoded values in the unique constraint list ( constraint uniq {unique {nibbles, excludes,7};}

In reply to kvssrohit:

My guess is your compiler sees “7” as 32-bit integer and hence saying “non-equivalent” - try 4’d7

Srini
www.verifworks.com

In reply to Srini @ CVCblr.com:

Hello Everyone,

In reference with discussion going on unique constructs i have few points as a query.

I have compiled & executed this below simple code to check the sv-2012 unique construct.However it is executing successfully with VCS 2014.10 but for cadence incisive 15.20 it is reporting an error like below::
ncvlog: *E,MSTBER (design.sv,5|38): Expecting a random variable (declared with the ‘rand’ modifier).

Is it having possibility like we have to pass some switch to enable 2012 constructs?
Also the concept of unique is related only with randomizing unique array elements or it has some other use cases as well apart from array randomizing?

 class dummy;
   rand bit [3:0] mode[5];
   bit[3:0] exludes[]={1,2,3,4,5,6};
   constraint uniq{unique {mode,exludes};} //excluding elements 
  endclass : dummy

module test_unique;
  
  initial begin
  dummy clkgen = new();
  clkgen.randomize();
  for(int i=0;i<5;i++) 
    begin
    $display("clkgen.mode = %0d\n",clkgen.mode[i]);
    end   
   end

endmodule

Regards,
Geet

In reply to Geet:

It seems Incisive has a problem with the unique constraint or it is caused by a weakness in your code. You should clean-up your code in test_unique:
(1) make the declaration of clkgen outside of the inital block.
(2) construct clkgen in the initial.

It works fine with Questa.
unique is not a simple keyword. It defines the so-called ‘Uniqueness constraints’.
See chapter 18.5.5 in the SV Standard 2012.

In reply to chr_sue:

Thanks for reply,

I had referred the 18.5.5 chapter in SV and by overriding ‘exclusion’ constraint we can achieve the requirement


  class dummy;
    rand bit [3:0] mode[5];
    rand bit [3:0]excluded[5];
    constraint uniq{unique {mode,excluded};}
    constraint exclusion { excluded[0] == 12; excluded[1] == 13;excluded[2] == 14;excluded[3] == 15;}
  endclass : dummy

I had overridden the constraint for the values which i desired to exclude & it is working fine with cadences as well.

It was necessary to call this constraint to exlude the numbers,it was not dependant on the declaration on the construct clkgen.

Thank you for your pointer to LRM it has the solution.

hi sir,
i would like to generate the randomize array value with constraint method in sv.
for example
0_th location store the array value is 0…;
1_th location store the array value is 5,10,15…;
2_th location store the array value is 6,12,18…;
3_th location stote the array value is 7,14,21…;
4_th location stote the array value is 8,16,24…;
5_th location stote the array value is 9,18,27…;

code but not this working.

class A;
rand bit[31:0] data[6];
//constraint data_values { foreach(data[i]) data[i] > data [i-1] ;}
constraint data_0_1 {data[0] == 0; data[1] == 1;data[2]==2;data[3]==3;data[4]==4;data[5]==5;}
constraint data_values { foreach(data[i])
data[i] == data[i*0];data[i*5];data[i*6];data[i*7];data[i*8];data[i*9];}
//constraint data_values { foreach(data[i])
// data[i] == data[00];data[15];data[26];data[37];data[48];data[59];}

//constraint data_values { foreach(data[i])
// foreach(data[j])
// if(i != j) data[i] != data [j] ;}
endclass

program main;
A a;
initial begin
bit k;
a=new();
k=a.randomize();
$display(“k=0%d”,k);
foreach(a.data[i])
$display(“data[%0d]=0%d”,i,a.data[i]);
end
endprogram

In reply to baladevi:

To be honest this has nothing to do with randomization. You want to generate data following a certain rule. For this reason you should write your algorithm Meeting your requirements-

Hi Dave,

How would you initialize (in SV) a two dimensional array (4x3) to all numbers from 1 to 12 in a unique manner? This is how I wrote it, but I am sure there are more efficient ways, besides, I am not even sure if what I wrote below would work! Thanks in advance!

rand byte my_array[4][3];
int my_q[$] = {1,2,3,4,5,6,7,8,9,10,11,12};
int max_idx =11;
int idx = $urandom_range(11,0);
for (int i=0; i<4; i++)
  for (int j=0; j<3; j++) begin
     my_array[i][j] = my_q[idx];
     my_q.delete(idx);
     max_idx--;
     idx = $urandom_range (max_idx,0);
  end
end

Vahid

In reply to vnaraghi:

Vahid,
Assuming your code was inside a clas

rand byte my_array[4][3];
constraint c {unique {my_array};
              foreach(my_array[ii,jj]) my_array[ii][jj] inside {[1:12]};
             }

P.S. Next time, start a new topic for a new question.

Thank you Dave. Sure, I will, but I have a follow up question. How would you achieve the same result using shuffle() function? I did this, but it only shuffled the rows and not the columns!

module init_array;
byte my_array[4][3];
int k = 1;

initial begin
 for (int i=0; i<4; i++) 
   for (int j=0; j<3; j++) 
       my_array[i][j] = k++;
 my_array.shuffle();
end
endmodule

In reply to vnaraghi:
Because SystemVerilog has arrays of arrays - not really multi-dimensional arrays. All the unpacked array methods work on one dimension at a time.

You could create an array with one dimension of 12 elements; shuffle that array; and then fill my_array with that.

In reply to dave_59:

Hello all,

This discussion is quite old but i came accross this recently and trying to implement random number generator but outputs are not expected.

class uniquenumber;
  rand bit [3:0] num [10];
  rand bit [3:0] data[10];
  rand bit [3:0] uniqnum[10];
  
  constraint rand_num{foreach (num[i]) num[i+1] != num[i];};
  constraint data_values { foreach(data[i]) 
                               foreach(data[j])
                                 if(i != j) data[i] != data [j] ;} 
  constraint rand_unitnum{unique {uniqnum};}
  
    function disp();    
      foreach (num[i])
      $display("num[%0d] %0d" , i,num[i]);
      foreach (uniqnum[i])
      $display("uniqnum[%0d] %0d" , i,uniqnum[i]);
      foreach (data[i])
      $display("data[%0d] %0d" , i,data[i]);    
    endfunction
endclass


module uniqnu ();

uniquenumber un;
initial begin

un = new();
assert(un.randomize());
un.disp();
end
endmodule 

For this above code I am getting below output

num[0] 7
num[1] 8
num[2] 0
num[3] 4
num[4] 14
num[5] 1
num[6] 6
num[7] 13
num[8] 5
num[9] 13
uniqnum[0] 0
uniqnum[1] 0
uniqnum[2] 0
uniqnum[3] 0
uniqnum[4] 0
uniqnum[5] 0
uniqnum[6] 0
uniqnum[7] 0
uniqnum[8] 0
uniqnum[9] 0
data[0] 0
data[1] 0
data[2] 0
data[3] 0
data[4] 0
data[5] 0
data[6] 0
data[7] 0
data[8] 0

Question

  1. num[*] is not all unique numbers as foreach loop check only next number to compare . look at num[7] and num[9] both are 13. What is the best stretagy to have all unique number generated without unique constraint ? i looked at other solutions too where shuffle() is used but what if we need to generate big addressing range for e.g.?

  2. all output of uniqnum is 0 that means my tool does not support that built in functionality ?

  3. i tried other constraint mentioned in this post for data[*] but it is all 0s Any suggestion why it is 0 ?

In reply to edaboy:

Are you sure you are not getting any other warnings or error messages before the displayed output. The tool you are using has lots of problems. Consider a different tool or upgrading to a more recent version.

The first constraint should be an error because it would try to create the constraint num[10] !=num[9], and num[10[ is out of bounds. You need to write it as

  constraint rand_num{foreach (num[i]) i+1 < $size(num) -> num[I+1] != num[i];};

The other two constraints work for me.

In reply to dave_59:

Thanks Dave for quick reply. I did not see any error or warning. I still see weird behavior with code that you asked me to modify. However with that code i see that both the other constraint works fine.
notice that i modified code , converted bit to int and i want to make sure int are generated in specific range. is it a proper way to do it? or any other better way can you suggest ?>

constraint rand_num{foreach (num[i]) i+1 < $size(num) → num[I+1] != num[i];};



  rand int unsigned  num [10];
  rand int unsigned  data[10];
  rand int unsigned  uniqnum[10];

  constraint rand_num{foreach (num[i]) i+1 < $size(num) -> num[i+1] != num[i];
                      foreach (num[i]) num[i] inside {[0:20]};   
                  };
  constraint data_values { foreach(data[i]) 
                               foreach(data[j])
                                 if(i != j) data[i] != data [j] ;} 
  constraint rand_unitnum{unique {uniqnum};}
[\systemverilog]


num[0] 11
num[1] 10
num[2] 5
num[3] 18
num[4] 1
num[5] 8
num[6] 17
num[7] 6
num[8] 17
num[9] 12
uniqnum[0] 2585900447
uniqnum[1] 2885502533
uniqnum[2] 4138482668
uniqnum[3] 3688754642
uniqnum[4] 565161356
uniqnum[5] 3727708039
uniqnum[6] 1611526103
uniqnum[7] 1088663520
uniqnum[8] 405083532
uniqnum[9] 1919651944
data[0]  3040365644
data[1]  1549177249
data[2]  2520948884
data[3]  671157517
data[4]  3642241582
data[5]  1668691443
data[6]  2694328522
data[7]  616240321
data[8]  2242663180
data[9]  3757757259

In reply to dave_59:

Hi Dave ,
How to generate unique values for array of array without using unique ?

 constraint c {
	    foreach(fx_arry[i]) {
       	     // fx_arry[i] inside{[0:SIZE-1]};
               foreach(fx_arry[j]) {
       		  if(j != i){
		   fx_arry[j] !=fx_arry[i]
		  };
               }
            }
         }

I am unable get the logic right .can you help out.

In reply to rambarki.satish:

It seems to be a typo Satish.

constraint fx_arry_size_c{
    fx_arry.size() inside {[1:100]};
}

constraint uniq_c {
    foreach(fx_arry[i]) {   	
        foreach(fx_arry[j]) {
       		if(j != i){
		        fx_arry[j] !=fx_arry[i];
		    }
       }
    }
 }

In reply to deepthig:

I didn’t get the expected output after using the above approach.What is wrong in my code

class a;
  
  rand bit [3:0]a[15];
  
        
        constraint uniq_c {
          foreach(a[i]) {   	
            foreach(a[j]) {
       		if(j != i){
              a[j] !=a[i];
		    }
       }
    }
 }
        
        
   
  
function void post_randomize();
a.shuffle();
    endfunction
endclass

 
module test;
  a a_i;
  int temp,i=0;
  initial begin
  a_i = new();
 
    foreach(a_i.a[i])begin
        a_i.randomize();
        temp=a_i.a[i];
      $display("array value[%d] =%d",i,temp);
      
    end  
     
      
#100;
  end
endmodule

output:

array value[ 0] = 3
array value[ 1] = 5
array value[ 2] = 3
array value[ 3] = 6
array value[ 4] = 5
array value[ 5] = 4
array value[ 6] = 10
array value[ 7] = 8
array value[ 8] = 4
array value[ 9] = 14
array value[ 10] = 1
array value[ 11] = 7
array value[ 12] = 11
array value[ 13] = 15
array value[ 14] = 13

In reply to Bharat100:
Move
a_i.randomize();
in front of the foreach loop. Also, there is no need to shuffle() the array.

In reply to dave_59:

That was my fault You are right. Thank you Dave.