SystemVerilog随机化(四)

在这里插入图片描述

一、随机变量类型

随机化变量以及随机约束都只能在类class中声明

1.1.rand与randc随机变量

1)、使用关键字rand声明随机变量,随机变量的值在指定范围内均匀分布;如果不添加约束,随机变量可以是指定有效范围内的任何值。

rand  bit[7:0]  y;      //y为8bit无符号整形数,取值范围:0~255,  每个数出现的概率都为1/256

2)、使用关键字randc声明周期性随机变量,取值按照声明的有效范围周期性出现,且数据类型只可以是bit或者enum型。

randc  bit[1:0]  y;      //y为2bit无符号整形数,取值范围:0~3,  在一个周期内必然会产生0、1、2、3四个数,顺序不定

注:rand 理解为有放回抽样;randc 无放回抽样。

1.2.constraint指定约束范围

使用关键字constraint来添加约束语句块,指定随机变量的取值范围,或者各个变量之间的相互关系。

  • 约束块不像是自上而下执行的程序性代码,它们是声明性代码,是并行的,所有的约束表达式同时有效。
class date;
    rand bit [2:0] month;
    rand bit [4:0] day;
    rand int year;
    constraint c_date{
        month inside {[1:12]};
        day inside {[1:31]};
        year inside {[2010:2030]};
}
endclass

二、随机约束操作

2.1.声明约束(>、<、=、>=、<=)

2.2.范围约束(inside)

使用$指定最大值和最小值

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

2.3.权重分布约束(dist)

在这里插入图片描述

2.4.条件约束(if-else; ->)

class BusOp;
    ...
    constraint c_io {
        (io_space_mode) -> addr[31] == 1'b1;
}
//->操作符可以产生和case操作符类似效果的语句块,可以用于枚举类型的表达式。->与if-else约束可以相互转化。
    constraint c_io_if {
        if(io_space_mode)
            addr[31] == 1'b1;
}

class BusOp;
    ...
    constraint c_len_rw {
        if(op == READ)
            len inside {[BYTE:LWRD]};
        else
            len == LWED;

2.5.双向约束

对于约束而言,是双向约束,是一种声明性质的代码,并行的,所有约束表达式同时有效。

rand logic [15:0] r, s, t;
constraint c_bidir {
    r < t;
    s == r;
    t < 30;
    s > 25;
}
//结果见表6.1

在这里插入图片描述

2.6.内嵌约束randomize ( )with{ }

SV允许使用randomise( )with{}来增加额外的约束,这和在类里面增加约束是等效的

在这里插入图片描述

注意:

  • 在with{}语句里,SV使用了类的作用域,所以在上例中使用了addr变量,而不是t.addr。

  • 在使用randomise()with语句时常犯的错误就是使用()而不是{}内嵌的约束。

  • 记住,约束块应该使用{},内嵌约束也应该使用{},{}用于声明性的代码。

2.7.solve…before约束

前面的约束 (符号约束、inside约束、条件约束、内嵌约束)条件下,其随机值出现的概率是均等的。

**randc类型变量不被允许使用solve…before约束;**这个也好理解,无放回怎么保证每个值的特定概率。

class transaction;
  rand bit        a;
    rand bit[1:0]   data; //data 取值0,1,2,3

    constraint c1{ a -> data==3'h3;       //条件约束 a =1,那data=3
                  solve a before data;}   //在给出data随机值之前先给出a的随机值  
endclass

module gen_data;
  initial begin
    transaction tr=new() ;
    for(int i=0; i<10; i++ ) begin
      tr.randomize() ;
      $display("a= %0d,  data= %0d",tr.a, tr.data) ;
    end
  end

endmodule

打印结果如下:
a= 1,  data= 3;
a= 0,  data= 2;
a= 0,  data= 0;
a= 0,  data= 1;
a= 1,  data= 3;
a= 0,  data= 2;
a= 1,  data= 3;
a= 0,  data= 3;
a= 0,  data= 1;
a= 0,  data= 1;
adata概率
001/2*1/4 = 1/8
011/2*1/4 = 1/8
021/2*1/4 = 1/8
031/2*1/4 = 1/8
131/2*1 = 1/2

三、 随机化函数

在这里插入图片描述

  1. $random —— 系统随机化调用函数,返回32bit有符号数;
  2. $urandom() —— 系统随机化调用函数,返回32bit无符号数;
  3. $urandom_range()—— 系统随机化调用函数,返回指定范围内的无符号随机整数;
  4. srandom() —— 对象和线程(手动添加种子seed)的随机化方法;
  5. randomize() —— 对象的随机化方法;
  • 调用randomize( )函数可以为对象中的所有随机变量赋值,随机变量的值要符合约束;
  • randomize( )函数成功时,返回1,失败时返回0。如果随机变量没有添加约束,那么产生的值是有效范围内的任何值。

在这里插入图片描述

class Rising;
    byte low;        //未被随机约束变量
    rand byte med, hi;    //随机化的变量,8位有符号值
    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

上述代码中,例化了r之后,先调用r.randomize(low),那么low,med和hi的组合值可能是下面哪一组?

(A)low = -1,med=0, hi=0
(B)low = -1,med=1, hi=2
(C)low = 报错,med=0, hi=0
(D)low = 报错,med=null, hi=报错

此时 只随机low,而med和hi不被随机。 C

注:low 没有被rand 修饰也能被随机。

3.1.关闭或打开随机变量与约束

constraint_mode()函数打开或关闭约束

含义描述
0OFF约束语句块设为非激活态(INACTIVE),constraint约束将不起作用
1ON约束语句块设为激活态(ACTIVE),constraint约束将起作用
class  packet();
    rand  int   src, dst;
    constraint   filter {src>2*dst;}
endclass

function int toggle_rand(Packet p);
    if(p.filter.constraint_mode() == 1)
       p.filter.constraint_mode(0);      //关闭约束
    else
       p.filter.constraint_mode(1);      //打开约束
    toggle_rand = p.randomize();      //随机化返回函数值
endfunction

rand_mode()函数可以打开或关闭随机变量

含义描述
0OFF随机变量设为非激活态(INACTIVE),不能通过randomize()函数随机化赋值
1ON随机变量设为激活态(ACTIVE),可以通过randomize()函数随机化赋值

四、数组的约束

4.1.动态数组的随机化

在约束随机标量 的同时,我们还可以对随机化的数组进行约束

class dyn_size;
    rand logic [31:0] d[];            //随机化d[]数组;
    constraint d_size (d.size() inside {[1:10]};)    //调用d.size对数组长度范围进行约束
endclass

动态数组分别可以对其长度和内容做随机化处理。此外,还可以通过在约束中结合数组的其它方法sum(), product(), and(), or()和xor()。例如要求随机出来的数组 元素满足(1)个数在1-8 之间;每个数组的数值大小在1-255之间;每个数组的求和要小于1024。

class good_sum5;
    rand uint len[];
    constraint c_len{
        foreach (len[i]) len[i] inside {[1:255]};
        len.sum() < 1024;
        len.size() inside {[1:8]}}

4.2. 产生唯一元素的数组

class UniqueSlow;
    rand bit [7:0] ua[64];
    constraint c {
        foreach (ua[i])        //对数组中每一个元素操作
            foreach (ua[j])
                if(i != j)     //除了元素自己
                    ua[i] != ua[j];     //和其它元素比较
}

使用randc变量辅助生成唯一元素,无放回约束。

class randc8;
    randc bit [7:0] val;    //随机变量的值的范围为0~255,每一次randmize的256次值都不相同
endclass
 
class LittleUniqueArray;
    bit [7:0] ua [64];      //定义一个含有64个元素的数组
    function void pre_randomize();
        randc8 rc8;
        rc8 = new();
        foreach (ua[i])    begin
            assert(rc8.randomize());    //从256个元素中随机化64次,每次随机化的值都不同
            ua[i] = rc8.val;            //之后将随机化后的值赋值给数组
        end
    endfunction
endclass

pre_randomize主要的功能是:

LittleUniqueArray  lua = new();
    lua.randmozie();

在外部声明句柄lua, 通过句柄调用函数lua.randomize()函数时,先调用pre_randomize,其作用就是把每个值后复制到每个数组中,因为LittleUniqueArray中没有元素被声明为rand。

4.3. 随机化句柄数组

数组里面的每一个元素都指向一个对象,这就是句柄数组。

在这里插入图片描述

parameter MAX_SIZE = 10;
class RandStuff;
    bit[1:0] value = 1;//没有rand,和绿皮书不一样
endclass
class RandArray;
    rand RandStuff array[];//不要忘记使用rand
    constraint c {
        array.size() inside
        {[1:MAX]};
    }
function new();
    //分配最大容量
    array = new[MAX_SIZE];
    foreach (array[i])
        array[i] = new();
    endfunction
endclass
 
RandArray ra;
initial begin
    //构造数组所有对象
ra = new();
    //随机化数组,但是可能会减小数组
assert(ra.randomize());
foreach (ra.array[i])
    $display(ra.array[i].value);
end

问:ra.randomize() with {array.size == 2}的合法求解是多少呢?

分析ra.randomize随机化函数, 首先随机化句柄的个数为2;同时由于 rand RanfStuff array[];语句,因此还需要随机化句柄中的动态数组元素。句柄为randomize表明句柄指向的类中变量,但本例中类中的变量违背randomize修饰,因此该值一直为1。

注:句柄不同悬空。开始要对变量数组分配最大容量,每次new一次对象,让对象中变量得到随机化

五、随机控制

在这里插入图片描述

或者使用随机树。

参考:

Mr.翟的博客

Systemverilog(绿皮书)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值