☰
从半加器到全加器:用Logisim构建4位加法器实战解析
2026/10/4 6:10:34 网站建设 项目流程

1. 为什么学计算机的人都绕不开这个加法器实验

先聊点题外话。很多人第一眼看到“logisim 实验:通过 2 个半加器实现 1-bit 全加器,通过 4 个一位全加器构成 4-bit 加法器”这个题目,内心多半是“这有什么好写的?不就是画个电路图吗”。但我可以负责任地说,这个实验是数字逻辑和后续 CPU 设计之间真正的分水岭。我当年是在《计算机组成原理》实验课上第一次在 Logisim 里把 4 个一位全加器串起来,当时觉得不过是在连线,后来学到 ALU、流水线进位、溢出标志位,才发现当年亲手接过的这条进位链,几乎是理解整个处理器核心运算逻辑的基础。

这个项目标题里其实隐藏了三层递进关系。第一层是半加器,它处理两个二进制位的相加;第二层是全加器,它把人人都容易忽略的“低位进位 Cin”引入加法过程;第三层是 4-bit 加法器,它把多个一位全加器按进位关系串联,扩展成能算多位二进制数的电路。三步走完,你不仅在 Logisim 里画出了一张能动的电路图,也把“组合逻辑电路设计”从理论变成了自己能亲手验证的东西。

这篇文章适合这几类人看:正在上数字逻辑课、需要交 Logisim 实验报告的同学;自学计算机底层,想搞懂加法器到底怎么工作的爱好者;还有打算做 CPU 设计实验,想先把数据通路基础打牢的人。我会尽量把每一步的“为什么”也讲清楚,而不只是告诉你该怎么连线,这样才能在换了一道类似题、甚至换了一个仿真工具之后,你依然能自己推出来。

2. 准备知识:Logisim 里需要掌握的“几个小动作”

2.1 Logisim 界面里你必须先认识的几个元件

Logisim 是一个教学用的数字电路仿真软件,常见版本是 2.7.1,开源、跨平台,很多学校的计算机组成原理课都用它。打开软件后,左侧栏是元件库,我们这次用到的都在“导线(Wiring)”和“门(Gates)”两个分类下面:

  • 输入引脚 / 输出引脚(Pin):在“导线”分类里。默认位宽是 1 位,可以双击改属性里的“位宽(Bit Width)”。输入引脚通常放在电路左边,输出引脚放在右边,这不是硬性规定,但这样画出来的图一眼就能看懂信号流向。
  • 与门(AND Gate)、或门(OR Gate)、异或门(XOR Gate)、非门(NOT Gate):在“门”分类里。默认输入数是 2,双击或改属性可以增加输入端口数。需要说明的是,全加器里的“第二个半加器”要求异或门,搭出来之后如果输出不对,先检查门的类型有没有选错。
  • 连线工具(箭头图标):默认选中状态下,点击一个引脚端口拖到另一个端口就能连线。只要端口之间是高亮状态,就说明这一头能连上,松手即可。
  • 文本标签(Text Label):用来给输入端、输出端、进位信号加注释。实验报告里老师一般都要求标注清楚 A、B、Cin、Sum、Cout,所以这个功能别忽略。
  • 探针(Probe)和小灯泡(LED):都可以用来观察信号状态。探针在“导线”分类里,LED 在“输入/输出”分类里,实测探针更方便,因为它能直接显示引脚名和当前电平。

Logisim 有一个对新手很不友好的细节:当你从元件库拖动元件时,默认是“选择模式”,也就是用鼠标拖动、连线;但如果你不小心敲击了键盘上的字母,会触发快捷放置元件的功能,比如按a会直接放一个与门,按x会放一个异或门,按i会放一个输入引脚。本来只想按 Ctrl+S 存盘,结果屏幕上冒出一个莫名其妙的元件,这种情况我见过太多人踩坑。万一出现,直接按 Delete 删掉就行,不用慌。

2.2 为什么是半加器 → 全加器 → 4-bit 加法器这个路线

先把这个“三步走”的设计逻辑理清楚,你后面才会有方向感。

半加器解决的是“两个二进制位相加”的问题。二进制加法和十进制一样,也可能出现进位,所以半加器要输出一个“和位”以及一个“进位位”。但它最大的问题在于,它完全没有考虑低位可能传上来的进位。做 1 位以内加法还好,一旦做多位加法,低位相加产生的进位必须传到高位参与运算,半加器就无能为力了。

全加器则是在半加器的基础上,多了一个输入端口 Cin(Carry in,低位进位输入)。它不仅要算 A 加 B,还要把 Cin 一起算进去。这样,多位二进制加法才能通过“低位进位 → 高位输入”的方式串联起来。这也是实验标题里“通过 2 个半加器实现 1-bit 全加器”的道理所在:半加器是积木,全加器是更完整的积木,而 4 个全加器串起来就是能算具体数字的 4-bit 加法器。

整个路线本质上是把复杂问题逐层分解。数字电路设计里最常用的思维方式是“先设计功能单元,再考虑如何组合扩展”,你跟着这个实验走一遍,以后不管是做计数器、乘法器还是 CPU 里的运算器,都会习惯性地先找“基础模块”。

3. 第一步:用 Logisim 搭出半加器

3.1 半加器的真值表与逻辑表达式

半加器(Half Adder)有两个输入 A、B,分别是被加数和加数;两个输出 S(Sum)和 C(Carry)。

先列出真值表:

ABS(和)C(进位)
0000
0110
1010
1101

从这个表可以直接看出两个逻辑关系:

  • S = A XOR B,异或门正好实现“两个输入不同则为 1”的规则。
  • C = A AND B,与门实现“两个输入都为 1 才输出 1”。

所以半加器在 Logisim 里的结构非常简单:一个异或门接出 S,一个与门接出 C,输入分别并联到两个门。这里有个需要注意的地方:很多人一开始会把 S 和 C 的输出接反,或者把异或门和或门混用,结果测试时看到 01 和 10 两种情况输出正确,但 11 时进位和和位对不上。所以每接完一步,立刻用真值表逐行测试,别等全部电路搭完再去查。

3.2 在 Logisim 里具体怎么连线

我按我演示时的步骤写一遍,你照做基本不会有问题:

  1. 新建一个项目,保存为half_adder.circ。
  2. 在左侧“导线”分类里拖出两个输入引脚,分别命名为 A、B。双击引脚可以修改标签,建议把位宽保持为 1。
  3. 拖出一个异或门(XOR Gate)和一个与门(AND Gate)。两个门可以垂直对齐摆放,异或门放上面,与门放下面,方便后续连线。
  4. 把 A 分别连到异或门的上面输入端和与门的上面输入端。B 分别连到异或门的下面输入端和与门的下面输入端。连线时鼠标靠近端口,端口会变亮,说明已经对准。
  5. 拖出两个输出引脚,一个命名为 S,一个命名为 C。S 接异或门输出端,C 接与门输出端。

连接完成后,点击菜单栏“仿真(Simulate)”里的“复位(Reset)”,然后用“手指工具”点击输入引脚切换电平。你按下 CTRL+T 可以持续自动仿真,也可以手动切换。把四行真值表都测一遍:

  • A=0,B=0 时,S=0,C=0;
  • A=0,B=1 时,S=1,C=0;
  • A=1,B=0 时,S=1,C=0;
  • A=1,B=1 时,S=0,C=1。

只要这四种情况全部对上,半加器就算完工了。

提示:Logisim 的默认仿真模式下,导线的颜色会随信号变化。在很多版本中,绿色/深绿色表示 0,亮绿色或淡绿色表示 1;也有的版本用蓝绿色调区分。如果你在连线后看到某个连接点是红色的小方块,说明有冲突或没接好,这不是正常的“逻辑 1”状态,需要重点检查。

3.3 半加器的局限:为什么单靠它不能做多位加法

这一步很容易被忽略,但恰恰是理解全加器的钥匙。

你试一下把两个半加器串联:让第一个半加器的 S 作为第二个半加器的一个输入,再给第二个半加器加一个“能表示低位进位”的输入,这不就是标题里的“全加器”了吗?但是在动手搭之前,先想清楚半加器的问题在哪。

半加器只有两个输入 A、B,当它做 1+1 的时候,输出 S=0、C=1,这个 C 就是进位。如果上面还有更高位,这个进位必须“加”到那一位的计算里。可是半加器自己根本没有另一个输入端口可以去接收这个来自低位的进位。所以只要超过 1 位,半加器单独就撑不住了。你需要一个带第三个输入 Cin 的全加器来接收它。这也是为什么实验标题强调“先实现全加器,再构成 4-bit 加法器”,顺序不能乱。

4. 核心环节:两个半加器加一个或门,组成全加器

4.1 全加器到底多了一个什么输入

全加器(Full Adder)有三个输入:A、B、Cin(低位进位输入),两个输出:Sum(和)、Cout(进位输出)。

列出全加器真值表:

ABCinSumCout
00000
00110
01010
01101
10010
10101
11001
11111

这个表值得多看两遍。你会发现 Sum 这一列和“三个输入中 1 的个数是奇数则输出 1”的规则对应,也就是说 Sum = A XOR B XOR Cin。而 Cout 这一列则是“三个输入中至少有两个 1 则输出 1”。这个规律不是巧合,它正是二进制加法进位的本质:只要参与相加的三个位里 1 的个数不少于 2,那结果必然产生进位。

4.2 两个半加器是如何配合的

现在来看标题里的关键操作:用两个半加器加一个或门来实现全加器。

第一个半加器负责计算 A 和 B 的和,输出一个中间和 S1,以及一个中间进位 C1。

第二个半加器负责把 S1 和 Cin 再相加,输出最终的 Sum;同时也会产生一个新的中间进位 C2。

这时候会出现一个情况:C1 和 C2 都可能是 1,那么最终 Cout 到底怎么取?逻辑是:只要 C1、C2 任意一个是 1,最终进位就是 1。所以用一个或门把 C1 和 C2 连接起来,输出就是 Cout。

这里有一个很多初学者会纠结的问题:C1 和 C2 会不会同时为 1?理论上不会,因为 A 和 B 如果同时为 1,第一个半加器的 S1 就是 0,那么第二个半加器无论如何也不会产生 C2=1;反过来,如果 A、B 不同时为 1,那么 S1 可能是 1,此时只有当 Cin=1 时 C2 才为 1,而 C1 在 A=1、B=0 或 A=0、B=1 时都是 0。所以两个中间进位最多只有一个为 1,或者两个都为 0,绝不会同时为 1。但也正因为如此,这里用或门是完全正确的,而不是异或门或与门。这个推论过程最好自己推一遍,比死记“加一个或门”要有效得多。

4.3 完整搭建步骤与连线细节

在 Logisim 里,你有两种做法:

第一种是“平铺法”,也就是在一张图里画两个半加器再加一个或门。第二种是“子电路法”,把之前做好的半加器保存成子电路,然后反复调用。这里我先讲平铺法,因为子电路法在 4-bit 加法器部分更常用,到时我会详细说。

平铺法的连线步骤:

  1. 新建一个电路,命名为full_adder,或者直接在原来的画布里接着画。
  2. 先画第一个半加器:一个异或门(XOR1)、一个与门(AND1)。这两个门的输入都接 A、B。
  3. 把 XOR1 的输出作为 S1,接到第二个半加器的第一个输入;把 AND1 的输出作为 C1,暂时留着,最后接或门。
  4. 画第二个半加器:再放一个异或门(XOR2)和一个与门(AND2)。XOR2 的一个输入接 S1,另一个输入接 Cin;AND2 的两个输入也分别接 S1 和 Cin。
  5. 把 XOR2 的输出命名为 Sum,这就是全加器的和位输出。
  6. 放一个或门(OR1),把 AND1 的输出 C1 和 AND2 的输出 C2 分别接到或门的两个输入,或门输出命名为 Cout。
  7. 把 A、B、Cin 三个输入引脚放好,把 Sum、Cout 两个输出引脚放好。

连完后测试一下,把三种 8 组输入全部试一遍。重点看 A=1、B=1、Cin=1 这一行,此时 Sum=1、Cout=1,代表 1+1+1 = 3,二进制数是 11。如果你发现这一行输出不是 11,问题大概率出现在 or 门或者第二个半加器的输入端接错了。

这里还有一个非常常见的实操问题:在 Logisim 里,当你同时拖动两条线靠近时,它们有时会自动合并成一个节点,这是仿真软件自动连线功能导致的。如果你不希望两条线被连在一起,可以选择“线束”工具或使用快捷键调整,或者干脆把信号的布局拉得更开,避免交叉。画电路图时,尽量养成“输入在左、输出在右、走线不交叉”的习惯,这能减少很多不必要的错误。

4.4 为什么全加器不是“半加器 + 半加器 + 或门”这么简单

这个问题听起来有点绕,但实际是实验报告里老师最爱问的思考题。答案是:结构上确实是“两个半加器 + 一个或门”,但每个半加器的输入输出角色并不相同。第一个半加器处理的是原始两个加数 A、B;第二个半加器处理的是第一个半加器的和 S1 与 Cin。如果你把 Cin 当成“另一个加数”,那第二个半加器本质上还是在做“两个二进制位相加”,只不过其中一位变成了进位输入。

所以全加器的内部结构并没有出现“三个数同时相加”的魔法,它只是通过两次两数相加,把三数相加结果拆解掉了。这个思想在后来的加法器优化(比如超前进位加法器)里也一样:用基本的门单元去组合,只是换了一种让进位更快产生的方式。

5. 第三步:用 4 个一位全加器构成 4-bit 加法器

5.1 并行加法器结构里的“进位链”

当你有了一个能处理 1-bit 的全加器,扩展到 4-bit 就顺理成章了。思路是把 4 个全加器按从低位到高位的顺序排好,让低位的 Cout 连接到高一位的 Cin。这就是典型的“行波进位加法器(Ripple Carry Adder)”,也是教科书里最朴素的加法器实现。

假设要计算 A3A2A1A0 + B3B2B1B0,最低位是第 0 位。最低位的 Cin 固定为 0(因为没有更低位给它进位了),然后:

  • 第 0 位:A0 + B0,产生 Sum0 和 C1,C1 接到下一位的 Cin;
  • 第 1 位:A1 + B1 + C1,产生 Sum1 和 C2,C2 接到下一位的 Cin;
  • 第 2 位:A2 + B2 + C2,产生 Sum2 和 C3,C3 接到下一位的 Cin;
  • 第 3 位:A3 + B3 + C3,产生 Sum3 和 Cout(第 4 位进位)。

最终结果是一个 5 位的二进制数:Cout Sum3 Sum2 Sum1 Sum0。这个 Cout 就是我们通常说的“溢出位/进位标志”,在 CPU 里会被写进状态寄存器。我当年做实验时,一开始把形成最终结果的顺序搞反了,导致把进位当成最高位,结果死活验算不对。这里要特别注意:最低位在最右边,最高位在最左边,和我们平时写二进制数的习惯一致。

5.2 在 Logisim 中如何快速补齐 4 位电路

在 Logisim 中你有两种方式:

方式一:每次都手动复制粘贴全加器。复制的时候选中整个全加器,按 Ctrl+C、Ctrl+V。但这样布线容易乱,而且元件名会重复,调试起来很痛苦。

方式二:把全加器封装成子电路,然后实例化 4 次。这也是我最推荐的方式,因为后面假如要改成 8-bit,只要再拉 4 个实例就行,不用重画整个加法器。

子电路步骤:

  1. 在工程面板里,右键点击电路列表,选择“添加电路(Add Circuit)”,把当前做的全加器电路重命名为FullAdder。
  2. 把这个电路的输入输出引脚整理好。这里要注意:Logisim 会自动识别电路里的输入引脚 Pin 和输出引脚 Pin,它们是子电路的对外接口。你双击子电路实例时,引脚的位置就是你在 FullAdder 电路里摆的位置。
  3. 回到顶层电路(可以新建一个adder4bit电路),从左侧元件库最下面找到“FullAdder”,直接拖 4 个出来。
  4. 把这 4 个 FullAdder 垂直排列,最下面是低位,最上面是高位。

接着开始连线。A0、B0 接到第一个全加器,它的 Cin 接地(也就是接逻辑 0),Cout 接到第二个全加器的 Cin,以此类推。最终第 4 个全加器的 Cout 就是进位输出 C4。

5.3 测试方案:输入、输出、以及用十进制验证

我强烈建议你在顶层电路里加 8 个输入引脚和 5 个输出引脚,分别表示:

  • A3 A2 A1 A0:加数
  • B3 B2 B1 B0:被加数
  • Sum3 Sum2 Sum1 Sum0:和
  • C4:进位输出

然后选几组典型数据测试:

十进制A 二进制B 二进制期望结果(二进制)
3 + 40011010000111
7 + 10111000101000
10 + 61010011010000(C4=1)
15 + 151111111111110(C4=1)

测试时最直观的方法是把输入引脚按顺序排列,比如最高位 A3 在最上面,最低位 A0 在最下面,然后从右往左读数据。比如 A=1010,就是从上到下点成 1、0、1、0。很多人在这一步会看反方向,导致测试结果和期望完全不符。

测完之后,把仿真输出和手算结果对比。如果 C4 为 1,代表结果超出 4 位二进制能表示的范围,这是正常现象,说明加法器正确实现了溢出的物理行为,而不是“算了 0”。这时候不要急着说错误,先看整体输出二进制序列是否和手算一致。

5.4 位宽知识:为什么不直接把输入引脚位宽改成 4

这个问题非常关键,也是很多人在做完之后才醒悟的。Logisim 里输入引脚可以设置位宽为 4,那样你可以输入一个 4 位向量,但门电路和全加器子电路的引脚位宽都是 1。即使你把输入位宽改成 4,也不能直接接到 1 位端口上,因为位宽不匹配,Logisim 会出现错误提示。

所以,在做这个 4-bit 加法器时,有两种合理策略:

  • 策略一:保持 1 位输入,并列放置 8 个输入引脚。这种做法接线清晰,适合教学实验和调试。
  • 策略二:把加法器封装成更大的子电路,让子电路内部用 1 位端口,外部再用位宽为 4 的引脚对接。这属于更高阶的用法,适合做 CPU 设计实验时复用。

我建议初学者先把策略一跑通。等你彻底明白了每个全加器只能处理 1 位,你再去研究位宽向量合并,就不会一头雾水。

6. 排错实录:我踩过并且你应该避开的坑

6.1 Logisim 仿真没反应,或输出全是 0

先排除最基本的问题:你点击输入引脚切换电平,但输出没有任何变化,大概率是输入引脚根本没有连到门电路上。在 Logisim 里,连线的判定非常严格,如果端口没有完全对齐,线会处于“悬空”状态,而不是自动吸附。检查时把鼠标悬停在导线上,如果发现某个端口高亮但导线没有连过去,重新拉线。

还有个容易忽略的点:电路顶层的“输入引脚”和“输出引脚”在默认状态下,位宽可能不是 1。如果你从元件库拖出来的是默认的 1 位引脚,但某个引脚属性里被改成了 4,那它接 1 位门时不会生效。解决办法是双击引脚,把位宽改回 1。

6.2 进位输出 Cout 总是得多 1 位

我见过太多人在这里卡壳。比如 0111 + 0001,手算是 01000(5 位),可是电路里只输出 4 位 Sum,最后的进位 C4 单独作为输出。如果你把 C4 和 Sum4 合并看数时,顺序写反,很容易把 01000 当成 00010,误判为“错误”。这里必须养成的习惯是:加法和手算一样,进位要写在最高位前面。在电路图上,我会把 C4 输出引脚放在 Sum3 的左边,这样从左往右读就是 C4 Sum3 Sum2 Sum1 Sum0,刚好对应 5 位二进制结果。

6.3 最低位的 Cin 忘了接 0

如果最低位的 Cin 悬空,Logisim 会默认把它当作未定义状态,而不是 0,这时结果会完全不可预测。正确的做法是往最低位全加器的 Cin 输入端接一个常数 0。在 Logisim 里可以在“导线”分类下找到“常量(Constant)”,把它的值设置为 0,然后连到最低位的 Cin 上。别忘了这个小小的连接,否则你整个加法器在所有奇数相加的情况下都可能出错。

6.4 门电路类型选错

全加器里,第一个半加器的和位用异或门,第二个半加器的和位也用异或门;进位合并用或门。如果你在“Cout = C1 OR C2”这一步误用了异或门,由于 C1 和 C2 不会同时为 1,功能上可能仍然正确,但一旦碰到某些边界情况,比如仿真器对悬空值的处理,就可能出现不可靠结果。而如果你把“S = A XOR B”误写成了“S = A OR B”,那么 1+1 时你会得到 S=1、C=1,算出来是 3 其实没错,但 1+0 和 0+1 时也没错,只有 0+0 时 S=0 也正确——看起来好像全对,但事实上你把加法和二进制真值表理解错了,等到做全加器时就会彻底乱套。所以每一步都要用真值表严格验证,不要只看一两个典型输入。

6.5 线的颜色和节点问题

Logisim 里连线交叉时,如果没有节点,两条线互不相连,只是视觉上交叉。有节点则代表相连。如果你画图时不小心在交叉点点击了一下,可能会自动生成节点,导致两条本不该相连的信号被短路。排查异常输出时,先检查所有交叉点,看看有没有意外出现的实心小圆点。如果不需要连接,直接选中节点按 Delete 删除。这个问题在图纸越复杂时越致命,因为它会悄无声息地改变整个电路的逻辑。

7. 后续的扩展:加法器还能怎么玩

做完这个 4-bit 加法器,其实你的实验基础已经很扎实了。我再提供几个扩展方向,你可以根据兴趣尝试。

7.1 用加法器实现减法

有了加法器,减法并不难。减去一个数,等于加上它的补码。对一个二进制数取反加 1,就得到它的补码。你可以在 B 输入端前面加一排非门取反,再把最低位的 Cin 从 0 改成 1,这样整个电路就相当于在算 A + (~B) + 1,也就是 A - B。扩展之后,你会更加理解为什么 CPU 里加法器才是核心,减法只是个“变体”。

7.2 用子电路封装出可复用加法器

把 4-bit 加法器封装成一个子电路,然后实例化两次,就能组合出 8-bit 加法器。配合 Logisim 的位宽设置,你还可以做一个更通用的参数化加法器。这在后面做单总线 CPU 设计、只有 ADD 指令的微型计算机实验时会非常有用。反正我当年做单总线 CPU 时,整个 ALU 就是从 4-bit 加法器慢慢扩展来的。

7.3 研究更快的进位方式

行波进位加法器每高一位都要等低位的进位算出来,速度慢得感人。感兴趣的话可以去搜索“超前进位加法器(Carry Look-Ahead Adder)”的实现思路,它在电路里用额外逻辑直接计算各位的进位,而不是逐级传递。虽然实验不一定要求,但能亲手在 Logisim 里画出这种优化结构,对理解“电路速度和复杂度平衡”这个问题帮助极大。

最后再分享一个我个人的习惯:每次搭完一个子电路,我都会复制一份留底,然后在原图上用不同颜色把输入、输出、进位路径分开标注。实验课上我还见过有人用笔在纸上把每个元件的真值表先写出来再连线,虽然看起来慢,但极大减少了返工时间。你愿意的话,也可以试试:先在纸上画好结构图,再打开 Logisim 照图连线,而不是一边想一边连。这种“先设计、再实现”的顺序,才是这个实验真正想教给你的东西。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询