关于systemverilog中的随机化的使用

在 SystemVerilog 中,有两种主要的随机化方法:

  1. 类的 randomize() 方法 - 只能在 class 中使用

  2. 全局的 std::randomize() 函数 - 可以在任何地方使用

1、std::randomize

std::randomize 是 SystemVerilog 提供的轻量级随机化接口 ,区别于 class 内的 randomize() 方法,它无需定义类 / 约束块,可直接对任意变量(包括模块内的 reg/wire、局部变量)进行随机化,特点:

  1. 无类依赖:直接作用于变量,无需封装成类,适合简单随机场景;
  2. 动态约束:支持 inline(内联)约束,灵活控制随机值范围;
  3. 类型兼容:支持整数、实数、枚举、数组等几乎所有 SystemVerilog 类型;
  4. 返回值判断 :返回 1 表示随机化成功,0 表示约束冲突 / 失败,便于错误处理

std::randomize()是一个内置函数,它不需要在类中调用,也不依赖于类的rand修饰符。它可以直接对任何变量进行随机化,只要这些变量是可赋值的。

复制代码
//*********第一个例子**********//
module test;
  int addr;
  bit [3:0] data;
  enum {READ, WRITE, IDLE} op;

  initial begin
    // 约束1:addr在0~1023之间,且为16的倍数
    if (!std::randomize(addr) with {addr >= 0; addr < 1024; addr % 16 == 0;}) begin
      $error("addr randomize failed!"); // 约束冲突时报错
    end
    $display("addr = %0d", addr); // 输出如 16/32/128 等

    // 约束2:data>5,且op不为IDLE
    std::randomize(data, op) with {
      data > 5;
      op != IDLE;
    };
    $display("data = %0d, op = %s", data, op.name()); // data:6~15,op:READ/WRITE
  end
endmodule


//*********第二个例子**********//
module test;
  int arr[5]; // 5元素整数数组

  initial begin
    // 约束:数组元素都在0~100之间,且总和<200,第一个元素>最后一个
    std::randomize(arr) with {
      foreach (arr[i]) arr[i] inside {[0:100]}; // 每个元素0~100
      sum(arr) < 200; // 数组总和<200
      arr[0] > arr[4]; // 第一个元素>最后一个
    };
    $display("arr = %p", arr); // 输出如 '{90, 10, 20, 30, 80}
  end
endmodule
与类内 randomize() 的区别
特性 std::randomize 类内 randomize()
依赖 无类依赖,直接用 需定义类 + 约束块
约束 内联约束(临时) 类内约束块(可重载)
复用性 低(约束随用随写) 高(约束封装在类中)
适用场景 简单随机、临时激励 复杂测试用例、可复用激励

2、randomize

在类中,我们可以声明rand或randc修饰的变量,然后调用该类的randomize()方法来随机化这些变量

复制代码
class pkt;
  rand int addr;
  rand bit [7:0] data;

  // 软约束:addr默认0~1023,data默认0~200
  constraint c_default {
    soft addr inside {[0:1023]}; // 软约束:地址默认范围
    soft data <= 200;            // 软约束:数据默认上限
    data >= 0;                   // 硬约束:数据下限不可覆盖
  }
endclass


module test;
  pkt p = new();

  initial begin
    p.randomize();//****注意****,这里是使用的pkt类的句柄进行随机化的
    $display("默认约束:addr=%0d, data=%0d", p.addr, p.data); // addr:0~1023,data:0~200

    if (!p.randomize() with {
      addr inside {[2000:3000]}; // 覆盖soft addr约束
      data == 250;               // 覆盖soft data <=200约束
    }) begin
      $error("随机化失败");
    end
    $display("覆盖后:addr=%0d, data=%0d", p.addr, p.data); // addr:2000~3000,data=250

    if (!p.randomize() with {
      data < 0; // 与硬约束data>=0冲突
    }) begin
      $error("硬约束冲突,随机化失败"); // 触发报错
    end
  end
endmodule
相关推荐
蓝天下的守望者3 天前
SystemVerilog中 `timescale的使用问题
systemverilog·uvm·vcs
Chef Chip13 天前
定宽数组的随机约束
systemverilog·数字ic验证
北方孤寂的灵魂24 天前
systemverilog中随机std::randomize的用法
verilog·systemverilog·sv·数字验证
蓝天下的守望者25 天前
由continue引发的一个debug灾难
算法·systemverilog
蓝天下的守望者1 个月前
systemverilog系统函数$test$plusargs和$value$plusargs
systemverilog·芯片验证
lbt_dvshare1 个月前
MTCMOS flow
systemverilog
蓝天下的守望者1 个月前
systemverilog中的virtual function
systemverilog
Nick.Q1 个月前
$cast用法
systemverilog
不会武功的火柴1 个月前
UVM验证入门(18)-Callback机制
systemverilog·ic验证·uvm方法学