System Verilog的约束与随机
约束
简单表达式:一个表达式中最多只能使用一个关系操作符,约束块里只能包含表达式,所以在约束块里不能进行赋值。
权重分布:dist
src dist {0:40,[1:3]:=60}; //权重和不用等于100,值和权重可以是常数或者变量
集合(set)和inside
c inside {[lo:hi]} ; c inside {[$:4],[20:$]} //可以使用$取位宽范围内的最大或者最小值 int fib[5] = '{1,2,3,4,5}; c inside fib; //可以使用数组进行约束
randc:
//randc变量表示周期随机性,即所有可能的值都被取过之后才可能重复 class RandcInside; //集合里的值只被取一次 int array[] ; randc bit [15:0] index ; function new(input int a[]); array = a ; endfunction function int pick; return array[index] ; endfunction constraint c_size {index < array.size;} endclass initial begin RandcInside ri ; ri = new('{1,3,5,6,2,8}) ; repeat(ri.array.size) begin assert(ri.randomize()); $display("Picked %2d[%0d]",ri.pick(),ri.index) ; end end
条件约束:
-> 操作符
//相当于case type == 0 -> a == 0 ; type == 1 -> a == 1 ; type == 2 -> a == 2 ; //相当于: case(type) 0: a == 0 ; 1: a == 1; 2: a == 2; endcase //当然约束中不能使用case
if-else //程序代码中使用begin end分割代码块,而在约束中使用{}
双向约束
> 、< 、== 等这种比较操作符回同时计算左右两边的值
简单的数学运算:
约束求解器可以处理简单的数学运算,如加、减、位提取和移位,约束求解对于32位数值的乘除和取模运算量是非常大的。有时可以用移位计算代替乘除减少计算量。
使用solve before约束引导概率分布
constraint c_xy{ x==0 -> y==0; solve x before y; } //先求解x再求解y
randomize () with
t.randomize () with {addr >= 50 ;} ;
pre_randomize 和 post_randomize
分别在randomize之前和之后自动执行
随机数函数
$random() //平均分布,返回32位有符号随机数 $urandom() //平均分布,返回32位无符号随机数 $urandom_range() //在指定范围内的平均分布 $dist_exponential() //指数衰落 $dist_normal() //钟型分布 $dist_poisson() //钟型分布 $dist_uniform() //平均分布
rand_mode
class Packet; rand bit [3:0] length , load ; endclass Packet p ; initial begin p = new(); p.constraint_mode(0) ; //关闭约束 , 1为打开 p.length.rand_mode(0) ; //设置length为非随机值; p.length = 42 ; p.randomize; p.ramdomize(load); //随机化load end
handle.randomize(null)
调用时,sv会把所有的变量当作非随机变量,仅仅检查变量是否满足约束条件。
可以使用条件操作符(-> 或者 if-else)构建由非随机变量控制的约束
迭代和数组约束:
数组大小:size()方法
元素的和:sum()方法;但是需要注意,这里保存的和的位宽和元素的位宽是一致的,所以很容易sum溢出导致约束错误,所以约束数组的和时需要特别注意,如果元素位宽为8位,约束如下:
bit [10:0] array[$]; //宽度设为sum的最大宽度,确保不会溢出 constraint size_con{ array.size <= 8 ; array.size >= 3 ; } constraint sum_con{ solve array.size before array.sum; array.sum <= 11'1f; //11位确保sum不会溢出 foreach(array[i]) { array[i] <= 8'hff ; //单独约束每个元素至8位 } }
产生具有唯一值的元素
class UniqueSlow; rand bit [7:0] ua [64] ; constraint c{ foreach(ua[i]) foreach(ua[j]) if(i!=j) ua[i] != ua[j] ; } endclass //使用foreach 这种方式比较慢 class randc8; randc bit [7:0] val ; endlcass class LittleUniqueArray; bit [7:0] ua [64]; function viod pre_randomize; randc8 rc8; rc8 = new(); foreach(ua[i]) begin assert(rc8.randomize()); ua[i] = rc8.val ; end endfunction endclass //使用randc更高效的获取目标数组
使用randcase建立决策树
randcase: AA:do_aa(); BB:do_bb(); CC:do_cc(); endcase