5.2 乘法器的实现

计算机组成

5 乘法器和除法器

5.2 乘法器的实现

屏幕快照 2018-07-05 15.18.33

如果希望CPU支持某一种运算,我们就需要用硬件电路来实现对应的功能部件。我们现在已经有了一种乘法运算的方法,适合硬件来进行实现。而且,我们还掌握了一些硬件电路的基本知识。我们就可以一起来尝试如何构建一个硬件的乘法器。

屏幕快照 2018-07-05 15.18.47

现在我们来看乘法器是怎么实现的。我们用一个简单的二进制乘法作为例子,1000乘以1001,这是两个四位的二进制数相乘,那么为此我们要实现一个四位的乘法器。

首先我们需要一个寄存器来保存被乘数(Multiplicand),被乘数寄存器是一个8位的寄存器,而且带有左移的功能。它有一个左移的控制信号输入,当外部的控制逻辑(Control test)将这个信号视为有效时,在下一个时钟顺延到来的时候,被乘数寄存器当中的内容就会向左移动一位。

第二个寄存器是乘积(Product)寄存器,这也是一个8位的寄存器,用来保存运算的结果。被乘数寄存器当中的内容和乘积寄存器当中的内容需要进行加法运算,这里我们就需要进行一个8位的加法器,它会将被乘数寄存器当中的内容和乘积寄存器当中的内容进行相加,并将结果再送到乘积寄存器当中。

另外,我们还需要一个寄存器来保存乘数。这个寄存器只要4位就可以了,但有一点比较特殊,乘数寄存器的最低位被连到了控制逻辑(Control test),也就说控制逻辑可以观察当前乘数寄存器的最低位,并据此来生成相关的控制信号。这些控制信号就包括是否要让加法器进行加法运算,以及是否要让乘积寄存器保存当前的运算结果。另外,这个乘数寄存器还需要有向右移位的功能,同样也是由控制逻辑发出的信号来进行控制的。

现在我们就有了一个完整的乘法器,就来看一看这样的一个乘法器是如何工作的。

屏幕快照 2018-07-05 15.18.57

首先我们要做的工作是初始化,也就是对这三个寄存器的内容进行设置。

我们现在要进行的运算当中被乘数是1000,也就要把1000放置到被乘数寄存器当中去,那这个4 bit的数是如何放到8 bit的寄存器当中去的呢?我们现在已经看到,我们需要在高位填上4个0,为了便于区分,我在这里将我们运算所得的数1000用粗体表示, 那么在被乘数寄存器当中现在的第四位1000就是我们这个运算本身所有的数,而高四位的4个0是这个乘法器的系统自动补入的,所以这里用斜体来表示。那这就是被乘数寄存器的内容了。

然后我们看乘数寄存器。乘数寄存器很简单,它是4位宽的,对应了4位的乘数,直接填入即可。

然后是乘积寄存器,现在运算工作还没有开始,所以乘积寄存器中当前的内容是0。

现在初始化工作已经完成,我们就开始运算了。

屏幕快照 2018-07-05 15.19.05

第一步,请大家回忆我们用纸笔是如何进行这个运算的。第一步我们应该做什么呢?首先是检查乘数寄存器的最低位,看是否为1。现在发现它是1,那么就需要将被乘数寄存器当中的内容和当前乘积寄存器当中的内容进行相加,我们把这一步命名为第一步之后的一个小的步骤,称为1a。

屏幕快照 2018-07-05 15.19.14

在这一步控制逻辑会控制加法器将加法器的两个输入,也就是被乘数寄存器的内容和乘积寄存器当中的内容进行加法运算,然后将加法器的运算结果送入乘积寄存器,在下一个时钟上升沿来临的时候,因为乘积寄存器的写入信号是有效的,所以它就会采样输入端的数据,并保存到寄存器当中。这样在这个时钟上升沿之后,乘积寄存器当中的内容就变成了00001000。然后我们来看第二步。

屏幕快照 2018-07-05 15.19.24

第二步应该做什么呢?我们还是需要回忆之前讲过的适合硬件做的乘法运算。这时候我们需要对被乘数进行左移,以便为下一次运算进行准备。所以控制逻辑会给出左移的信号。

屏幕快照 2018-07-05 15.19.33

那么在下一个时钟上升沿来临的时候,被乘数寄存器就会完成一次左移,最左端的0被丢弃了,在最右端补入一个0。然后我们再来看第三步,第三步又是要做什么呢?我们注意乘数寄存器是有右移功能的,控制逻辑会给出右移的控制信号。

屏幕快照 2018-07-05 15.19.45

当下一个时钟上升来临的时候,乘数寄存器就会向右移动一位。这样做只是为了方便对乘数的对应位进行判断,在硬件上如果要依次的对乘数从低位到高位进行逐位的判断,那就要用硬件来记住之前判断到了哪一位。那与其记住这样的信息,不如把乘数每次向右移一位,这样每次只需要判断乘数寄存器当中的最低位就可以了,而且我们根据乘法运算的过程也可以知道,我们对乘数的使用是由低到高逐位使用的,一旦使用过之后就不会再用了。所以我们可以放心的把乘数进行右移,并把刚才的最低位丢弃。所以在做完加法运算之后的第二步和第三步,实际上是在为下一轮的工作做准备。

但是我们还需要进行一个判断,那就是到底有没有下一轮,这就是第四步,由控制逻辑进行判断现在是否已经完成了运算。对这个4位的乘法器来说,一共要产生四个中间结果并将他们相加,所以与刚才类似这样的工作一共要执行四轮。简单的计数对硬件来说是非常容易的,所以控制逻辑可以很容易的判断出当前是否已经是第四次循环了,当然现在不是,所以我们需要进行下一轮。

屏幕快照 2018-07-05 15.19.53

第二轮的运算方式和刚才第一轮是完全一样的。首先判断乘数寄存器当前的最低位是否为1,如果为1,则要进行加法并进行更新乘积寄存器当中的内容。但是现在是0,所以不需要做这一步工作。那控制逻辑就不会产生对应的加法控制信号,以及要写入乘积寄存器的写控制信号。

于是直接进入第二步,还记得第二步是什么吗?

屏幕快照 2018-07-05 15.20.01

屏幕快照 2018-07-05 16.13.44

第二步是让被乘数寄存器左移一位,所以,在下一个时钟上升沿之后,被乘数寄存器就会左移。

屏幕快照 2018-07-05 15.20.09

屏幕快照 2018-07-05 16.16.55

然后是第三步,第三步是让乘数寄存器右移一位,再过了一个时钟上升沿,乘数寄存器就右移了一位。

屏幕快照 2018-07-05 15.20.18

然后是第四步,第四步是做什么?第四步是判断当前的运算是否已经结束了,当然现在还没有到第四轮,所以运算还没有结束。

屏幕快照 2018-07-05 15.20.27

因此我们还继续执行第三轮。每轮的第一步都是一样的,就是判断乘数寄存器的最低位,在这里我们就可以看出来这样机制的好处 —— 就是每轮的操作内容完全是一样的, 硬件上不需要设计额外的机制去知道当前是进行到哪一轮,也不需要智力因素的介入去判断当前到底要分析乘数的哪一位或者如何进行中间结果的对齐等工作。它所需要做的都是很机械的左移,右移,判断当前乘数寄存器的最低位,这些非常简洁明了的工作。

那在第三轮的第一步我们发现乘数寄存器的最低位还是0,那我们就不再详细描述第三轮当中的每一步了。我们会直接跳到第四轮,但请先想一想当我们到了第四轮的第一步的时候,被乘数寄存器当中的内容应该是什么?乘积寄存器当中的内容应该是什么?而乘数寄存器当中的内容又会是什么?如果你有纸笔的话不妨在纸上把你所设想的这三个寄存器当中的内容写下来,然后我们一起对比一下你的判断是否正确。

屏幕快照 2018-07-05 15.20.39

好了现在我们假设硬件已经依次的做完了第三轮的第二步第三步和第四步。

现在我们到了第四轮的第一步,我们注意到被乘数寄存器又左移了一位,它的最低3位现在都是移位补入的;乘积寄存器的内容没有变化;而乘数寄存器又往右移动了一位,现在只剩下最低位的这个1是我们初始化的时候填入的值的一部分,而它高位的3个0,我们看到它都是斜体的,就标明了是后来移位补入的。

那么在第4轮的第1步,我们还是要判断乘数寄存器的最低位,这时候我们发现是1,这时候控制逻辑会做什么工作呢?其实和第1轮一样,它就会控制加法器进行加法运算,将当前被乘数寄存器的内容和乘积寄存器的内容进行相加,并向乘积寄存器发出信号,让乘积寄存器在下一个时钟上升沿的时候,采样加法器的输出结果。我们要注意,被乘数寄存器当中的内容已经移到了合适位置。

从这里我们也可以看出用这样的方法,控制逻辑不需要关心当前被乘数寄存器和乘积寄存器的内容进行相加时如何进行对齐,它只要保证每一次往左移一位,然后在需要进行加法的时候,它们的对齐关系一定是正确的。那么在执行完加法运算,并将运算结果保存到乘积寄存器当中之后,我们还需要对被乘数寄存器和乘数寄存器进行一个移位的操作。那么还是和刚才一样,你可以在纸上写一下你所预想的这三个寄存器当中的内容,我们将直接跳到第4轮的第4步。

屏幕快照 2018-07-05 15.20.48

这时候我们注意,乘积寄存器当中的内容已经发生了变化,而被乘数和乘数寄存器也都发生了移位。这时候被乘数寄存器当中真正的被乘数1000已经移到了高4位,而低4位都是后来移位补入的;我们再看乘数寄存器,现在乘数寄存器当中这4个0全都是后来移位补入的,原先的乘数已经全部移出了,这也说明我们对乘数的每一位都进行了判断,我们已经完成了所有的中间结果。当然对于硬件控制逻辑来说,它不可能像我们这样用人眼去观察乘数寄存器当中乘数是否已经全部的移出,但它的判断方法更为简单,还是看这是否是第4次循环,当然我们知道这确实是第4次循环,所以在这个时候,这个乘法运算就已经完成了。所以在最后一轮当中,被乘数和乘数这两个寄存器的移位并没有实际的意义。

屏幕快照 2018-07-05 15.20.57

好了,现在我们已经得到了这个乘法的乘积,它就在现在的乘积寄存器当中。这个运算结果是0100 1000,这和我们用纸笔算出来的结果是一样的。现在,我们用这个四位乘法器的例子,知道了一个乘法器的运算过程,那我们就来对这个运算的过程进行一个总结。

屏幕快照 2018-07-05 15.21.06

这是一个N位的乘法器的工作流程图。当我们做好了初始化工作之后:

第1步,就是检查乘数寄存器的最低位。如果这个最低位是1,那么就将被乘数寄存器和乘积寄存器的内容相加,运算结果还放入乘积寄存器当中。

之后,再执行第2步,也就是将被乘数寄存器的内容左移一位。当然,如果在第1步的检查当中,最低位等于0,那就跳过第1a步,直接执行第2步。

执行完第2步之后,第3步,是将乘数寄存器的内容右移一位。

第4步,是检查是否已经到了第N次循环。如果不是,那就意味着运算还没有结束。我们只需要回到第1步,再检查当前乘数寄存器的最低位,并执行相应的操作就可以了。如此往复循环,直到有一次在第4步检查发现已经是第N次循环了,那这就意味着这个乘法运算的工作就已经完成了,我们所需的运算结果就放在乘积寄存器当中。

这就是一个N位乘法器的工作流程。

屏幕快照 2018-07-05 15.21.19

屏幕快照 2018-07-05 15.21.30

现在,我们只要有足够的晶体管构造出合适的逻辑门和触发器就可以制造出一个完整的,可以正常工作的乘法器了。虽然它的实现还非常地初级,但它肯定可以正确地完成我们想要的乘法运算。

猜你喜欢

转载自www.cnblogs.com/narisu/p/9269343.html
5.2