跳转到内容

微处理器设计/加减模块

来自维基教科书,自由的教科书,自由的世界

加法和减法

[编辑 | 编辑源代码]

加法和减法是相似的算法。看一下减法,我们可以看到

利用这种简单的关系,我们可以看到加法和减法可以使用相同的硬件来执行。然而,使用这种设置时,必须注意在执行减法时反转第二个操作数的值。还要注意,在二进制补码算术中,第二个操作数的值不仅要反转,还要加 1。因此,在执行减法时,LSB 的进位输入应该是 1 而不是 0。

那么,我们在本页的目标是找到适合执行加法的硬件。

位加法器

[编辑 | 编辑源代码]

半加法器

[编辑 | 编辑源代码]

半加法器是一种对两个位进行二进制加法的电路。半加法器没有明确考虑进位输入信号。

在 SystemVerilog 中,可以按以下方式实现半加法器

module half_adder(input logic a, b, output logic carry_out, sum);
  assign {carry_out, sum} = a + b;
endmodule

全加法器

[编辑 | 编辑源代码]

全加法器电路类似于半加法器,不同之处在于它们考虑了进位输入和进位输出。全加法器可以被视为一个 3 位加法器,具有 2 位结果,也可以被视为一个较大加法器中的单个阶段(一个 3:2 压缩器)。


如下所示,全加法器电路中的门延迟数量为 3

我们可以使用 Verilog 实现全加法器模块

module full_adder(a, b, cin, cout, s);
   input a, b, cin;
   output cout, s;
   wire temp;
   temp = a ^ b;
   s = temp ^ cin;
   cout = (cin & temp) | (a & b);
endmodule


串行加法器

[编辑 | 编辑源代码]

串行加法器是一种 ALU,它一次计算输出的每一位,重新使用一个全加法器(总计)。此图像显示了一个 2 位串行加法器,以及相关的波形。

串行加法器的优点是它们在所有加法器中需要最少的硬件,但它们速度最慢。

并行加法器

[编辑 | 编辑源代码]

并行加法器是一种 ALU,它使用一个全加法器来计算输出的每一位,基本上是同时计算的。1947 年的 Whirlwind 计算机是第一个使用并行加法器的计算机。

在许多 CPU 中,CPU 在 “状态寄存器” 中将并行加法器的最终进位输出锁存到外部 “进位标志” 中。

在一些 CPU 中,锁存的进位标志值始终连接到并行加法器的第一个进位输入;这使得使用 2 的补码加法进行 “带进位的加法”。(在极少数 CPU 中,循环进位 - 并行加法器的最终进位输出直接连接到相同并行加法器的第一个进位输入 - 执行 1 的补码加法)。

行波进位加法器

[编辑 | 编辑源代码]

长度超过 1 位的数字需要不止一个全加法器才能使用算术和按位逻辑指令进行操作[需要引用]。操作较大的数字的一种简单方法是将多个全加法器模块级联在一起,形成一个 行波进位加法器,如上所示。行波进位加法器之所以这样称呼,是因为进位值从一个模块“传播”到下一个模块,一直传播到整个全加法器链。在进位信号完全传播到整个全加法器链之前,高位位的输出值不正确,算术运算也不完整。

如果每个全加法器需要 3 个门延迟才能完成计算,那么一个 n 位行波进位加法器将需要 3n 个门延迟。对于 32 位或 64 位计算机(或更高),这种延迟可能非常大。

行波进位加法器的优点是它们在所有加法器中需要最少的硬件(串行加法器除外),但它们速度最慢(串行加法器除外)。

使用我们上面定义的全加法器 Verilog 模块,我们可以在 Verilog 中定义一个 4 位行波进位加法器。可以逻辑地扩展加法器

wire [4:0] c;
wire [3:0] s;
full_adder fa1(a[0], b[0], c[0], c[1], s[0]);
full_adder fa2(a[1], b[1], c[1], c[2], s[1]);
full_adder fa3(a[2], b[2], c[2], c[3], s[2]);
full_adder fa4(a[3], b[3], c[3], c[4], s[3]);

在这个模块的最后,s 包含 4 位的和,而 c[4] 包含最终的进位输出。

这种“行波进位”安排使得“加法”和“减法”比 ALU 的其他运算(AND、NAND、左移、除以二等)花费的时间长得多。一些 CPU 使用行波进位 ALU,并要求程序员插入 NOP 来给“加法”留出足够的时间来完成。[1] 其他一些 CPU 使用行波进位加法器,只是将时钟频率设置得足够低,这样进位位就有足够的时间通过加法器传播。还有一些 CPU 使用行波进位加法器,并使“加法”指令的执行周期比“异或”指令多,以便进位位在“加法”运算中可以通过加法器有更多的时间进行传播,但不会在“异或”运算期间不必要地减慢 CPU 的速度。但是,如果每个指令的执行周期数相同,那么流水线会变得简单得多。

进位跳跃加法器

[编辑 | 编辑源代码]

进位超前加法器

[编辑 | 编辑源代码]

进位超前加法器使用特殊的 “超前” 模块来计算 4 个全加法器组的进位,并将此进位信号传递到下一个 4 个全加法器组。超前单元也可以级联,以最大限度地减少进位信号完全传播到链条末端的门延迟数量。进位超前加法器是速度最快的加法器电路之一,但它们需要大量的硬件来实现。实现进位超前加法器所需的晶体管数量与输入数量的立方成正比。

两个一位输入 AB 的加法如果在进位输入情况下(或者等效地,无论较低有效位的和是否进位),加法总是进位,则称为 产生。例如,在十进制加法 52 + 67 中,十位数字 5 和 6 的加法 产生,因为无论个位数字是否进位,结果都会进位到百位数字(在这个例子中,个位数字显然不会进位)。

在二进制加法中, 产生当且仅当 AB 都为 1。如果我们写 来表示当且仅当 产生时为真的二元谓词,我们有

两个一位输入 AB 的加法被称为传播,如果加法在有输入进位时会进位(等价于,当和的下一个较低有效位进位时)。例如,在十进制加法 37 + 62 中,十位数字 3 和 6 的加法传播,因为如果个位进位(在本例中,它没有),结果会进位到百位。注意,传播和产生是相对于加法的一个单独的数字定义的,不依赖于和中的任何其他数字。

在二进制加法中, 传播当且仅当 AB 中至少有一个为 1。如果我们写 来表示当且仅当 传播时为真的二元谓词,我们有

级联加法器

[编辑 | 编辑源代码]

先行进位加法器的强大之处在于,加法器的位长可以扩展,而不会过分增加传播延迟。通过级联先行进位模块,并将“传播”和“产生”信号传递到先行进位模块的下一级。例如,一旦我们将 4 个加法器组合成一个简单的先行进位模块,我们就可以使用它通过级联来创建 16 位和 64 位加法器。

16 位先行进位单元与 4 位先行进位加法器完全相同。
64 位先行进位单元与 4 位和 16 位单元完全相同。这意味着,一旦我们设计了一个先行进位模块,我们就可以将其级联到任何更大的尺寸。

广义级联

[编辑 | 编辑源代码]
广义 CLA 模块图。每个青绿色块代表一个较小的 CLA 加法器。
我们可以将上面的广义 CLA 模块级联起来,形成一个更大的 CLA 模块。然后,这个更大的模块可以使用相同的方法级联成一个更大的 CLA 模块。
  1. "MuP21 Machine Forth": "Ripple Carry on + and +*"
华夏公益教科书