我正在构建一个在 FPGA 上运行的神经网络,最后一块拼图是在硬件中运行一个 sigmoid 函数。这可以是:
1/(1 + e^-x)
或者
(atan(x) + 1) / 2
不幸的是,这里的 x 是一个浮点值(real
SystemVerilog 中的一个值)。
是否有关于如何在 SystemVerilog 中实现这些功能的任何提示?
这真的让我感到困惑,因为这两个函数都很复杂,而且由于浮点值增加了复杂性,我什至不知道从哪里开始实现它们。
我正在构建一个在 FPGA 上运行的神经网络,最后一块拼图是在硬件中运行一个 sigmoid 函数。这可以是:
1/(1 + e^-x)
或者
(atan(x) + 1) / 2
不幸的是,这里的 x 是一个浮点值(real
SystemVerilog 中的一个值)。
是否有关于如何在 SystemVerilog 中实现这些功能的任何提示?
这真的让我感到困惑,因为这两个函数都很复杂,而且由于浮点值增加了复杂性,我什至不知道从哪里开始实现它们。
正如您似乎意识到的那样,类型 real 是不可合成的。您需要分别对整数尾数类型和整数指数类型进行操作,并在完成后将它们组合起来,并跟踪符号。一旦你处理了 (e^-x),剩下的就应该是直截了当的。
试试这个页面以获得快速解释:https ://www.geeksforgeeks.org/floating-point-representation-digital-logic/
并搜索“浮点数字设计”以获取更多解释/示例。
一种更简单的方法是为此函数创建一个内存/数组。但是,该选项可能非常低效。
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};
以硬件 (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 集成在一个芯片上)。
我刚刚通过 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]);
}
}
但是有一个问题是不可能创建一个未调整大小的矩阵。也许还有另一种我不知道的方法。
你真的需要一个浮点数吗?定点是否足够?
考虑到 (atan(x) + 1) / 2,x 的唯一有用值很可能是指数相当小的值。(如果指数很大,你的答案是 pi/2)。
定点数的 atan 可以很容易地在 HW 中计算;有cordic方法(见https://zipcpu.com/dsp/2017/08/30/cordic.html)和直接方法;参见例如https://dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization/