ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

组间串行进位ALU与计数器:计算机组成原理实验三实践详解

组间串行进位ALU与计数器:计算机组成原理实验三实践详解 正式动手做山大软院计算机组成原理课程设计实验三之前我一直以为前面的实验一、实验二已经够折腾了——天天跟译码器、三态门、寄存器较劲看着面包板上密密麻麻的杜邦线头都是大的。结果到了实验三我才意识到什么叫“把散件组装成电脑”这一轮实验要把运算器、计数器、总线和控制信号串起来做一个真正能跑通指令的最小数据通路。尤其是组间串行进位的ALU设计和计数器时序控制这两块理论课上听的时候觉得也就那么回事真到自己连线、调信号的时候才发现坑一个接一个。这篇文章把我做“山东大学软件学院计算机组成原理课程设计实验三”的完整流程、设计思路、连线细节和排错过程整理成文。如果你是正在做这门课实验三的学弟学妹或者只是自学计算机组成原理时卡在加法器、进位链、计数器这些知识点上这篇内容可以帮你少走不少弯路。我尽量把话说得直白按我实际操作的顺序来写而不是按课本目录来讲。1. 实验整体拆解实验三到底在做什么1.1 从课程主线看实验三的定位山大软院组成原理课程设计的主线其实非常清晰先认识基础芯片再搭功能部件最后组装成一台能跑简单指令的模型机。实验一通常围绕基本门电路和数据选择器实验二开始接触寄存器和总线到实验三就是把这些部件组合起来做一个带控制信号的完整功能模块。它的核心目的在于让你亲手体会到一条指令从取指到执行到底是谁在什么时候把数据送到了哪里。以我当时拿到的实验三任务为例重点有两个一个是设计一个8位的运算器进位方式要求用组间串行进位另一个是设计一个计数器模块用来产生节拍信号或者充当程序计数器PC。这两个模块并不是各做各的最后要接到同一条数据总线上由控制信号决定当前总线上是谁在输出、谁在接收。这里顺便说一句很多软件学院的同学会觉得“我是写代码的为什么要折腾这些芯片”。但等你做完实验三再看“王道计算机组成原理笔记”里的指令周期、总线周期、微操作序列这些知识点会发现它们突然变得非常具体——原来课本上那些波形图和控制信号就是你在实验箱上一个个拨码开关、一根根跳线调出来的东西。1.2 功能需求与设计目标实验三的功能需求大致可以拆成四块。第一块是8位ALU至少能完成加减法、与、或、异或等运算进位链要能体现组间串行的结构特征第二块是计数器要能完成清零、置数、计数输出三种基本操作计数结果要能接到总线或者指示灯上第三块是总线系统需要一个带三态门隔离的输入输出通道避免多个部件同时占用数据总线第四块是一个简单的时序控制部分用计数器的输出去控制“取数、运算、写回”这几个微操作按顺序发生。我做的版本是一个能够完整执行“读出A数、读出B数、计算、写回寄存器、结果输出”的小流程。计数器按节拍产生T0、T1、T2三个控制信号每个节拍对应一个微操作。这样以后再做模型机实验时可以把这套节拍信号直接当作微程序控制器的基础来用相当于实验三在给实验四铺路。1.3 软件学院为什么也要啃这块硬骨头这个问题我一开始也问过。直到后来写代码遇到内存对齐、并发时序、性能优化这些话题才慢慢明白计算机组成原理对软件工程师的意义。软件开发的很多“灵异问题”往底层追最后都会追到硬件行为上。比如你并发下总是偶发数据错乱可能不是锁写错了而是缓存一致性问题你循环跑得慢可能不是算法问题而是分支预测和流水线停顿导致的。亲手做运算器和计数器最大的收获是建立“时序感”。软件里一句a b c背后至少有取数、运算、写回三个节拍每个节拍都由时钟边沿驱动。你亲手拨过一次手动时钟、亲眼看过进位信号从低位传到高位的过程以后再分析性能瓶颈和硬件特性直觉会比只看书的人准很多。所以哪怕你是纯粹的软件方向这门实验也值得把它认真做完不要抱着“混过去就完了”的心态。2. 关键原理与方案选型组间串行进位和计数器到底怎么理解2.1 组间串行进位从全加器到进位链的工程直觉做实验三之前先把进位链的原理掰开来理解透。一个全加器的进位输出可以写成C_out A·B (A ⊕ B)·C_in这里的A·B就是“本组自己产生的进位”叫进位生成函数GA ⊕ B则是“把低位进来的进位继续传上去的条件”叫进位传递函数P。于是每一位的进位可以统一写成C_i G_i P_i · C_{i-1}如果只是像小学加法一样从低位往高位逐位传播进位那一个8位加法器最坏情况下信号要依次穿过8级进位逻辑延迟非常大。解决办法就是超前进位CLA把4位分成一组组内各位的进位不依赖前一位的结果而是直接由G和P并行算出来。4位一组的组内进位可以写成C_1 G_1 P_1·C_0 C_2 G_2 P_2·G_1 P_2·P_1·C_0 C_3 G_3 P_3·G_2 P_3·P_2·G_1 P_3·P_2·P_1·C_0 C_4 G_4 P_4·G_3 P_4·P_3·G_2 P_4·P_3·P_2·G_1 P_4·P_3·P_2·P_1·C_0这样一来4位一组内部就不再一位一位串行等进位了。但如果做8位、16位甚至32位总不能无限扩展CLA逻辑硬件的扇入扇出会爆炸。工程上的折中方案就是组内用超前进位组和组之间串行。低一组算完把本组的进位输出C_4送到高一组作为它的进位输入C_in高一组内部再用CLA快速消化这个进位。这就是“组间串行进位”的基本思想。做实验时你不需要自己搭这些逻辑门因为74LS181这个4位ALU芯片内部已经集成了CLA逻辑。你只需要把两片181串起来让低片的C_n4接到高片的C_n就能直观看到“组间串行”到底串在哪儿。示波器上看进位信号从低片传到高片会有一个肉眼可见的延迟这个延迟就是组间串行带来的。2.2 计数器时序电路的节拍发生器与程序计数器实验三里计数器出现的场景一般有两个。一个是当作节拍发生器产生T0、T1、T2这样的时序信号用来控制总线上不同部件轮流工作另一个是当作程序计数器PC用来给出指令存储器的地址支持顺序执行和跳转。我在实验里用的是74LS161这是一片非常经典的4位二进制同步计数器。它有几个关键引脚你得把功能彻底搞清楚CLR是异步清零端低电平有效一拉低输出立刻变成0000LOAD是同步置数端低电平有效在时钟上升沿把输入端D0~D3的数据装进去ENP和ENT是两个计数使能端只有两个都是高电平时钟上升沿到来时才会计数RCO是进位输出当计数值到达1111且ENT为高时输出高电平可以用来级联扩展。用74LS161搭节拍发生器时最常用的套路是把计数器做成一个自动循环的“0→1→2→3→0”小状态机。比如我希望每4个时钟周期循环一次就利用LOAD端在计数到3后把0装入把Q0和Q1相与后接到LOAD计数到3时LOAD被拉低下一个时钟上升沿装入0000。这样计数器就成了一个简单的4分频器Q0、Q1正好分别对应T0、T1两个节拍信号。如果当PC用还要考虑跳转功能转移指令到来时把目标地址放到D0~D3上拉低LOAD下一个时钟上升沿PC就变成了目标地址。这个“同步置数”的动作和课本里“PC←PC1条件满足时PC←目标地址”的描述是对应的。2.3 芯片选型与仿真工具怎么组合实验三涉及的核心芯片按我用的方案整理如下芯片类型在这个实验里的作用74LS1814位ALU两片拼成8位ALU支持算术/逻辑运算组内CLA74LS2834位二进制加法器如果不追求逻辑运算也可以用它做纯加法器方案74LS1614位同步计数器节拍发生器或程序计数器74LS245八路总线收发器数据总线的双向隔离控制方向74LS244八路缓冲器/线驱动器输入数据的隔离驱动74LS273八D触发器寄存器暂存运算结果74LS04六反相器信号取反、消抖辅助电路用方案选型上有一条主线如果你用的是课程配发的实验箱比如COP2018教学系统芯片基本已经固定在实验台上你需要做的是理解每个模块的接法和信号定义如果是从面包板自己搭那上述芯片清单都买得到连线工作量会大不少。我个人建议是先在Logisim里把整个数据通路仿真跑通再上实验箱接实物。实测下来仿真十分钟解决的问题放到实物上可能要一小时因为还要排查接触不良、供电不稳、按键抖动这些“物理因素”。3. 从原理到实操核心设计与连线细节3.1 8位ALU的组间串行进位实现先用两片74LS181搭8位运算器。181是一片4位ALU它支持两个4位操作数A[3:0]和B[3:0]输出F[3:0]有进位输入C_n和进位输出C_n4。M引脚决定是算术运算还是逻辑运算S3~S0这4个引脚决定具体执行哪种操作。比如S3S2S1S01001时做的是算术加M0、C_n0时FAB1对应课本里的补码加法S3S2S1S00110时做的是逻辑异或M1。连线的关键动作是把低4位的C_n4接到高4位的C_n。这样低4位算完产生的进位会成为高4位计算的进位输入组间串行进位结构就出来了。高4位的C_n4则是整个8位运算器的最终进位输出建议用指示灯观察。如果C_n这个引脚没接悬空电平不确定加法结果会莫名其妙少个1这是我第一次上板时踩过的第一个坑。操作方式上我做了两组4位拨码开关代表A和B的低高位一共8个开关作为输入M和S3~S0用5个独立开关控制。为了能看到结果8位F输出接两排发光二极管。这样每拨一次开关就能直接看出运算结果对不对。验证组间串行连没连对的技巧很简单做一个“跨组进位”的加法比如0x0F 0x01。低4位是15加1必然产生进位C_1这个进位要能成功传给高4位最终输出才会是0x10。如果高4位毫无反应基本可以断定高4位的C_n没接好。3.2 计数器电路清零、置数、使能、进位扩展74LS161的接法我分成两种场景来说。场景一是做4位循环节拍发生器。我把CLK接到手动时钟源实验箱上有按键产生单脉冲ENT、ENP接到高电平CLR接高电平保持不清零LOAD端接到Q0和Q1的与非结果上。这样计数值走过0、1、2、3后Q1和Q0同时为1LOAD拉低下一个上升沿把0000装进去实现自动循环。Q0和Q1这两个输出就是T0和T1节拍信号。注意LOAD是同步置数如果用的是异步清零的芯片比如74LS160系列有的不同设计逻辑会不一样这点一定要查数据手册确认。场景二是做程序计数器PC。这时CLR由复位信号控制上电瞬间拉低复位成0000然后拉高开始计数。LOAD端接转移控制信号D3~D0接目标地址。顺序执行时LOAD为高每个时钟上升沿PC自增1转移时LOAD拉低下一个上升沿PC被写入目标地址。这里要提醒一个很容易忽视的点按键作为时钟源时必须有消抖处理。机械按键按下的一瞬间会产生多次抖动相当于连按了好几下计数器可能一次跳好几个数字。最简单的做法是用一个RC低通滤波器接在按键输出和CLK之间或者用实验箱上自带消抖的按键模块。我当时偷懒直接加拉电阻结果计数总是跳变排查了很久才想到是抖动问题。多片161级联做8位、16位计数器时用RCO进位输出。低片计到1111且ENT为高时RCO输出高接到高片的ENT或ENP即可。RCO本质上只在“1111 AND ENT”时有效所以高片恰好能在低片回滚到0的那个时钟沿加1逻辑上是严丝合缝的。3.3 数据通路控制信号约定与总线设计实验三的进阶要求是把ALU、计数器、寄存器接到同一条总线上由控制信号决定每个时刻谁在占用总线。这里最关键的概念是三态门隔离——挂在总线上的器件不能同时输出否则多个输出互相打架总线数据直接乱了。我当时的数据通路结构是这样的两个输入寄存器A、B的输出端通过三态门接到数据总线ALU从总线上取数结果暂存到结果寄存器结果寄存器输出通过另一个三态门接回总线计数器输出直接显示在指示灯上。控制信号里约定三个选通信号控制“把A输入送上总线”、“把B输入送上总线”、“把结果送上总线”每次只有一个有效。焊接和连线时要用74LS244做输入缓冲、74LS245做总线收发。244的G引脚是输出使能低电平有效不用的那一路一定要接高电平禁用不然三态门一直是通的总线永远是冲突状态。245的DIR引脚控制数据方向使用前也要明确约定好当前方向否则数据你能读进来我还能读出去等于没有隔离。重要提示上电前先用万用表蜂鸣档测一遍电源和地之间有没有短路。芯片插反、电源接反在实验箱上不算常见但在面包板上真的太容易发生了一旦短路可能烧一片芯片重新排查和更换芯片的时间成本远高于你提前花两分钟检查。控制信号的时序逻辑我用状态表来约定这样后续接逻辑门也方便节拍控制信号总线内容动作T0EN_A有效输入A把A数据送上总线T1EN_B有效输入B把B数据送上总线T2ALU_EN有效ALU运算结果把结果写入寄存器T3REG_OUT有效寄存器内容把寄存器结果显示到指示灯T0~T3由计数器输出的译码产生可以用一片74LS139双2-4译码器把Q0/Q1译成四选一的节拍信号。这样整个实验就已经具备了一个微型处理器指令周期的雏形取操作数、运算、写回、输出。4. 实验过程实录从仿真到实物4.1 在Logisim里先把功能仿真跑通我强烈建议先用Logisim建一个总电路图把所有模块放进去用虚拟时钟和按钮模拟实验箱操作。Logisim不需要写Verilog但画出来的电路就是一张可以交互的图特别适合验证数据通路设计是否合理。你可以在同一个文件里建几个子电路一个放ALU模块一个放计数器模块一个放整体数据通路。仿真步骤大概是新建项目从库里面拖出两个4位加法器或者直接用开发者自己做的ALU子电路按组间串联方式把进位接起来加一个计数器模块设置同步置数和清零逻辑用分线器把8位总线拆成高低四位分别接LED灯显示。所有模块连线完毕后用手动时钟一根根点脉冲观察每拍数据的流向。如果仿真时哪一步数据不对比如ALU结果没写入寄存器那大概率是控制信号的时序设计有问题要先在仿真里改到正确再上板。我实测下来Logisim调试的时间大约占整个实验的三分之一。这个时间花得非常值因为它逼着你把每个控制信号的逻辑关系画清楚。等到上实验箱再发现问题往往已经是连线、接触和电平匹配这些纯硬件问题和你的逻辑设计无关了。4.2 在实验箱/开发板上做最终验证上板之前对照自己画的连接图逐根检查跳线重点检查电源引脚、地引脚、每个芯片的使能引脚是否接对了。上电后先不接输入数据只观察计数器上电复位的状态是否是0000。我当时的实验箱CLR是异步清零端直接用RC电路做了上电复位实测很稳。验证过程按顺序来先单测计数器给脉冲看是否按0→1→2→3循环再单测ALU不接总线拨码开关给定A、B看指示灯输出和进位灯最后接通所有三态门控制信号做一次完整的“取A→取B→运算→写回→输出”。每一步只做一件事方便出现问题能立刻定位到具体模块。我记录过一组典型验证数据A输入00001100B输入00000101选择加法ALU输出应该是00010001进位输出为0。跨组进位用A00001111、B00000001验证输出必须是00010000且进位输出为1。如果发现高4位没有变化优先检查高片181的C_n是否和低片的C_n4相连。如果用的是COP2018这类教学系统需要注意它通常自带实验操作软件里面有“使用手册”可以查每个模块的引脚说明和示例连接方式。跟着手册走一遍标准连接再换成自己的数据通路设计会减少很多不必要的折腾。4.3 常见问题与排查技巧速查表实验做多了之后就会发现硬件实验的报错方式没有软件那么直接。芯片不会告诉你“第3行错误”只会静静让某个灯的状态不对。我把这次实验里遇到的典型问题按现象整理成了一张表现象可能原因排查思路与解决方法计数器上电后不是0000复位信号没生效或复位时间不够检查CLR引脚是否被拉低过增大RC复位时间常数按键按一下计数值乱跳机械按键抖动加RC消抖或使用实验箱自带消抖按键计数器始终不计数ENP/ENT没接高电平检查两个使能端电平必须有稳定的高电平ALU结果总是少1C_n进位输入悬空把C_n接到确定的电平加法时接0不要悬空高4位结果不对组间串行进位没接检查低片C_n4与高片C_n之间的跳线总线上数据乱窜多个三态门同时使能检查各选通信号每时刻只能有一个输出有效某个灯微亮但不稳定驱动能力不足或干扰检查该输出是否接了三态门测电压是否达到高电平阈值仿真正常但实物错误引脚电平不匹配、接触不良用万用表逐段测信号从输出端往前一级一级找排查的实际方法上我习惯从输出端往输入端倒推。比如ALU输出不对先看F引脚电平再往前看S选择线和A、B输入线最后看M和C_n。用万用表单测一个引脚的电平往往比肉眼盯指示灯靠谱得多。你也可以用示波器看进位脉冲的边沿延迟能看到组间串行进位从低片传到高片的那段延迟非常直观。5. 做这个实验我最后悔和最有收获的事如果让我给正在做实验三的同学一句最直接的忠告那就是一定要先理解时序关系再动手接线。我当时有一半的时间浪费在“看着连接图一根一根接完上电发现完全不对然后拆掉重接”的循环里。后来逼着自己先在纸上画出每一拍时钟沿到来时哪些信号有效再动第二根线效率反而高了很多。我的一个实际操作建议是把整个数据通路的状态表打印出来放在手边接完一条线就在表上打个钩。这样既不会漏线排查时也能快速判断哪个控制信号没生效。还有养成每完成一个模块就单独测试的习惯。计数器先测ALU先测三态门单独测然后再合起来联调。联调出问题时永远先怀疑信号时序再怀疑芯片损坏最后怀疑连线。这个实验做完之后你再去看后续的模型机实验会觉得豁然开朗——所谓取指、译码、执行本质上就是在不同的节拍里让不同的控制信号轮流有效让数据沿着总线按预定路线走一圈。能把实验三完整走下来你对计算机组成原理的理解已经不只是课本上那些图和名词了。
返回列表