【IC验证】systemverilog_随机约束

一.注意

随机约束一般只能在类中使用。

二.语法

(1)第一步:

随机的变量需用rand或randc关键字进行修饰;

rand  变量声明;
randc 变量声明;

(2)第二步:

使用约束块约束变量取值范围;

constraint {
	语句1;
	语句2...
	语句n;
}

(3)第三步:

实例化类后,调用randomize方法实现随机约束;

句柄.randomize();

三.rand和randc关键字的不同

(1)说明

rand:代码在一次执行过程中多次使用randomize产生数据,rand修饰的变量的取值,均是在整个约束范围内随机取值的;
randc:代码在一次执行过程中多次使用randomize产生数据,rand修饰的变量的取值,第一次是整个约束范围内随机取值的,第二次是在约束范围内除去第一个值的范围内随机取值的,直至遍历取遍所有值;

(2)例子

class rand1;
    rand int data1;
    //randc int data1;
    constraint c1 {
            data1<3;
            data1>-3;
        }
endclass
module tb;
    rand1 r1;
    initial begin
        r1 =new();
        r1.randomize();
        $display("data1 = %0d",r1.data1);
        r1.randomize();
        $display("data1 = %0d",r1.data1);
        r1.randomize();
        $display("data1 = %0d",r1.data1);
        r1.randomize();
        $display("data1 = %0d",r1.data1);
        r1.randomize();
        $display("data1 = %0d",r1.data1);
        r1.randomize();
        $display("data1 = %0d",r1.data1);
        r1.randomize();
        $display("data1 = %0d",r1.data1);
        r1.randomize();
        $display("data1 = %0d",r1.data1);
    end
endmodule

rand修饰的data1结果:
在这里插入图片描述

randc修饰的data1结果:
在这里插入图片描述

四.常见的随机约束

1. 双向约束

(1)说明:

约束块之间是并行的 ,约束语句之间也是并行;

(2)例子:

class randomize_test;
  rand bit [31:0] src,dst,data[4];
  rand bit [7:0] kind;
  constraint cstr{
    src >10;
    src <15;
  }
  function void print();
    $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
  endfunction
endclass
module tb;
  randomize_test p;
  initial begin
    p = new();
    $display("Before randomize");
    p.print();
    p.randomize();
    $display("After randomize");
    p.print();
  end
endmodule

c结果:
src的取值范围是10<src<15

2.取值范围约束

(1)说明

限制变量取值范围;

(2)语法:

成员变量 inside 取值范围;

(3)例子

A 例子1
代码:

class my_class5;
    rand int data1;
    constraint con5{
        data1 inside {[1:3],[5:8],9};
        };
endclass
module tb5;
    my_class5 c5;
    initial begin
        c5 = new();
        $display("Before randomize data1 = %0d",c5.data1);
        c5.randomize();
        $display("First time randomize out data1 = %0d",c5.data1);
        c5.randomize();
        $display("Second time randomize out data1 = %0d",c5.data1);
        c5.randomize();
        $display("Third time randomize out data1 = %0d",c5.data1);
    end
endmodule

说明:
data1的取值范围设置为1~3,5~8和9;
结果:
在这里插入图片描述
B 例子2
代码:

class my_class6;
    int data1 [4] = {-1,-2,-3,-4};
    rand int data2;
    constraint con6{
        data2 inside {data1,[1:3]};
        };
endclass
module tb6;
    my_class6 c6;
    initial begin
        c6 = new();
        $display("Before randomize data1 = %0d",c6.data2);
        c6.randomize();
        $display("First time randomize out data1 = %0d",c6.data2);
        c6.randomize();
        $display("Second time randomize out data1 = %0d",c6.data2);
        c6.randomize();
        $display("Third time randomize out data1 = %0d",c6.data2);
    end
endmodule

说明:
变量也可作为取值范围;
结果:
在这里插入图片描述

3.内嵌约束

(1)说明:

添加额外的约束;

(2)语法:

实例化随机约束句柄.randmize() with {额外的约束};

(3)例子

class randomize_test;
  rand bit [31:0] src,dst,data[4];
  rand bit [7:0] kind;
  constraint cstr{
   src inside {[1:5],[7:8]};
  }
  function void print();
    $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
  endfunction
endclass
module tb;
  randomize_test p;
  initial begin
    p = new();
    $display("Before randomize");
    p.print();
    p.randomize() with { 5<src;};
    $display("After randomize");
    p.print();
  end
endmodule

c 结果
在这里插入图片描述

4.权重约束

(1)说明:

分配每个取值的权重

(2)语法:

变量名 dist {值:=每个值分配权重,值:/共同分配的权值};

(3)例子

class randomize_test;
  rand bit [31:0] src,dst,data[4];
  rand bit [7:0] kind;
  constraint cstr{
   src dist {[1:3]:/1,[7:8]:=2,10:=5};
  }
  function void print();
    $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
  endfunction
endclass
module tb;
  randomize_test p;
  initial begin
    p = new();
    $display("Before randomize");
    p.print();
    p.randomize();
    $display("After randomize");
    p.print();
  end
endmodule

c 结果
权重分配情况:
1,2,3共同分配1的权重,即每个对应1/3;
7,8每个分配的权重为2;
10分配的权重为5;

5.唯一标识约束

(1)说明

声明后,约束的变量取值不会重复;

(2)语法:

unique {多个成员变量};

(3)例子

class randomize_test;
  rand bit [1:0] src,dst,data[4];
  rand bit [7:0] kind;
  constraint cstr{
      unique {src,dst};
  }
  function void print();
    $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
  endfunction
endclass
module tb;
  randomize_test p;
  initial begin
    p = new();
    $display("Before randomize");
    p.print();
    p.randomize();
    $display("After randomize");
    p.print();
  end
endmodule

c 结果
在这里插入图片描述

6.条件约束

(1)说明

如果条件满足,约束要满足;

(2)语法:

方法一:
条件 -> 约束;
方法二:
if(条件1)
约束1;
else if(条件2)
约束2;
else
约束3;

(3)例子

在这里插入图片描述

7.动态数组的长度约束

(1)说明

约束动态数组的长度;

(2)语法:

动态数组名.size() 约束;//可以使用各种约束,比如取值范围约束

(3)例子

例子1:

class randomize_test;
  rand bit [31:0] src,dst,data[];
  rand bit [7:0] kind;
  constraint cstr{
      data.size < 5;
  }
  function void print();
    $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
  endfunction
endclass
module tb;
  randomize_test p;
  initial begin
    p = new();
    $display("Before randomize");
    p.print();
    p.randomize();
    $display("After randomize");
    p.print();
  end
endmodule

c 结果
在这里插入图片描述
例子二:

class my_class8;
    rand int data1 [];
    constraint con8{
        data1.size < 5;
        foreach(data1[j]) data1[j]<20;
        foreach(data1[j]) data1[j]>0;
        };
endclass
module tb8;
    my_class8 c8;
    initial begin
        c8 = new();
        $display("Before randomize data1 = %p",c8.data1);
        repeat(8)begin
            c8.randomize();
            $display("Afte randomize data1 = %p",c8.data1);
        end
    end

endmodule

在这里插入图片描述

8.软约束

(1)说明

当多个约束冲突时,可以用soft关键字修饰(soft表示软约束,默认是硬约束),当软约束和硬约束冲突时会优先执行硬约束;
一般:底层约束用soft关键字修饰,额外的约束用硬约束;
注意:
soft关键字修饰的是约束语句,不是约束块;
硬约束和硬约束冲突时,约束失败;
硬约束和软约束冲突时,执行硬约束;
软约束和软约束冲突时,会就近执行;(后写的:with额外约束 -> 子类约束 ->父类约束)

(2)例子

class randomize_test;
  rand bit [31:0] src,dst,data[4];
  rand bit [7:0] kind;
  constraint cstr{
      soft src inside {[1:5]};
  }
  function void print();
    $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p",src,dst,kind,data);
  endfunction
endclass
module tb;
  randomize_test p;
  initial begin
    p = new();
    $display("Before randomize");
    p.print();
    p.randomize() with{src inside {[6:10]};};
    $display("After randomize");
    p.print();
  end
endmodule

c 结果
在这里插入图片描述

9.数组的迭代约束

(1)说明

对一定长度的数组各成员进行约束,可以搭配foreach实现;

(2)语法

foreach(数组[索引])
每个成员的约束;

(3)例子

代码:

class my_class7;
    rand int data1[4];
    constraint con7{
            foreach(data1[i])    
                data1[i] > (2*i);
            foreach(data1[i])
                data1[i] < 20;
        };
endclass
module tb7;
    my_class7 c7;
    initial begin
        c7 = new();
        $display("Before randomize data1 = %p",c7.data1);
        c7.randomize();
        $display("First time randomize out data1 = %p",c7.data1);
        c7.randomize();
        $display("Second time randomize out data1 = %p",c7.data1);
        c7.randomize();
        $display("Third time randomize out data1 = %p",c7.data1);

    end
endmodule

结果:
在这里插入图片描述

五.特殊知识点

1.使用系统函数产生随机数

(1)语法

$urandom(): 随机产生一个32位无符号数;
$urandom_range(maxval,minval):在指定范围内随机产生一个32位无符号数;

(2)例子

module tb1;
   initial begin
        $display("$urandom() data = %0d",$urandom());
        $display("$urandom_range() data =%0d",$urandom_range(5,3));
   end
endmodule

在这里插入图片描述

2.使用系统内建包(std)实现指定成员的随机化

(1)语法

std::randomize(成员1,成员2...);

(2)例子

module tb2;
    int data1;
    int data2;
    initial begin
        $display("Before randomize: data1 = %0d,data2 = %0d",data1,data2);
        std::randomize(data1,data2);
        $display("After randomize: data1 = %0d,data2 = %0d",data1,data2);
    end
endmodule

结果:
在这里插入图片描述

(3)补充

此方法也可以添加内嵌约束;
语法:

std::randomize(成员1,成员2...)with{
	约束1...
	约束n;
};

例子:

module tb2;
    int data1;
    int data2;
    initial begin
        $display("Before randomize: data1 = %0d,data2 = %0d",data1,data2);
        std::randomize(data1,data2) with {
                data1 <5;
                data1 >1;
            };
        $display("After randomize: data1 = %0d,data2 = %0d",data1,data2);
    end
endmodule

结果:
在这里插入图片描述

3.使用系统内建包(std)实现结构体的随机化

(1)说明

需先将需要随机化的成员用rand或randc关键字进行修饰;

(2)例子

代码:

typedef struct{
    rand int data1;
    rand int data2;
    }m_struct;
module tb3;
    m_struct s1;
    initial begin
        $display("before randomize: data1 = %0d,data2 = %0d",s1.data1,s1.data2);
        std::randomize(s1);
        $display("after randomize: data1 = %0d,data2 = %0d",s1.data1,s1.data2);
    end
endmodule

结果:
在这里插入图片描述

4.内嵌约束的变量的索引原则

(1)原则

变量索引满足就近原则,先在定义当前随机约束类中查找,然后再在当前随机约束语句作用的区域内查找;
要索引到当前随机约束语句作用的方法中的同名成员,使用关键字local::变量名
this关键字索引的区域为定义当前随机约束语句类的内部,要索引到当前随机约束语句作用的类中的同名成员,使用关键字locall::this.变量名

(2)例子

例子1:
代码:

class my_class11;
    rand int x;
    constraint con11{
        x > 0;
       };
endclass
class my_class12;
    int x;
    int y;
    task doit(my_class11 c11,int x,int z);
        c11.randomize() with {
            x<y+z;
            };
        $display("c11.x = %0d,x = %0d,z = %0d,y = %0d,this.x = %0d",c11.x,x,z,y,this.x);
    endtask
endclass
module tb11;
    my_class11 c11;
    my_class12 c12;
    initial begin
        c11 = new();
        c12 = new();
        c12.doit(c11,10,15);
    end
endmodule

注意:(语句x<y+z为例)
内嵌约束变量索引满足就近原则,变量会优先找约束语句所在的类(x为当前随机约束语句定义的类c11中的随机约束的x),然后再找作用域内(z对应doit任务的参数,y对应myclass的成员y);
在这里插入图片描述
结果:
在这里插入图片描述
例子2:
代码:
在这里插入图片描述
结果:
在这里插入图片描述
例子3:
在这里插入图片描述
结果:
在这里插入图片描述

六.随机约束的控制

(1)简介

随机约束的整体或局部的开启或关闭;

(2)变量随机特性的控制1

(a)语法

随机约束实例化句柄名.rand_mode(控制值); //所有变量随机特性的开启或关闭,控制值0表示关闭1表示开启;
随机约束实例化句柄名.变量名.rand_mode(控制值);//指定变量随机特性的开启或关闭,控制值0表示关闭1表示开启;

(b)例子

代码


class my_class15;
    rand int x;
    rand int y;
endclass
module tb15;
    my_class15 c15;
    initial begin
        c15 = new();
        $display("First time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
        c15.rand_mode(0);
        c15.randomize();
        $display("First time:After randomize x = %0d, y = %0d",c15.x,c15.y);
        
        c15 = new();
        $display("Second time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
        c15.rand_mode(1);
        c15.randomize();
        $display("Second time:After randomize x = %0d, y = %0d",c15.x,c15.y);
        
        c15 = new();
        $display("Third time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
        c15.x.rand_mode(0);
        c15.y.rand_mode(1);
        c15.randomize();
        $display("Third time:After randomize x = %0d, y = %0d",c15.x,c15.y);
    end
endmodule

结果:
在这里插入图片描述

(c)问题

描述:定义了多个变量的随机和约束特性,关闭一个变量的随机特性,所有变量的随机约束特性都被关闭了;
例子:

class my_class15;
    rand int x;
    rand int y;
    constraint con15_1{
        x inside {[3:10]};
        }
    constraint con15_2{
        y inside {[3:10]};
        }
endclass
module tb15;
    my_class15 c15;
    initial begin
        c15 = new();
        $display("First time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
        c15.rand_mode(0);
        c15.randomize();
        $display("First time:After randomize x = %0d, y = %0d",c15.x,c15.y);
        
        c15 = new();
        $display("Second time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
        c15.rand_mode(1);
        c15.randomize();
        $display("Second time:After randomize x = %0d, y = %0d",c15.x,c15.y);
        
        c15 = new();
        $display("Third time:Before randomize x = %0d, y = %0d",c15.x ,c15.y);
        c15.x.rand_mode(0);
        c15.y.rand_mode(1);
        c15.randomize();
        $display("Third time:After randomize x = %0d, y = %0d",c15.x,c15.y);
    end
endmodule

结果:
在这里插入图片描述

(3)变量随机特性的控制2

(a)语法

随机约束类句柄.randomize(); //按照随机约束类定义,决定随机变量
随机约束类句柄.randomize(变量1,…,变量n); //指定变量为随机变量

(b)例子

class my_class16;
    rand int x;
    rand int y;
    int w,z;
    constraint con16{
        (x < w && y>w);
        }
endclass
module tb16;
    my_class16 c16;
    initial begin
        c16 = new();
        $display("Before randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
        c16.randomize();
        $display("First time:After randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
        c16.randomize(x);
        $display("Second time:After randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
        c16.randomize(w,z);
        $display("Third time:After randomize x = %0d, y = %0d, w = %0d, z = %0d",c16.x ,c16.y,c16.w,c16.z);
    end
endmodule

结果:
第一次randomize随机约束类定义的x、y是随机变量,第二次randomize指定的x是随机变量,第三次randomize指定的w、z是随机变量。
在这里插入图片描述

(4)约束的控制

(a)语法

随机约束实例化句柄名.constraint_mode(控制值); //所有约束的开启或关闭,控制值0表示关闭1表示开启;
随机约束实例化句柄名.约束块名.constraint_mode(控制值);//指定约束块的开启或关闭,控制值0表示关闭1表示开启;

(b)例子

代码:

class my_class17;
    rand int x,y;
    constraint con1 {
         x > 0;
         y > 0;
        }
    constraint con2{
            x < 15;
            y < 15;
        }
endclass
module tb17;
    my_class17 c17;
    initial begin
        c17 = new();
        $display("First time:Before randomize x = %0d, y = %0d",c17.x ,c17.y);
        c17.randomize();
        $display("First time:After randomize x = %0d, y = %0d",c17.x ,c17.y);
        
        c17 = new();
        $display("Second time:Before randomize x = %0d, y = %0d",c17.x ,c17.y);
        c17.constraint_mode(0);
        c17.randomize();
        $display("Second time:After randomize x = %0d, y = %0d",c17.x ,c17.y);

        c17 = new();
        $display("Third time:Before randomize x = %0d, y = %0d",c17.x ,c17.y);
        c17.con1.constraint_mode(1);
        c17.con2.constraint_mode(0);
        c17.randomize();
        $display("Third time:After randomize x = %0d, y = %0d",c17.x ,c17.y);

    end
endmodule

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值