systemverilog中的constraint约束的使用
约束的使用
1.逻辑关系<,<=,==, >=,>
逻辑关系约束,比较直接的指定随机数产生的范围,<,<=,==, >=,>
rand byte data;
constraint data_cons{ data > 0; data <5; } //约束data的值大于0,小于5
2.inside
inside可以约束data从指定的数据集合中获取数据值,取得每个值的概率是相同的。
rand byte data;
constraint data_cons{
data inside {[0:3],[8:10]}; } //data 的值可以从0,1,2,3,8,9,10中取出
即使如下面的array,取出的1,2,3,4的概率也是相同的
rand byte data;
int array = '{1,2,2,3,3,3,4,4,4,4}
constrain data_c {
data inside array; //此时,1,2,3,4取到的概率是相同的 }
3.dist
dist约束data从列表中获取数据值,可指定获取数据的权重也可不指定,有两种指定权重的方式
rand byte data;
constraint data_cons{
data dist {0,2,[5:10]};
}
//data 的值从0,2,5,6,7,8,9,10中取出
第一种权重:=,表示取0的概率是10/(10+45+45+45),1、2、3的概率均是45/(10+45+45+45)
rand byte data;
constraint data_cons{ data dist {0:=10,[1:3]:=45}; }
第二种权重:/,表示取0的概率是10/(10+45),1、2、3的概率均是45/3/(10+45)=15/(10+45)
rand byte data;
constraint data_cons{
data dist {0:/10,[1:3]:/45};
}
:= | :/ | |
0 | 10/145 | 10/55 |
1 | 45/145 | 15/55 |
2 | 45/145 | 15/55 |
3 | 45/145 | 15/55 |
4.条件判定
->蕴含判定,只有在data_flag大于2时,data从1、2、3中取值,在data_flag小于等于2时,data从4、5、6中取值.
rand byte data;
constraint data_cons{ (data_flag > 2) -> data inside {[1:3]}; (data_flag <= 2) -> data inside {[4:6]}; }
if else 条件判定,只有在data_flag大于2时,data从1、2、3中取值,在data_flag小于等于2时,data从4、5、6中取值.
rand byte data;
constraint data_cons{ if(data_flag>2) data inside {[1:3]}; else data inside {[4:6]}; }
slove before操作符
constraint data_cons{ (x == 0) -> y== 0; solve y before x; //规定在y产生之前先产生x //x=0,则y必为0;y=0,x不一定为0。 }
5.数组的约束
rand byte pload[]; constraint pload_cons { foreach(pload[i]) { pload[i] inside {[1:255]}; } pload.sum < 1024; pload.size() inside {[1:8]}; } //动态数组pload,可通过foreach约束pload中每个元素的值,和整个数组的sum和还有size大小,条件同时成立
6.约束的开关
可控制transaction中的约束的关闭,也可控制ransaction中的某一个约束的关闭
my_transaction m_trans m_trans.crc_err_cons.constraint_mode(0);//关闭m_trans中的crc_err_cons的约束 m_trans.constraint_mode(0);//关闭m_trans中的所有的约束 `uvm_do(m_trans)
7.约束的重载
先构建一个自己的my_transaction,在其中指定约束crc_err_cons和sfd_err_cons
class my_transaction extends uvm_sequence_item; rand bit crc_err; rand bit sfd_err; constraint crc_err_cons{ crc_err == 1'b0; } constraint sfd_err_cons{ sfd_err == 1'b0; } `uvm_object_utils_begin(my_transaction) `uvm_field_int(sfd_err, UVM_ALL_ON | UVM_NOPACK) `uvm_field_int(pre_err, UVM_ALL_ON | UVM_NOPACK) `uvm_object_utils_end function new(string name = "my_transaction"); super.new(); endfunction endclass
在case中可以创建一个my_transaction的子类new_transaction,在子类中重新定义约束crc_err_cons,则new_transaction中的crc_err_cons约束是重载后的,sfd_err_cons得约束条件任然使用my_transaction的约束条件
class new_transaction extends my_transaction; `uvm_object_utils(new_transaction) function new(string name= "new_transaction"); super.new(name); endfunction constraint crc_err_cons{ crc_err dist {0 := 2, 1 := 1}; } endclass
case中使用时,直接使用子类的transaction即可以完成新约束的使用。
virtual task body(); new_transaction ntr; repeat (10) begin `uvm_do(ntr) end #100; endtask