在进行验证已编写过的模块时,我们往往需要一些随机的测试方法来检测隐藏的漏洞。

sv相比于verilog而言,在随机化上则是非常有力,有许多关于随机化的操作。

===================================================

一 随机数据:

一般而言随机化的操作都是需要封装成为类的。

class Bus;
    rand  bit[15:0] addr;
    rand  bit[31:0] data;
    constraint word_align {addr[1:0] == 2’b0;}
endclass

这是个简单的例子,只要在类的数据类型前加上了rand或者randc,那么只要对这个类的实例化

对象调用randomize()方法,这些带有rand与randc的数据类型则是会被随机化。

但往往随机化并非完全的随机化,很多时候需要有一定的限制,所以还需要使用constraint语句

构造约束条件。

其中约束有很多种:

(1)表达式约束:

constraint word_align {addr[1:0] == 2’b0;   data < 32 }

(2)条件约束:

class MyBus extends Bus;
    rand AddrType atype;
    constraint addr_range
   {
        (atype == low ) -> addr inside { [0 : 15] };
        (atype == mid ) -> addr inside { [16 : 127]};
        (atype == high) -> addr inside {[128 : 255]};
        //   (  先前的条件 )-> (相应的约束)
   }
endclass

条件约束可以使用->的方式也可以使用if-else的方式。只有当先前的条件满足时才可以进行后面的约束。

(3)嵌套约束:

task    exercise_bus (MyBus bus);
    int  res;
    // EXAMPLE 1: restrict to low addresses 
    res = bus.randomize() with {atype == low;}; 
    // EXAMPLE 2: restrict to address between 10 and 20
    res = bus.randomize() with {10 <= addr && addr <= 20;};
   // EXAMPLE 3: restrict data values to powers-of-two
    res = bus.randomize() with {data & (data - 1) == 0;};
endtask

在randomize()方法后使用with { } 加入约束的条件。

(4)权重约束:

x dist { [100:102] := 1, 200 := 2, 300 := 5}   //    其中在:=前的每个元素的权重值都为:=后的值
x dist { [100:102] :/ 1, 200 :/ 2, 300 :/ 5}     //    其中在:/前的每个元素平分:/后的权重值

二 随机序列:

randsequence ( main )
main     : first second done ;   //   从main处顺序执行 first second done
first    : add | dec ;           //   执行add  或者 dec
second    : pop | push ;
done     : { $display("done"); } ;
add      : { $display("add");  } ;
dec      : { $display("dec");  } ;
pop      : { $display("pop");  } ;
push     : { $display("push"); } ;
endsequence

三 决策树:

randcase
    3 : x = 1;     //    :前的值为相应的权重
    1 : x = 2;
    4 : x = 3;
    6 : randcase 
            4 :  x = 4 ;
            5 :  x = 5 ;
        endcase
endcase