如何在 VHDL 中生成随机数
VHDL 有一个内置的伪随机生成器,但它只能生成介于 0 和 1 之间的浮点数。幸运的是,您可以从中派生出您应该需要的任何其他类型的随机数据格式。继续阅读本文以了解如何生成 real
或 integer
任何范围的值,以及随机的 std_logic_vector
序列和 time
价值观。
uniform
IEEE MATH_REAL 包中的过程是本文描述的算法的基础。请注意 uniform
依靠软件生成随机数。因此,这些算法都不是可综合的。您只能在测试平台中使用它们。
procedure UNIFORM(variable SEED1, SEED2 : inout POSITIVE; variable X : out REAL);
上面的清单显示了 uniform
的原型 程序。它需要两个种子变量才能工作,并且每次调用过程时都会修改它们。输出 X 是随机数,其值始终介于 0 和 1 之间。
就像其他伪随机数生成器一样,uniform
当使用相同的初始种子值调用时,将生成相同的数字序列。由于这种行为,您可以在使用相同的种子值时重新运行测试台并获得相同的结果。
请参阅 Pierre L'Ecuyer 撰写的 Efficient and Portable Combined Random Number Generators 论文,了解该算法如何工作的详细说明。也可以在GHDL开源VHDL模拟器中查看算法的实际实现。
测试用例
本文中的所有示例都将值 999 用于两个种子。我们在进程的声明区域中声明种子变量,如下所示。然后,我们在同一进程中将自定义随机化算法实现为不纯函数。
variable seed1, seed2 : integer := 999;
您可以使用下面的表格下载包含本文中所有示例的完整测试平台。 Zip 文件还包含一个 ModelSim 项目,其中包含一个为您编译和运行仿真的脚本。
随机实数值
uniform
程序生成一个随机的real
值介于 0.0 和 1.0 之间。 real
type 是 VHDL 的浮点格式。但是,您可能希望随机数在不同的范围内。
impure function rand_real(min_val, max_val : real) return real is variable r : real; begin uniform(seed1, seed2, r); return r * (max_val - min_val) + min_val; end function;
幸运的是,我们可以轻松地翻译 uniform
的输出 通过乘以比例并为其添加偏移量。上面的代码显示了一个返回随机 real
的函数 最小/最大范围内的值。
随机整数值
生成随机 integer
指定范围内的值,您必须乘以比例并为其添加偏移量。但是有一个陷阱是你必须避免的。您不能简单地生成随机 real
范围内的值并将其四舍五入为 integer
.
上图显示了问题。在示例中,我们打算生成一个随机的 integer
值在 -1 到 1 的范围内。如果我们基于 integer
随机 real
精确到端点,最小和最大整数仅获得被选择概率的一半。四舍五入到 0 integer
即使有三个数字选择,价值也会发生一半。
impure function rand_int(min_val, max_val : integer) return integer is variable r : real; begin uniform(seed1, seed2, r); return integer( round(r * real(max_val - min_val + 1) + real(min_val) - 0.5)); end function;
在上面的代码中,我们通过调整随机 real
来纠正端点舍入问题 值以在端点上方和下方包含额外的 0.5。
随机标准逻辑向量
有很多方法可以用随机值填充向量,但这种方法适用于任意长度的向量。我正在使用 for 循环遍历向量并为每一位选择一个随机值。在下面的代码中,len
参数决定随机std_logic_vector
的长度 返回。
impure function rand_slv(len : integer) return std_logic_vector is variable r : real; variable slv : std_logic_vector(len - 1 downto 0); begin for i in slv'range loop uniform(seed1, seed2, r); slv(i) := '1' when r > 0.5 else '0'; end loop; return slv; end function;
随机时间值
有时你需要生成一个随机的time
测试台中的价值。也许您想模拟一个随机写入数据突发的外部接口。不管是什么原因,随机 time
值很容易产生。
impure function rand_time(min_val, max_val : time; unit : time := ns) return time is variable r, r_scaled, min_real, max_real : real; begin uniform(seed1, seed2, r); min_real := real(min_val / unit); max_real := real(max_val / unit); r_scaled := r * (max_real - min_real) + min_real; return real(r_scaled) * unit; end function;
生成随机 time
VHDL 中的值,您必须首先将所需的最小值和最大值转换为 real
类型。然后,在随机化公式发挥作用后,将结果转换回 VHDL time
类型。请注意,您必须将您在模拟器中使用的模拟时间单位作为该函数的参数,如上面的代码所示。
OSVVM 随机包
最后,作为手工制作随机化算法的替代方法,您可以使用 OSVVM 库中的 Random 包。它具有多个重载函数,用于为各种 VHDL 类型生成随机值。
开源 VHDL 验证方法 (OSVVM) 是用于创建结构化测试平台的 VHDL 库。 Random 包只是这个库中众多有用的包之一。
library osvvm; use osvvm.RandomPkg.all;
上面的代码显示了如何导入 OSVVM 包。 ModelSim 包含开箱即用的库,因此您无需为此模拟器下载它。请参阅 OSVVM GitHub 存储库中的 RandomPck.vhd 文件,找到适合您需要的随机化函数。
VHDL