加法器的实现及优化

1、半加器

半加器有一个异或门和与门组成,异或门赋值记录数值,与门记录是否产生了进位。但是半加器是无法完成加法运算的。

需要完成加法运算,需要用到全加器

2、全加器

全加器由两个半加器组成,绿色的为一个半加器,橙色的为另一个半加器。三个输入,两个输出。

两个输出表示了他能表示的范围为0,1,2,3  对应的二进制则为表上的Cout 与 S

例如进行1+1的运算时

先来看看S的输出:

A端输入1,B端输入1,C端输入0(最低位加法运算默认为0),1(A)异或1(B) 结果为0(记为D)0(D)+0(Cin)结果是0,所以绿色的异或门输出(S)为0,说明该位的运算结果为0。

再来看看Cout(进位)的输出:

1(A)与1(B) 结果为1,说明产生了进位,橙色的与门输出1。由S的输出过程可得绿色的与门的输入为0,0,绿色的与门输出为0,这个时候需要一个或门即可判断两次加法(A+B和B+Cin)是否产生了进位,只要其中一个产生的进位,Cout置1。

运算结果:

将Cout与S连起来,就是10,也就是2。

 

减法的实现:

减法实际上就是加法  A-B 可以表示为 A+ (-B)  这个-B可以用补码来表示。

如上图所示,sub-mode负责加减法的选择,同时他连接到最低位的Cin端。

如果为加法,则sub-mode为0,那么直接进行加法运算

如果为减法,则sub-mode为1,最低位数字Cin(C0端)被置为1,同时控制电路对B的每一位是输入数字作取反处理,这样就完成的(-B)补码的“按位取反,末位加一”的操作。然后按加法运算即可

 

 

3、行波进位加法器

行波进位加法器就是由n个全加器构成的,可以运算n位的加法。

例如计算:1101+0110。将每个低位的Cout(进位输出)作为对应高位的Cin(进位输入)。

这里Cout最高位为1,而假设我们当前的寄存器的位数为4位,则产生了溢出。

溢出和进位的区别:

溢出:表示数据超过了正常的表示范围,如果采用浮点表示还分成上溢出和下溢出。

进位:N进制进位这个就是逢N进一

需要注意,溢出和进位并没有直接关系。溢出的发生只在有符号位时发生,也就是说你的机器数是带符号的就有可能产生溢出。

 

判断溢出的方法:

1、最高位数值和符号位都发生了进位或者都不产生进位,则没有溢出。最高位数值和符号位有一个产生进位,另一个没有进位,则为溢出。计算机实现用异或电路

例如 1,111+0,100 ->10011(舍去最高位) ,最终结果为 0,011  未发生进位

2、如果采用两位符号位表示,原理和方法1一样,采用了两位符号位来记录原来的1位符号位和最高数值位的进位情况,这样就不需要用异或电路。符号位为00或11则未溢出,如果为01为正溢出(此时真正的符号位正),10为负溢出(此时真正的符号为负)

 

行波进位加法器的运算过程:

在进行加法运算时,首先准备好的是(从右往左为1,2,3,4号)1号全加器的3个input。而2、3、4号全加器的Cin全部来自前一个全加器的Cout,只有等到1号全加器运算完毕,2、3、4号全加器才能依次进行进位运算,最终得到结果。 这样进位输出,像波浪一样,依次从低位到高位传递, 最终产生结果的加法器,也因此得名为行波进位加法器(Ripple-Carry Adder,RCA)。

RCA的优点是电路布局简单,设计方便, 我们只要设计好了全加器,连接起来就构成了多位的加法器。 但是缺点也很明显,也就是高位的运算必须等待低位的运算完成, 这样造成了整个加法器的延迟时间很长。那么,RCA的效率到底如何呢?让我们来算一算:

将4bit的RCA内部结构全部打开,就得到了如图2所示的4-bit RCA的门电路图。要对一个电路的性能进行分析,我们就要找出其中的最长路径。 也就是找出所有的从输入到输出的电路连接中,经过的门数最多的那一条,也称为关键路径(如下图所示)。

 

判断延迟的两个指标:

(1)门延迟

经过每个门所花费的实际,称为门延迟

(2)线延迟

输入信号进入到这块电路之后,在连接线上传递需要花时间。 称为线延迟

 

行波进位加法器的延迟分析:

以只考虑门延迟为例

.从第一个全加器的A-S这条通路来看,产生第一个S输出,需要通过两个门的延迟。 所以它显然不是最长的路径,当然,从A出发或着从B出发都是一样的, 所以对于第一个全加器,它的最长路径,是红色线标记的那条,后面的全加器关键路径同理可得。

那么,假设经过一个门电路的延迟时间为T,那么经过4个全加器所需要的总延迟时间就是:2T x 4 + T(第一个全加器产生3个T) = 9T。所以推出,经过n个全加器所产生的总延迟时间为2T x n + T = (2n+1)T。

对于一个32bit的RCA,有总延迟时间:(2n+1)T =(2×32+1)×T =65T,这是什么概念呢?举个例子,iPhone 5s的A7 SoC处理器采用28nm制造工艺,主频1.3GHz(0.66ns  CPU时钟周期中每两个上沿所隔的时间)。按照这个工艺水平,门延迟T设为0.02ns,那么32-bit RCA的延迟时间为1.3ns ,时钟频率为769MHz,远超A7处理器的主频延迟时间,更别说这个32bit的RCA只是一个加法运算器,更更别说,我们在计算过程中只考虑了门延迟,还有线延迟等各种延迟没有加入计算……

 

4、超前进位加法器

从上面可以看到,影响行波进位加法器(RCA)运算效率的主要因素是高位的运算必须等待低位的“进位输出信号”,那我们的优化思路就是‘能否提前计算出“进位输出信号’ ?”

答案是有的,如图所示。

全加器有三个输入,当其中的两个为1时,必定产生进位。这样就有了如下的公式:

Ai Bi Ci 分别是全加器的三个输入,Ci+1为进位输出 Ci为进位输入。

如果是最低位,则Ci=C0,C0根据加法或是减法置为0或者1。

简化公式得:

如果表示4个全加器的进位输入输出:

可以得到由每个低位全加器的进位输出得到每个高位全加器的进位输入。

最终我们需要得到的是C4,经过换算,C4=G3+P3·G2+P3·P2·G1+P3·P2·P1·G0+P3·P2·P1·P0·C0,而这些参数,全部已知!并不需要前一个全加器运算输出,由此我们得到了提前计算进位输出的方法, 用这样的方法实现了加法器就被称为超前进位加法器(Carry-Lookahead Adder,CLA)。

这样就实现了提前获得进位输入的能力,这样就大大提高了加法运算的效率。但有得必有失,这样的代价是电路比较复杂。

 

超前进位加法器的实现

C4的结果由或门实现,把每个多项式进行求和,乘用与门实现。

延迟分析

使用CLA来进行加法运算的效率如何呢?还是按照Apple A7处理器的工艺水平,单个CLA的延迟为0.08ns,4级CLA的延迟为0.26ns,时钟频率3.84GHz,都远远小于主频的延迟,完全符合标准。然而,由图可见,计算4bit的二进制数,就要平行排列4个全加器,那么要是计算8bit,16bit,32bit……的呢?可能就需要更复杂的布线方式,这就是CLA的缺点。

比较一下RCA和CLA的优缺点:

 行波进位加法器(RCA)超前进位加法器(LCA)
结构特点低位全加器的Cout连接到高一位全加器Cin每个全加器的进位输入并不来自于前一级的全加器,而是来自超前进位的逻辑电路
优点电路布局简单,设计方便计算Ci+1的延迟时间固定为三级门延迟,与加法器的位数无关
缺点高位的运算必须等待低位的运算完成,延迟时间长如果进一步拓宽加法器的位数,则电路变得非常复杂

 

 

 

 

 

 

 

32位的加法器如果采用行波进位的方式,我们已经分析过需要65级的门延迟, 那如果采用超前进位的方式,理想情况下也只需要四级的门延迟,但可惜的是, 这也只是一个理想。因为要实现32位的完全的超前进位,电路就会变得非常的复杂。 因此通常的实现方法, 是采用多个小规模的超前进位加法器拼接而成一个较大的加法器,例如,用4个8-bit的超前进位加法器连接成32-bit加法器。

 

 

 

  • 6
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: TCL是一种脚本语言,可以用于快速编写和执行程序。要实现补码加法器的功能,我们可以使用TCL编写一个函数来完成此任务。 首先,我们需要定义一个函数,例如addition,用于接收两个补码数字作为输入,并返回其和的补码。 函数的实现步骤如下: 1. 首先,我们需要将输入的两个补码数字转换为整数。补码的转换可以通过判断最高位是否为1来确定符号,并进行逆码的转换得到原码。然后,将原码转换为十进制整数。 2. 接下来,将两个整数相加得到结果。 3. 将结果转换为补码形式。如果结果是负数,需要将结果转为逆码,再取反得到补码。如果结果是正数,直接将结果转换为补码即可。 4. 返回结果的补码形式。 以下是一个简单的实现示例,供参考: ```tcl # 定义补码加法器函数 proc addition {binary1 binary2} { # 将补码转换为整数 set num1 [expr {[binary1 >= 2**7] ? (int(binary1) - 2**8) : int(binary1)}] set num2 [expr {[binary2 >= 2**7] ? (int(binary2) - 2**8) : int(binary2)}] # 两个整数相加 set sum [expr {$num1 + $num2}] # 将结果转换为补码形式 set result [expr {($sum >= 0) ? $sum : (2**8 + abs($sum))}] # 返回结果的补码形式 return $result } # 测试案例 set binary1 11000111 ;# 补码为-49 set binary2 01010101 ;# 补码为85 set result [addition $binary1 $binary2] puts "结果补码:" $result ;# 输出补码结果 ``` 在上述示例中,输入的两个补码为"11000111"(-49的补码)和"01010101"(85的补码),通过调用addition函数计算后,得到结果补码为"00010010"(18的补码)。 ### 回答2: TCL语言可以通过以下代码实现补码加法器: ```tcl #定义补码加法函数 proc twosComplementAddition {number1 number2} { #将两个数转换为补码形式 set binary1 [format "%08s" [binary format B $number1]] set binary2 [format "%08s" [binary format B $number2]] #获取补码加法的结果 set sum [binary format B [expr {binary format B [expr {binary scan $binary1 b* decimal1; binary scan $binary2 b* decimal2; ($decimal1 + $decimal2) & 0xFF}] & 0xFF}]] #将结果转换为十进制形式 set result [expr {binary scan $sum B* decimal; binary format I $decimal}] return $result } #测试补码加法函数 set number1 -10 set number2 5 set result [twosComplementAddition $number1 $number2] puts "补码加法的结果为:$result" ``` 上述代码中的`twosComplementAddition`函数实现了补码加法的功能。该函数首先将输入的两个数转换为8位的补码形式。然后进行补码加法运算,将结果存储在`sum`变量中。最后,将`sum`变量转换为十进制形式作为函数的返回值。在测试部分,将-10和5作为输入参数调用`twosComplementAddition`函数,并将结果打印输出。 在输出中,补码加法的结果应该为-5,即-10 + 5 = -5。 ### 回答3: 补码加法器是计算机中常用的一种电路,用于对两个补码进行加法运算,并得出结果。TCL语言是一种解释性脚本语言,可以用于快速编写、测试和执行各种计算任务。下面是使用TCL语言实现补码加法器的一种方法: ```tcl # 初始化输入补码 set a "0110" ;# 第一个补码 set b "1010" ;# 第二个补码 # 判断输入位数是否相同,如果不同,则在短的补码前面补0 set diff [expr {[string length $a] - [string length $b]}] if {$diff > 0} { set b [string repeat "0" $diff]$b } elseif {$diff < 0} { set a [string repeat "0" -$diff]$a } # 定义一个变量carry作为进位标志 set carry 0 # 定义结果变量 set result "" # 从低位到高位逐位相加 for {set i [expr {[string length $a] - 1}]} {$i >= 0} {incr i -1} { set bit_a [string index $a $i] set bit_b [string index $b $i] # 计算当前位的和 set sum [expr {${bit_a} ^ ${bit_b} ^ ${carry}}] # 更新进位 set carry [expr {(${bit_a} & ${bit_b}) || ((${bit_a} ^ ${bit_b}) & ${carry})}] # 将当前位的和插入到结果的最前面 set result "${sum}${result}" } # 输出结果 puts "加法结果为:$result" ``` 以上代码实现了一个简单的补码加法器。首先,我们通过设置变量`a`和`b`来表示输入的两个补码。然后,我们检查两个补码的位数是否相同,并在较短的补码前面补零,以保证它们的位数一致。接下来,我们使用for循环从最低位到最高位逐位相加,并使用`^`、`&`和`|`等位运算符来计算每一位的和、进位和更新进位。最后,我们将计算得到的每一位和插入到结果的最前面,并输出最终结果。 请注意,以上代码仅实现了简单的补码加法器,可能还需要考虑更多的特殊情况(如溢出等)。此外,TCL语言也提供了更多的位运算函数和操作符,可以根据具体需求进行调整和优化

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值