Constrain sum of elements in an array

Hi,

I am generating 5 unique elements in an array using values 1,2,3…9 whose sum is greater than 20
I use the constrain “data_sum_c” to constraint the sum of elements and with this constraint all values of data are 0;
Without the constraint “data_sum_c” i am able to generate unique data values. Is my code wrong ?

class pkt;
  rand int unsigned data[];
 
  //data elements constraint
  constraint data_ele_c {
    data.size == 5;
    foreach (data[i]) {
      data[i] inside {[1:9]};
    }  
  }// data_c      
  
  //data elements sum constraint    
  constraint data_sum_c{
    data.sum() >20;
  }    
      
   
  constraint data_unique_c {
     foreach(data[i])
       foreach (data[j])
         if(i!=j)
           data[i]!=data[j];
   }
  
      
  function void print();
    foreach(data[i]) 
      $write("\n DATA[i]=%0d, ", i,data[i]);
    $display("\n =============================");
  endfunction
endclass : pkt
      
//=============================================== 
module top;
    pkt pkt1;
 
    int count;
     
    initial begin
         
      repeat(3) begin
        pkt1 = new;
        if(!pkt1.randomize()) $display("\n ****FAILED**** \n");
        pkt1.print();
      end //repeat 
    
    end  
endmodule

Thanks

In reply to georgean:

Your code worked on EDAPlayground on VCS. You should contact your tool vendor.

P.S. You could have also used unique for your uniqueness constraint:


constraint data_unique_c {
  unique { data };
}

In reply to Tudor Timi:

Thanks Tudor.

In reply to georgean:

Hi georgean,
I would like to share my knowledge when you use a constraint on sum().
For ex:
rand bit [2:0] a;
Constraint on the sum of a is less than or equal to 7 and size of a is 3.
now there is no wonder if you see the following values of a:
a[0] = 'h7, a[1] = 'h7, a[2] = 'h7
Reason is the lower 3 bits of a.sum() is 5 and the constraint is still valid!

Solution would be to use one extra bit when declaring “a” i.e. declare it as, “rand bit [3:0] a” and constrain the MSB of a i.e. a[3] = 0. Now you can see valid values on a.

Regards,
Naveen

In reply to naveensv:

Naveen,

I think you meant to declare a dynamic array:

rand bit [2:0] a[];

And you would have to add at least 2 bits to catch the error with the given constraints.

What you are trying to explain is that the result of the array.sum() method only has the precision of the individual array elements. But there is no need to add extra bits to the array, you can use the with clause to cast the elements to a greater width.

a.sum(item) with ( 32'(item) )

In reply to dave_59:

This is so cool! Thanks Dave.
Feeling good :)

In reply to naveensv:

Please explain your point regarding sum() constraint in more detail.

In reply to Tudor Timi:

In reply to georgean:
Your code worked on EDAPlayground on VCS. You should contact your tool vendor.
P.S. You could have also used unique for your uniqueness constraint:


constraint data_unique_c {
unique { data };
}

Hi Timi:

I have used the unique constraint as your advice
but I got error log as blow:
*System verilog keyword ‘unique’ is not expected to be used in this context.
*

And I check the [SystemVerilog 3.1a
Language Reference Manual] , did not find discription about this.

Could you tell me where I can get any more detail about this unique constraint?

Thank you in advance.

class ttt ;
    rand bit[2:0] ddd ;
    rand bit[3:0] SA[10] ;

    constraint data_sum_c{
    SA.sum() >20;
    }
    constraint data_unique_c {
    unique { SA };
    }
endclass


module  test() ;
reg[31:0] mmm[3:0]  ;
ttt ttt_u ;

initial begin

    foreach (mmm[i]) mmm[i] = 0 ;
    ttt_u = new() ;

    ttt_u.randomize() ;
    foreach ( ttt_u.SA[i] )
    $display(" SA[%0d] = %0d", i, ttt_u.SA[i] ) ;
end
endmodule

In reply to jtian:

No one should be using the SystemVerilog 3.1a LRM. It was released over 15 years ago before anyone had implemented anything in the specification.

See http://go.mentor.com/ready-for-systemverilog-2012

and http://go.mentor.com/get-1800

In reply to dave_59:

Thank you so much for your helpful reply.
I will change my specification to IEEE Std 1800™-2012.

In reply to georgean:

Just FYI. This is already solved under Constraint randomization of an array | Verification Academy. Maybe you can complement the information shown here.

In reply to dave_59:

I think i have a similar question. I am using the following code to put constraints on sum of arrays and vector sum of arrays.

I see the following warning and I am trying to see if i can work around this warning.

ncelab: *W,SUMOFL (./testbench.sv,14|32): Constraint expression with unqualified array.sum may overflow.
constraint sum_c { dataq1.sum() < 1000; dataq2.sum() < 1000; }

Dave, Can you explain me how I can fix this warning by casting ?


module tb;
  class c;
    rand logic [7:0] dataq1 [];
    rand logic [7:0] dataq2 [];
    constraint data_size {dataq1.size() == 10; dataq2.size() == 10; }
    constraint data_items { foreach(dataq1[i]) 
                                dataq1[i] < 100;
                            foreach(dataq2[i])
                                dataq2[i] < 50; }
    constraint sum_c { dataq1.sum() < 1000; dataq2.sum() < 1000; }
    constraint sum_product_c {sum_pro() < 100000; }

    function longint sum_pro();
      sum_pro = 0;
      foreach(dataq1[i])
        sum_pro += dataq1[i] * dataq2[i]; 
    endfunction 
    
  endclass
  
  initial
    begin
      c c1;
      c1 = new;
      void'(c1.randomize());
      
      foreach(c1.dataq1[i])
        $display("%0d  %0d", c1.dataq1[i], c1.dataq2[i]);
    end
    
  
endmodule


In reply to aksistla:

from Dave’s reply:


constraint sum_c { dataq1.sum() with ( 32'(item) ) < 1000; 
                   dataq2.sum() with ( 32'(item) ) < 1000; 
                 }

I had a question about constraining a column of a 2d array.
rand int unsigned data[8][4];

How do I write a constraint using unique to make sure the columns in the array are unique.
For eg:
constraint uniq { unique { data[0:7][0] }; }

The about didnt work.

In reply to dave_59:

In reply to naveensv:
Naveen,
I think you meant to declare a dynamic array:

rand bit [2:0] a[];

And you would have to add at least 2 bits to catch the error with the given constraints.
What you are trying to explain is that the result of the array.sum() method only has the precision of the individual array elements. But there is no need to add extra bits to the array, you can use the with clause to cast the elements to a greater width.

a.sum(item) with ( 32'(item) )

Hi Dave,

My requirement is:

  1. array size should be 4
  2. Each element should be divisible by 8
  3. Sum of all elements should be equal to 40

When I run the below code I am getting constraint conflicting error:

module tb;

class sum_array;
   rand int unsigned arr[];

   constraint arr_c { arr.size() == 4;
                      foreach(arr[i]) { (arr[i]%8) == 0; }

   constraint sum_c { arr.sum() with (32'(item)) == 40 ; }
}

endclass

 initial
    begin
      sum_array c1;
      c1 = new;
      void'(c1.randomize());
    end
 
endmodule

Can you please guide me in this regard.

Thank you,

Regards,
Muneeb

In reply to muneebullashariff:

Can you think of a solution that should have worked?

In reply to dave_59:

In reply to muneebullashariff:
Can you think of a solution that should have worked?

Hi Dave,

Element’s value can be as follows :
8,8,16,8 ; sum being 40

Thank you,

Regards,
Muneeb

In reply to muneebullashariff:

I am not seeing any constraint conflicts. I changed the code a little, as below


module tb;
 
class sum_array;
   rand int unsigned arr[];
 
   constraint arr_c { arr.size() == 4;
                      foreach(arr[i]) { (arr[i]%8) == 0; } }
 
   constraint sum_c { arr.sum() with (36'(item)) == 36'h0_0000_0028 ; } //hex equivalent of dec 40 

 //added extra bits to make sure, it is the sum that is 40, not the sum after overflow

endclass
 
 initial
    begin
      sum_array c1;
      c1 = new;
      void'(c1.randomize());
      $display("%p",c1.arr);
    end
 
endmodule


I see following output over diff runs
'{'h18,'h8,'h8,'h0}
'{'h0,'h0,h28,'h0}
'{'h0,'h28,'h0,'h0}
'{'h0,'h8,'h20,'h0}

In reply to ssureshg_:

In reply to muneebullashariff:
I am not seeing any constraint conflicts. I changed the code a little, as below


module tb;
class sum_array;
rand int unsigned arr[];
constraint arr_c { arr.size() == 4;
foreach(arr[i]) { (arr[i]%8) == 0; } }
constraint sum_c { arr.sum() with (36'(item)) == 36'h0_0000_0028 ; } //hex equivalent of dec 40 
//added extra bits to make sure, it is the sum that is 40, not the sum after overflow
endclass
initial
begin
sum_array c1;
c1 = new;
void'(c1.randomize());
$display("%p",c1.arr);
end
endmodule

I see following output over diff runs
'{'h18,'h8,'h8,'h0}
'{'h0,'h0,h28,'h0}
'{'h0,'h28,'h0,'h0}
'{'h0,'h8,'h20,'h0}

Hi,

Many thanks for your reply.

The above mentioned solution is working perfect with questa and Synopsis tools.
The constraint conflict is seen in Cadence tool.

I am puzzled with this behavior!

Thank you,

Regards,
Muneeb

In reply to muneebullashariff:

In case you still have a problem, try this code below.

module tb;
 
class sum_array;
   rand int unsigned arr[];
  constraint  c1_c { foreach (arr[u]) { arr[u]<=40; }  //This seems to be something you want.  No?
   }
   constraint arr_c { arr.size() == 4;
                      foreach(arr[i]) { (arr[i]%8) == 0; }
                    }
   constraint sum_c { arr.sum() with (32'(item)) == 40 ; }
endclass
 
 initial
    begin
      sum_array c1;
      c1 = new;
      void'(c1.randomize());
      $display("ANSWER: arr:%p",c1.arr);
    end
 
endmodule