资讯详情

从逻辑门到完整4位ALU:手把手搭建CPU算数核心

📅 2026/10/7 5:21:49 | 华诺云谱 👁 阅读
从逻辑门到完整4位ALU:手把手搭建CPU算数核心
如果问一个学计算机的人CPU里最核心的部件是什么十有八九会回答ALU。但不少人学完计算机组成原理ALU始终是课本上那个模糊的方块图里面到底怎么工作完全没概念。我当初也是这样——直到自己动手用逻辑门搭了一个4位ALU才真正明白一条加法指令是怎么被电路算出来的。这篇文章我就把整个过程完整写出来。我会从最基础的逻辑门开始一路搭出半加器、全加器、4位行波进位加法器再配上逻辑运算单元和多路选择器最后组成一个支持加减法和多种逻辑运算的完整4位ALU。整个过程用仿真软件就能完成不需要买任何硬件。适合正在学数字电路、计算机组成原理的同学也适合想重新理解底层原理的软件工程师。我尽量不写废话每一步都会解释为什么这么做调试时容易踩的坑也一并列出来。1. 4位ALU先搞清楚要做个什么东西1.1 ALU在CPU里的角色以及我们这次的目标ALU的全称是Arithmetic Logic Unit中文叫算术逻辑单元。CPU取指后送进控制器由控制器产生运算指令真正执行计算的就是ALU。工作流程可以理解成控制器按照指令内容告诉ALU这次是a加b还是a与bALU把两个操作数拿过来按控制信号执行对应操作然后把结果和几个状态标志送回处理器。你写的高级语言里的a b最终落到底层就是ALU里一组逻辑门在做机械式的真值表匹配。4位ALU就是一次只能处理4个比特的ALU操作数范围是0~15。这个规模非常合适教学因为每个模块都能看得见摸得着。但规模小不代表简单麻雀虽小五脏俱全——进位、溢出、符号标志一个都少不了。学懂了4位的原理扩展到8位、16位、32位无非是复制粘贴加布线的事。设计之前先列需求清单我给自己定的目标支持两种算术运算加法A B和减法A - B支持四种逻辑运算按位与AND、按位或OR、按位异或XOR、按位取反NOT A输出4位结果F[3:0]输出四个标志位零标志Z、符号标志N、进位标志C、溢出标志V用3位控制信号S[2:0]选择8种功能1.2 为什么用3位控制信号而不是拉8根控制线有人可能会想8种功能直接上8根控制线哪根线拉高就执行哪个功能不也挺直观吗可以但代价是控制线数量随功能数量线性增长。16种功能要16根线256种功能要256根这种方案在真实芯片上根本不可行。所以业界习惯用一小段二进制编码去选功能再用内部译码逻辑把控制信号翻译成具体操作。3位二进制编码能表示8种状态刚好覆盖我们要的8个功能这就叫用较少的线传指令用电路内部的开销换外部的引脚数。我设计的功能编码表如下后面的所有模块都围绕这个表转S2S1S0功能说明000F A B加法001F A - B减法即 A (~B 1)010F A AND B逻辑与011F A OR B逻辑或100F A XOR B逻辑异或101F ~A按位取反110F A 1增量留作扩展111F A直通测试用这个编码不是标准答案完全可以按需调整。设计ALU最忌讳一上来就画门电路先把功能表定下来后面等于按图索骥。1.3 模块化设计把大问题切小整个ALU直接画会很花眼所以我把它切成三层。第一层是算术单元核心是一个加法器减法靠补码转成加法实现。第二层是逻辑单元四个逻辑运算并行算出结果。第三层是多路选择器根据控制信号从所有候选结果中选出一路接到输出。每一层都是独立模块可以单独测试、单独调试。这样排错的时候不用盯着整张电路图发呆哪个模块输出不对就查哪个模块。模块化是数字电路里最基本也最重要的工作方法后面做任何复杂系统都会用到养成这个习惯越早越好。2. 逻辑门基础搭之前先吃透这几种门2.1 基本逻辑门的规则以及TTL芯片的隐藏陷阱逻辑门是数字电路的基本积木三种最基础的是与门、或门、非门。与门AND的规则是全1才为1输入A和B输出Y A·B。拿生活场景类比就是串联电路两个开关都闭合灯才亮。或门OR的规则是有1即为1Y AB类比是并联电路任何一个开关闭合灯都亮。非门NOT最简单输入什么就反什么Y ~A。如果你打算用TTL芯片在面包板上实搭有一个隐藏陷阱必须知道TTL芯片悬空的输入引脚会被自动当作高电平。我当年搭电路时突然所有输出都是1查了好几个晚上最后发现是一根数据线没接端口悬空被当成了1。CMOS芯片则相反悬空输入容易导致逻辑不定就读出一些乱七八糟的值。所以无论用哪种工艺不用的输入引脚都一定要处理好要么接地、要么上拉绝不能悬着不管。2.2 异或门ALU里的万金油实际搭建时会发现用得最多的其实是异或门XOR。异或的规则是相异为1相同为0Y A ⊕ B。这个门在ALU里地位极高因为它的行为太巧妙了如果B接0Y A数据原样通过如果B接1Y ~A等价于取反。再配合两个相同数异或得0这个特性它既能做比较又能做可控取反器后者正是减法电路的核心。如果手里没有现成的异或门用基本门也能搭出来常见表达式是Y (~A · B) (A · ~B)也可以用与非门更省元件地实现Y (A B) · (~(A · B))。建议动手在仿真软件里搭一遍体会一下不同实现方式的差别后面接减法器时你会感谢自己做过这个练习。2.3 搭建工具选型仿真软件还是面包板我强烈建议第一步先用仿真软件而不是急着买面包板。免费好用的工具推荐三个Logisim开源免费专为教学场景设计拖拖拽拽就能画电路自带测试引脚很多大学的数字电路课程都用它Digital跟Logisim类似但界面更现代支持HDL命令适合再进阶一点的人如果你只是临时想试试也可以用浏览器版逻辑电路模拟器。Logisim里搭逻辑门的具体操作很简单新建电路后左侧工具栏选择AND Gate拖到画布再配合Pin组件做输入输出连线直接拉就行。双击门组件可以改位宽把1-bit改成4-bit这一步非常关键能省掉大量重复布线。如果你坚持上真实面包板常用的TTL芯片有74LS08四2输入与门、74LS32四2输入或门、74LS86四2输入异或门、74LS04六反相器、74LS2834位二进制加法器、74LS153双4选1多路选择器。面包板方案的优点是手感真实能测电压看真值缺点也很明显连线多了极容易乱排查接触不良非常费时。我自己的习惯是先在仿真里把逻辑完全跑通再考虑实搭这样物理层面之外的问题基本已经排干净了。3. 算术单元搭建加减法的核心电路3.1 半加器加法的最小编码一位数加法只有4种情况0000111011110。最后一种出现了进位这是加法器要解决的第一个问题。半加器Half Adder只做一位加法输入A、B输出S和与C进位逻辑表达式S A ⊕ B C A · B比如11时S0、C1二进制结果就是10。可以把它想成两个水桶一个装本位结果一个装满了溢出来的部分。半字的含义是它没有考虑从更低位传来的进位所以只能用在多位数加法的最低位。为什么半加器没法用于其他位因为中间每一位都可能收到来自低位的进位半加器没有这个输入口。3.2 全加器多位数加法的基础单元全加器Full Adder补上了进位输入Cin输入三个信号A、B、Cin输出S和Cout逻辑表达式S A ⊕ B ⊕ Cin Cout (A · B) (Cin · (A ⊕ B))这里不建议死记真值表最好记表达式和构造思路。全加器可以看作两个半加器拼接先用一个半加器把A和B相加得到中间和与中间进位再用第二个半加器把这个中间和与Cin相加得到最终的和最后把两个进位做逻辑或合并成最终进位Cout。这个结构画电路图时特别清晰也很好验证——你甚至可以把它拆成两层一层算AB本位是否产生进位另一层算AB本位是否有1能跟Cin一起进位。3.3 4位行波进位加法器串联的艺术把4个全加器串联起来每个全加器的Cout接到下一个全加器的Cin就得到了4位行波进位加法器Ripple Carry Adder。名字很形象——进位像波浪一样从低位向高位逐级传递。输入是两个4位加数A[3:0]、B[3:0]输出是4位和F[3:0]以及最高位进位C4。这个电路简单缺点也非常明显慢。第0位的进位要经过第1位、第2位才能传到第3位。假如每一级全加器的进位传递要经过2到3个门延迟4位串起来就是6到12个门延迟。位数一多延迟成倍增长16位加法器已经可能拖慢整个处理器。工程上解决这个问题会用超前进位加法器Carry Lookahead Adder提前算出每一位的生成信号G和传播信号P让进位并行计算不再逐级等待。4位ALU教学里通常不做超前进位但我建议学有余力的朋友去了解一下这是理解现代CPU加法器的关键一步。3.4 减法把减法变成加法做减法的核心思路是补码A - B A (~B 1)。~B是B按位取反再加1就是B的补码也就是它的相反数。这样一来减法器只需要在加法器上多加一点逻辑把B的每一位都过一个异或门控制信号Sub接异或门的一个输入。Sub0时B原样进入加法器Sub1时B全部取反再把进位输入Cin设成1就补上了那个额外的1。这个设计非常优雅一排异或门加一条控制线加法器立刻升级成加减法器。网上很多ALU教程管这一排异或门叫可控取反器很贴切。但这里有一个极容易踩的坑做加法时Sub0Cin0做减法时Sub1Cin1。很多新手第一次画会漏掉Cin的1结果减法结果总差1排查半天发现是少补了那个1。4. 逻辑单元与多路选择让ALU按指令干活4.1 逻辑单元同时算不排队逻辑运算和算术运算最大的不同在于逻辑运算是按位独立的每一位之间没有进位关联。所以逻辑单元可以做得非常暴力四路运算同时算最后再挑一路。我设计的逻辑单元包含四部分AND模块4个与门并行、OR模块4个或门并行、XOR模块4个异或门并行、NOT模块4个非门对A取反。四路输出的结果同时存在看起来有点浪费资源换来的却是极高速度——只需一个门延迟就能出结果。在可编程逻辑器件比如FPGA里空间换时间的思路极其常见。真实CPU的ALU内部逻辑单元也基本是这个思路只不过位数更多、功能更复杂。逻辑单元的输出等于同时给出了A AND B、A OR B、A XOR B、NOT A四个候选答案后面交给多路选择器决定放哪一个出去。4.2 多路选择器从N路里选一路多路选择器Multiplexer简称MUX是ALU内部的出题人。输入有多路数据输出只有一路由选择信号决定放哪一路出去。最简单的2选1 MUX有两路输入A0、A1一个选择信号S一个输出YY (~S · A0) (S · A1)S0时选A0S1时选A1。实现也不复杂一个非门、两个与门、一个或门就够了。多选一可以通过级联实现4选1 MUX用两级2选1第一级用S0分别处理(A0,A1)和(A2,A3)得到两个中间结果第二级用S1在中间结果里二选一。8选1就是三级级联。在我的方案里输出F[3:0]需要从8路候选结果中选1路也就是每个输出位对应一个8选1 MUX。这里可以玩个小优化8选1 MUX连线太多容易乱可以先用一个4选1把算术运算结果加法、减法、增量、直通选出来再用另一个4选1把逻辑运算结果与、或、异或、取反选出来最后加一个2选1在算术组和逻辑组之间二选一。这种两级选择结构连线更清爽排错时也更清晰。4.3 控制信号译码把二进制指令翻译成电路操作控制信号S[2:0]本身只是三个位要把它翻译成各模块需要的使能信号和选择信号需要一组组合逻辑。按我的功能编码表可以这样拆分当功能是减法001时异或门阵列的Sub信号要置1加法器的Cin也要置1。当S20时走算术组当S21时走逻辑组。具体布尔表达式可以写成SubEnable (~S2) · (~S1) · S0 ArithSelect ~S2 LogicSelect S2用与门、非门就可以组合出来。如果用的是Logisim也可以直接用译码器Decoder组件3位输入译出8条线每条线对应一个功能再把这些译码输出分别接到对应的使能端和选择端。用译码器最大的好处是逻辑清晰不会漏功能。每种方案都有各自优势我个人的建议是先从门级表达式搭一遍再用译码器对比一次你会对译码这件事有更深的体感。5. 整体集成、标志位设计与仿真测试5.1 标志位ALU的体检报告ALU除了输出4位运算结果通常还会给出几个标志位CPU根据它们做条件跳转等操作。四个最常用的标志位分别是Z零标志结果F[3:0]全为0时置1。实现方式是F的4位全部接入一个或非门。F只要有一位是1或非门输出就是0只有全0时Z才是1。N负标志直接取结果最高位F[3]。在补码体系里最高位就是符号位所以F[3]1代表负数。C进位标志加法器最高位的进位Cout。做无符号加法时C1表示结果超出了4位能表示的范围。比如0b11110b00010b0000C1意味着实际结果是16。V溢出标志有符号加法溢出标志。判断规则是V C3 ⊕ C4即最高位进位C4和次高位进位C3不同。这公式有点反直觉解释一下两个正数相加变成负数或者两个负数相加变成正数一定是有符号溢出。最高位进位和次高位进位不同说明符号位被进位改写了。典型例子01117 01106 1101-3C40但C31所以V1一看就知道结果不对。5.2 完整数据通路把模块捏在一起所有模块都有了剩下就是连接。完整数据通路从上到下是这个流程两个4位操作数A[3:0]和B[3:0]从左侧进入。B先经过一排异或门Sub信号接异或门一个输入实现可控取反。取反后的B进入4位加法器减法控制信号同时接到加法器的Cin。加法器输出算术结果同时A和B直接送入逻辑单元得到AND、OR、XOR、NOT四种逻辑结果。这六路结果连同A1和A直通两路一起进入8选1多路选择器。S[2:0]决定放哪个结果到F[3:0]。与此同时从加法器内部引出C3、C4接到溢出标志从F[3:0]引出Z、N标志。整条通路是纯组合逻辑没有时钟、没有寄存器控制信号和输入一变输出立刻跟着变中间只隔几级门延迟。这是初学ALU最容易理解的形式——等以后学时序电路才会在ALU前后加寄存器把输入输出锁存起来。5.3 在Logisim里完整跑一遍测试搭完不等于能跑测试才是检验设计的地方。我一般分三步走。第一步跑基础真值表固定几个典型值比如A0b0000、B0b0000A0b1111、B0b0001A0b0111、B0b0111逐个切换S[2:0]对照功能表检查输出和标志位。第二步做穷举测试。4位ALU加法有16×16256种输入组合加上减法和其他运算总共大约两千种组合手工测试太累。好在Logisim支持测试向量功能可以写CSV文件让软件自动比对实际输出和期望输出。我的习惯是先测加法器的全部256个组合再逐个测逻辑功能按模块扩大范围。第三步专门测标志位。重点测两组一组是溢出测试比如01110110应该让V1一组是借位测试比如0000-0001应输出1111同时C0。减法里C这个标志位的行为比较反直觉不少教材对ALU标志位定义不完全一致建议在设计阶段就把标志位含义写清楚再针对性地验证。6. 实际搭建中的高频问题与调试方法6.1 高频问题排查速查表我在仿真加面包板实搭里踩过不少坑整理成一张速查表问题现象可能原因排查方法减法结果总比预期大1减法时Cin没接1检查控制信号到Cin的连线某些输入组合输出完全乱真值表或功能编码表有误回到功能表逐项核对逻辑运算结果总为0MUX选择信号接反了顺序检查S[2:0]与MUX端口的对应关系输出有位总为1某输入引脚悬空被当高电平把未用引脚接地或上拉标志位C、Z和理论不符标志位取自加法器或输出的位置不对确认C取最高位进位Z取最终F仿真速度越来越慢画了太多重复电路使用子电路封装模块面包板芯片莫名发热电源地接反或输出短路断电后逐芯片检查VCC/GND和输出引脚6.2 调试方法论不要对着整张图瞎猜调试ALU时最有效的方法就是分而治之。第一步把整个电路拆成独立模块分别给输入、观察输出。加法器单独测完逻辑单元单独测完再组合起来。第二步从输出往前查——如果F[0]不对顺着MUX、逻辑单元一步步往前追找到第一个异常点那通常就是根因。第三步固定一组简单的输入组合比如A0001、B0001故意改变其中一个输入观察输出怎么变做单变量实验。第四步在仿真软件里充分利用探针和指示灯关键节点都加观察点比用眼睛硬看波形高效得多。很多新手常犯的毛病是卡在一个小问题上死磕一整个下午其实只要肯把电路切两半问题往往立刻现形。调试数字电路和调试软件代码本质一样——先定位到最简复现单元再动手修不要漫无目的地瞎试。6.3 仿真通过后要不要上真实面包板玩够了仿真想挑战实物的话有几条经验值得记第一芯片插面包板时注意凹口方向电源VCC和地GND千万别接反74LS系列常见14脚芯片是7脚GND、14脚VCC但不同型号位置可能有差异必须查datasheet确认。第二用不同颜色导线区分功能——红色电源、黑色地线、其他颜色走数据信号。第三每接完一块电路就立刻通电测试别等全部接完再通电否则一处短路可能导致连锁烧毁损失一堆芯片。如果只想快速验证ALU的逻辑而不想手工焊一堆门电路可以用74LS283这个现成4位加法器芯片搭配74LS86做可控取反、74LS153做多路选择器整套4位ALU用不到十颗芯片就能落地。这个方案对理解芯片级组成很有帮助但对理解逻辑门内部结构帮助有限——所以我还是建议先在Logisim里用门级电路完整搭一遍然后再考虑芯片组装那才是真正从逻辑门到完整电路的完整路径。写到这里这个4位ALU从逻辑门一路走到完整电路的过程就讲完了。我自己当年第一次把全套电路跑通的时候看着指示灯在加法和减法之间切换好像突然就明白了计算机的计算二字到底在算什么。后来我又尝试把这个4位ALU扩展到8位、加超前进位、做多级选择每一次改动都比第一次简单得多——因为底层的模块化思路和调试方法已经刻在脑子里了。希望你也亲手搭一次别怕慢哪怕只是搭通一个加法器也比背十遍课本概念管用。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑