《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

3.11 二进制加减法器

采用二进制补码,我们剔除了减法运算,仅需要补码器和一个加法器即可实现二进制加减法器。当执行减法时,我们对减数N取补,而执行加法时,无须对N取补。这些操作可以利用一个可选的补码器和加法器相连而形成的加减法器来实现。我们使用的二进制补码在现代系统中非常流行,它可以通过在反码的最低有效位上加1得到。二进制反码可以用取反电路轻松地获取,而其结果加1则可以设置并行加法器的进位输入为1来实现。因而通过使用反码和加法器的进位输入,可以用较低的成本求二进制数的补码。在二进制补码减法中,相加后的校正操作,即当没有产生最终进位时,需对结果求补并添加一个负号。校正操作可以再一次使用M=0的加减法器或者采用如图3-44所示的可选的补码器来完成。
A―B的减法电路包含了一个如图3-43所示的并行加法器,并在B的每一位和全加器的相应输入端之间插入了一个反相器。进位输入C0必须为1,这样实现的操作变成了A加上B的反码再加1,即等价于A加上B的补码。对于无符号数,如果A≥B则实现了A―B,如果A<B则得到了B―A的补码。
加法和减法运算可采用一个普通的二进制加法器在一个电路内实现,即在每个全加器前添加一个异或门。图3-45给出了一个4位的加减法器。输入S控制电路实现的运算。当S=0时电路是一个加法器,当S=1时电路变为一个减法器。每个异或门接收S的输入和B的某一位输入Bi。当S=0时,异或门实现的是Bi0,这时全加器接收B的值,且进位输入为0,电路执行A加B运算。当S=1时,有Bi1=Bi且C0=1,这时电路执行A加B的补码操作。

《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

3.11.1 有符号的二进制数
在前一部分中,我们处理了无符号数的加、减法。现在我们进一步使用补码,消除校正步骤,将上面的方法应用到有符号数。
正整数和数字零表示无符号数。为了表示负整数,我们需要给负号一个标记。在普通的算术运算中,负数是在前面加个负号表示,正数在前面添加正号。由于受硬件的限制,计算机用0和1表示所有的事物,包括数的符号。因此习惯上,在n位数字的最高有效位之前增加一位表示符号,并约定用0表示正数,1表示负数。
理解有符号数和无符号数在计算机中都表示成一串二进制数是至关重要的。用户决定数字是有符号数还是无符号数。如果一个二进制数是有符号数,那么最左边的那位表示符号位,其余位表示数值。如果假定这个二进制数是无符号数,则最左边的位为该数的最高有效位。例如,位串01001可以看作9(无符号数)或+9(有符号数),因为最左边的位为0。同样,位串11001如看作无符号数时表示25,看作有符号数时表示-9。后者是因为最左边的位指定为负号,剩下的4位表示值9。一般来说,确定位串的值是没有争论的,因为位串表示的类型事先已知道。刚刚讨论的有符号数表示法称为符号-数值(signed-magnitude)表示法。在这个表示法中,数字由一个数值和一个代表正负性的符号(+或-)或位(0或1)组成。这就是普通算术运算中的有符号数表示法。
在n位有符号数的符号-数值加、减法运算中,最左边的符号位与n―1位数值部分是分别处理的。数值部分的运算与无符号的二进制数的处理步骤相同。因此,减法仍包含结果校正步骤。为了避免这一步骤,我们采用一种不同的表示法—符号-补码(signed-complement)表示法来表示负数。在这个表示法中,负数用补码表示。符号-数值表示法通过改变符号来表示负数,而符号-补码表示法则通过求补来表示负数。由于正数总是从最左边的0(表示正号)开始,故其补码总是从1开始以表示负数。虽然符号-补码表示法可以采用一进制补码(二进制反码)和二进制补码表示,但二进制补码更为普遍。举例来说,如采用8位二进制数表示数字9。+9表示成最左端为0,再紧跟等于9的二进制数,即00001001。注意到所有的8位都必须有明确的值,因此在符号位和第一个1之间插入0。尽管+9只有一种表示方法,但是-9采用8位二进制数表示有两种不同的方法:
符号-数值表示法:10001001
符号-二进制补码表示法:11110111
在符号-数值表示法中,-9可以通过将+9的符号位由0变为1得到,而在符号-二进制补码表示法中,-9通过对正数即+9取补得到,包括符号位0。
表3-13列出了4位有符号二进制数采用两种表示法的所有情况,同时还给出了该有符号数对应的十进制数值。注意两种表示法中正数的表示相同,最左边的位都为0。在符号二进制补码表示法中,0只有一种表示,总为正。符号-数值表示法中有正0和负0,这在普通的算术运算中是不会出现的。还要注意的是,两种表示法的负数其最左边的位都为1,从而使我们能区分正数和负数。我们可以用4位表示16个二进制数。在符号-数值表示法中,这16个二进制数中有7个正数、7个负数和2个有符号的0。在二进制补码表示法中,有7个正数、1个0和8个负数。
《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器
《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

符号-数值表示法通常用于普通的算术运算,但如果应用于计算机,由于符号位单独处理以及减法运算中的校正步骤,就显得比较笨拙。因此,在计算机中通常采用符号-补码表示法。接下来在有符号二进制数的算术运算中,负数将采用符号二进制补码表示,因为这在实际应用中非常盛行。
3.11.2 有符号二进制数的加法与减法
两个数相加,M+N,在符号-数值表示法中遵循普通运算规则:如果符号相同,两个数的数值部分相加,并将M的符号赋给结果。如果符号不同,M的数值部分减去N的数值部分。最终借位的发生与否决定补码的校正操作是否执行,并且和M的符号共同决定结果的符号。例如,由于两个数的符号不同,(0 0011001)+(1 0100101)使得0011001减去0100101,结果为1110100,产生了一个最高位借位1。这个借位表明M的数值小于N的数值,所以结果的符号与M相反,为负。这个借位还表示结果的数值,即1110100,必须取补才是正确的结果。将符号与校正后的数值部分合起来,我们得到最终结果10001100。
与符号-数值表示法相反,在符号二进制补码表示法中,加法运算不需要比较或相减,仅需要相加。对于二进制数,这个过程简单,可以按照下述方法进行:
用补码表示负数的两个有符号的二进制数加法运算,就是包括符号位在内的两个数相加。符号位处产生的进位位丢弃。
例3-21给出了有符号二进制数的加法。注意负数采用补码表示,相加得到的和,如果为负,也采用补码表示。
例3-21 采用补码的有符号二进制数的加法
《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

在这4个例子中,执行的操作是包含符号位在内的加法运算。符号位处产生的进位都被丢弃,结果为负数时,自动采用补码表示。 ■
负数的补码表示对习惯于符号-数值法的人来说是不太熟悉的。为了确定一个用符号二进制补码表示的负数的值,有必要将其转变成正数,用大家熟悉的形式表示出来。例如,有符号二进制数11111001是负数,因为它最左边的那位为1,它的补码为00000111,即+7。因此我们可以知道原始值等于–7。
用补码表示负数的两个有符号的二进制数的减法运算也同样很简单,具体描述如下:
对减数取补(包括符号位),再将其与被减数相加(包括符号位),丢弃符号位处产生的进位。
如果改变减数的符号,那么减法运算可以转变成做加法操作,即
(±A)―(+B)=(±A)+(―B)
(±A)―(―B)=(±A)+(+B)
对一个正数取补就得到了其相应的负数,反过来也成立,因为一个负数的补码就是其对应正数的补码。例3-22给出两数相减的实例。
例3-22 采用补码表示的有符号二进制数的减法
《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

最终的进位位丢弃。 ■
值得注意的是,在符号-补码表示法中,二进制数的加减运算与无符号数的加减运算遵循相同的运算规则,因而计算机只需要一套共同的硬件电路来处理这两种类型的算术运算。根据给定的数是无符号还是有符号,用户或程序员应当对这些加、减的结果进行不同的解释。因此,为无符号数设计的加减法器同样适用于有符号数。如果有符号数用二进制补码表示,那么就能使用图3-45的电路。
例3-23 电子秤的功能
在货物或材料称重的时候,通常将它们装到一个容器里。下面3个定义适用于称重的容器:
总重量—容器和其内物品的重量。
皮重—空容器的重量。
净重—物品的重量。
问题:对一个特别的电子秤,显示净重的功能可以由下列一系列操作实现:
1)将空容器放到秤上。
2)按下TARE按钮,显示当前空容器的重量。
3)将待称重的物品放到容器里(衡量总重量)。
4)从秤的显示上读出净重。
假设容器的重量(皮重)能被电子秤记录下来,
(a)需要实现什么算术逻辑?
(b)假设电子秤的最大刻度为2200克(最小单位为克)。实现运算需要多少位?
解答:(a)电子秤正在称重的是总重量,而显示的结果是净重。所以需要一个减法器来执行:
净重=总重―(记录的)皮重
由于容器和其内物品的重量至少不小于容器的重量,故计算的结果总是非负的。但是,
如果使用者想利用这个功能来区分两个物品的重量差异,那么结果可能为负。在实际的电子秤设计中,负的结果在显示逻辑中也要一并考虑。
(b)假定重量和减法运算采用二进制数表示,则需要12位表示2200克。如果重量和减法用BCD码表示,那么需要2+3×4=14位。 ■
3.11.3 溢出
为了得到加、减运算的正确结果,我们必须确保有足够多的位来存放结果。如果两个n位数产生的结果需要n+1位保存,那么我们称发生了溢出(overflow)。无论是有符号数还是无符号数,对二进制或十进制数来说溢出的概念都是相同的。当用纸和笔来演算加法时,不存在溢出问题,因为纸的宽度是足够的。我们可以在数字的最高有效位前增加一位,如在正数前加一个0,在负数前加一个1,将其扩展为n+1位,再来执行加法。而对计算机来说就存在溢出问题,因为存放数的位数是固定的,超出这个位数表示范围的结果不能存储。由于这个原因,计算机要适时检测,当发生溢出时,应能发出信号。计算机要能中断程序的执行,采取特殊的操作自动处理溢出。一个可供选择的方法是利用软件监视溢出状态。
两个二进制数相加的溢出检测依赖于这些数是有符号还是无符号。当两个无符号数相加时,如果最高有效位处产生进位,则表明发生溢出。对于无符号数的减法,结果的数值总是等于或小于两个操作数较大的那个,溢出是不可能发生的。在符号-二进制补码表示法中,最高有效位表示符号。当两个有符号数相加时,符号位作为数的一部分处理,最终的进位1不能指示溢出。
对于有符号数的加法,如果一个数为正,另一个数为负,则溢出不会发生,因为负数加正数产生的结果的数值等于或小于两个操作数中较大的那个。如果两个加数都为正或都为负,那么溢出可能发生。为了考察溢出是如何发生的,我们来看下面二进制补码的例子:两个有符号数,+70和+80,用两个8位寄存器存储。8位二进制数的表示范围用十进制表示,每个寄存器可以存储+127~-128之间的数。由于两个数的和等于+150,超出了8位寄存器的存储范围。-70和-80相加也是如此。这两个加法以及两个最高有效位的进位如下所示:
《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

注意,应该为正的8位结果其符号位为负,该为负的8位结果其符号位反而为正。但是,如果把符号位产生的进位看作结果的符号,那么得到的9位结果是正确的。但是没有地方存储第9位,因此发生了溢出。
溢出的检测可以通过观察符号位的进位输入和符号位的进位输出来判定。如果这两个进位不相等,则产生了溢出。刚讨论的二进制补码实例就说明了这种方法,两个进位都明确地标了出来。如果把这两个进位输入到一个异或门,则当异或输出为1时,就表示发生了溢出。为了用此方法保证二进制补码运算的正确性,加法器在对减数求反再加1时,或者求两个补码相加时需添加一个溢出检测电路。这是因为对最大的负数取补时也会发生溢出。
一个简单的溢出检测逻辑如图3-46所示。如果两数为无符号数,那么C为1时表示加法运算产生了一个进位(即发生溢出),对于减法则指明不需要校正步骤。当C为0时表明加法运算没有产生进位(即没有溢出),对于减法则指明需要对结果进行校正。《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

如果参加运算的是有符号数,那么输出V用来表示溢出。若加或减运算后V=0,则表示没有发生溢出,结果正确。若V=1,则运算结果有n+1位,但仅仅最右边的n位保存了下来,所以产生了溢出。第n+1位实际是符号位,但是它不能占用结果的符号位。
乘法器与除法器 一些关于乘法器和除法器的补充讨论参见本书配套的网站。
3.11.4 加法器的HDL模型
到目前为止,我们所讲述的HDL描述实例都只包含一个实体(VHDL)或模块(Verilog)。不过采用层次结构描述的电路有多个实体,每个实体对应层次中不同的组件,如例3-24所示。
例3-24 四位行波进位加法器的VHDL结构描述
图3-47与图3-48中的实例使用3个实体构建了一个四位行波加法器,结构体采用结构和数据流的混合描述方式。3个设计实体分别为半加器、采用半加器的全加器以及四位加法器本身。half_adder的结构体包含两个数据流赋值语句,一个对s赋值,一个对c赋值。full_adder的结构体采用half_adder作为组件。另外,还声明了3个内部信号hs、hc和tc,这些信号连接至两个半加器上,并使用一个数据流赋值语句以实现图3-42所示的全加器。在adder_4实体中,4个全加器组件使用图3-43给定的信号简单地连接在一起。

《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

注意C0和C4分别为输入和输出端口,而C(0)到C(4)是内部信号(即它们既不是输入也不是输出端口)。C(0)赋值给C0,C(4)赋值给C4。在此,C(0)和C(4)两个信号并不是必需的,但用来说明VHDL的约束非常有用。假设我们想像图3-46所示的加法器一样添加一个溢出检测,如果没有定义C(4),那么溢出表达式为:
V <= C(3) xor C4
这在VHDL中是错误的,因为输出信号不能当作内部信号使用。因此代替C4定义一个内部信号(例如C(4))是非常有必要的,这样溢出表达式变为:
V <= C(3) xor C(4)

《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

3.11.5 行为描述
接下来以四位加法器为例介绍比逻辑级更高的电路描述,这种描述称为行为或者寄存器传输级描述,我们将在第6章具体讲述寄存器传输。虽然在本章还没介绍寄存器传输的相关知识,我们仍将在此介绍行为级的描述方法。
例3-25 四位行波进位加法器的VHDL行为描述
图3-49是四位加法器的行为描述。在adder_4_b的结构体中,加法逻辑使用+和&运算实现,+表示相加,&表示一个拼接(concatenation)操作。拼接操作将两个信号拼接成一个信号,拼接后的信号位数等于所有原始信号的位数之和。如本例中,'0'&A代表信号向量
'0'A(3)A(2)A(1)A(0)
该向量为1+4=5位。注意,拼接操作最左边的'0'在得到的信号列表的左端。加法运算的输入都一致地转换成5位,因为包含C4的输出为5位。这种转换不是必需的,但却是一种安全的方法。
因为std_logic类型不能执行+运算,我们需要另外一个程序包来定义std_logic类型的加法。在这里,我们使用了一个ieee库里的std_logic_arith程序包。另外,我们需要明确定义无符号数的加法,因此又使用了扩展的unsigned程序包。在VHDL中,拼接操作不能出现在赋值语句的左边。为了从加法的结果中获取C4和S,结构体中声明了一个5位的内部信号sum,sum信号是包括进位的相加结果。下面的两个赋值语句将sum分解成C4与S后输出。

《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

例3-26 四位行波进位加法器的Verilog层次描述
图3-50的描述采用了三个模块来表示四位行波进位加法器的层次构架。该设计风格是结构化描述和数据流描述的混合。这三个模块分别是一个半加器、一个使用半加器构建的全加器以及四位加法器本身。
half_adder模块由两个数据流赋值语句组成,一个对s赋值,一个对c赋值。full_adder模块如图3-42一样采用half_adder作为组件实现。在full_adder中,声明了三个内部连线,hs、hc和tc。输入、输出和这些连线加载到两个半加器,同时tc与hc进行逻辑或产生进位c。注意相同的名称可以应用到不同的模块中(例如,x、y、s和c同时应用到half_adder与full_adder两个模块中)。
在adder_4模块中,4个全加器使用图3-43中给出的信号简单地连接在一起。注意C0和C4分别是输入和输出,而C(3)到C(1)是内部信号(既不是输入也不是输出)。
例3-27 四位行波进位加法器的Verilog行为级描述
图3-51给出了4位加法器的Verilog描述。在adder_4_b_v模块中,使用“+”和“{}”两个操作符实现了加法逻辑,“+”表示加法运算,“{}”表示拼接操作。对连线数据类型执行“+”运算的结果为无符号数。拼接操作将两个信号组合成一个信号,结果信号的位数为两个原始信号的位数之和。在本例中,{C4,S}表示信号向量
C4 S[3] S[2] S[1] S[0]

《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

得到的信号位数为1+4=5。注意,出现在拼接操作符左边的C4,它的位置处在所得到的信号的左边。

《逻辑与计算机设计基础(原书第5版)》——3.11 二进制加减法器

上一篇:转载:Ubuntu下deb包的安装方法


下一篇:刀片与虚拟化结合将实现云计算基础