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.

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

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

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