CSDN上最详细的——System Verilog约束
原文链接:https://blog.csdn.net/u010491580/article/details/114112599
尊重别人的知识产权就是尊重自己的人格!
本文还有一些地方去要改进和完善,后续会不断地更新!
约束编程是system verilog中一个很强大的编程方法,它让我们创建的对象可以很轻松扩展功能或约束对象实现指定的功能
1、约束块(constrain block)
约束块是类的成员,像变量、task和function一样,约束块的名字在一个类里是唯一的,约束块的声明如下:
class bus;
rand bit [31:0] addr,data
constrain addr_c {
addr[1:0] == 2'b0;
}
endclass
上面的代码中构建了一个约束块addr_c,约束快的修饰符是constrain,约束的内容是地址的低2bit为0,在调用randomize()函数随机时,随机出的地址,低2bit一直为0;
class test_a;
bus bus_a = new();
task bus_test;
repeat(50) begin
if(bus_a.randomize() == 1)
$display ("addr = %0h data = %h\n", bus.addr, bus.data);
else
$display ("Randomization failed.\n");
end
endtask
endclass
等效表达式:==,表示约束的随机值取固定值,如上面的constrain addr_c,约束地址的低2bit取0
2、约束块的取值
A、简单表达式
在约束块中,只能使用关系操作符(<,<=,==, >=,>),一个表达式只能使用一个关系操作符。
class bus
....
constrain data_c {
data > 20;
data<100;//不能写为20<data<100,这样一个表达式就有两个关系符,
}
endclasss
class bus
....
constrain data_c { data = 32'h5a5a_5a5a};//约束data的值恒为5a5a5a5a
endclasss
B、约束块权重取值:dist
使用dist操作符,可以是变量按我们设定的权重值随机,以增加某些值的随机概率,产生我们期望的激励,dist权重取值有两种写法:
1、:=取权重
class bus
....
constrain data_c {
data dist {0:=10,[1:3]:=80};
//data = 0,权重为10/250,250=10+80*3;
//data = 1/2/3的权重均为80/250;
}
endclasss
2、:/取权重
class bus
....
constrain data_c {
data dist {0:/10,[1:3]:/90};
//data = 0,权重为10/100;
//data = 1/2/3的权重均为30/100;
}
endclasss
C、inside运算符
inside运算符用于在集合set中取值,system verilog在集合中取值时,每个值取中的概率是相等的。
class bus
....
constrain data_c {
data inside {[$:5],[10:100]};
//表示在0-5和10-100中取值,$表示边界值
! (data inside {[110:200]});
//表示取110-200之外的值
}
endclasss
当集合set中的值有重复的时候,每个值取值概率也是一样的,不会因为某个值重复多次,概率就增加。
class bus
....
int array = '{1,2,2,3,3,3,4,4,4,4}
constrain data_c {
data inside array;
//此时,1,2,3,4取到的概率是相同的
}
endclasss
3、约束块中的条件约束
约束块中的条件约束有两种写法:
1、隐含操作符:->
typedef enum {low, mid, high} AddrType;
class bus
......
rand AddrType a_type ;
constrain data_c {
(a_type == low) -> addr inside {[0:50]};
(a_type == mid) -> addr inside {[60:70]};
(a_type == high) -> addr inside {[80:100]};
}
endclasss
2、if-else
typedef enum {low, mid, high} AddrType;
class bus
......
rand AddrType a_type ;
constrain data_c {
if(a_type == low)
addr inside {[0:50]};
esle if(a_type == mid)
addr inside {[60:70]};
else if(a_type == high)
addr inside {[80:100]};
}
endclasss
3、约束块中的约束关系都是双向的
约束块代码不是自上而下的程序性代码,是声明性的代码,是并行的,所有的约束表达式同时有效。
class test;
rand bit x;
rand bit[1:0] y;
cosntrain xy_c {
y>0;
(x==0) -> (y==0);
}
endclass
上面代码中的,x为0时,y为0,但约束是双向的,y是一直都大于0的!!!
y不为0时,x的取值不为0,解的概率如下:
所以我们需要注意细节!!!
4、sovle…before…修改解的概率
sovle…before…不会改变解的个数和范围,只会改变各个值的概率分布。
(没有理解!如果大家谁理解了,请一定要分享一下!!!)
class test;
rand bit x;
rand bit[1:0] y;
cosntrain xy_c {
(x==0) -> (y==0);
solve x before y;
}
endclass
(y的取值0,1,2,3,X的取值0,1)
sovle x before y约束的解
sovle y before x约束的解
tips:当修饰符为randc时,不要使用sovle…before…,因为randc默认最先计算,使用sovle…before…可能会带来未知错误。