systemverilog_随机约束
一.注意
随机约束一般只能在类中使用。
二.语法
(1)第一步:
随机的变量需用rand或randc关键字进行修饰;
rand 变量声明;
randc 变量声明;
(2)第二步:
使用约束块约束变量取值范围;
constraint {
语句1;
语句2;
...
语句n;
}
(3)第三步:
实例化类后,调用randomize方法实现随机约束;
句柄.randomize();
三.rand和randc关键字的不同
(1)说明
rand:代码在一次执行过程中多次使用randomize产生数据,rand修饰的变量的取值,均是在整个约束范围内随机取值的;
randc:代码在一次执行过程中多次使用randomize产生数据,rand修饰的变量的取值,第一次是整个约束范围内随机取值的,第二次是在约束范围内除去第一个值的范围内随机取值的,直至遍历取遍所有值;
(2)例子
class rand1;
rand int data1;
//randc int data1;
constraint c1 {
data1<3;
data1>-3;
}
endclass
module tb;
rand1 r1;
initial begin
r1 =new();
r1.randomize();
$display("data1 = %0d",r1.data1);
r1.randomize();
$display("data1 = %0d",r1.data1);
r1.randomize();
$display("data1 = %0d",r1.data1);
r1.randomize();
$display("data1 = %0d",r1.data1);
r1.randomize();
$display("data1 = %0d",r1.data1);
r1.randomize();
$display("data1 = %0d",r1.data1);
r1.randomize();
$display("data1 = %0d",r1.data1);
r1.randomize();
$display("data1 = %0d",r1.data1);
end
endmodule
rand修饰的data1结果:
randc修饰的data1结果:
四.常见的随机约束
1. 双向约束
(1)说明:
约束块之间是并行的 ,约束语句之间也是并行;
(2)例子:
class randomize_test;
rand bit [31:0] src,dst,data[4];
rand bit [7:0] kind;
constraint cstr{
src >10;
src <15;
}
function void print();
$display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
endfunction
endclass
module tb;
randomize_test p;
initial begin
p = new();
$display("Before randomize");
p.print();
p.randomize();
$display("After randomize");
p.print();
end
endmodule
c结果:
src的取值范围是10<src<15
2.取值范围约束
(1)说明
限制变量取值范围;
(2)语法:
成员变量 inside 取值范围;
(3)例子
A 例子1
代码:
class my_class5;
rand int data1;
constraint con5{
data1 inside {[1:3],[5:8],9};
};
endclass
module tb5;
my_class5 c5;
initial begin
c5 = new();
$display("Before randomize data1 = %0d",c5.data1);
c5.randomize();
$display("First time randomize out data1 = %0d",c5.data1);
c5.randomize();
$display("Second time randomize out data1 = %0d",c5.data1);
c5.randomize();
$display("Third time randomize out data1 = %0d",c5.data1);
end
endmodule
说明:
data1的取值范围设置为1~3,5~8和9;
结果:
B 例子2
代码:
class my_class6;
int data1 [4] = {-1,-2,-3,-4};
rand int data2;
constraint con6{
data2 inside {data1,[1:3]};
};
endclass
module tb6;
my_class6 c6;
initial begin
c6 = new();
$display("Before randomize data1 = %0d",c6.data2);
c6.randomize();
$display("First time randomize out data1 = %0d",c6.data2);
c6.randomize();
$display("Second time randomize out data1 = %0d",c6.data2);
c6.randomize();
$display("Third time randomize out data1 = %0d",c6.data2);
end
endmodule
说明:
变量也可作为取值范围;
结果:
3.内嵌约束
(1)说明:
添加额外的约束;
(2)语法:
实例化随机约束句柄.randmize() with {额外的约束};
(3)例子
class randomize_test;
rand bit [31:0] src,dst,data[4];
rand bit [7:0] kind;
constraint cstr{
src inside {[1:5],[7:8]};
}
function void print();
$display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
endfunction
endclass
module tb;
randomize_test p;
initial begin
p = new();
$display("Before randomize");
p.print();
p.randomize() with { 5<src;};
$display("After randomize");
p.print();
end
endmodule
c 结果
4.权重约束
(1)说明:
分配每个取值的权重
(2)语法:
变量名 dist {值:=每个值分配权重,值:/共同分配的权值};
(3)例子
class randomize_test;
rand bit [31:0] src,dst,data[4];
rand bit [7:0] kind;
constraint cstr{
src dist {[1:3]:/1,[7:8]:=2,10:=5};
}
function void print();
$display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
endfunction
endclass
module tb;
randomize_test p;
initial begin
p = new();
$display("Before randomize");
p.print();
p.randomize();
$display("After randomize");
p.print();
end
endmodule
c 结果
权重分配情况:
1,2,3共同分配1的权重,即每个对应1/3;
7,8每个分配的权重为2;
10分配的权重为5;
5.唯一标识约束
(1)说明
声明后,约束的变量取值不会重复;
(2)语法:
unique {多个成员变量};
(3)例子
class randomize_test;
rand bit [1:0] src,dst,data[4];
rand bit [7:0] kind;
constraint cstr{
unique {src,dst};
}
function void print();
$display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
endfunction
endclass
module tb;
randomize_test p;
initial begin
p = new();
$display("Before randomize");
p.print();
p.randomize();
$display("After randomize");
p.print();
end
endmodule
c 结果
6.条件约束
(1)说明
如果条件满足,约束要满足;
(2)语法:
方法一:
条件 -> 约束;
方法二:
if(条件1)
约束1;
else if(条件2)
约束2;
else
约束3;
(3)例子
7.动态数组的长度约束
(1)说明
约束动态数组的长度;
(2)语法:
动态数组名.size() 约束;//可以使用各种约束,比如取值范围约束
(3)例子
例子1:
class randomize_test;
rand bit [31:0] src,dst,data[];
rand bit [7:0] kind;
constraint cstr{
data.size < 5;
}
function void print();
$display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
endfunction
endclass
module tb;
randomize_test p;
initial begin
p = new();
$display("Before randomize");
p.print();
p.randomize();
$display("After randomize");
p.print();
end
endmodule
c 结果
例子二:
class my_class8;
rand int data1 [];
constraint con8{
data1.size < 5;
foreach(data1[j]) data1[j]<20;
foreach(data1[j]) data1[j]>0;
};
endclass
module tb8;
my_class8 c8;
initial begin
c8 = new();
$display("Before randomize data1 = %p",c8.data1);
repeat(8)begin
c8.randomize();
$display("Afte randomize data1 = %p",c8.data1);
end
end
endmodule
8.软约束
(1)说明
当多个约束冲突时,可以用soft关键字修饰(soft表示软约束,默认是硬约束),当软约束和硬约束冲突时会优先执行硬约束;
一般:底层约束用soft关键字修饰,额外的约束用硬约束;
注意:
soft关键字修饰的是约束语句,不是约束块;
硬约束和硬约束冲突时,约束失败;
硬约束和软约束冲突时,执行硬约束;
软约束和软约束冲突时,会就近执行;(后写的:with额外约束 -> 子类约束 ->父类约束)
(2)例子
class randomize_test;
rand bit [31:0] src,dst,data[4];
rand bit [7:0] kind;
constraint cstr{
soft src inside {[1:5]};
}
function void print();
$display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
endfunction
endclass
module tb;
randomize_test p;
initial begin
p = new();
$display("Before randomize");
p.print();
p.randomize() with{src inside {[6:10]};};
$display("After randomize");
p.print();
end
endmodule
c 结果
9.数组的迭代约束
(1)说明
对一定长度的数组各成员进行约束,可以搭配foreach实现;
(2)语法
foreach(数组[索引])
每个成员的约束;
(3)例子
代码:
class my_class7;
rand int data1[4];
constraint con7{
foreach(data1[i])
data1[i] > (2*i);
foreach(data1[i])
data1[i] < 20;
};
endclass
module tb7;
my_class7 c7;
initial begin
c7 = new();
$display("Before randomize data1 = %p",c7.data1);
c7.randomize();
$display("First time randomize out data1 = %p",c7.data1);
c7.randomize();
$display("Second time randomize out data1 = %p",c7.data1);
c7.randomize();
$display("Third time randomize out data1 = %p",c7.data1);
end
endmodule
结果:
五.特殊知识点
1.使用系统函数产生随机数
(1)语法
$urandom(): 随机产生一个32位无符号数;
$urandom_range(maxval,minval):在指定范围内随机产生一个32位无符号数;
(2)例子
module tb1;
initial begin
$display("$urandom() data = %0d",$urandom());
$display("$urandom_range() data =%0d",$urandom_range(5,3));
end
endmodule
2.使用系统内建包(std)实现指定成员的随机化
(1)语法
std::randomize(成员1,成员2,...);
(2)例子
module tb2;
int data1;
int data2;
initial begin
$display("Before randomize: data1 = %0d,data2 = %0d",data1,data2);
std::randomize(data1,data2);
$display("After randomize: data1 = %0d,data2 = %0d",data1,data2);
end
endmodule
结果:
(3)补充
此方法也可以添加内嵌约束;
语法:
std::randomize(成员1,成员2,...)with{
约束1;
...
约束n;
};
例子:
module tb2;
int data1;
int data2;
initial begin
$display("Before randomize: data1 = %0d,data2 = %0d",data1,data2);
std::randomize(data1,data2) with {
data1 <5;
data1 >1;
};
$display("After randomize: data1 = %0d,data2 = %0d",data1,data2);
end
endmodule
结果:
3.使用系统内建包(std)实现结构体的随机化
(1)说明
需先将需要随机化的成员用rand或randc关键字进行修饰;
(2)例子
代码:
typedef struct{
rand int data1;
rand int data2;
}m_struct;
module tb3;
m_struct s1;
initial begin
$display("before randomize: data1 = %0d,data2 = %0d",s1.data1,s1.data2);
std::randomize(s1);
$display("after randomize: data1 = %0d,data2 = %0d",s1.data1,s1.data2);
end
endmodule
结果:
4.内嵌约束的变量的索引原则
(1)原则
变量索引满足就近原则,先在定义当前随机约束类中查找,然后再在当前随机约束语句作用的区域内查找;
要索引到当前随机约束语句作用的方法中的同名成员,使用关键字local::变量名;
this关键字索引的区域为定义当前随机约束语句类的内部,要索引到当前随机约束语句作用的类中的同名成员,使用关键字locall::this.变量名;
(2)例子
例子1:
代码:
class my_class11;
rand int x;
constraint con11{
x > 0;
};
endclass
class my_class12;
int x;
int y;
task doit(my_class11 c11,int x,int z);
c11.randomize() with {
x<y+z;
};
$display("c11.x = %0d,x = %0d,z = %0d,y = %0d,this.x = %0d",c11.x,x,z,y,this.x);
endtask
endclass
module tb11;
my_class11 c11;
my_class12 c12;
initial begin
c11 = new();
c12 = new();
c12.doit(c11,10,15);
end
endmodule
注意
:(语句x<y+z为例)
内嵌约束变量索引满足就近原则,变量会优先找约束语句所在的类(x为当前随机约束语句定义的类c11中的随机约束的x),然后再找作用域内(z对应doit任务的参数,y对应myclass的成员y);
结果:
例子2:
代码:
结果:
例子3:
结果:
六.随机约束的控制
(1)简介
随机约束的整体或局部的开启或关闭;
(2)变量随机特性的控制1
(a)语法
随机约束实例化句柄名.rand_mode(控制值); //所有变量随机特性的开启或关闭,控制值0表示关闭1表示开启;
随机约束实例化句柄名.变量名.rand_mode(控制值);//指定变量随机特性的开启或关闭,控制值0表示关闭1表示开启;
(b)例子
代码
class my_class15;
rand int x;
rand int y;
endclass
module tb15;
my_class15 c15;
initial begin
c15 = new();
$display("First time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
c15.rand_mode(0);
c15.randomize();
$display("First time:After randomize x = %0d, y = %0d",c15.x,c15.y);
c15 = new();
$display("Second time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
c15.rand_mode(1);
c15.randomize();
$display("Second time:After randomize x = %0d, y = %0d",c15.x,c15.y);
c15 = new();
$display("Third time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
c15.x.rand_mode(0);
c15.y.rand_mode(1);
c15.randomize();
$display("Third time:After randomize x = %0d, y = %0d",c15.x,c15.y);
end
endmodule
结果:
(c)问题
描述:定义了多个变量的随机和约束特性,关闭一个变量的随机特性,所有变量的随机约束特性都被关闭了;
例子:
class my_class15;
rand int x;
rand int y;
constraint con15_1{
x inside {[3:10]};
}
constraint con15_2{
y inside {[3:10]};
}
endclass
module tb15;
my_class15 c15;
initial begin
c15 = new();
$display("First time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
c15.rand_mode(0);
c15.randomize();
$display("First time:After randomize x = %0d, y = %0d",c15.x,c15.y);
c15 = new();
$display("Second time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
c15.rand_mode(1);
c15.randomize();
$display("Second time:After randomize x = %0d, y = %0d",c15.x,c15.y);
c15 = new();
$display("Third time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
c15.x.rand_mode(0);
c15.y.rand_mode(1);
c15.randomize();
$display("Third time:After randomize x = %0d, y = %0d",c15.x,c15.y);
end
endmodule
结果:
(3)变量随机特性的控制2
(a)语法
随机约束类句柄.randomize(); //按照随机约束类定义,决定随机变量
随机约束类句柄.randomize(变量1,…,变量n); //指定变量为随机变量
(b)例子
class my_class16;
rand int x;
rand int y;
int w,z;
constraint con16{
(x < w && y>w);
}
endclass
module tb16;
my_class16 c16;
initial begin
c16 = new();
$display("Before randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
c16.randomize();
$display("First time:After randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
c16.randomize(x);
$display("Second time:After randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
c16.randomize(w,z);
$display("Third time:After randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
end
endmodule
结果:
第一次randomize随机约束类定义的x、y是随机变量,第二次randomize指定的x是随机变量,第三次randomize指定的w、z是随机变量。
(4)约束的控制
(a)语法
随机约束实例化句柄名.constraint_mode(控制值); //所有约束的开启或关闭,控制值0表示关闭1表示开启;
随机约束实例化句柄名.约束块名.constraint_mode(控制值);//指定约束块的开启或关闭,控制值0表示关闭1表示开启;
(b)例子
代码:
class my_class17;
rand int x,y;
constraint con1 {
x > 0;
y > 0;
}
constraint con2{
x < 15;
y < 15;
}
endclass
module tb17;
my_class17 c17;
initial begin
c17 = new();
$display("First time:Before randomize x = %0d, y = %0d",c17.x ,c17.y);
c17.randomize();
$display("First time:After randomize x = %0d, y = %0d",c17.x ,c17.y);
c17 = new();
$display("Second time:Before randomize x = %0d, y = %0d",c17.x ,c17.y);
c17.constraint_mode(0);
c17.randomize();
$display("Second time:After randomize x = %0d, y = %0d",c17.x ,c17.y);
c17 = new();
$display("Third time:Before randomize x = %0d, y = %0d",c17.x ,c17.y);
c17.con1.constraint_mode(1);
c17.con2.constraint_mode(0);
c17.randomize();
$display("Third time:After randomize x = %0d, y = %0d",c17.x ,c17.y);
end
endmodule
结果: