SystemVerilog 提供以下系统函数和方法来生成随机数:
$urandom()
$urandom_range()
srandom()
get_randstate()
set_randstate()
$urandom( ) 函数提供了一种生成伪随机值的机制。调用时会返回一个无符号的 32 位随机数。
function int unsigned $urandom [(int seed)];
请注意,“seed”是一个可选参数,用于确定生成的随机数序列。这是为了随机数生成的可预测性。换句话说,每次使用相同的种子时都会生成相同的随机数序列。 “seed”对于每次运行都需要使用相同的随机数序列的回归运行非常重要。每次运行仿真时提供一个新种子将会提供一组不同的随机数。
还有 $urandom_range 函数返回指定范围内的无符号整数。
function int unsigned $urandom_range(int unsigned maxval, int unsigned minval);
如果 maxval 小于 minval,则数字生成器会自动反转参数,使第一个参数大于第二个参数。如果只提供 1 个值,如 $urandom(15),那么将获得 15…0 范围内的数字。
看一个示例:
module random; integer in1, in2, sin1; bit [63:0] bi1; int seed,i1; initial begin $display("\n$urandom( ) – same seed"); seed=1234; repeat (4) begin //same seed through each iteration in1 = $urandom(seed); //with seed in2 = $urandom & 'h0000_00ff; //Mask top 24-bits bi1 = {$urandom, $urandom}; //64-bit random number $display("in1=%0h in2=%0h bi1=%0h",in1,in2,bi1); #1; end $display("\n$urandom( ) – changing seed"); seed=1234; repeat (4) begin seed=seed+1; //different seed through each iteration in1 = $urandom(seed); //with seed in2 = $urandom & 'h0000_00ff; //Mask top 24-bits bi1 = {$urandom, $urandom}; //64-bit random number $display("in1=%0h in2=%0h bi1=%0h",in1,in2,bi1); #1; end $display("\n$urandom_range( )"); repeat (4) begin in1 = $urandom_range(15,7); //max_value > min_value in2 = $urandom_range(0,15); //max_value < min_value bi1 = $urandom_range(7); //No min_value. So, 7...0 $display("in1=%0d in2=%0d bi1=%0d",in1,in2,bi1); end process::self().srandom(1234); in1 = $urandom; // seed set by srandom $display("in1=%h",in1); end endmodule
仿真结果:
Compiler version S-2021.09; Runtime version S-2021.09; Aug 28 10:53 2022 $urandom( ) ? same seed in1=d473f645 in2=ce bi1=46d3933a17f96ab4 in1=d473f645 in2=ce bi1=46d3933a17f96ab4 in1=d473f645 in2=ce bi1=46d3933a17f96ab4 in1=d473f645 in2=ce bi1=46d3933a17f96ab4 $urandom( ) ? changing seed in1=f7c14f9 in2=8e bi1=d4d64b41c99e7e59 in1=4ae225b5 in2=ef bi1=59fa737b1b1b34a0 in1=30310970 in2=18 bi1=cfb535dbb9987038 in1=8de5b5bf in2=4c bi1=f16b5c1f826512c5 $urandom_range( ) in1=12 in2=2 bi1=4 in1=8 in2=9 bi1=7 in1=11 in2=1 bi1=0 in1=14 in2=1 bi1=7 in1=d473f645 V C S S i m u l a t i o n R e p o r t
SystemVerilog中负责生成随机值的元素称为Random Number Generator,缩写为RNG。每个线程、包、模块实例、程序实例、接口实例或类实例都有一个内置的 RNG。线程、模块、程序、接口和包 RNG 用于为 $urandom()(以及 $urandom_range()、randomize()、randsequence、randcase 和 shuffle())选择随机值,并初始化子线程或子类实例。类实例 RNG 专门用于选择类的预定义 randomize() 方法(Ahmed Yehia,Mentor Graphics)返回的值。
每当一个 RNG 用于选择一个随机值或用于初始化另一个 RNG 时,它都会“改变状态”,以便它生成的下一个随机数是不同的。因此,特定随机调用生成的随机值取决于 RNG 的使用次数及其初始化。反过来,初始化 RNG 取决于其父 RNG 已被使用的次数以及父 RNG 初始化。最顶层的 RNG 始终是模块、程序、接口或包 RNG,所有这些 RNG 都初始化为相同的值,由模拟器根据模拟种子选择。对于一个约束,给定 randomize() 调用,该过程在分配对象之前基本上是相同的。一旦分配了对象,它就会获得自己的 RNG,与包、模块、程序、接口或线程 RNG 不同,它仅在调用 randomize() 时更改状态。因此,从实例化点开始,影响给定 randomize() 调用结果的唯一指令是较早的 randomize() 调用。