vhdl - 在 VHDL 中比较实数

标签 vhdl

我目前比较两个实数(计算后)的方法是取差并转换为整数并与 0 进行比较(例如,只是为了突出问题,示例可能在模拟器中工作)

variable a : real := 0.1;
constant epsilon : real := 1.0E-5; -- Whatever accuracy needed, not too low though
a := a + 5.3;

assert a = 5.4;                -- Yields intermitent errors
assert integer(a - 5.4) = '0'; -- Erroneous if 4.8 < a < 5.9 due to cast rounding
assert abs(a - 5.4) < epsilon;    -- Will work everytime, but seems a bit forced

采用这种方式的原因是我在编写的测试台中遇到了很多断言错误(比示例代码更复杂)。我将这些错误视为 GHDL 模拟器中的浮点错误。有没有更好的方法来比较两个实数,例如使用机器 epsilon 或任何内置方法?

最佳答案

正如@Philippe 所指出的,实数比较需要一定的余量来说明最低有效位中的有限精度和累积误差。使用简单的 epsilon 值是一种常见的方法,但它有一个局限性,因为它的值相对于被比较的数字是绝对的。您需要提前知道要比较的预期值,才能选择合适的 epsilon。

如果您需要比较的数字集涵盖了很宽的量级范围,您最终会得到一个太大而无法正确比较小值的 epsilon。在这种情况下,当比较小的实数时,您需要一个小的 epsilon,而对于较大的数字,您需要一个较大的 epsilon。这是通过使用考虑相对误差的比较来实现的。

This page很好地概述了一种方法,该方法允许使用相对误差而不是绝对误差来比较实数。以下函数是相对比较在VHDL中的实现:

-- Adapted from: http://floating-point-gui.de/errors/comparison/
function relatively_equal(a, b, epsilon : real) return boolean is
begin
  if a = b then -- Take care of infinities
    return true;
  elsif a * b = 0.0 then -- Either a or b is zero
    return abs(a - b) < epsilon ** 2;
  else -- Relative error
    return abs(a - b) / (abs(a) + abs(b)) < epsilon;
  end if;
end function;

这里的 epsilon 参数是一个分数,它指定要比较相对相等性的有效位数。

-- Compare for relative equality to three significant digits
-- These are all considered equal while using the same epsilon parameter
assert relatively_equal(1.001, 1.002, 1.0E-3) report "1.001 != 1.002";
assert relatively_equal(100.1, 100.2, 1.0E-3) report "100.1 != 100.2";
assert relatively_equal(1001.0, 1002.0, 1.0E-3) report "1001 != 1002";

-- Compare for relative equality to four significant digits
-- This will raise the assertion
assert relatively_equal(1.001, 1.002, 1.0E-4) report "1.001 != 1.002";

关于vhdl - 在 VHDL 中比较实数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27837029/

相关文章:

vhdl - 从命令行重新加载 gtkwave 中的 VCD 文件

vhdl - 如何将SV接口(interface)信号绑定(bind)到VHDL类型?

audio - VHDL 音频采样音量控制

gtk - 如何在 Windows 上安装 GTKWave?

vhdl - vhdl 中的 "unexpected others"

c - 将数据读入 VHDL

recursion - VHDL 递归组件/实体

vhdl - 非法顺序语句错误

vhdl - 如何在 FPGA 中实现无限循环?

algorithm - 快速、小面积、低延迟的部分排序算法