Constraint for 32 bit addr to be different than prev addr by 2 bits

I need to create a constraint for a 32 bit address, such that it is always 2 bits different than previous randomized value.

Does this look right? any better ways to do this?


class A;

rand bit[31:0] addr;
bit [31:0] addr_q;
rand int position 1 ;
rand int position 2;

constraint adr_c {
position1 inside {[0:31]};
position2 inside {[0:31]};

position1 != position2;

addr[position1] ^ addr_q [position1] == 1;
addr[position2] ^ addr_q [position2] == 1;

}

function post_randomize();

addr_q = addr;

endfunction


Hi,

What do you see as output ?

I think you have added constraint to have 2 bits position different than last address but there is no constraint on other bits so they will be random (same or different). Do you expect to have other bits random ?

Thanks

In reply to sv_uvm_learner_1:

since its a rand variable, it will be randomized anyways, but constraint is on 2 bit being different …

Since most simulators support the $countones system function in constraints, you can do:

class a;
  rand bit [31:0] addr;
  bit [31:0] prev_addr;
  
  function void pre_randomize;
    prev_addr = addr;
  endfunction
  
  constraint addr_constraint {$countones(addr ^ prev_addr) == 2;}
  
endclass : a

In reply to n347:


// This code will be helpful for you
class A;
	rand bit [31:0]a;
	// static bit [31:0]a_temp;
	static bit [31:0]aQ[$:10];

	constraint a_a {$countones(a^const'(a))==2;}
	// constraint a_a {$countones(a^a_temp)==2;}

	constraint a_non_rep{unique{a,aQ};}

	function void post_randomize();
		// a_temp=a;
		aQ.push_back(a);
	endfunction
endclass
module top;
	A b=new;
	initial begin
		for(int i=0;i<10;i++)begin
			// b=new();
			b.randomize();
			$display("value of a=%b",b.a);
		end
	end
endmodule

In reply to Raghunandan Reddy:

class A;
 rand bit[31:0] addr;  
 constraint addr_c {
   $countones(addr ^ const'(addr)) == 2;
 }
endclass

Thanks everyone for the answers.

I have a question about the xor, would it return 32 bit variable, or just xor of all the 32 bits ,

addr ^ const’(addr)

$countones(addr ^ const’(addr)) == 2;

In reply to n347:

The binary XOR operator is bitwise so it returns a 32-bits value.

In reply to dave_59:

Hi Dave,

I tried the pre_randomize method instead const. I observed that prev_addr initializes to 0. So if I want the addr to be between certain range say [200:800] constraint fails.


  rand int addr;
  int prev_addr;
  
  function void pre_randomize();
    prev_addr = addr;
  endfunction
  
  constraint c1{
    addr inside{[200:800]};
    addr == prev_addr +4;
  }

In reply to ak_verifsj:

Yes it will fail regardless of whether you use the const’(addr) cast or prev_addr mechanisms. You need to define how you want the series to start and what happens when addr+4 is greater than 800. For example you could do

 constraint c1{
    addr inside{[200:800]};
    !((const'(addr) + 4) inside {[200:800]}) -> addr == const(addr) +4;
  }

In reply to dave_59:

$countones(addr ^ const’(addr)) == 2;’

what does const do here?

In reply to diptishe:
https://verificationacademy.com/forums/systemverilog/constraint-0#reply-56455

In reply to dave_59:

I believe this won’t work for 1st randomize ( previous value of addr is 0 )


 !((const'(addr) + 4) inside {[200:800]}) 

would return 1 . Hence we would have ::


addr == const'( addr ) + 4  ; // Basically Constraints addr to 4 

Now this conflicts constraint ::


addr inside {[200:800]} ;

In reply to ak_verifsj:

You would need this ( For Simulators that don’t support const’() ) ::



rand int addr ;
     int prev_addr; 
  
function void pre_randomize() ;
  
   if ( addr inside {[200:796]} ) // Max is 796 !!
     prev_addr = addr ;
   else 
     prev_addr = 196 ; // Helps during 1st randomize() as well as when addr reaches 800 !!

endfunction

constraint c1 {
         addr == prev_addr +4  ;
         addr inside{[200:800]} ;
              }

  

This gives addr values from 200 to 800 . Then again it iterates from 200