Verilog 随机数及概率分布
Verilog 教程高级篇
随机数
Verilog 中使用系统任务 $random(seed) 产生随机数,seed 为随机数种子。
seed 值不同,产生的随机数也不同。如果 seed 相同,产生的随机数也是一样的。
可以为 seed 赋初值,也可以忽略 seed 选项,seed 默认初始值为 0。
不使用 seed 选项和指定 seed 并对其修改来调用 $random 的代码如下所示:
实例
//seed var
integer seed ;
initial begin
seed = 2 ;
#30 ;
seed = 10 ;
end
//no seed
reg [15:0] randnum_noseed ;
always@(posedge clk) begin
randnum_noseed <= $random(); //不指定随机种子
end
//with seed
reg [15:0] randnum_wtseed ;
always@(posedge clk) begin
randnum_wtseed <= $random(seed); //指定随机种子
end
仿真波形图如下。
无论是否赋初值,每产生一次随机数后,seed 值改变,随机数也随之改变。
每改变一次 seed 值,当前输出的随机值会改变;但是下一个状态时,随机数的走向又恢复成系统内部产生的随机序列。
例如仿真图中 t1 和 t2 时刻随机种子不同,产生是随机数也不同。但是其他时钟周期,产生的随机数都是相同的。
建议调用系统任务 $random 时,不指定 seed 选项,或指定 seed 选项时使用变量传递参数。
不建议调用 $random 时,将常数项写到 seed 参数处。此时 seed 值被固定,可能只会产生一个随机数。例如以下写法是不建议的:
randnum_wtseed <= $random(2); //不建议将常数项指定给 seed
可以使用取余的方法,将随机数限定在一定的数据范围内。例如:
实例
//with a range
parameter MAX_NUM = 512;
parameter MIN_NUM = 256;
reg [15:0] num_range1, num_range2, num_range3 ;
always@(posedge clk) begin
//产生的随机数范围为 -511 ~ 511, ±(MAX_NUM-1)
num_range1 <= $random() % MAX_NUM;
//产生的随机数范围为 0 ~ 511, (0 ~ MAX_NUM-1)
num_range2 <= {$random()} % MAX_NUM;
//产生的随机数范围为 MIN_NUM ~ MAX_NUM,包含边界
num_range3 <= MIN_NUM + {$random()} % (MAX_NUM-MIN_NUM+1);
end
随机数按照有符号、十进制格式显示,前几个数据结果如下:
概率分布
Verilog 提供了许多按一定概率分布产生数据的系统任务,简单描述如下:
系统任务 | 调用格式 | 任务描述 |
---|---|---|
均匀分布 | $dist_uniform(seed, start, end); | start、end 为数据的起始、结尾 |
正态分布 | $dist_normal (seed, mean, std_dev); | mean 为期望值,std_dev 为标准差 |
泊松分布 | $dist_po |