64位先行进位加法器的原理

最近体系结构课程学到了CPU功能部件部分,其中谈到了先行进位加法器,网上对32位和16位加法器说的比较多,但64位的参考比较少,研究了好久终于能大致明白,在此把自己的理解做个记录供大家参考~

本文参考自中科院胡伟武老师的《计算机体系结构》第2版。

本文章分三部分:
1.串行进位加法器
2.16位串行进位加法器
3.64位串行进位加法器

1.串行进位加法器

加法运算的重要性对于一个CPU来说不言而喻。对于两个16位二进制数的相加,我们要怎么操作呢?
作为手写计算的话,我们往往会把两个数写成下图的形式然后计算:
64位先行进位加法器的原理_第1张图片
计算的次序是从右往左依次计算,如果每一位的结果大于1则向下一位进位,这是小学生都知道的,完成每一位相加逻辑的部件我们叫它全加器,那么我们可以得出结论,一个全加器应该有哪些输入,哪些输出呢?显然输入应该有两个数的对应位以及上一位计算的进位,输出应当有这一位的计算结果和这一位的进位。忽略其内部具体结构,我们将其简化为如下形式:
64位先行进位加法器的原理_第2张图片
A,B代表两个输入数字,Cin为上一位进位,Cout为输出进位,S为这一位求和结果。
也就是说,我们手算的方法一次只能计算一位,下一位的计算必须要等待看上一位是否有进位才能计算,按照这种原理,诞生了串行进位加法器,原理图如下:
64位先行进位加法器的原理_第3张图片
这种串行结构肯定是能解决问题的,但是弊端很明显,时延太长,假设一个全加器时延为3T(至于为什么设成三T,是因为全加器内部逻辑电路产生结果需要三层门电路,设每层时延为T,所以一个全加器为3T),那么16位加法时延就为16*3T=48T,更不要说32位加法和64位加法了,所以这种结构实用性很低,于是人们想到,能不能用并行的方法解决时延的问题?

2.16位先行进位加法器

要让每一位并行计算,最重要的问题就是要解决进位的问题,因为进位使相邻的位之间产生了依赖关系,那我们来看看每一位进位能否简化。
c0自然不用说,我们看c1。
c1 = a1&b1 | a1&c0 | b1&c0
这个逻辑想表达什么意思呢?要知道,每一位进位最多进1,而不可能进2,那么这个进位的来源是什么?第一种情况就是,两个加数都为1必然产生进位,第二种情况就是至少一位加数为1,上一位进位也为1,而上面的式子就表达了这个意思。现在继续看下一位,我们用相同的逻辑可以得到:
c2 = a2&b2 | a2&c1 | b2&c1
可以看出c2对c1的依赖关系,这时候就有人想到,我要是把c1代进c2会怎么样?
c2 = a2&b2 | a2&(a1&b1 | a1&c0 | b1&c0) | b2&(a1&b1 | a1&c0 | b1&c0)
我们惊喜的发现,原来c2可以直接由第一位加数和第二位加数已经最初的进位c0求出来而不再依赖于c1,后面为不再继续演示原理相同。现在我们回到c1的表达式。
c1 = a1&b1 | a1&c0 | b1&c0
我们对其进行化简得到:
c1 = a1&b1 | (a1|b1)&c1
这时候有人问了,这个化简有什么意义?这个问题问得好!我们发现,式子里有a1&b1和a1|b1了,我们令g1 = a1&b1,p1 = a1|b1,表达式变成了:
c1 = g1 | p1&c1
那么这样做的意义在哪里?还记得我之前说的,如果两个加数都为1那么一定会产生进位,也就是说,当g1等于1的时候一定有进位,于是我们叫g为进位生成因子,如果两个加数有一个为1,并且进位为1,那么也会进位,也就是说,p1 = 1的时候,如果c为0,输出0,如果c为1,输出1,于是给p起了个名字叫进位传递因子。类似的方法,我们把它扩展到接下来的几位就可以得到下面的表达式:

c1 = g0 | (p0&c0)
c2 = g1 | (p1&g0) | (p1&p0&c0)
c3 = g2 | (p2&g1) |(p2&p1&g0) | (p2&p1&p0&c0)
c4 = g3 | (p3&g2) | (p3&p2&g1) | (p3&p2&p1&c0) | (p3&p2&p1&p0&c0)

那么有人问了,为什么我只写到c4而不是一直写到c15?因为单个门电路输入太多会导致效率更低的。
好了,有了这个表达式,我们就可以并行计算出c1~c4了,由于作者比较懒,这个具体逻辑图真的很难画,如果哪天闲了来补,可以参考胡伟武老师《计算机体系结构》第二版第169页图。在此将四位并行的加法器简化为下图:

64位先行进位加法器的原理_第4张图片
需要提醒的是,这个部件只是计算了进位c而不是最终结果。
那么现在我们能算四位的了,16位的要怎么算呢?很明显,我们可以串行四个上面的那种块,变成下面的样子:
64位先行进位加法器的原理_第5张图片
于是又带来了最初的问题了,这些块之间又被进位连在了一起,导致一个块的计算需要等上一个块计算结束传入c才能开始计算,那么我们能不能向刚才那样想办法让这四个也能并行计算呢?当然可以!
我们要解决的问题还是进位的问题,不过我们已经知道,进位可以用p,g和c0表示出来,那么我们只要找到每一块的p,g就可以了。回想一下,p叫什么?进位传递因子!那我们来看看,什么时候,第一个块的c0能够传给第二个块?显然应该是第一个块里面每一位的进位因子p都为1才能传递到最后,同理,g叫进位生成因子,那什么时候才能保证有进位呢?第一个块的最后一位g3为1肯定没问题,还有呢?g2和p3同时为1也可以,意思是我第三位位有进位,并且第四位的传递因子可以把你的进位传下去,同理还有两种情况不再赘述,于是对于一个四位加法块我们也有了p和g了,表示为:
64位先行进位加法器的原理_第6张图片
(提醒读者一定要想清楚图中的P和G是怎么来的)
既然有了P,G,我们就可以根据P,G和初试进位c0算出后续的进位了。这里补充一句,P,G的计算只依赖于输入的p3~0和g3 ~0,而不依赖于c0,也就是说,后面的块即使未得到进位,也能算出自己的P和G,只不过不能计算出进位罢了。
也就是说,对于四个四位加法块,我们能并行计算出各自的p和g了,既然有了各自的p和g又已知了第一个块的初始进位c0,我们用相同方法,即如下:

c1 = g0 | (p0&c0)
c2 = g1 | (p1&g0) | (p1&p0&c0)
c3 = g2 | (p2&g1) |(p2&p1&g0) | (p2&p1&p0&c0)
c4 = g3 | (p3&g2) | (p3&p2&g1) | (p3&p2&p1&c0) | (p3&p2&p1&p0&c0)

可以设计出逻辑图:
64位先行进位加法器的原理_第7张图片
图中四个块并行计算各自的p和g并传入第二层(由下往上),并在第二层计算出每一块需要的c再传回第一层,再由第一层计算出最终的c0~c16。
我们可以来看看这么做的时延是多少,第一层和第二层的时延都是2T(更据内部逻辑结构得出),第一次由第一层计算2T,第二次第二层计算2T,第三次由第一层计算2T,加上初试p,g计算2T以及最终加法运算3T一共是11T,相比于之前的48T优化相当大!

3.64位先行加法器原理

相信到了这里,如果你已经完全理解了上面的过程,64位就不用我再多说了,我这里就大致讲一下我的想法。
64位也就是4个16位组合起来,你发现规律了吗?从一开始,我们把四个一位组合起来,然后把四个四位组合起来,现在把四个16位组合起来,可以发现,始终我们逻辑和解决方法都是一样的!
我们会怎么去考虑呢?
首先四个16位的块串行行,然后我们发现块之间有依赖时延偏高,于是我们想让它们并行,要解决的问题是块之间的进位传递的问题,还记得我们怎么解决16位的块之间进位传递问题的吗?没错,就是增加了一层来接受下面的P和G,这样我们就可以利用下面传上来的P和G以及初试进位c0来得到每一块需要的进位了,那么我们现在也用相同的方法来解决64位,不多废话直接上图:
64位先行进位加法器的原理_第8张图片
最后再简述一下其计算过程(从下往上依次是第一层到第三层):
1.第一层并行计算出各自的p和g传给第二层;
2.第二层并行计算出第二层的p和g传给第三层;
3.第三层更据第二层传上来的p和g以及初始进位c0计算出相应的c并传回给第二层;
4.第二层拿到各自的c0计算出各自的c并传给第一层;
5.第一层拿到c计算出最终需要的c;
以上过程每一个时延都为2T,整个结构时延为10T,加上初始输入的p,g计算的2T以及最终加法计算的3T,一共是15T。

你可能感兴趣的:(体系结构)