Constraint for row total with each element in the array less than a given value

Hi, I wrote the following program for a constraint where each element of the array must be less than 80, but the sum of each individual row must be equal to 100. Can someone explain why the constraint fails for rows 2 and 3?

module array;
  class array;
    rand bit [7:0] array [3][4];
    int i,j;
    constraint abc{foreach(array[i]){
      foreach(array[,j]){	
        array[i][j] < 80;
      }
    }
        array[i].sum(item) with (int'(item))==100;}
      function void display();
    foreach (array[i]) begin
      foreach (array[i][j]) begin
        $write("  %d  ",array[i][j]);
      end
      $display("\n");
    end
  endfunction
 endclass

 initial begin
 array obj;
 obj = new();
 if(obj.randomize())
 obj.display();
 $display("Randomization successful");
 end
endmodule

This is the output

23     57     14      6  
# 
#    36     51     68     30  
# 
#    41     65     55     21

Also, if I want to make the column total to be = 100 instead of the row total, would changing i to j in the line array[i].sum(item) with (int’(item))==100 work?

You need to wirte two seperate constraints for element less than 80, and sum of row equal to 100.
Try this:


constraint abc{foreach(array[i]){
  foreach(array[i,j]){
    array[i][j] < 80;
}
}
}
constraint def{foreach(array[i]){
  array[i].sum(item) with (int'(item))==100;}}

In reply to Yuankun:

shouldn’t

constraint abc{
     foreach(array[i,j]){
        array[i][j] < 80;
     }
}

suffice?

In reply to Yuankun:

Hello Yuankun, thank you for your reply. I was wondering if it would be possible to use only one constraint. Because I see some examples that use multiple conditions within one constraint.

Also, if instead of sum of row, I want to keep sum of column as 100, can I change i to j in the lines
constraint def{foreach(array[i]){
array[i].sum(item) with (int’(item))==100;}}

In reply to vk7715:

Please use code tags making your code easier to read. I have added them for you.

You have a general problem with the use of foreach loops. You do not declare the iterating variables before the foreach loop, they are implicitly declared local to the loop. If you remove the declaration of int i,j; in your example, you would have gotten an error message that i was undeclared in your array[i].sum constraint because it was outside the foreach loop. Instead it is just using the non-random variable I, which remains at 0. That is why only the first row is getting constrained.

When you want to iterate over multiple dimensions use the this from

foreach (array[i,j]) ...

That declares local variables i and j and iterates over the all their permutations of the ranges.

If instead you write

foreach (array[i][j]) ...

That is supposed to only iterate over the j dimension. However because of a lot of sloppy code, some tools incorrectly iterate over both dimension if i was not previously declared. That is very dangerous code.

And I guess you are in the same course as this person who also wants to know about the same question.

In reply to dave_59:

Hello Dave, thank you for your reply. All three rows are getting constrained now.

However, when I try to constrain the column total to be 100 rather than row, I replaced i with j in the line:

array[i].sum(item) with (int'(item))==100;}}

but I got some errors. Why is it that so? I thought the ‘i’ in array[i].sum() was to indicate we were referring to the row, and hence a ‘j’ should refer to a column.

In reply to vk7715:

Don’t just say “I got some errors”. Tell us something what the error message was.

I have to assume you got an “out of range” error.

That is because when iterating with

foreach (array[i,j]) ...

That is equivalent to this nested for loop:

for(int i=0;i<3;i++) for(int i=0;i<4;i++)  ...

Except that SystemVerilog automatically figures out the ranges for i and j. Once inside the loop, you can use i and j however you would like, even indexing another array. Whatever value you use for an index has to be in range.

In reply to vk7715:
Try this

module array;
class array;
rand bit [7:0] array [3][4];
int i,j;
constraint abc{
  foreach(array[i,j]){
	array[i][j] < 80;
  }
}
//constraint def{
//  foreach(array[i]){
//   	array[i].sum(item) with (int'(item))==100;
//  }
//}
constraint ghi{
  foreach(array[,i]){
    array.sum(item) with (int'(array[item.index][i]))==100;
  }
}
function void display();
foreach (array[i]) begin
  foreach (array[i][j]) begin
    $write(" %d ",array[i][j]);
  end
  $display("\n");
end
endfunction
endclass

In reply to Yuankun:

Thank you. This works.