404-乘法器的优化 2
# 404-乘法器的优化 2
当我们购买一台计算机时,不仅希望它的性能足够好,还希望他的价格足够低。 那对于 CPU 这样的集成电路芯片来说, 它的价格的一个重要因素就是其中晶体管的数量。 或者说是芯片的面积。因此,在我们设计各个功能部件的时候, 如何减小芯片的面积也是一个重要的优化方向。
我们还是对照这个乘法器的结构图, 我们来一起分析在哪些地方我们只是为了实现的方便 而设置了不必要的硬件资源。这些都是我们可以优化的方向。 首先我们来看被乘数寄存器。这是一个八位的寄存器。 但是实际上我们的被乘数只有四位。 那我们可能要说那是因为我们要进行移位啊,而移位是为了和乘积的中间结果进行对齐,然后进行运算,这就是这个乘法运算的要点之一啊。我们先不管这些,在这里显然用八位的寄存器来保存了一个四位的被乘数,这就是浪费。至于如何解决,或者能不能解决,我们一会再说,我们先把所有的浪费的情况都找出来。
然后第二个, 这个乘数寄存器是个四位的,那这个就没有浪费了,因为乘数本来就是四位的, 但我们仔细想一想我们会发现这个乘数实际上每一个周期都会往右移动一位, 所以在这个乘数寄存器当中虽然一开始是没有浪费的, 但是在运算的过程中每个周期有效的数字会减少一位, 所以逐渐就会出现浪费的位数,而且越来越多, 那好我们又找到了一个浪费的地方
再来看第三个, 乘积寄存器,最后的乘积确实需要 8 位才能保存, 但是问题在于这个乘积寄存器在不断的保存中间结果, 而中间结果一开始并不是 8 位的。 当被乘数还集中在最低四位的时候,这个运算结果实际的有效数字,只有最低的四位,只有随着被乘数寄存器不断的左移, 那乘积寄存器当中的有效数字还在不断地增加,最后才达到了 8 位。 所以说对于乘积寄存器,虽然最终它没有浪费, 但是在最开始,它的高四位是浪费的。 而且其中的有效数字每个周期也是增加一位。 这样我们就找到了第三个浪费的点。
第四点,在这个加法器, 实际上每一次在将被乘数和当前的乘积进行相加的时候,无论被乘数左移到什么程度, 实际上只有真正有效的那四位的被乘数需要和乘积寄存器当中对应的位进行相加, 被乘数寄存器当中从右边补入的那些 0,实际上 是不用参加运算的。所以这个 8 位的加法器也是一个浪费的点。
那好,现在我们就找到了四个浪费的点。 那我们就来看一看如何进行优化。 这就是刚才我们找到的那四个浪费的点。 我们先来看第一个。被乘数寄存器有 8 位宽,而且带左移的功能。 但是他有效的数字时钟只有 4 位,那我们用一个非常直截了当的方法, 既然你的有效数字只有四位,那么就给你一个四位的寄存器,用来保存这个被乘数。 那我们可能要说,左移怎么办呢?我现在只有一个四位的寄存器,那一左移,岂不把一个有效的数字给丢掉了吗?被乘数这四位可都一直要保持参与运算呢?
那方法也很简单。 既然我削减了你的地盘,那我也相应的减少一点你的任务, 你就不需要左移了。所以这个寄存器也被取消了左移的功能, 从实现上来说,没有了左移的功能,它的实现还会变得更为简单,但是我们不能一味的为了减少浪费而削减功能。被乘数左移是为了和中间的结果进行对齐,以便进行运算。这件事情总得有一个功能部件来做。那么等会再去看看别的地方。 至少现在第一个问题已经解决了。被乘数寄存器缩减为 4 位 而且取消了左移的功能,在被乘数寄存器这个地方已经没有了浪费的现象。
然后我们来看乘积寄存器。乘积寄存器是 8 位宽的,但是初始时有效数字只有四位,而且每周期增加一位。 对于乘积寄存器,虽然它开始时有浪费,但是因为它最后的结果需要 8 位宽, 所以我们没有削减它的宽度, 但是一样,我既然保留了你的地盘,就得增加你的任务, 刚才我们不是取消了被乘数寄存器的左移功能吗? 被乘数寄存器左移就为了跟乘积寄存器当中的内容进行某种方式的对齐。 那既然它不能左移了,那你就右移呗,反正都是你们两对齐, 要么它向左,要么你向右,效果都是一样的。 所以我们就在乘积寄存器上增加一个功能。 就是右移的功能。既然我们用乘积寄存器的右移,代替被乘数的左移,那么乘积寄存器初始值的放置位置也发生了一点变化, 我们把它放置在高四位的地方, 并在这个寄存器中间加一条虚拟的线来标志高四位和第四位的分界。 那好,我们对乘积寄存器的改造暂时先到这里。我们给增加了右移的功能, 而且乘积的初始值防在其中的高四位,随着运算的过程不断的右移, 现在从运算功能上来说我们已经解决了被乘数寄存器被取消左移的这件事情。 虽然乘积寄存器本身的浪费问题我们还没有解决。
现在我们来看下一个问题。就是加法器有 8 位宽,但是参与运算的有效数字实际只有 4 位。 那现在这个问题已经很好解决了。 因为乘积寄存器已经被削减到了四位,而乘积寄存器,初始值放在了高四位的地方, 所以我们就将加法运算改成被乘数寄存器的这四位和乘积寄存器的高四位进行运算。 这里我们需要仔细想一下。如果想不明白可以拿出纸笔再重现一下 乘法运算的过程。这样我们就解决了三个问题。
现在还有最后一个问题。 我们还需要一个乘数寄存器。它是四位宽的,而且有右移的功能。但是其中有效的数字每周期是减少一位的。 我们仔细看一看这个功能的描述,再看一看现在这个结构,我们真的还有必要设置这个寄存器吗? 如果没想明白,就请多看几遍这个乘数寄存器的功能描述。 一开始是 4 位宽,而且带右移, 它所需要的有效数字每周期减少一位,再仔细想一想,并且可以看一看 乘积寄存器还空余的这一部分,它是不是正好是一个最开始有四位宽的寄存器而且带右移, 当然因为乘积的有效位每个周期会右移一位, 因此这个控制的部分每个周期会减少一位,但这不正好是乘数寄存器所需要的功能吗? 所以,我们其实就可以把乘数放在乘积寄存器的第四位, 从而可以取消乘积寄存器这个部件。同时也解决了乘积寄存器在一开始有浪费的这个问题。
peterjxl 注:汇编里 乘法的话,结果的寄存器里就是有乘数的,这里是不是有巧合?
这样我们就完全解决了刚才分析出的这四个硬件资源浪费的问题。与此同时,我们的控制逻辑也需要做一些调整。
现在需要把乘积寄存器的最低位连接到控制逻辑,这也就是我们当前所需要观察的乘数的对应位, 如果发现这位为 1,控制逻辑就需要向加法运算的控制信号,并向乘积寄存器发出写入的控制信号, 并向乘积寄存器发出写入的控制信号,但这个写入只发生在 但这个写入只发生在这个寄存器的高四位, 然后每个周期会发出右移的控制信号,那么随着乘积寄存器的右移, 原先存放在低四位的乘数就在逐渐的被移出, 而原先只在高四位的乘积则逐渐占满了乘积寄存器。 而在这个过程中,控制逻辑每一轮都可以观察到乘数的对应位,从而产生对应的控制信号, 因此这个结构可以完成刚才我们所介绍的那个乘法运算流程的所有工作。 当然这只是一个四位乘法器的例子。 但我们可以很容易的推广到 N 位,
这就是一个经过优化后的 N 位乘法器。 我们需要一个 N 位的寄存器保存被乘数,还需要一个 N 位的加法器进行中间结果的运算,再需要一个 2N 位的带右移的寄存器同时保存乘积和乘数。 这就是我们进行了性能优化和面积优化之后的乘法器的实现结构。
通过对乘法器的分析和优化, 我们要意识到两件事情。首先,这些原理性的描述虽然易于理解, 但是不见得适合真正的实现。而从另一个角度来看, 对于这些原理性的实现,我们只要采用一些很简单的方法, 就能够在性能和面积上获得很好的优化效果。 当然,我们现在有的这个乘法器和 现实中我们真正使用的乘法器还是有相当大的距离的。 也就是说,还有更多的其他的优化方法可以使用。 如果你对这些方法有兴趣,可以进一步的深入挖掘和学习。