Hi,
Can someone help me to code constraint for below scenario.
Constraint for 32 bit address, to generate continuous 10 bits as 0 and remaining bits as 1.
Thanks in advance.
Hi,
Can someone help me to code constraint for below scenario.
Constraint for 32 bit address, to generate continuous 10 bits as 0 and remaining bits as 1.
Thanks in advance.
In reply to Ammu786:
Not what you asked, working on the continuous 10 bits a
class c;
rand bit[31:0] v;
constraint ct12 {$countones(v)==12;}
// $countones (expression) returns the number of ONEs in a bit vector expression.
endclass
module m;
c c1=new();
initial begin
repeat(5) begin
if (!randomize(c1)) $error();
$display("c1.v= %b", c1.v);
ai_12: assert($countones(c1.v)==12)
else $display("ERROR c1.v= %b, countones= %d", c1.v, $countones(c1.v));
end
end
endmodule
/* sim results
# c1.v= 01010001000101000100110010001011
# c1.v= 01000100001110000101100011010001
# c1.v= 00111111010000001010001000010100
# c1.v= 10100110100100100001010001100100
# c1.v= 01001110100000101011010000100100 */
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
** SVA Handbook 4th Edition, 2016 ISBN 978-1518681448
…
Udemy courses by Srinivasan Venkataramanan (http://cvcblr.com/home.html)
https://www.udemy.com/course/sva-basic/
https://www.udemy.com/course/sv-pre-uvm/
In reply to Ammu786:
class c;
rand bit[31:0] v;
rand int int1 , int2 ;
constraint LOW_BOUND { int1 inside { [ 0 : 31 ] } ; }
constraint UPPER_BOUND { int2 inside { [ 0 : 31 ] } ; }
constraint DIFF { int2 == int1 + 9 ; } // Range of Indexes is 10 !!
// constraint ct12 { $countones(v) == ( 32 - 10 ) ; } // Can be Skipped !!
constraint VAL { foreach( v[i] )
{
if( i inside { [ int1 : int2 ] } )
v[ i ] == 0 ;
else
v[ i ] == 1 ;
}
}
function void post_randomize() ;
$display(" int1 is %0d , int2 is %0d" , int1 , int2) ;
endfunction
endclass
module m;
c c1=new();
initial begin
repeat(5) begin
if (! c1.randomize() ) $display(" XXX FAILS !! XXX ");
$display("c1.v= %b", c1.v);
end
end
endmodule
In reply to ABD_91:
Good solution, thank you.
Added an assertion
module m;
c c1=new();
initial begin
repeat(15) begin
if (!randomize(c1)) $display(" XXX FAILS !! XXX ");
$display("c1.v= %b", c1.v);
ai_12: assert($countones(c1.v)==22)
else $display("ERROR c1.v1= %b, countones= %d", c1.v, $countones(c1.v));
end
end
endmodule
// simulation
# int1 is 1 , int2 is 10
# c1.v= 11111111111111111111100000000001
# int1 is 8 , int2 is 17
# c1.v= 11111111111111000000000011111111
# int1 is 16 , int2 is 25
# c1.v= 11111100000000001111111111111111
# int1 is 15 , int2 is 24
# c1.v= 11111110000000000111111111111111
# int1 is 1 , int2 is 10
# c1.v= 11111111111111111111100000000001
# int1 is 17 , int2 is 26
# c1.v= 11111000000000011111111111111111
# int1 is 22 , int2 is 31
# c1.v= 00000000001111111111111111111111
# int1 is 15 , int2 is 24
# c1.v= 11111110000000000111111111111111
# int1 is 11 , int2 is 20
# c1.v= 11111111111000000000011111111111
# int1 is 10 , int2 is 19
# c1.v= 11111111111100000000001111111111
# int1 is 22 , int2 is 31
# c1.v= 00000000001111111111111111111111
# int1 is 3 , int2 is 12
# c1.v= 11111111111111111110000000000111
# int1 is 22 , int2 is 31
# c1.v= 00000000001111111111111111111111
# int1 is 14 , int2 is 23
# c1.v= 11111111000000000011111111111111
# int1 is 20 , int2 is 29
# c1.v= 11000000000011111111111111111111
In reply to ben@SystemVerilog.us:
It was pointed ot on LinkedIn that “This would fail if int1 is greater than 22. Ex: if int1 is 25, would int2 become 34 or it would wrap around and have the value 2?”
Changing the Low bound constraint for int1 fixes this.
class c;
rand bit[31:0] v;
rand int int1 , int2 ;
constraint LOW_BOUND { int1 inside { [ 0 : 22 ] } ; }
constraint UPPER_BOUND { int2 inside { [ 0 : 31 ] } ; }
constraint DIFF { int2 == int1 + 9 ; }
// constraint ct12 { $countones(v) == ( 32 - 10 ) ; } // Can be Skipped !!
constraint VAL { foreach( v[i] )
{
if( i inside {[int1:int2] } )
v[ i ] == 0 ;
else
v[ i ] == 1 ;
}
}
function void post_randomize() ;
$display(" int1 is %0d , int2 is %0d" , int1 , int2) ;
endfunction
endclass
In reply to ben@SystemVerilog.us:
Hi Ben ,
As the constraints are solved in conjunction with each other ,
the constraint solver would implicitly ensure that max value of int1 is 22 .
If int1 were to be chosen as 25 the constraint :: ( int2 == int1 + 9 )
would Never be Successful as int2 can’t be greater than 31 !!
( due to constraint UPPER_BOUND )
Another way is to check this is using in-line constraint ::
if (! ( c1.randomize() with { int1 == 25 ; } ) ) $display(" XXX FAILS !! XXX ");
This ALWAYS Fails due to Conflicting Constraint UPPER_BOUND and DIFF
In reply to ABD_91:
The solver would ensure that max value of int1 is 22 .
If int1 is chosen as 25 the constraint :: ( int2 == int1 + 9 )
would Never be Successful as int2 can’t be greater than 31 !!
Excellent point. The question then is, why not limit the low bound to 22
constraint LOW_BOUND { int1 inside { [ 0 : 22 ] } ; }
Doesn’t it make it more readable or understandable?
It fooled me and another user.
In reply to ABD_91:
The solver would ensure that max value of int1 is 22 .
If int1 is chosen as 25 the constraint :: ( int2 == int1 + 9 )
would Never be Successful as int2 can’t be greater than 31 !!
Excellent point. The question then is, why not limit the low bound to 22
constraint LOW_BOUND { int1 inside { [ 0 : 22 ] } ; }
Doesn’t it make it more readable or understandable?
It fooled me and another user.
In reply to ben@SystemVerilog.us:
I agree it would better to constraint max value of int1 to 22 to make it more readable .
I tried an alternate solution ::
class c;
rand bit[31:0] v;
rand int int1 ;
constraint LOW_BOUND { int1 inside { [ 0 : 22 ] } ; }
constraint ct22 { $countones(v) == ( 32 - 10 ) ; }
constraint VAL { foreach( v[i] ) // Iterates from 31 to 0 .
{
if( i == int1 )
{ v[ i+:10 ] == 10'h0 ; } // Issue here , not sure why
}
}
endclass
module m;
c c1=new();
initial begin
repeat(5) begin
if (! c1.randomize() ) $display(" Randomization fails ");
$display("c1.v= %b", c1.v);
end
end
endmodule
// When Max( int1 ) is 22 , v[ 22 +: 10 ] == 10'h0 i.e v[ 31:22 ] == 10'h0 ;
// When Min( int1 ) is 0 , v[ 0 +: 10 ] == 10'h0 i.e v[ 9:0 ] == 10'h0 ;
This throws Randomization Failure on some Simulators while it works on others .
Any suggestions ?
In reply to Ammu786:
module test;
class gen;
bit [31:0] pattern = 32'hFFFF_FC00;
rand bit [31:0] value;
rand bit [4:0] rotate;
constraint c { value == (pattern << rotate | pattern >> 32-rotate); } // circular rotate
endclass
gen h =new;
initial repeat (10) begin
assert(h.randomize());
$display("%2d %b", h.rotate, h.value);
end
endmodule
Depending on your definition of “consecutive” you may want to limit rotate < 23.
[br]
In reply to Have_A_Doubt:
Because sometimes v[i+:10] is out of range.
In reply to dave_59:
Since I constraint the max value of int1 to 22 , v[22 +: 10] i.e v[ 31 : 22 ]
Even for the min. value as 0 the range would be v[ 0+:10 ] i.e v [ 9:0 ] .
As these are Valid Index range I am confused why and when ( for which value of int1 ) does the Out of range Occur ?
Won’t the if condition ensure that the Indexes are within Valid range ?
In reply to Have_A_Doubt:
Because the constraint solver is going to iterate over v[i] before knowing what the range of int1 could be. if you rewrote the constraint as
constraint VAL { foreach( v*) // Iterates from 31 to 0 .
if( i < 23 && i == int1 )
v[ i+:10 ] == 10'h0 ;
}
The i<23 acts as a constraint guard and prevents references to invalid ranges. (LRM section [i]18.5.13 Constraint guards*)
In reply to dave_59:
Thanks for the clarification Dave .
The constraint expression ( without constraint guard ) is equivalent to ::
constraint VAL {
( ( 31 == int1 ) && ( v[ 31 +: 10 ] ) ) == 10'h0 ;
( ( 30 == int1 ) && ( v[ 30 +: 10 ] ) ) == 10'h0 ;
( ( 29 == int1 ) && ( v[ 29 +: 10 ] ) ) == 10'h0 ;
............................
( ( 0 == int1 ) && ( v[ 0 +: 10 ] ) ) == 10'h0 ;
}
Although the left part ( i == int1 ) is False for index value 23 and upwards ,
the right part ( v[ i +:10 ] ) still has Out of bound indexes .
Hence we observe Randomization Failure
In reply to Have_A_Doubt:
So far we saw 2 solutions:
The following table lookup solution was provided to me by a colleague;
it is more efficient than solving many constraints.
class c;
rand int position;
bit[31:0] data;
constraint ct12 {position inside {[0:22]};}
const bit [0:22][31:0] lookup = {32'b00000000001111111111111111111111, //0
32'b10000000000111111111111111111111,
32'b11000000000011111111111111111111,
32'b11100000000001111111111111111111,
32'b11110000000000111111111111111111,
32'b11111000000000011111111111111111, // 5
32'b11111100000000001111111111111111,
32'b11111110000000000111111111111111,
32'b11111111000000000011111111111111,
32'b11111111100000000001111111111111,
32'b11111111110000000000111111111111, // 10
32'b11111111111000000000011111111111,
32'b11111111111100000000001111111111,
32'b11111111111110000000000111111111,
32'b11111111111111000000000011111111,
32'b11111111111111100000000001111111, // 15
32'b11111111111111110000000000111111,
32'b11111111111111111000000000011111,
32'b11111111111111111100000000001111,
32'b11111111111111111110000000000111,
32'b11111111111111111111000000000011, // 20
32'b11111111111111111111100000000001,
32'b11111111111111111111110000000000};
function void post_randomize();
data= lookup[position];
//$display("position=%d, data=%b", position, data);
endfunction : post_randomize
endclass
module m;
bit clk;
initial forever #5 clk=!clk;
c c1=new();
initial begin
repeat(50) begin
@(posedge clk) #2;
if (!randomize(c1)) $error();
$display("%t position=%d, c1.data=%b", $realtime, c1.position, c1.data);
ai_12: assert($countones(c1.data))
else $display("ERROR val = %b, countones= %d", c1.data,
$countones(c1.data));
end
$finish;
end
endmodule
/*
7 position= 6, c1.data=11111100000000001111111111111111
# 17 position= 6, c1.data=11111100000000001111111111111111
# 27 position= 15, c1.data=11111111111111100000000001111111
# 37 position= 19, c1.data=11111111111111111110000000000111
# 47 position= 6, c1.data=11111100000000001111111111111111
# 57 position= 16, c1.data=11111111111111110000000000111111
# 67 position= 8, c1.data=11111111000000000011111111111111
# 77 position= 3, c1.data=11100000000001111111111111111111
# 87 position= 6, c1.data=11111100000000001111111111111111
# 97 position= 21, c1.data=11111111111111111111100000000001
# 107 position= 3, c1.data=11100000000001111111111111111111
# 117 position= 9, c1.data=11111111100000000001111111111111
# 127 position= 14, c1.data=11111111111111000000000011111111
# 137 position= 14, c1.data=11111111111111000000000011111111
# 147 position= 6, c1.data=11111100000000001111111111111111
# 157 position= 7, c1.data=11111110000000000111111111111111
# 167 position= 5, c1.data=11111000000000011111111111111111
# 177 position= 1, c1.data=10000000000111111111111111111111
# 187 position= 15, c1.data=11111111111111100000000001111111
# 197 position= 6, c1.data=11111100000000001111111111111111
# 207 position= 19, c1.data=11111111111111111110000000000111
.....
# 237 position= 7, c1.data=11111110000000000111111111111111
# 247 position= 0, c1.data=00000000001111111111111111111111
# 257 position= 1, c1.data=10000000000111111111111111111111
# 267 position= 20, c1.data=11111111111111111111000000000011 */
In reply to ben@SystemVerilog.us:
I feel Dave’ Solution is generic as in user could change the
non - random property ’ pattern ’ at run - time and we would see the new pattern .
For other solution user would need to change the constraints .
In reply to dave_59:
Hi All.,
Please go through below code, which generates a continues zero for 10 bits. and remaining bits as 1.
For this i have considered a variable to generate some random value within 0,21. why 21 because 21+10=31 which is msb bit(if it is more than 21 example., 22. 22+10=32 but msb bit is 31 where that will appear as only continues 9bit instead of 10 bit). So considere only till (0,21) in random range.
So, after getting the random range i have used the if condition for iterating for continues 10bit.
we any queries , please reply back.
//Constraint for 32 bit address, to generate continuous 10 bits as 0 and remaining bits as 1.
module top;
class test;
rand bit[31:0] addr;
constraint cnst2{addr ==func();} //using a func to accomplish continues 10bits as '0'
function bit[31:0] func();
bit[31:0] addr1;
bit[4:0] val;
bit[3:0] j;
val=$urandom_range(0,21); //considering range from (0,21). till 21 because (21+10=31) to achieve continues 10bit zeros.
for(int i=0;i<32;i++)
begin //in if condition.,
if(i==val || i==(val+j)) //after val generating some random value, from that bit to continues 10bit assiging zero.
begin
addr1[i]=1'b0;
if(j<9)
begin
j++;
end
end
else //remaining bits assigned with 1 in else condition.
begin
addr1[i]=1'b1;
end
end
$display("val is %0d",val);
$display("addr1 is %b",addr1);
return addr1;
endfunction
endclass
test t1;
initial begin
repeat(15) begin
t1=new();
t1.randomize();
$display("addr is %b",t1.addr);
$display("addr is %h",t1.addr);
end
end
endmodule
output:-
val is 6
addr1 is 11111111111111110000000000111111
addr is 11111111111111110000000000111111
addr is ffff003f
val is 4
addr1 is 11111111111111111100000000001111
addr is 11111111111111111100000000001111
addr is ffffc00f
val is 11
addr1 is 11111111111000000000011111111111
addr is 11111111111000000000011111111111
addr is ffe007ff
val is 9
addr1 is 11111111111110000000000111111111
addr is 11111111111110000000000111111111
addr is fff801ff
val is 9
addr1 is 11111111111110000000000111111111
addr is 11111111111110000000000111111111
addr is fff801ff
val is 10
addr1 is 11111111111100000000001111111111
addr is 11111111111100000000001111111111
addr is fff003ff
val is 15
addr1 is 11111110000000000111111111111111
addr is 11111110000000000111111111111111
addr is fe007fff
val is 4
addr1 is 11111111111111111100000000001111
addr is 11111111111111111100000000001111
addr is ffffc00f
val is 9
addr1 is 11111111111110000000000111111111
addr is 11111111111110000000000111111111
addr is fff801ff
val is 6
addr1 is 11111111111111110000000000111111
addr is 11111111111111110000000000111111
addr is ffff003f
val is 9
addr1 is 11111111111110000000000111111111
addr is 11111111111110000000000111111111
addr is fff801ff
val is 4
addr1 is 11111111111111111100000000001111
addr is 11111111111111111100000000001111
addr is ffffc00f
val is 14
addr1 is 11111111000000000011111111111111
addr is 11111111000000000011111111111111
addr is ff003fff
val is 18
addr1 is 11110000000000111111111111111111
addr is 11110000000000111111111111111111
addr is f003ffff
val is 17
addr1 is 11111000000000011111111111111111
addr is 11111000000000011111111111111111
addr is f801ffff
Hi Dave,
To avoid the 0s wrapped around, I have added constraint on rotate
module test;
class gen;
bit [31:0] pattern = 32'hFFFF_FC00;
rand bit [31:0] value;
rand bit [4:0] rotate;
constraint c { value == (pattern << rotate | pattern >> 32-rotate);
rotate inside {[0:22]};
} // circular rotate
endclass
gen h =new;
initial repeat (20) begin
assert(h.randomize());
$display("%2d %b", h.rotate, h.value);
end
endmodule
21 10000000000111111111111111111111
12 11111111110000000000111111111111
4 11111111111111111100000000001111
4 11111111111111111100000000001111
16 11111100000000001111111111111111
19 11100000000001111111111111111111
13 11111111100000000001111111111111
3 11111111111111111110000000000111
8 11111111111111000000000011111111
6 11111111111111110000000000111111
19 11100000000001111111111111111111
16 11111100000000001111111111111111
10 11111111111100000000001111111111
17 11111000000000011111111111111111
1 11111111111111111111100000000001
11 11111111111000000000011111111111
14 11111111000000000011111111111111
9 11111111111110000000000111111111
14 11111111000000000011111111111111
10 11111111111100000000001111111111
Hi @dave_59,
Won’t this be a simpler solution?
class prac;
rand bit [31:0] x;
rand bit [4:0] rot;
bit [31:0] val = 31'h000003FF;
constraint ROT{rot inside {[0:22]};}
constraint PAT{x==val<<rot;}
endclass
module tb;
prac pr;
initial begin
pr = new();
repeat(5)
begin
pr.randomize();
$display("Value of Generated constraint is %032b",pr.x);
end
end
endmodule
As the requirement is for 10 consecutive zeros
function void post_randomize();
x = ~x;
endfunction