随机化 | Systemverilog 笔记 5

Posted by Kion on January 21, 2020

为什么要随机化?

随着设计复杂度的增加,验证的难度也会增加。这体现在激励的角度上,就是需要尽可能多样的激励进行验证。如果人为的去增加各种激励,显然工作量非常大,所以要采用随机化的方法。用受约束随机的手段,尽可能多地覆盖各种激励。

需要随机化的方面有器件配置;环境配置;原始输入数据;封装后的输入数据;协议异常;延时;事务状态;错误和违规。

如何随机化?

建立具有随机变量及其约束的类,然后利用随机函数对其赋值。

class rnd;/*一个带有随机变量的类*/
    rand bit [31:0] data0;
    randc bit [7:0] data1; /*randc类型会在所有可能值出现后才有重复值*/
    /*变量的约束*/
    constraint c {data0 > 20; /*约束中一个关系式只有一个关系操作符;表达式并行*/
                  data0 < 50;}
endclass

rnd r1;
initial begin
    r1 = new();
    r1.randomize(); /*随机化这个对象*/
end

约束的多样性

可以利用dist操作符对随机值施加权重。权重之和不一定是100。如下列代码,data为25的概率是40/140;31~35每个值的概率是20/140。

constraint c {
    data dist {25:=40; [31:35]:/100}; /*:= 指权重均为某值;:/指权重为某值的平均数*/
}

可以用inside运算符指定随机值的集合。

int low = 20,high = 50;
constraint c {
    data inside {[low:high],[10:40]};/*也可以用$符号指定最大最小值*/
}
constraint copp {
    !(data inside {[low:high],[10:40]});/*可以取反*/
}

可以用if-else语句及->操作符进行条件约束。

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

class BusOp;
    constraint c_io {
        (io_space_mode) -> 
        addr[31] = 1'b1;
    }
endclass

可以用内建的constraint_mode()控制约束的生效与否。

BusOp.constraint_mode(0);/*约束全部禁止*/
BusOp.c_io.constraint_mode(1);/*开启约束*/
BusOp.op.rand_mode(0);/*设置参数为非随机数*/
BusOp.randomize(op);/*只随机化op*/

可以在randomize()语句后用wit{}语句添加内嵌约束。

assert(BusOp.randomize() with {len > 10;});

可以用pre_randomize()及post_randmize()进行随机化前后处理。

对于数组的约束,可以利用foreach进行单个元素约束,也可以用操作数组的函数进行整体约束,比如sum。

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