简介:本资源是华中科技大学网络安全学院《计算机组成原理》课程的完整实验报告,面向计算机类、信息安全专业本科生及硬件设计初学者,聚焦CPU底层实现能力培养。报告系统覆盖单周期与多周期MIPS CPU的数据通路构建、硬布线控制器与微程序控制器设计、Logisim平台实操步骤及sort.hex冒泡排序测试验证,兼具理论深度与工程实践性。资源为1个1.59MB的DOCX文档,内容结构严谨,含详细电路图(如取指/运算/访存通路)、控制器逻辑说明、分步实验记录及总结心得,便于对照学习、复现设计并理解性能差异。目前已有1117人学习下载,适合课程复习、课程设计参考或数字系统综合实验备赛使用。
1. 一张图看懂CPU设计实验的知识地图:单周期 vs 多周期、硬布线 vs 微程序,到底在比什么?
如果你刚打开这份《计算机组成原理实验报告》,第一眼看到“单周期MIPS CPU”“多周期微程序控制器”“sort.hex冒泡排序测试”这些词,可能会下意识觉得:这不就是Logisim里拖拖拽拽、连连线、调调信号的课设作业吗?但梳理下来会发现——这不是一次简单的电路搭建练习,而是一次对CPU控制流本质的系统性解剖。整份报告用8条核心MIPS指令(add / slt / lw / sw / beq / bne / addi / syscall)为锚点,构建出四条并行的技术路径:单周期硬布线、多周期微程序、多周期硬布线,外加一条隐含的“数据通路统一建模”主线。它真正考的是你能不能把《计算机组成原理》教材里分散在“数据通路”“控制器设计”“指令周期”“微程序”“硬布线逻辑”“时序分析”等章节的知识,拧成一股可执行、可验证、可对比的完整能力链。适合谁?不是零基础小白,而是已经学完前六章(运算器、存储器、总线、指令系统)、正卡在“控制器怎么从指令码变成一堆开关信号”这个黑匣子门口的人;是复习考研408、准备校招底层岗、或刚接手某高校网安方向《硬件安全基础》课程设计的同学。尤其对华科网安背景的同学来说,这份报告的价值远超“交作业”——它训练的正是未来分析侧信道攻击中时序特征、理解TEE可信执行环境底层调度、甚至逆向固件中BootROM初始化流程所必需的“硬件直觉”。别被“.docx”后缀骗了,这是一份用Logisim实现的、可复现的、带完整测试验证的CPU设计说明书。
2. 单周期MIPS CPU:所有操作挤进一个时钟,快得玄学,慢得真实
单周期CPU的设计哲学非常直白:一条指令,一个时钟周期,全部搞定。取指、译码、ALU运算、访存、写回——五个阶段像叠罗汉一样压在一个时钟沿上完成。这种设计看似简单粗暴,实则对数据通路和控制逻辑提出了极致要求:所有部件必须同时就绪,所有信号必须在同一个周期内稳定传播。一旦某条路径延迟超标(比如ALU加法器+内存读取+寄存器写入的总延迟超过时钟周期),整个CPU就直接失效。这也是为什么它只支持8条精简指令——每多一条指令,数据通路就要更复杂一分,关键路径就更长一截。
2.1 数据通路:MUX是灵魂,ALU是心脏,寄存器堆是枢纽
单周期数据通路的核心矛盾在于:不同指令需要的数据流向完全不同。R型指令(add/slt)要从寄存器堆取两个操作数,经ALU运算后写回寄存器;I型指令(lw/sw/addi)要从寄存器取一个操作数,再与立即数运算或计算地址;分支指令(beq/bne)则要比较两个寄存器值并决定是否跳转。解决之道,就是用多级数据选择器(MUX)将所有可能的输入源汇聚到关键节点。
// Logisim中典型MUX配置示意(以ALU第二输入为例) // ALUSrcB 控制信号决定ALU B端输入来源: // 0 -> 寄存器堆输出B(R型指令) // 1 -> 立即数符号扩展结果(I型指令) // 2 -> PC+4(用于beq/bne目标地址计算,需额外MUX) // 实际电路中,此信号常由3位控制线驱动,对应表1.1中"AluSrcB"字段提示:ALUSrcB信号的编码方式极易混淆。表1.1写“Lw指令,sw指令,addi”,但实际在Logisim实现中,
lw和sw共用同一编码(如0b01),addi用另一编码(如0b10),而beq/bne的目标地址计算需要PC+4,往往需独立MUX路径。若直接照搬表格未做区分,会导致sw写内存时ALU误算地址。
关键部件连接逻辑如下:
| 部件 | 输入来源 | 控制信号依赖 | 易错点说明 |
|---|---|---|---|
| 寄存器堆 | 读端口A/B:由IR[25:21]和IR[20:16]指定寄存器地址;写端口:由IR[15:11]或IR[20:16]指定 | RegWrite, RegDst | RegDst=0时写入IR[20:16](I型),=1时写入IR[15:11](R型);syscall需禁用写使能 |
| ALU | A端:寄存器堆输出A;B端:MUX选择(寄存器B/立即数/PC+4) | ALUSrcB, ALUOp | ALUOp需区分加法(add/addi)、减法(beq/bne)、比较(slt);slt的ALU功能码易配错为0b10而非0b11 |
| 数据存储器 | 写数据:ALU输出(sw)或寄存器B(lw?不,lw是读!);读地址:ALU输出 | MemWrite, MemRead, MemToReg | MemWrite=1仅在sw时有效;MemToReg=1仅在lw时有效,控制写回寄存器的数据源 |
| PC寄存器 | 下址:MUX选择(PC+4 / 跳转目标地址 / 停机) | PCWrite, Branch, Jump | beq的Branch信号需由ALU零标志与指令译码共同产生,漏掉零标志检测将导致永远不跳转 |
2.2 硬布线控制器:用门电路“翻译”指令,逻辑爆炸的起点
硬布线控制器的本质,是把指令的操作码(Op)和功能码(Func)当作输入,通过组合逻辑电路,直接“翻译”出所有控制信号(MemWrite、RegWrite、ALUSrcB等)。它的设计分三步走:指令译码 → ALU控制生成 → 全局控制信号合成。
指令译码:Op与Func的双重解码
8条指令中,lw/sw/beq/bne/addi由Op字段唯一确定(见表1.2),而add/slt/syscall同属R型(Op=0x00),必须结合Func字段(表1.3)才能区分。因此译码电路需两层:
- Op比较层:用6个比较器分别判断Op是否等于
0x23(lw)、0x2b(sw)、0x04(beq)、0x05(bne)、0x08(addi)、0x00(R型); - Func比较层(仅R型):当Op=0x00时,再用3个比较器判断Func是否为
0x20(add)、0x2a(slt)、0x0c(syscall); - 信号合成:
R_TYPE = (ADD || SLT) && !SysCall;ADDI = (Op==0x08);LW = (Op==0x23)……以此类推。
注意:
syscall指令的处理是易漏点。它不写寄存器、不访存、不跳转,只停机。但表1.1中Halt信号产生条件写的是“syscall指令”,而实际Logisim中常通过禁用PC使能端实现停机。若只生成Halt信号却不连接到PC的Enable引脚,CPU会无限循环执行syscall后的垃圾指令。
ALU控制逻辑:从功能到硬件的映射
ALU需要知道本次运算该做什么。ALUOp字段(通常2位)是关键桥梁。根据指令类型,ALUOp应设置为:
0b00:传递(Pass-through),用于lw/sw的地址计算(ALU做加法:基址+偏移);0b01:减法(Subtract),用于beq/bne的相等性判断(A-B,查零标志);0b10:加法(Add),用于add/addi;0b11:比较(Set Less Than),用于slt。
这个映射关系必须严格对应ALU内部电路设计。例如,若ALU模块的0b11功能被定义为“逻辑与”,而控制器却给slt发0b11,结果必然错误。
全局控制信号:OR门的暴力美学
有了7个基础译码信号(R_TYPE、ADDI、LW、SW、BEQ、BNE、SysCall),其余控制信号就是它们的逻辑或组合。例如:
RegWrite = R_TYPE || ADDI || LW(R型、addi、lw都要写寄存器)MemWrite = SW(只有sw写内存)MemToReg = LW(只有lw的写回数据来自内存)ALUSrcB = (LW || SW || ADDI) ? 1 : 0(I型指令用立即数,R型用寄存器B)
这里最容易翻车的是ALUSrcB的编码。表1.1写“Lw指令,sw指令,addi”,但sw和addi虽都用立即数,sw的ALU输出是地址,addi的ALU输出是运算结果,二者在数据通路中流向不同。若用同一ALUSrcB信号控制,可能导致sw时ALU错误地将立即数送入写数据端。
2.3 测试验证:sort.hex不是玩具,是压力探针
sort.hex冒泡排序程序(6,5,4,3,2,1,0xffff)是检验CPU完备性的黄金标准。它密集使用了所有8条指令:lw/sw加载存储数组、add/addi计算地址和索引、slt比较大小、beq/bne控制循环和交换、syscall终止。单周期CPU执行它耗时224个时钟周期(报告图1.21),这个数字本身就有深意:
- 理论最小值:冒泡排序最坏情况(逆序)需n(n-1)/2次比较和最多等量交换。n=7时,比较次数=21,每次比较至少需1条
slt+1条bne(2周期),仅比较就需42周期;加上数组加载(7次lw)、结果存储(7次sw)、循环变量更新(大量addi)……224是完全合理的。 - 调试价值:若执行后内存80h单元数据非
06 05 04 03 02 01 ff,说明数据通路有断裂;若周期数远小于224,可能是beq/bne未生效导致循环提前退出;若远大于224,可能是syscall未停机,CPU在执行无效内存地址的垃圾指令。
3. 多周期MIPS CPU:把大象装进冰箱,分五步走,但每步都得踩准节拍
如果说单周期CPU是“大力出奇迹”,那么多周期CPU就是“精打细算过日子”。它把一条指令的执行拆分成多个时钟周期(Fetch、Decode、Execute、Memory、Writeback),每个周期只做一件事,让关键路径大大缩短,时钟频率得以提升。但代价是:状态管理变得极其重要——CPU必须记住自己当前在执行哪条指令的哪个阶段,并据此发出正确的控制信号。这就引出了两种截然不同的状态管理方案:微程序控制器(软件思维)和硬布线控制器(硬件思维)。
3.1 数据通路:复用是王道,状态寄存器是命脉
多周期数据通路的设计原则是最大化部件复用,最小化冗余连线。与单周期相比,最显著的变化是引入了状态寄存器:IR(指令寄存器)、A(寄存器A值)、B(寄存器B值)、ALUOut(ALU输出)、MDR(内存数据寄存器)。它们像驿站一样,在不同周期间暂存中间结果。
// 多周期关键状态寄存器作用示意 // Fetch周期:PC -> Memory Address; Memory Data -> IR; PC+4 -> PC // Decode周期:IR[31:26] -> Op; IR[25:21] -> RegA Addr; IR[20:16] -> RegB Addr; // RegA Data -> A; RegB Data -> B; PC+4 -> C (for branch) // Execute周期:A + B -> ALUOut (for add); A - B -> ALUOut (for beq); // A + SignExt(IR[15:0]) -> ALUOut (for lw/sw/addi) // Memory周期:ALUOut -> Memory Address; Memory Data -> MDR (for lw); // B -> Memory Data (for sw) // Writeback周期:ALUOut -> Reg[IR[15:11]] (for R-type/addi); MDR -> Reg[IR[20:16]] (for lw)提示:
A和B寄存器的加载时机极易出错。它们必须在Decode周期就从寄存器堆读出并锁存,因为Execute周期需要它们进行运算。若在Execute周期才去读寄存器堆,会因读取延迟导致ALU输入不稳定。Logisim中需确保A和B的Load使能信号在Decode周期的上升沿有效。
核心复用体现在:
- ALU:同一ALU在不同周期承担不同任务——Execute周期做运算,Memory周期计算
lw地址,Writeback周期可能闲置; - 数据存储器:同一端口在Memory周期既读(
lw)又写(sw),靠MemRead/MemWrite信号切换; - 寄存器堆:同一组读端口在Decode周期读
A/B,Writeback周期写回结果,靠RegWrite和RegDst控制。
3.2 微程序控制器:用“微指令”写CPU的汇编语言
微程序控制器的思想是:把CPU的每一步操作,都编译成一条“微指令”。每条微指令是一个控制字,每一位对应一个硬件控制信号(如IRWrite=1,PCWrite=1,ALUSrcA=0)。所有微指令存放在一个高速ROM(控制存储器)中,CPU的状态(当前微地址)决定读取哪条微指令。这本质上是用存储器实现了“控制器”的可编程性。
微指令格式与地址生成:从指令码到微地址的两次跳转
微程序的核心挑战是:如何根据当前指令(Op/Func)和当前状态(微地址),快速定位下一条微指令的地址?报告采用经典的两级地址生成法:
- 指令入口地址:
Op字段(有时加Func)决定该指令的第一条微指令在微程序ROM中的起始位置。表1.13给出了R_Type/ADDI/LW等指令对应的入口地址(如LW入口为0x03)。 - 状态转移逻辑:每条微指令的末尾包含一个“下址字段”(Next Address Field),它由当前微地址和部分控制信号(如
Zero标志、Branch信号)共同决定。例如,beq指令的微程序中,若Zero=1,则下址跳转到循环体;否则下址为顺序执行的下一条。
// 表1.15中"BEQ"指令的微指令片段(十六进制) // 地址 0x09: 0xC0120 -> 含义:PCWrite=1, Branch=1, ALUSrcA=0, ALUSrcB=1, ... // 地址 0x0A: 0xC00A0 -> 含义:若Zero=1则跳转,否则顺序执行 // 这里的"0xC00A0"的低4位"0000"是默认下址,高12位编码了条件跳转逻辑注意:微指令的“下址字段”不是简单递增。表1.15中
BEQ的0x09地址微指令,其下址字段是0x0A(顺序),但0x0A地址微指令的下址字段却是条件跳转目标。若在Logisim中将微程序ROM的地址线直接连到微地址计数器,会导致无条件顺序执行,beq永远无法跳转。必须用专用的“微地址转移逻辑”电路(图1.14)来解析Zero、Branch等信号,动态生成下址。
微程序表编写:手写十六进制是体力活,更是逻辑体检
将表1.15的微指令表导入Logisim,需将其转换为.txt文件,每行一个十六进制数(如000000000100001001100100000000113201)。这个过程看似机械,实则是终极debug环节:
- 若某条微指令的
MemWrite=1但MemRead=0,而当前周期是lw的Memory阶段,则错误——lw需读内存,不应写; - 若
R_TYPE指令的Writeback阶段,RegWrite=0,则结果无法写回,sort.hex必然失败; - 若
syscall的最后一条微指令未置PCWrite=0且Halt=1,CPU会继续取指执行无效地址。
3.3 硬布线控制器:用状态机取代ROM,速度与复杂度的博弈
硬布线多周期控制器抛弃了微程序的ROM,改用有限状态机(FSM)直接生成控制信号。它更快(无ROM访问延迟),但设计更复杂。其核心是两张表:状态转换表(现态+输入→次态)和输出控制表(现态+输入→控制信号)。
状态机设计:从流程图到卡诺图的硬核推导
报告中图1.7的指令状态变换图是设计起点。它将CPU生命周期划分为14个状态(S0-S13),每个状态对应一个时钟周期的操作。例如:
S0(0000):取指(IR←Mem[PC], PC←PC+4)S1(0001):译码(A←R[rs], B←R[rt], C←PC+4*SignExt(offset))S2(0010):R型执行(C←A op B)S3(0011):R型写回(R[rd]←C)S4(0100):lw执行(C←A + offset)S5(0101):lw访存(MDR←Mem[C])S6(0110):lw写回(R[rt]←MDR)
状态转换逻辑(表1.16)描述了在每个状态下,遇到不同指令(R_TYPE/LW/SW等)时,下一状态是什么。例如,从S0(取指后),若指令是LW,则下一状态是S4(lw执行);若是R_TYPE,则下一状态是S2(R型执行)。
易错点:状态编码与指令译码信号的交叉耦合。表1.16中
S0的下一状态列,R_Type对应S2,LW对应S4,SW对应S5……但SW的执行只需S5(计算地址)和S6(写内存),没有S7写回。若错误地将SW的下一状态设为S7,会导致sw指令多执行一个空周期,sort.hex的时钟周期数会异常增加。
组合逻辑生成:用最小项表达式对抗逻辑爆炸
将表1.16的状态转换关系转化为硬件电路,传统方法是写出每个次态位(N3/N2/N1/N0)的最小项表达式(表1.17),再用Logisim的“自动电路生成”功能。例如,N0(次态最低位)的表达式是:N0 = Σm(1,2,3,4,5,6,7,8,9,10,11,12,13) + ...(具体项略)
这个过程极易出错:
- 遗漏最小项:表1.16中
S1(0001)状态,R_TYPE指令的下一状态是S2(0010),N0应为0;若在表达式中漏掉此项,S1-R_TYPE会跳转到错误状态; - 混淆输入信号:
R_Type、LW等是译码信号,必须确保它们在S0之后的下一个周期才稳定。若状态机在S0就采样这些信号,而译码电路有延迟,会导致误判。
4. 易漏点与易错点:那些让你调试到凌晨三点的“幽灵Bug”
在Logisim中搭建CPU,最折磨人的不是不会做,而是“明明逻辑看起来对,但就是跑不通”。这些Bug往往藏在细节的缝隙里,成为横亘在“理论正确”和“波形稳定”之间的最后一道墙。以下是这份报告实践中最高频、最隐蔽的5个易漏/易错点,每一条都附带血泪经验总结。
4.1 指令译码信号的“毛刺”与“建立时间”:信号没稳,状态已变
易漏点:在单周期或多周期的指令译码电路中,R_TYPE、LW等信号在时钟上升沿到来时,可能尚未稳定(存在毛刺或建立时间不足),导致后续控制器采样到错误值。
为什么漏:Logisim默认仿真不显示信号传播延迟,初学者容易忽略门电路的固有延迟。尤其当Op/Func比较器输出经过多级与/或门后,延迟累积,R_TYPE信号可能比Op晚几个纳秒才有效。
怎么补:在关键译码信号(尤其是作为状态机输入的R_TYPE、LW等)后,强制插入一个D触发器(DFF),用主时钟同步。即:R_TYPE_sync = DFF(R_TYPE, CLK)。这牺牲了一个周期,但换来绝对稳定的信号。多周期CPU中,S0状态采样的译码信号必须同步化,否则S1状态会基于错误指令类型执行。
4.2 ALU零标志(Zero Flag)的“幽灵输出”:beq/bne永远不跳
易漏点:beq和bne指令依赖ALU的Zero输出信号。但很多Logisim ALU组件(或自建ALU)的Zero信号,在ALU输入未定义(如全0)或ALU未执行减法时,会输出随机值(X),而非稳定的0或1。
为什么漏:教材和手册通常假设ALU功能完备,但实际搭建时,若ALU模块未显式处理Zero信号的默认状态(如在非减法模式下强制Zero=0),beq的分支逻辑就会失效。
怎么补:在ALU输出端,用一个MUX和一个常量0对Zero信号进行“钳位”。逻辑:Zero_safe = (ALUOp == 0b01) ? Zero_raw : 0。即只有在执行减法(beq/bne)时,才使用真实的Zero;其他时候强制为0,避免幽灵跳转。
4.3 多周期CPU的“状态粘滞”:PC卡在某个地址不动了
易漏点:多周期CPU执行到syscall后,PC寄存器停止更新,但其他部件(如ALU、寄存器堆)仍在消耗时钟,导致波形图上PC值不变,而时钟计数器狂涨。
为什么漏:syscall的停机逻辑常被简化为“置Halt=1”,但忽略了Halt信号必须同时切断PC的Load使能和所有其他部件的时钟使能。若只断PC,IR仍会不断从内存读新指令,A/B寄存器持续更新,整个CPU陷入“空转”。
怎么补:设计一个全局ClockEnable信号,由Halt控制。Halt=1时,ClockEnable=0,所有寄存器(PC、IR、A、B、ALUOut、MDR)的Load端均失效,CPU彻底静默。sort.hex测试中,若看到时钟周期数远超891(报告值),大概率是Halt未生效。
4.4 微程序“下址字段”的“位宽陷阱”:跳转地址错了一位,全盘皆输
易漏点:表1.15微指令的“下址字段”是4位(S3-S0),但Logisim中微程序ROM的地址线可能是8位或更多。若直接将4位下址连接到8位地址总线,高位默认为0,导致跳转地址永远在0x00-0x0F范围内,无法到达S10(1010)等高位状态。
为什么漏:Logisim的ROM组件属性中,“Address Bits”和“Data Bits”需手动设置。新手常只关注数据位宽(32位),忽略地址位宽必须≥4(本设计14状态需4位),且下址信号必须零扩展(Zero-Extend)到ROM地址总线宽度。
怎么补:在微地址转移逻辑输出端,添加一个“Bit Extender”组件,将4位下址扩展为8位(高位补0)。或者,在ROM属性中将“Address Bits”设为4,并确保微程序文件(.txt)的地址索引与之匹配。
4.5 sort.hex数据加载的“字节序幻觉”:内存里看着对,其实全反了
易漏点:sort.hex文件内容为06 05 04 03 02 01 FF FF,但在Logisim内存中加载后,80h单元显示为00000006(正确),84h单元却显示00000005(应为00000005,但若字节序错误会是05000000)。
为什么漏:Logisim内存组件默认按小端序(Little-Endian)解释数据。sort.hex是按字节序列写的,但CPU的lw指令是以字(4字节)为单位读取的。若sort.hex文件未按小端序组织,或Logisim内存加载设置错误,会导致字内字节顺序颠倒。
怎么补:在Logisim中,右键点击内存组件 → “Edit...” → 在“Data”选项卡下,确认“Endianness”设置为“Little-Endian”。同时,检查sort.hex文件:前4字节06 05 04 03应对应内存地址80h的字0x03040506(小端),而非0x06050403(大端)。若文件是大端,需用工具转换。
5. 查漏补缺实战清单:一份可打印、可勾选、可救命的CPU设计自查表
当你在Logisim里反复修改、波形图上信号乱飞、sort.hex输出始终不对时,与其从头重画,不如拿出这份按模块拆解的“手术刀式”自查清单。它不讲原理,只列动作;不求全面,但求致命。每一条都对应一个真实翻车现场,勾选一项,就排除一类故障。建议打印出来,贴在显示器边框上,调试时逐条打钩。
5.1 数据通路层:先保“路”通,再求“车”快
这是最底层的物理连接,也是最先崩溃的环节。务必在控制器设计前,用最简指令(如add $1,$2,$3)单独测试。
| 检查项 | 操作步骤 | 预期现象 | 不通过意味着 |
|---|---|---|---|
| 寄存器堆读写 | 1. 将$2=0x1234,$3=0x5678写入;2. 执行 add $1,$2,$3;3. 观察 $1输出 | $1应显示0x68AC | 寄存器堆地址线/数据线接错,或RegWrite/RegDst信号未生效 |
| ALU基本运算 | 1. 手动设置ALU输入A=0x00000001, B=0x00000002;2. 设置 ALUOp=0b10(加法) | ALU输出=0x00000003 | ALU内部加法器未连接,或ALUOp译码错误 |
| 内存读写 | 1. 向内存80h写入0x0000000A;2. 执行 lw $1,0($0)(从80h读) | $1=0x0000000A | MemRead信号未连,或内存地址线(ALUOut)未接入,或字节使能错误 |
| PC更新 | 1. 初始PC=0x00000000;2. 执行一条指令(如 add);3. 观察PC变化 | PC应变为0x00000004 | PCWrite信号未生效,或PC+4加法器输出未连到PC数据端 |
提示:以上测试务必关闭控制器,用手动开关(Tunnel)直接驱动控制信号。例如,测试ALU时,将
ALUSrcA=0,ALUSrcB=0,ALUOp=0b10全设为常量;测试内存时,手动置MemRead=1,MemWrite=0。这是隔离问题的黄金法则。
5.2 控制器层:信号是灵魂,时序是生命
控制器是CPU的大脑,它的信号必须精准、稳定、按时序发放。这是调试中最烧脑的部分。
| 检查项 | 操作步骤 | 预期现象 | 不通过意味着 |
|---|---|---|---|
| 指令译码稳定性 | 1. 在PC=0x00000000处放add指令(0x00000020);2. 用探针观察 R_TYPE信号波形 | R_TYPE在S0周期后稳定为1,无毛刺 | 译码电路延迟过大,或Op/Func比较器输入未同步 |
| ALU控制信号 | 1. 执行add指令;2. 在 S2(Execute)周期,观察ALUOp | ALUOp应为0b10(加法) | ALUOp生成逻辑错误,或状态机未在正确周期激活该信号 |
| 分支条件信号 | 1. 执行beq $1,$1,label($1=$1,必跳);2. 在 S2周期,观察Zero和Branch | Zero=1,Branch=1同时为高 | ALU的Zero输出未正确连接到分支逻辑,或Branch生成逻辑漏了Zero |
| 写回控制信号 | 1. 执行lw $1,0($0);2. 在 S6(Writeback)周期,观察RegWrite和MemToReg | RegWrite=1,MemToReg=1 | RegWrite的OR逻辑漏了LW信号,或MemToReg未与LW关联 |
5.3 系统级验证:用sort.hex做最终审判
当所有模块单独测试通过,就进入终极考验。sort.hex不是用来“跑通”的,是用来“榨干”CPU所有路径的。
| 测试场景 | 操作步骤 | 关键观测点 | 失败原因指向 |
|---|---|---|---|
| 基础执行 | 加载sort.hex,运行至停机 | 1. 内存80h起:06 05 04 03 02 01 FF;2. 时钟周期数 |
本文还有配套的精品资源,点击获取