Constraint Interview Question

Write a constraint where you have a 32 bit value bit [31:0] val where you’d want to randomize this to where every randomization would only allow 2 bits to differ from the previous randomization.

Can we solve it by using

$countones(prev_val^cur_val) == 2)

This is so because if only two bits are different in the previous and current value, their XOR should have only two bits set. Any other logic is welcome.

1 Like

You should try it. Asking better questions on the Verification Academy Forums with EDAPlayground - Verification Horizons

This seems to work for me. Any other solutions/suggestions are welcome.

class abc;
 
  static bit [31:0] prev_val;
  rand bit [31:0] cur_val;
  
 static int count = 0;
 
constraint sel{
  
  (count > 0) -> ($countones((prev_val^cur_val))==2);   
    
  }
  
function void pre_randomize();
  if(count>0) begin
    prev_val = cur_val;
  end
    count+=1;
    
endfunction
    
endclass
    
   

module tb;
  initial begin
  abc xx1 = new();
    repeat(10) begin
    xx1.randomize();
      $display("prev_val = %b",xx1.prev_val);
      $display("cur_val =  %b",xx1.cur_val);
      $display("count =  %d  diff = %d",xx1.count,$countones(xx1.cur_val^xx1.prev_val));
    end
    
  end
endmodule
1 Like

No need for static variables or a counter.

This also works

class abc;
  rand bit [31:0] cur_val;
  constraint sel{
    $countones( const'(cur_val)^cur_val)==2;
  }
endclass
1 Like

Could you please explain the need for the “const`” in this solution. Where exactly are you comparing the previous randomized value with the current one?

My apologies, I’m more than a little rusty at this, but does the constraint solver efficiently handle the ‘flip two bits’ constraint via $countones? (A long time ago) I would have generated two values between 0 and 31 and inverted those bits.

That might be fine if there were no other constraints on the random value. But what if there was another constraint like cur_val % 5 == 0 in addition to the number of changed bits? Generating the equations for that would be much less efficient.

Hi Dave,

I was trying this code and ended up with below error

Error-[SE] Syntax error
Following verilog source has syntax error :
“testbench.sv”, 458: token is ‘const’
$countones( const’(cur_val)^cur_val)==2;
^
SystemVerilog keyword ‘const’ is not expected to be used in this context.

could you help on this?

I tried this way, and it worked for me. crude, but works if we cant remember solution using XOR!!! Thanks.

class class1;
rand bit [31:0] a;
static bit [31:0] prev_a;
static int cnt;

//make sure number of 1’s are always 2.
constraint c1{
$countones(a) == 2;
}
//constraint the same location to be not 1’b1.
constraint c2{
if(cnt >0)
{
foreach(prev_a[i]) {
if(prev_a[i] ==1){
a[i] != 1;
}
}

}

}

function post_randomize();
cnt = cnt+1;
prev_a = a;

endfunction

endclass

An alternate solution without using $countones

class class1;
  rand bit [9:0] a;
  rand int ind1 , ind2 ;

  // Constraint the Indexes which would be 1’b1.
  constraint c1{  if( const'(a) != 0 )  // False for 1st call to randomize
                  { !(ind1 inside { const'(ind1) , const'(ind2) } );
                    !(ind2 inside { const'(ind1) , const'(ind2) } ); 
                  }
                
                  ind1 != ind2 ;
                
                  ind1 inside { [0:9] }; // Alt: [ 0:($bits(a)-1) ]
                  ind2 inside { [0:9] }; // Alt: [ 0:($bits(a)-1) ]
               }  

 // Make sure number of 1’s are always 2.  
  constraint c2{   foreach(a[i])
                 { if(i inside { ind1 , ind2 } )
                    a[i] == 1;
                   else
                    a[i] == 0;                     
                 }
               }
endclass
1 Like