Verilog 随机数及概率分布

在 Verilog 中生成随机数及实现特定的概率分布主要用于仿真(simulation),因为硬件综合(synthesis)通常不直接支持随机数生成器。本文将介绍 Verilog 中随机数的生成方法、常用系统函数,以及如何实现特定的概率分布(如均匀分布、伯努利分布等)。


1. Verilog 中的随机数生成

Verilog 提供了一些内置系统任务用于生成伪随机数,主要用于仿真环境。以下是常用的随机数生成方法:

1.1 $random 函数

$random 是 Verilog 中最基本的随机数生成函数,返回一个 32 位有符号整数,其值在 [-2^31, 2^31-1] 范围内。

integer rand_num;

initial begin
    rand_num = $random; // 生成随机整数
    $display("Random number: %d", rand_num);
end
  • 特点$random 生成的随机数是伪随机的,依赖于仿真器的种子(seed)。每次运行仿真时,若不设置种子,结果可能是可重复的。
  • 控制种子:可以使用 $urandom 或设置种子来改变随机序列:
initial begin
    $srandom(42); // 设置随机种子为 42
    rand_num = $random;
    $display("Random number with seed: %d", rand_num);
end

1.2 $urandom 函数

$urandom 是 SystemVerilog 引入的函数,返回一个 32 位无符号整数([0, 2^32-1])。相比 $random,它更常用且更现代化。

logic [31:0] urand_num;

initial begin
    urand_num = $urandom; // 生成无符号随机数
    $display("Unsigned random number: %0d", urand_num);
end
  • 范围限制:可以用取模运算将随机数限制在特定范围内:
logic [7:0] limited_rand;

initial begin
    limited_rand = $urandom % 256; // 生成 0 到 255 的随机数
    $display("Random number (0-255): %0d", limited_rand);
end

1.3 $urandom_range 函数

SystemVerilog 提供的 $urandom_range(min, max) 返回指定范围 [min, max] 内的随机整数。

integer rand_range;

initial begin
    rand_range = $urandom_range(10, 20); // 生成 10 到 20 的随机整数
    $display("Random number in range [10, 20]: %d", rand_range);
end

2. 实现特定概率分布

在 Verilog 中,$random$urandom 默认生成均匀分布的随机数。如果需要其他概率分布(如伯努利分布、正态分布等),需要通过算法实现。以下是常见概率分布的实现方法:

2.1 均匀分布

$urandom$urandom_range 默认生成均匀分布的随机数,适用于大多数仿真场景。例如,生成 0 到 99 的均匀随机数:

initial begin
    integer i;
    repeat (10) begin
        i = $urandom % 100; // 均匀分布在 [0, 99]
        $display("Uniform random: %d", i);
    end
end

2.2 伯努利分布

伯努利分布是一种二值分布(0 或 1),适合模拟概率事件(如成功/失败)。例如,生成概率为 p = 0.3 的伯努利分布:

real p = 0.3; // 概率 p
logic bernoulli;

initial begin
    repeat (10) begin
        bernoulli = ($urandom % 100) < (p * 100); // 0 到 99 的随机数,<30 表示成功
        $display("Bernoulli (p=0.3): %b", bernoulli);
    end
end
  • 说明:将 $urandom % 100 映射到 [0, 99],然后与概率阈值比较。

2.3 二项分布

二项分布可以看作多次伯努利试验的和。例如,模拟 n=10 次试验,每次成功概率 p=0.3:

integer n = 10;
real p = 0.3;
integer successes;

initial begin
    successes = 0;
    repeat (n) begin
        if (($urandom % 100) < (p * 100)) begin
            successes = successes + 1; // 统计成功次数
        end
    end
    $display("Binomial successes (n=10, p=0.3): %d", successes);
end

2.4 正态分布(近似)

Verilog 本身不支持直接生成正态分布,但可以通过 中心极限定理近似实现。将多个均匀分布的随机数求和,近似得到正态分布:

integer n = 12; // 累加次数
real sum;
integer i;

initial begin
    sum = 0.0;
    repeat (n) begin
        sum = sum + ($itor($urandom % 100) / 100.0); // 累加 [0, 1) 的均匀随机数
    end
    sum = sum - n / 2.0; // 中心化,近似正态分布
    $display("Approximate normal distribution: %f", sum);
end
  • 说明:通过累加多个均匀分布随机数并中心化,可以近似正态分布。n 越大,近似效果越好。

2.5 指数分布

指数分布可通过均匀分布的逆变换法生成。公式为:X = -ln(U) / λ,其中 U 是 [0, 1] 的均匀随机数,λ 是速率参数。

real lambda = 1.0; // 速率参数
real u, exp_dist;

initial begin
    u = $itor($urandom) / 4294967295.0; // 归一化到 [0, 1]
    exp_dist = - $ln(u) / lambda; // 指数分布
    $display("Exponential distribution: %f", exp_dist);
end
  • 注意:需要 $ln 函数支持(SystemVerilog 提供),且仿真器需支持数学函数。

3. 硬件中的随机数生成

在硬件设计中,$random$urandom 不可综合,因此需要使用硬件随机数生成器(如 线性反馈移位寄存器 LFSR)来生成伪随机数。

LFSR 示例

以下是一个简单的 8 位 LFSR 实现:

module lfsr (
    input clk,
    input rst,
    output reg [7:0] rand_out
);
    always @(posedge clk or posedge rst) begin
        if (rst)
            rand_out <= 8'h1; // 非零初始值
        else
            rand_out <= {rand_out[6:0], rand_out[7] ^ rand_out[5] ^ rand_out[4] ^ rand_out[3]}; // 特征多项式
    end
endmodule
  • 说明:LFSR 通过移位和异或操作生成伪随机序列,适用于硬件实现。
  • 概率分布:LFSR 默认生成均匀分布,可通过后续逻辑处理实现其他分布。

4. 注意事项

  • 仿真 vs. 综合$random$urandom$urandom_range 仅用于仿真环境。硬件实现需要 LFSR 或其他硬件随机数生成器。
  • 种子控制:使用 $srandom(seed) 设置种子,确保仿真可重复性。
  • 精度:实数运算(如正态分布、指数分布)需要 SystemVerilog 的数学函数支持,且可能不可综合。
  • 概率分布实现:复杂分布(如正态分布)在硬件中实现成本高,建议使用查找表(LUT)或预计算值。
  • 工具支持:确保仿真器(如 ModelSim、VCS)或综合工具(如 Synopsys DC)支持相关函数。

5. 总结

  • 随机数生成:使用 $random(有符号整数)、$urandom(无符号整数)或 $urandom_range(指定范围)。
  • 概率分布
  • 均匀分布:直接使用 $urandom$urandom_range
  • 伯努利分布:通过阈值比较实现。
  • 二项分布:多次伯努利试验累加。
  • 正态分布:通过中心极限定理近似。
  • 指数分布:使用逆变换法。
  • 硬件实现:使用 LFSR 或其他硬件随机数生成器,配合逻辑实现特定分布。

如果有具体的随机数生成或概率分布需求(例如特定的分布参数或硬件约束),请提供更多细节,我可以进一步优化代码或方案!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注