Bit Constraints of each element in array

Hi Forun,
Requesting help to fix below constraint:
Constraint: if any bit of byte_enable(be) is set correspondingly a byte of data should be a non zero value.
Issue: why be is all ones ? I tried fixing with $countones but unsuccessful.
For ex:

be[0]= 4’b0000, data[0] = 32’h0000_0000
be[1]= 4’b0001, data[1] = 32’h0000_00ab
be[2]= 4’b0010, data[2] = 32’h0000_cd00
be[2]= 4’b1111, data[2] = 32’h1234_5678

Ive below code:

class cls_array;

  rand bit [31:0] data[];
  rand bit [3:0]  byte_enable[];

  rand bit [31:0] size_var;
  
  constraint c {
    size_var inside {[5:10]};
    data.size() == size_var;
    byte_enable.size() == size_var;
                   
    foreach (byte_enable[i,j])
      	if (byte_enable[i][j]) 
          data [i][j*8 +:8] != 0;
        else
	         data [i][j*8 +:8] == 0;
          
  };
    
    function void post_randomize ();
      foreach (data[i]) begin 
        $write (" enab = %4b ", byte_enable[i]);
        $display (" data = %8h ", data[i]);
        
      end
    endfunction 
  
endclass
    
    module test;
      cls_array c;
      initial begin
        c = new();
        c.randomize();
      end
        
    endmodule

OUTPUT:

 enab = 1111  data = 12a272c2 
 enab = 1111  data = ef6d0aea 
 enab = 1111  data = 5e05e5f4 
 enab = 1111  data = e0686a28 
 enab = 1111  data = afbfc89a 
 enab = 1111  data = e22c1a6e 
 enab = 1111  data = 220ec4fa 
 enab = 1111  data = 82e40612 
 enab = 1111  data = 770a9de9 
2 Likes

Your problem is the distribution of solutions. Each enable bit has a 1-in-256 chance of being set to 0 because data has a 1-in-256 chance of being set to 8’b0.

If you add the constraint

solve byte_enable before data;

Then each bit of byte_enable has a 1-2 chance of being 0.

3 Likes

Thanks @dave_59 . I learned to always think about the solution space, in addition to writing the constraints.

I also tried the below, which worked well.

randc bit [3:0] byte_enable[];

Alternate solution


class prac;
  rand bit [31:0] be;
  randc bit [3:0]  x;
  int low, high;
  constraint c1 {foreach(x[i])
  { if(x[i] == 1)
  { 
    be[i*8 +:7] inside {[16:255]} ;}
    else
      be[i*8 +:7] == 0;
  
  }}
endclass

module tb;
  prac pr;   
  initial begin 
      	pr = new();
        repeat(5)
          begin
        	pr.randomize();
            $display("Value of x is %04b",pr.x);
            $display("Value of be is %8h",pr.be);
          end
    end
endmodule

Only issue is when I am running the test sometimes I am getting 80 (when byte enable is 0). Like this

Value of x is 0101
Value of be is 00a700f4
Value of x is 0110
Value of be is 805a2b00
Value of x is 1011
Value of be is c8805bd4
Value of x is 1100
Value of be is f7658000
Value of x is 1111
Value of be is c1e3d2a8

Apologies for inverted naming.

Here is another solution using if/else

class cls_array;

  rand bit [31:0] data[];
  rand bit [3:0]  byte_enable[];

  constraint c1 {foreach(byte_enable[i])
    				if($countones(byte_enable[i]) > 0)
      					data[i] != '0;
                 	else
                      data[i] == 0;
                 
                 
                  data.size() == 10;
                 byte_enable.size() == 10;}
  
  constraint c2 {
    foreach(byte_enable[i]) 
      byte_enable[i] dist { 0 := 5, [1:15] := 3 };
  }
  
endclass

module test;
      cls_array c;
      initial 
        begin
        	c = new();
          repeat (100) 
              begin
        		c.randomize();
                foreach(c.byte_enable[i]) 
                  if(c.byte_enable[i] == 0)
                    $display("bye_enable is 0 and data is also zero \t BYTE_ENABLE = %d\t DATA = %d", c.byte_enable[i], c.data[i]);
        		  else
                  	$display("byte enable is non-zero and data is non-zero \t BYTE_ENABLE = %d \tDATA = %d", c.byte_enable[i], c.data[i]);
      		  end
     	end
        
    endmodule

Result:

bye_enable is 0 and data is also zero BYTE_ENABLE = 0 DATA = 0
byte enable is non-zero and data is non-zero BYTE_ENABLE = 1 DATA = 2403843343
bye_enable is 0 and data is also zero BYTE_ENABLE = 0 DATA = 0
byte enable is non-zero and data is non-zero BYTE_ENABLE = 12 DATA = 3839444346
byte enable is non-zero and data is non-zero BYTE_ENABLE = 5 DATA = 3905969600
byte enable is non-zero and data is non-zero BYTE_ENABLE = 12 DATA = 4262674867
byte enable is non-zero and data is non-zero BYTE_ENABLE = 3 DATA = 3134952810

That’s because you wrote

instead of
be[i*8 +:8] == 0;

1 Like
class abc;
  rand bit[3:0] byte_en;
  rand bit[31:0] data;
  
  constraint addr_c{
    foreach(byte_en[i]){
      if(byte_en[i] == 1) 
        $countones(data[8*i +:8]) >= 1;
      else 
        $countones(data[8*i +:8]) == 0;
      
    }
  }
      
    function void post_randomize();
    $display("byte_en = %b data=%0h",byte_en, data);
    $display();
    endfunction
  
endclass: abc

module tb;
      abc abc_inst;
      
      initial begin 
        abc_inst = new();
        repeat(10)
        abc_inst.randomize();
      end
      
      
endmodule