我们正在尝试在FPGA上实现定点非线性数学函数。我们希望能够实现非常低的延迟(最多2-4个时钟周期),使计算流水线化,使得我们可以在每个时钟周期接收新的答案(因为它们在每个时钟周期都没有丢弃输入),具有良好的准确性,并具有合理的FPGA资源利用率。
我们使用CORDIC计算机和DSP模块的组合进行计算,这是一个非常好的解决方案,除了CORDIC计算机需要大约12个时钟周期才能获得良好的精度。
使用没有插值的LUT需要太多的RAM,因为我们有32位,所以我们把它扔掉了。
我们的下一个选择是使用带插值的查找表。延迟很好,因为我们可以使用输入值的高位自动索引LUT。问题在于非线性部分的准确性不是很好。
我们现在正在尝试使用样本间间距不均匀的LUT。基本上我们在非线性部分中更多地采样函数,并且当函数看起来更线性时采样更少。这应该有助于解决我们的精度问题,但我们现在面临的问题是我们无法使用输入值的高位自动索引LUT。我们研究了进行二进制搜索以找到索引的方法,但是遇到了延迟。资源利用率也不是很高,因为为了在每个时钟周期继续得到输出的答案,我们不得不在不同的流水线阶段复制我们的LUT以处理二进制搜索。我们尝试了一些技巧,比如使用双端口rams,但延迟仍然是杀手锏。
所以我们想知道是否有人有类似的问题,并且知道一个好的索引解决方案,或者是否有特殊/智能的方法来非均匀地对我们的函数进行采样并以这样的方式构建LUT,即索引仍然可以计算得相当快。
答案 0 :(得分:2)
让我们说你的功能执行
y = f(x)
你可以先用分段线性
来压缩xz = g(x)
实现为一个小的LUT +线性插值(只考虑x
的几个最重要的位),这样你就可以将更多的内存用于函数的有趣区域,而不是几乎恒定的区域。
然后将y
计算为
y = f(x)
= h(z)
= h(g(x))
其中h
将是一个预处理,"扭曲"原始表的版本。
h(z) = f(g'(x))
和
g'(g(x)) = x
那么你仍然只会在前几位使用LUT加上线性插值,但分两个阶段:
+--------+ +--------+
| LUT #1 | | LUT #2 |
| | | |
-- x -->| g(x) |-- z -->| h(z) |--> y
| | | |
| | | |
+--------+ +--------+
粗略勾画出这样的样子:
y = f(x)
^
| : : ..:..............:
| : : ........ : :
| : : .. : :
| : :.. : :
| : ...: : :
| :........... : : :
|..............: : : :
+-----------------------------------------------------------+->
| | | | |
z = g(x)
^
| : : ...O..............O
| : : .... : :
| : : .... : :
| : ...O... : :
| : .... : : :
| : .... : : :
O..............O... : : :
+-----------------------------------------------------------+->
| | | | |
y = h(z)
^
| : : ..:...:
| : : ......... : :
| : : ....... : :
| : :...... : :
| : ........: : :
| :.................. : : :
|...: : : :
+-----------------------------------------------------------+->
| | | | |
当然,有趣的问题是如何找到最佳g(x)
以使最坏情况(或平均情况)错误最小化。
但这可以离线甚至分析地执行。