赞
踩
Class Packet;
//The random variables
rand bit[31:0]src, dst, data[8];
randc bit[7:0]kind;
//Limit the values for src
constraint c(src > 10;
src <15;);
endclass
Packet p;
initial begin
p = new();//Create a packet
assert(p.randomize()) else
$fatal(0, "Packet::randomize failed");
transmit(p);
end
constraint c_dist{
src dist {0:=40, [1:3]:=60};
//src = 0, weight = 40/220
//src = 1, weight = 60/220
//src = 2, weight = 60/220
//src = 3, weight = 60/220
dst dist {0:/40, [1:3]:/60};
//dst = 0, weight = 40/100
//dst = 1, weight = 20/100
//dst = 2, weight = 20/100
//dst = 3, weight = 20/100
}
使用inside运算符产生一个值的集合。
//随机值的集合
rand int c;//随机变量
int lo, hi;//作为上限和下限的非随机变量
constraint c_range{
c_inside{[lo:hi]};// lo<=c且c<=hi
}
可以使用$来代表取值范围里的最小值和最大值。
rand bit[6:0]b;// 0<=b<=127
rand bit[5:0]e;// 0<=e<=63
constraint c_range{
b_inside{[$:4], [20:$]};//0<=b<=4||20<=b<=127
e_inside{[$:4], [20:$]};//0<=b<=4||20<=b<=63
}
通过->或者if-else来让一个约束表达式在特定时刻有效。
constraint c_io{
(io_space_mode) ->
addr[31] == 1'b1;
}
constraint c_len_rw{
if(op == READ)
len inside{[BYTE:LWRD]};
else
len == LWRD;
}
SV的约束是双向的,这表示它会同时计算所有的随机变量的约束。增加或删除任一个变量的约束都会直接或间接影响所有相关变量的值的选取。
使用constraint_mode()函数。
class Packet; rand int length; constraint c_short {length inside {[1:32]};} constraint c_long {length inside {[1000:1023]};} endclass Packet p; initial begin p = new(); //通过禁止c_short约束产生长包 p.c_short.constraint_mode(0); assert(p.randomize()); transmit(p); //通过禁止所有的约束,然后使能短包来产生短包 p.constraint_mode(0); p.c_short.constraint_mode(1); asser(p.randomize()); transmit(p); end
内嵌约束:SV允许使用randomize() with来增加额外的约束,这和在类里增加约束是等效的。
class Transaction; rand bit[31:0]addr, data; constraint c1{addr inside{[0:100],[1000:2000]};} endclass Transaction t; initial begin t =new(); // addr 范围:50-100,1000-1500 data < 10 assert(t.randomize() with {addr >= 50; addr <= 1500; data < 10;}); driveBus(t); //强制addr取固定值,data > 10 assert(t.randomize() with {addr == 2000; data > 10;}); driveBus(t); end
SV可以使用两个特殊的void类型的pre_randomize()和post_randomize()函数在调用randomize()之前或之后执行一些操作。
a = $urandom_range(3, 10);//3~10
a = $urandom_range(10, 3);//3~10
b = $urandom_range(5);//0~5
约束的技巧
rand int size;
int max_size = 100;
constraint c_size{
size inside{[1:max_size]};//通过改变max_size的值来改变随机变量size的上限
}
//带有权重变量的dist约束
rand rand_e;
rand rand_cmd;
int read8_wt = 1, read16_wt = 1, read32_wt = 1;
constraint c_read{
read_cmd dist{READ8:=read8_wt,
READ16:=read16_wt,
READ32:=rea32_wt};
}
如果在用一套约束在随机的过程中已经产生了几乎所有想要的激励向量,但还是缺少几种激励向量,可以采用先调用randomize()函数,然后再把随机变量的值设置为固定的期望值的方法来解决。
p.length.rand_mode(0);//设置包长为非随机值
p.length = 42;//设置包长为常数
class Rising;
byte low;//not random
rand byte med, hi;//random variable
constraint up{low < med; med < hi;}
endclass
initial begin
Rising r;
r = new();
r.randomize();//随机化hi,但不改变low
r.randomize(med);//只随机化med
r.randomize(low);//只随机化low
end
//带有外部约束的类
class Packet;
rand bit[7:0]length;
rand bit[7:0]payload[];
constraint c_valid{length > 0;
payload.size() == length;}
constraint c_external'
endclass
//test.sv
program automatic test;
include"packet.sv" constraint Packet::c_external{length == 1;}
...
endprogram
class dyn_size;
rand logic[31:0] d[];//随机化一个空数组
constraint d_size {d.size() inside {[1:10]};}//进行约束
endclass
多数情况下,数组的大小应该给定范围,防止生成过大体积的数组或者空数组。
SV可以利用foreach对数组的每一个元素进行约束。
class sum;
rand unit len[];
constraint c_len{foreach(len[i])
len[i] inside{[1:255]};
len.sum < 1024;
len.size() inside{[1:8]};}
endclass
使用foreach产生唯一的元素值。
class UniqueSlow;
rand bit[7:0] ua[64];
constraint c{
foreach(ua[i])//对数组的每个元素操作
foreach(ua[j])
if(i != j)//除了元素自己
ua[i] != ua[j];//和其它元素比较(即与其他元素都不同)
}
endclass
使用randc辅助类产生唯一的元素值。
class randc8;
randc bit[7:0]val;
endclass
class LittleUniqueArray;
bit[7:0]ua[64];
function void pre_randomize;
randc8 rc8;
rc8 = new();
foreach(ua[i])begin
assert(rc8.randmize());
ua[i] = rc8.val;
end
endfunction
endclass
initial begin
for(int i=0; i < 15; i++)begin
randsequence(stream)
stream:cfg_read :=1|
io_read :=2|
mem_read:= 5;
cfg_read:{cfg_read_task;}|
{cfg_read_task;} cfg_read;
io_read:{io_read_task;}|
{io_read_task;} io_read;
mem_read:{mem_read_task;}|
{mem_read_task;} mem_read;
endsequence
end
end
上述的代码产生了stream序列,它可以是cfg_read,io_read或mem_read,随机序列会随机地从三种操作中选取一种,权重分别为1,2,5。
使用randcase的随机控制
initial begin
int len;
randcase
1:len = $urandom_range(0, 2);//10%:0,1,2
8:len = $urandom_range(3, 5);//80%:3,4,5
1:len = $urandom_range(6, 7);//10%:6,7
endcase
end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。