左移 n 位与乘以 2^n 相同。这意味着左移可以在不使用桶形移位器的情况下通过使用硬件乘法器块进行。现代 FPGA 中有很多 DSP 块。这个问题是关于使用硬件乘法器的。
话虽如此,右移呢?右移可以实现为除以 2^n。但是,除法硬件基本上是不可能的。那么,如果我们不能使用除法器,是否仍然可以仅使用硬件乘法器来实现右移?
编辑:
我必须将 32 位字移位 n 位,然后与另外 32 位连接。原始输入是 32 位,但实际有效位数通常小于 32,这就是为什么可以使用左移和或连接的原因。
所以这里设计的是一个拼接模块,拼接之后,当字够大的时候,就把它压入FIFO中。
\endgroup
12
5 个回答
5
这是基本思想。我们讨论的是按可变位数进行移位。我应该把这一点讲清楚。
x << n can be implemented as x*2^n
x >> n can be implemented as x/2^n
现在 / 操作符无法在硬件中轻松实现。不过,还是有办法解决这个问题的。
如果我们想右移而不是左移,我们首先要翻转位顺序,即 x[m..0] 变为 x[0..m],这会导致 MSb 移到右端,LSb 移到左端。现在如果我们左移,我们实际上会丢弃原始数据的 LSb,因此实际上是在对原始数据进行右移!
然后将 2^n 与 x[0..m] 相乘,其中 n 是向右移动的位数。现在,将乘法结果翻转回来,这样 x[0..m] 又变成了 x[m..0]。
这就是我们如何通过对数据的镜像进行左移,然后再次对结果进行镜像来实现数据的右移。
\endgroup
4
-
\begingroup
是的,这是正确答案!如果我们更进一步,我会向你指出这一点。我很高兴你能自己意识到这一点。
\endgroup
– -
\begingroup
编辑你的问题以使其更清楚。我刚刚尝试了一次编辑。
\endgroup
– -
\begingroup
位交换-乘法-位交换是否比仅仅乘以并获取所需的 MSB 更好?
\endgroup
– -
\begingroup
@Justme,是的,非常多。除了更清晰易懂之外,它还提供了更大的输出位范围,因为没有丢弃乘数位。
\endgroup
–
|
是的,你可以这样做。诀窍是将可变左移(由硬件乘法器实现)与固定右移相结合,方法是选择结果的高位。例如,要按最多 16 个数量进行移位,你可以执行以下操作:
x >> n == (x * 2^(16-n)) >> 16
你必须确保中间结果不会溢出。不过,我使用过的大多数 FPGA 的乘法器输出足够大,可以避免这个问题。
\endgroup
|
如果是在 FPGA 上实现的,那为什么还要费心移位呢?保持输入位不变,并向原始位模式添加新的 LSB 或 MSB(即零)。无需移位。
如果需要任意左移和右移,请将输入乘以某个值并从 MSB 部分获取所需的输出位。例如,如果您有一个 8 位输入,请将其乘以 128 并忽略结果的 8 个 LSB,并将接下来的 8 位作为输出 – 输出为 128/256,即乘以 0.5 或除以 2,即右移 1 位。
\endgroup
3
-
\begingroup
如果是在 FPGA 上实现的,为什么还要费心移位呢?保持输入位不变,并向原始位模式添加新的 LSB 或 MSB(即零)。无需移位。您想象的只是一个固定的移位,但 OP 状态为 n 位。以可变的位数进行移位是数字逻辑和 FPGA 中较慢的操作之一,尤其是在位数较多的情况下。使用硬件乘法器进行可变左移是一种众所周知且有价值的加速方法。因此想要使用相同的方法进行右移。结果,恐怕会被否决。
\endgroup
–
-
1\begingroup
@TonyM 但是我确实提到了如果确实需要的话如何使用硬件乘法器进行右移。
\endgroup
– -
\begingroup
在第二段中继续说一些相反的话不会改变第一段,第一段非常具有陈述性和独立性。或者它发出了你没有读过这个问题的信息,我担心。(作为对你一段时间以来的回答的友好观察,我不认为你读你的答案就像你是另一个冷眼旁观的人一样,我认为你只是从你想要的角度看待它们。当人们评论说他们很困惑时,你经常回答说你没看到。只是一些值得思考的事情,可能会有所帮助。在这里,我甚至引用了整段话,这样你就知道该看什么了。)
\endgroup
–
|
如果考虑定点算术而不是整数算术,那么您就可以访问可以执行右移的被乘数。
以二进制计算,乘以 10.00(即十进制 2)即左移 1 位,乘以 01.00 则不变,乘以 00.10(即十进制 1/2)即右移 1 位。
\endgroup
|
如果没有必要,不要使用乘法器,它们使用的门数量很昂贵。这就是为什么你应该使用移位 2,这只需要很少的 Asic/FPGA 资源、右除法和左乘法(很容易看出,如果你用 0 填充 10b,你会得到 100b,也就是 4,相反,如果你删除 1000b 的一个数字,你会得到 4,也就是 8/2=4)
您可以使用硬件乘法器执行此操作并使其除法,如果您截断输出(大多数 DSP 块都可以做到这一点),但更有可能的是将其发送到移位寄存器并在不同的指令中移位值。可能有一些 DSP 可以在一次操作中完成此操作,但我不知道有任何 DSP。(我知道一些可以在一次操作中执行乘法加法)
\endgroup
1
-
2\begingroup
你没有正确阅读问题:OP 指出的是硬件乘法器,而不是 FPGA 门。因此实际上没有使用 FPGA 门。恐怕结果会是反对票。
\endgroup
–
|
很高兴你后来强调了硬件乘法器。这个问题目前已经得到了很多关于硬件乘法器以外的所有内容的答案。
\endgroup
–
我要亲自发布答案。如果没有解决方案,我相信我有一个解决方案。
\endgroup
–
在 FPGA 中实现移位所需的只是一些路由资源和多路复用器。根本不需要使用乘法器。您坚持使用乘法器有什么理由吗?基于乘法器的解决方案是否比有条件地移动某些位更快,这实际上取决于 FPGA 的架构,尤其是对于宽 LUT,其中 2 个甚至 3 个移位级别可以容纳在一个逻辑级别中。
\endgroup
–
我将解释乘法器的原因。使用大量多路复用器来移动数据无法让我达到所需的 100MHz。我被卡在 86MHz。但使用硬乘法器,我能够达到更高的 FMax。这是基本原因。
\endgroup
–
基本思路是这样的:我得到两个数据,一个长度在 1 到 16 位之间,另一个长度在 1 到 12 位之间。我需要将它们连接在一起。连接时,我需要将这个可变大小的数据与上次连接时已经存在的数据相结合。如果我使用乘法器,我可以在几个时钟周期内完成此操作。如果我使用多路复用器,则会需要大量逻辑并且无法满足时序要求,或者需要更多延迟。我实际上将同时使用这两种方法,并最终比较结果。
\endgroup
–
|