Constraint

I have a 2D array:: bit[31:0] reg_a [24], I want to randomise reg_a in a way that all reg_a[i] is mutually exclusive. none of the bits of any two reg_a[i] should be overlapping.

rand bit [31:0] reg_a [24];

if the array was just 2 deep this would be the solution.

foreach(reg_a[i]) begin	   
		std::randomize (reg_a[i]) with {
			foreach(reg_a[i][j]){
				if(i!=0){
					reg_a[i][j] != reg_a[i-1][j];
				}
		}
          };

if we could somehow also add another constraint which is on a counter, which counts $countones(reg_a[i]). like valid = valid+$countones[i] and on this valid if we put a constraint like, valid <32, will it work?
Any other solution is also welcome. Thanks.

In reply to 100rabhh:

If you mean none of the bits set in the same position should overlap, the following should work:

class A;
  rand bit [31:0] reg_a [24];
  constraint nonoverlapping {
    foreach(reg_a[,j]) reg_a.sum() with (int'(item[j])) == 1;
  }
endclass

module top;
  A a=new;
  initial repeat(10) begin
    assert(a.randomize());
    foreach(a.reg_a[i]) $displayb(a.reg_a[i]);
    $display;
  end
endmodule

In reply to dave_59:

Hi Dave,

Can you expand this constraint?

constraint nonoverlapping {
foreach(reg_a[,j]) reg_a.sum() with (int’(item[j])) == 1;
}

Is it reg_a[0]+reg_a[1]…reg_a[23] ==1?

Also since its a 1D array, why do you have reg_a[,j]?

In reply to rag123:

It is a 2-d array with 1 dimension unpacked and 1 dimension packed. So the expansion is

(int'(reg_a[0][j])+int'(reg_a[1][j])...int'(reg_a[23][j])) ==1?

In reply to dave_59:

So the iterator is here for packed dimension? So effectively this rolls up into


(int'(reg_a[0][j])+int'(reg_a[1][j])...int'(reg_a[23][j])) ==1

Also how is this different from the below constraint?

foreach(reg_a[j]) reg_a.sum() with (int'(item[j])) == 1;


In reply to rag123:

That would not work because the 1st dimension only iterates from 0…23. The 2nd dimention iterates from 0…31. It would leave the packed dimension bits 24…31 unconstrained. However it would work only for the cases where the 2 dimension ranges were the same.

In reply to dave_59:

Thanks a lot Dave :)
One last question,


foreach(reg_a[,j]) reg_a.sum() with (int'(item[j])) == 1;

In this case, when you do reg_a.sum() with (int’(item[j])) == 1, you mean the value of the packed dimension to be unique or in other words it should not be same as any other element in the array correct?

In reply to rag123:

No, it means at most one bit can be set in the particular [j] index of the packed dimension for all unpacked elements. Unique would only work if there were 2 unpacked elements.

In reply to dave_59:

Thanks Dave :)

In reply to dave_59:

Hi dave,
I tried the code that u suggested, I get an error msg suggesting ‘item’ has not been declared yet.
“Error-[IND] Identifier not declared
randomise.sv, 13
Identifier ‘item’ has not been declared yet.”

class my_trans;
	bit[31:0]  reg_a [24];
constraint non_overlapping {
    foreach(reg_a[,j]) reg_a.sum() with (int'(item[j])) == 1;
  };


endclass

module ab;
	my_trans trans_h= new ;
	initial
	begin
		trans_h.randomize();
	end
endmodule

it is not picking up the coloumn, when I only put item there it does expand, but putting item[j] causes a compilation error.

In reply to 100rabhh:

I believe you have run into a tool bug. The following code works on 4 SystemVerilog simulation tools on www.edaplayground.com.

class my_trans;
  rand bit[31:0]  reg_a [24];
  function void post_randomize;
    foreach(reg_a[,j]) $display(reg_a.sum() with (int'(item[j])));
  endfunction
endclass
module ab;
  my_trans trans_h= new ;
  initial  assert(trans_h.randomize());
endmodule

This Mentor/Siemens EDA sponsored public forum is not for discussing tool specific usage or issues. Please contact your tool vendor directly for support.

In reply to dave_59:

In reply to 100rabhh:
I believe you have run into a tool bug. The following code works on 4 SystemVerilog simulation tools on www.edaplayground.com.

class my_trans;
rand bit[31:0]  reg_a [24];
function void post_randomize;
foreach(reg_a[,j]) $display(reg_a.sum() with (int'(item[j])));
endfunction
endclass
module ab;
my_trans trans_h= new ;
initial  assert(trans_h.randomize());
endmodule

This Mentor/Siemens EDA sponsored public forum is not for discussing tool specific usage or issues. Please contact your tool vendor directly for support.

Hi Dave,

2 follow-up questions:

  1. Why are you doing it in post_randomize()? why not as a constraint by itself?
  2. I do see your code to also have overlapping bits set. Pasted the snapshot running your code. Added display statement in addition.
class my_trans;
  rand bit[31:0]  reg_a [24];
  /*
  constraint c_no_overlap {
    foreach(reg_a[,j]) {
      reg_a.sum() with (int'(item[j]));
    }
  }*/
  
  function void post_randomize;
    foreach(reg_a[,j]) $display(reg_a.sum() with (int'(item[j])));
  endfunction
  
endclass
module ab;
  my_trans trans_h= new ;
  initial  begin 
    assert(trans_h.randomize());
    foreach(trans_h.reg_a[i]) 
      $display("%b",trans_h.reg_a[i]);
  end
endmodule

Output:

9

14

12

10

11

14

17

14

14

12

14

16

10

13

9

9

11

15

11

9

11

12

9

15

14

8

10

14

12

9

11

14

00000011011001110000000010010100

11101101100101101011010000011010

01111010111101111110001110111001

00110110100101001001111110000100

11101110110110000100010000010010

01001101101001101100010011100111

11110011001110100100010000011011

00100010111100000110100101001010

01010011101000011000100111110100

00010100001110011110100111001011

00101110111110001010110000010101

01001001110101001001001111001111

11010110001011001100001100101100

01110010011010000111000000110001

00000101111001000111100111111011

10101111010001100010111111111011

11001011100101000111010110000001

01010111001100010100011111100100

11001000110111010111000000010101

01110111110100111111111110100011

00111110000111110000111000111001

01100111101110100100010110011010

10000111010000010000100100011001

10001001001111001101101110000000