【问题标题】:Compute e^x for float values in System Verilog?在 System Verilog 中计算浮点值的 e^x?
【发布时间】:2017-04-04 08:40:51
【问题描述】:

我正在构建一个在 FPGA 上运行的神经网络,最后一个难题是在硬件中运行一个 sigmoid 函数。这是:

1/(1 + e^-x)

(atan(x) + 1) / 2

不幸的是,这里的 x 是一个浮点值(SystemVerilog 中的 real 值)。

有没有关于如何在 SystemVerilog 中实现这些功能的任何提示?

这真的让我很困惑,因为这两个函数都很复杂,而且由于浮点值增加了复杂性,我什至不知道从哪里开始实现它们。

【问题讨论】:

  • 您为哪种 FPGA 设计?它有任何 DSP 资源吗?
  • 使用 FPGA 上的 DSP 模块计算 sigmoid 函数。
  • 延迟和吞吐量要求是什么?这将严重影响我为此设计的任何东西。另外,我不熟悉任何可以将真实(浮点数)合成到硬件中的 FPGA 工具(它可能存在,但如果有的话,它是最近的)。
  • 在许多神经网络计算中,计算可能不需要很精确。如果你真的实现了浮点运算单元,那么评估上面的等式和复杂的实现可能会非常昂贵。一种选择是使用定点数学或查找表来实现特定的域范围。

标签: neural-network verilog fpga system-verilog sigmoid


【解决方案1】:

以硬件 (FPGA) 为目标的 FPGA 设计流程通常不支持 FPGA 架构中的浮点数。更常用的是精度有限的定点。

有限精度的定点方法:
使用 Matlab 为您的数学函数创建一个样本数组,使最大值为 +/- .99999。对于 8 位精度(实际上是带符号位的 7),将这些数字乘以 128,在小数点处四舍五入并去掉小数部分。将这些数字以 2s 补码十六进制格式写入文本文件。在 SystemVerilog 中,您可以使用该文本文件实现 ROM。使用 $readmemh() 将这些数字读入内存样式变量(具有压缩和未压缩维度的变量)。教程链接:
https://projectf.io/posts/initialize-memory-in-verilog/.
现在您有了一个 ROM,其中包含有限精度的函数样本

第 21.4 节从 SystemVerilog 规范中的文件加载内存数组数据提供了 $readmh() 的定义。这是那个文档:
https://ieeexplore.ieee.org/document/8299595

如果您需要浮点,一种可能性是使用带有在 FPGA 架构中实现的浮点单元的处理器软核,并在该核上运行软件。通过物理总线(如 axi4 steaming)与 FPGA 架构的其余部分的核心接口。请参阅:
https://www.xilinx.com/products/design-tools/microblaze.html 以开始使用。
这是一个与普通 FPGA 设计非常不同的工作流程,并且使用不同的工具。带有数学库(tan、exp、div 等)的 C 或 C++ 编译器将与处理器内核一起使用。

定点的另一种可能性是带有硬核处理器的 FPGA。 Xilinx Zynq 就是其中之一。这是一种复杂而强大的方法。一本免费的免费书籍提供有关如何使用 Zynq 的知识
http://www.zynqbook.com/.
这个工作流程比软核方法更复杂,因为 Zynq 是一个更复杂的平台(硬处理器和 FPGA 集成在一个芯片上)。

【讨论】:

    【解决方案2】:

    你真的需要一个浮点数吗?定点就够了吗?

    考虑到 (atan(x) + 1) / 2,x 的唯一有用值很可能是指数相当小的值。 (如果指数很大,你的答案是 pi/2)。

    在硬件中可以很容易地计算定点数的atan;有cordic方法(见https://zipcpu.com/dsp/2017/08/30/cordic.html)和直接方法;例如见https://dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization/

    【讨论】:

      【解决方案3】:

      您似乎意识到,类型 real 是不可合成的。您需要分别对整数尾数类型和整数指数类型进行操作,并在完成后将它们组合起来,并跟踪符号。处理完 (e^-x) 后,剩下的就很简单了。

      试试这个页面以获得快速解释:https://www.geeksforgeeks.org/floating-point-representation-digital-logic/

      并搜索“浮点数字设计”以获取更多解释/示例。

      【讨论】:

        【解决方案4】:

        我刚刚通过 Vivado HLS 完成了这个,它允许您用 C 编写电路。 这是我的 C 代码。

        #include math.h
        
        void exp(float a[10],b[10])
        
        {
            int i;
            for(i=0;i<10;i++)
            {
                b[i] = exp(a[i]);
            }
        }
        

        但是有一个问题是不可能创建一个未调整大小的矩阵。也许还有另一种我不知道的方式。

        【讨论】:

          【解决方案5】:

          为此,一种更简单的方法是为此函数创建一个内存/数组。但是,该选项可能效率极低。

          x 应该是内存的输入地址,该位置的值可以是函数的输出。

          假设你的函数值如下。 (这只是一个例子)

          x = 0 => f(0) = 1
          x = 1 => f(0) = 2
          x = 2 => f(0) = 3
          x = 3 => f(0) = 4
          

          因此您可以为此创建一个数组,用于存储输出值。

          int a[4] = `{1, 2, 3, 4};
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-03-27
            • 1970-01-01
            • 2021-02-03
            • 2021-01-24
            • 1970-01-01
            • 2012-03-10
            相关资源
            最近更新 更多