计算机组成原理这门课的课设,几乎是每个计算机专业学生绕不过去的一道坎。平时上课听老师讲冯诺依曼结构、数据通路、ALU、控制器,觉得都听懂了,真到了课设周要自己动手“造”一个CPU的时候,很多人当场懵掉:不知道指令集怎么定,不知道控制信号从哪来,连仿真波形里冒出来的高阻态都分不清是正常还是报错。这篇内容就是围绕计算机组成原理课设展开的实操总结,适合正在为课程设计发愁、想系统梳理CPU设计思路、以及准备课设答辩的同学参考。
我做计算机系统方向的教学辅导和开源项目有好几年了,见过大量课程设计报告和实验代码。一个比较扎心的发现是:很多人的课设分数低,并不是因为不够努力,而是从头到尾都在用“试错法”写课设——画图改一下、仿真不行再改一下,报告是最后一天拼凑出来的,答辩时一问原理就露馅。课程设计真正的验收点,是你有没有把这个系统“讲圆”:为什么这样设计、每条指令怎么走通、出问题时怎么定位。下面这篇总结,就是按这个逻辑来展开的,把我这些年见过的坑、用过的套路、以及报告里值得写的亮点,一次性讲清楚。
1. 课设不是造火箭:先想清楚你要“造”一个什么东西
1.1 计算机组成原理课设的典型选题,我为什么推荐CPU方向
计算机组成原理课设的题目其实就那么几大类。第一类是简易CPU设计,要求实现一个能执行若干条指令的处理器,可以是单周期、多周期或者流水线;第二类是运算器设计,比如定点加减法器、阵列乘法器、ALU;第三类是存储系统设计,比如Cache模拟器、主存地址映射;第四类是微程序控制器设计,本质上还是为了控制CPU;还有一类是综合应用型,像电梯控制器、交通灯控制器,这类偏接口和状态机,很多学校把它放在数字逻辑课设里而不是组成原理课设里。
我的建议很明确:能选CPU类就选CPU类,别躲。理由不复杂,CPU设计能把你课程里学的几乎所有重要知识点串起来——指令编码、寄存器堆、ALU、控制器、存储读写、PC跳转、时钟与复位,做完一个CPU,你等于把整本书复习了三遍。答辩的时候也最好讲:老师问“这条指令在你的机器里是怎么执行的”,你可以顺着数据通路把每个阶段讲清楚,而不是像ALU题目那样只盯着几个电路的逻辑表达式。ALU题和Cache题本身不简单,但它们的知识面偏窄,答辩时老师只能往深了问,反而不容易答。
另外,很多人觉得CPU课设一定很难,其实未必。真正难的是一上来就想做超标量、做五级流水线加分支预测,结果两三周时间根本不够。课设是让你巩固原理的,不是让你发论文。选定一个你能在一个月内完整做出来并且能讲清楚的设计,比什么都强。我见过有同学两星期做出了一个看起来非常漂亮的流水线CPU,但代码是从网上改的,控制逻辑完全说不清,答辩照样被挂,这就是典型的“贪多嚼不烂”。
1.2 学软件方向的人,为什么也躲不开这门课
每次计算机组成原理开课,总有人问:我是学软件方向的,以后写Java写Python,为什么要学什么组成原理,还要做课设?这个问题我在各种场合被问过很多次,每次我都会用一个例子回答:你写并发代码的时候,为什么知道要把变量声明成volatile?为什么频率特别高的计数器要考虑使用缓存行填充?这些问题的答案,都不在语言教科书里,而在计算机组成原理讲的内存一致性和Cache层级里。
软件方向的同学学这门课,重点不是学会写Verilog或者会画门电路,而是要建立“程序如何在硬件上真正跑起来”的模型。举个最简单的例子:如果不知道数据存储器读操作是组合逻辑、写操作是时钟触发,你就很难理解为什么在高性能计算里“读多写少”的数据结构可以做得比“写多读少”快那么多。再比如,理解了指令流水线和数据冒险,你再去看编译器为什么会对循环做软件流水,会有一种豁然开朗的感觉。
所以做课设的时候,软件方向的同学不要抱着“我画完图交了就行”的心态。这门课的回报周期很长,可能你毕业设计写一个性能分析工具的时候,才发现当年逼着自己搞懂的数据通路和控制信号,成了理解整个系统性能模型的基础。退一步说,就算你以后真的再也不接触硬件,这门课也能帮你建立一种“向下看一层”的思维方式,这种思维方式在排查线上性能问题、做数据库调优的时候,价值是实打实的。
2. 动手之前先立规矩:指令集与数据通路的整体设计
2.1 指令集别贪多,8到10条最小子集就够用
不管你用Logisim画电路,还是用Verilog写代码,做CPU课设的第一步都只有一个:定义指令集。注意,是“定义”,不是“抄”。很多同学上来就把MIPS手册里的指令搬过来几十条,结果是数据通路越画越复杂,控制信号表大到自己都不想看,最后每条指令都有bug。
我的经验是先做最小可运行子集。以32位MIPS风格为例,选这几类就足够了:
- 运算类R型4条:ADD、SUB、AND、SLT,覆盖加减、逻辑、比较;
- 访存类I型2条:LW、SW,覆盖读和写;
- 分支类I型1条:BEQ(相等则跳转),覆盖条件分支;
- 跳转类J型1条:J,覆盖无条件跳转;
- 立即数类I型1条:ADDI,顺便把立即数扩展这个知识点带出来。
一共9条指令,已经足够把一个完整的单周期CPU数据通路走通了。每条指令都能对应到取指、译码、执行、访存、写回这五个阶段,但又不至于让你陷入几十种opcode组合的控制逻辑泥潭。等你把这9条跑通,真想扩充,再加ORI、BGTZ之类,成本就很低了。反过来,你一开始就实现了30条指令,中间任何一条出问题,你排查的复杂度是指数级上升的。
指令格式这里要讲清楚。我们用经典的三种格式:R型是opcode(6位) + rs(5位) + rt(5位) + rd(5位) + shamt(5位) + funct(6位),I型是opcode(6位) + rs(5位) + rt(5位) + immediate(16位),J型是opcode(6位) + address(26位)。为什么rs和rt各占5位?因为32个寄存器需要5位来编码,2的5次方等于32。很多同学写报告时连这个基本编码原理都说不清,建议在设计说明里把这个编码表画出来,这是最基本的理论支撑。
2.2 单周期还是多周期?看清题目的隐藏要求再选
指令集定了以后,第二个关键决策是选单周期还是多周期。单周期CPU每条指令在一个时钟周期内完成,控制逻辑简单,数据通路一条线拉通,非常适合作为课程设计的基础实现。它的缺点是时钟周期被最慢的那条指令卡住——LW指令既要读寄存器、算地址、访存、再写回,所有操作串在一个周期里,其他指令也得陪着用这个长周期,整体效率不高。但课设不追求性能,单周期的“简单可控”就是最大的优势。
多周期CPU把每条指令拆成若干步,每一步占用一个时钟周期,比如经典的“取指、译码、执行、访存、写回”五步,ALU等部件可以复用,硬件利用率更高。但代价是控制器必须包含一个状态机,状态转换关系如果不在纸上画清楚,实现的时候几乎必然乱套。我见过有同学多周期控制器写了三百行case语句,最后状态跳转错了,问题找了两天。
怎么选?我建议看题目要求。如果题目只要求“实现一个能运行给定测试程序的CPU”,那单周期就是最稳的选择,把精力省下来做测试和报告。如果题目明确写了“要求采用多周期”或者“要求实现流水线”,那没有办法,硬着头皮也要上。还有一个隐藏选项是“单周期为主、报告里扩展讨论多周期对比”,这样既能显示你有全局视野,又不会把自己逼疯。选型这个理由,一定一定要写进报告,老师很看重设计者的权衡思路。
数据通路的结构,单周期的大致是:PC指向指令存储器,取出指令后送到寄存器堆和控制器;寄存器堆读出rs和rt的值,经过ALU运算;如果是访存指令,ALU算出的地址送到数据存储器;最后从ALU或者存储器的输出选择写回寄存器堆。分支指令要在ALU里做相等判断,并把目标地址回写到PC。整条通路画出来以后,你会发现控制信号其实就集中在几个多路选择器上,MCU输出所有选择信号,数据才能走对路。这也是为什么控制器设计要放在数据通路定型之后——通路没定,你根本不知道要生成哪些控制信号。
3. 核心模块逐个拆解:ALU、寄存器堆、控制器与存储
3.1 ALU里的加法器:从行波进位聊到组间串行进位
ALU是CPU的运算核心,加法器又是ALU的核心。课设里如果你是用Logisim画电路,加法器部分是最能体现水平的地方,也是老师最爱追问的地方。这里必须把进位方式讲清楚,这也是计算机组成原理里一个高频考点:组间串行进位。
最朴素的加法器是多位行波进位加法器(Ripple Carry Adder),把32个全加器一级一级串起来,低位进位输出接到高位的进位输入。这样做的好处是结构简单、一眼能看懂,但坏处也很明显:每一级的和都要等低一位的进位算出来以后才能算,32位加法时,进位从最低位“一路串”到最高位,路径时延随位数线性增长。在报告里你如果能算一笔账:假设一位加法器进位传播时延是t,32位行波进位总共要31t的进位时间,这么大的时延,在真实芯片里是没法接受的。
改进方案是超前进位加法器(Carry Lookahead Adder)。它的核心思路是引入两个信号:生成函数G_i = A_i & B_i,表示第i位自己就能产生进位;传播函数P_i = A_i ^ B_i,表示第i位会把输入进位原样传下去。于是第i位的进位可以写成C_i = G_i | (P_i & C_{i-1}),再往下展开,就能把C_i直接表达成G_0到G_{i-1}、P_0到P_{i-1}和C0的组合逻辑,从而不再依赖逐级进位。超前进位的速度很快,但位数一大,电路规模会爆炸,32位完全展开的逻辑门数量大得离谱,扇入扇出也受不了。
所以实际工程里最常见的是“组内并行、组间串行”的结构,这就是热搜词里反复出现的“组间串行进位”。做法是把32位分成若干个4位小组,小组内部用超前进位方式并行算出进位,小组之间再按照行波方式串联。这样4位一组的组内进位时延被压缩到一个很短的时间,组间串行只链接8个小组,时延大概是8倍单组时延加上一些余量,比32级行波快得多,电路规模又比32位完全超前进位小得多。这个折中方案非常值得在你的课设里实现,它体现的是计算机组成原理里经典的“延迟-面积权衡”思想。如果你用Logisim,可以搭一个4位CLA模块,再实例化8个组成32位ALU,控制信号里加一个2位的ALUOp选择加、减、与、或,剩下的交给多路选择器输出结果和零标志位。
减法怎么处理?A减B可以用A加B的补码,也就是B按位取反再加1,所以ALU里做减法时,把B输入取反、同时把低位进位C0设为1即可。这部分也建议在报告里写清楚,因为很多同学会在“减法为什么不单独做一个减法器”这个问题上被问住。
3.2 寄存器堆和控制器的时序细节
寄存器堆的典型设计是32个32位寄存器,带两个读端口和一个写端口。两个读端口意味着同一个周期内能同时读出两条源操作数,这是R型指令ALU需要两个输入所决定的。读操作是组合逻辑,只要地址稳定,输出就跟随变化;写操作必须是时钟触发,在时钟上升沿时把数据写入地址对应的寄存器。
这个“读是组合、写走时钟”的细节,是课设里翻车最多的点。很多同学为了让写功能“正常”,把寄存器堆写成了电平触发,结果出现一个周期内写入的数据立刻被同一周期的读操作读到,导致时序错乱。正确的做法是:写使能信号RegWrite有效时,在时钟上升沿把写数据写入目标寄存器;读端口则始终是组合输出,不受时钟控制。之所以要这样,是因为“先写后读”的顺序在硬件里必须靠时钟沿来划分,写发生在上升沿,读发生在沿与沿之间的组合逻辑阶段,才能保证逻辑正确。
控制器方面,硬布线控制器的本质是一张“指令到控制信号”的真值表。对每条指令,你需要确定RegDst(写回寄存器编号来自rt还是rd)、ALUSrc(ALU第二输入来自rt还是立即数)、MemRead、MemWrite、RegWrite、Branch、Jump、ALUOp(ALU执行什么操作)等信号。我的建议是先做一个Excel表,行是指令,列是控制信号,把所有信号逐条填好,再去写代码或者画电路。这个表很重要,一是写逻辑时不会漏信号,二是报告里可以直接放这张表作为设计依据,三是答辩时老师问你“某条指令的控制信号是什么”,你张口就能答。
ALUOp信号怎么映射到ALU内部操作?通常控制器只输出2位ALUOp,再结合funct字段译码出5位真操作。比如ALUOp等于00表示加法(用于LW、SW计算地址和ADDI),01表示减法(用于BEQ比较),10表示由funct字段决定具体运算(用于R型指令)。这个两层译码结构既减少了控制信号位数,也呼应了“译码”这个概念在现代CPU中的分层思想。
3.3 指令存储与数据存储为什么非要分开
课设里几乎都要求把指令存储器和数据存储器分开设计,很多同学不理解:教材上不是说冯诺依曼结构是“存储程序”吗?为什么不能共用一个存储器?这里有一个非常实际的硬件原因:在单周期CPU里,取指令和访存可能发生在同一个时钟周期。以LW指令为例,一个周期内既要取出一条新指令,又要根据地址从数据存储器里读数据。如果指令和数据在同一个存储器里,这个存储器就需要两个读端口,不然冲突无法避免。
这种“同一资源在一个周期内被请求两次”的现象,在体系结构里就叫结构相关(Structural Hazard)。课设里把指令存储和数据存储分成两块,就是为了从根上消除结构相关。这个点特别适合写进报告的“设计权衡”部分:我通过分离指令和数据存储器,避免了取指与访存的结构冲突。放到现代CPU里,这就是指令Cache和数据Cache分离的雏形。老师听到这个回答,会觉得你不是在画图,而是在理解设计。
存储器本身的读写时序也要说清楚。理想情况下,指令存储器的读操作是纯组合逻辑:PC地址给进来,指令内容立即在输出端出现,不依赖时钟。数据存储器同理,读操作组合实现,写操作在时钟上升沿或下降沿触发。如果你的仿真波形里,读数据总是晚了一个周期才出来,就要检查是不是误把读也做成了边沿触发。这是初学者最常见的存储器错误。
4. 从仿真到上板:实操流程、测试用例与调试实录
4.1 工具链选型:Logisim、Verilog还是教学平台
课设工具三选一的问题,几乎每个学校都在讨论。Logisim是图形化数字电路仿真工具,适合原理验证型课设,你可以拖拽门电路和触发器,直接看到每一根导线上的电平变化。它最大的优点是直观,CPU数据通路怎么走、控制信号怎么选,肉眼可见;缺点是做大规模电路会比较卡,而且图形化连线多了以后维护困难。如果你是用Logisim,强烈建议用Logisim-Evolution这个社区维护版本,修复了很多原版崩溃和中文兼容性问题。
Verilog/VHDL加FPGA开发板是另一种路线。用硬件描述语言写CPU,写完以后可以综合、布局布线、下载到FPGA上跑,甚至接上LED和数码管,体验更接近真实芯片设计流程。但这条路线学习曲线陡,你要同时掌握硬件描述语言的并行思维、时序约束概念、开发工具(Vivado或Quartus)的操作。我以为,如果你的目标是“体验一把真正的数字电路设计流程”,选Verilog没错;如果目标是“把组成原理的知识验证清楚”,Logisim的效率更高。
还有一类是学校指定的教学仿真平台,就是那种在电脑上模拟CPU运行的教学软件。很多学校的计算机组成原理实验课会用这类平台做单周期CPU验证,配套有一本《使用手册》,里面对每一步操作写得非常详细。我的建议是:如果学校指定了平台,一定要先看手册再动手,哪怕想用Logisim也别急着换。教学平台的手册通常包含实验平台引脚分配、时钟来源、存储上电初始化等关键信息,这些信息在通用仿真工具里不适用,但在指定平台上不照着做,上板就是黑屏。手册是第一手资料,比任何学长笔记都靠谱。
4.2 分步实现的顺序与测试用例设计
不管是哪种工具,实现的顺序都要按“数据通路骨架 -> 控制信号 -> 逐条指令验证”来推进,不要上来就想一次搞定。
第一步,搭数据通路骨架:PC寄存器、指令存储器、寄存器堆、ALU、数据存储器按顺序连接起来,先把连线画清楚,不急着加控制信号。第二步,固定指令编码:把你选定的9条指令的二进制编码写清楚,用手动赋值的方式,让PC指向某条指令,看看取出的机器码是否符合预期。这个步骤能帮你确认取指通路是不是通的。
第三步,给寄存器堆写初始数据,用最简单的ADD指令做加法,观察ALU输出是否正确。如果不对,先查寄存器堆的读地址有没有接反——rs和rt很容易接反,这个错误出现的概率极高。第四步,加控制信号,把ADD、SUB、AND、SLT逐条跑通,重点检查RegDst和ALUOp信号。第五步,加访存指令LW和SW,检查地址计算和存储器的读写时序。第六步,加BEQ和J,检查分支条件的零标志和PC跳转地址。最后,把所有指令组合成一个完整的小程序跑通。
测试用例要设计得有层次,不能拿一个几十行的大程序从头跑,跑不通也不知道问题在哪。建议按功能点拆开测,先R型,再立即数,再访存,再分支,最后组合。组合程序可以这样写:先给两个寄存器赋初值,做一次加法,结果存到内存,再从内存读回来,最后用BEQ判断两个寄存器是否相等并跳到结束。这一套程序能覆盖几乎所有指令类型和全部数据通路阶段。每跑通一个层次,就把仿真波形截下来,放进报告里作为验证证据,这个习惯会帮你省下大量写报告的时间。
4.3 仿真波形常见问题与定位方法
课设调试阶段的核心工作就是看波形。这里把我见过最多的几类问题列个清单,每一条都来自实际翻车现场。
第一类:输出全是X或Z。X表示未知,通常是没有初始化或者信号悬空;Z表示高阻态,通常是输出端口没接驱动。检查方法很简单,沿着数据通路从PC开始逐级看波形,看哪个节点第一个出现X,问题就往回找。第二类:寄存器永远写不进去。大概率是时钟极性接反了或者RegWrite信号没在正确的周期有效。注意看控制信号的波形,RegWrite是否在时钟上升沿到来之前已经稳定,如果稳定时间不够,就会漏写。第三类:分支指令该跳不跳。先看Z标志对不对,再看分支目标地址算得对不对——BEQ的目标地址是当前PC加4再加偏移量乘4,很多人忘了乘4或者忘了加4,导致跳飞。第四类:运行结果差1。这一般是立即数符号扩展没做对,比如ADDI对负数立即数做了零扩展,正数运算倒是没事,遇到负数就全错了。
定位问题有个通用套路:把每条指令的执行过程拆成“取指、读寄存器、运算、读写存储、写回”五个环节,对着波形一个一个环节看。这非常像软件调试里“断点定位”的思路,只是断点变成了时钟周期。建议在报告“问题与体会”部分写一两条你真实遇到的bug和解决过程,老师非常爱看这个,因为它证明你是真的自己动手调过的,而不是从网上抄了一份。
5. 如果题目是流水线:三种相关性从理论到落地
5.1 结构相关、数据相关与控制相关的本质区别
如果你的课设题目标明了“流水线CPU”,或者你想在报告里做一个扩展讨论,那三种相关性是绝对绕不开的核心内容,也是计算机组成原理期末考试和课设答辩都喜欢考的题目。
结构相关,刚才在存储器分离那里已经提过,本质是硬件资源不够用,两个阶段在同一周期想访问同一个部件。比如取指阶段要访问指令存储器,访存阶段要访问数据存储器,如果它们共用一块存储器,就撞车了。解法要么是物理上分开,要么是让流水线暂停一拍(Stall)。
数据相关的本质是“数据还没准备好,后面就要用”。典型场景是两条相邻指令:ADD r1, r2, r3 / SUB r4, r1, r5,第二条指令要读r1,但r1要等第一条指令写回之后才算数。如果流水线严格执行五级,写回在最末尾,第二条指令的读寄存器阶段早就过去了,读到的就是旧值。数据相关细分有RAW(先写后读)、WAR(先读后写)、WAW(先写后写),课设里最需要注意的就是RAW,也就是真正的“数据还没算出来就要用”。
控制相关最直观,就是分支指令还没判断出结果,PC还不知道下一条该指向哪里,指令已经被流水线预取进来了。取进来的指令如果发现不该执行,就得被清空(Flush),相当于白白浪费了几个周期。
很多同学容易把三种相关记混,我提供一个记法:结构相关是“部件不够用”,数据相关是“数据没到位”,控制相关是“不知道该往哪走”。这三种相关分别对应三种经典解法:加资源、加转发(Forwarding/Bypassing)、加预测或延迟槽。
5.2 转发、停顿和分支处理的课设实现
在课设里落地数据转发,是最能体现“我理解流水线”的操作。转发的基本思想是:虽然数据还没有写回寄存器堆,但它在执行阶段或者访存阶段末尾已经算出来了,直接从那个位置“抄近路”送给后面指令的ALU输入端,就可以避免等待写回。
实现方法是让ALU的两个输入端各接一个多路选择器,选择器的数据来源有三个:寄存器堆的正常输出、执行/访存阶段流水线寄存器的中间结果、访存/写回阶段流水线寄存器的最终结果。转发的控制条件需要比较当前指令的源寄存器号和前两条指令的目标寄存器号:如果相同并且目标寄存器写使能有效,就说明前一条指令的结果可以直接转发过来。这个多路选择器的切换逻辑,在代码里通常表现为一段复杂的条件判断,在Logisim里则体现为一组比较器和多路选择器连线。写这一段之前,一定要画一个“数据来源-目标寄存器”的对应表,不然条件判断很容易漏组合。
停顿(Stall)通常和转发配合使用,典型场景是LW指令后面紧跟一条要用LW结果的指令。因为Load的结果要到访存阶段末尾才出来,执行阶段的ALU反向转发也来不及,只能把后面那条指令堵一拍,硬件上就是插入一个气泡(NOP)。这个操作在Verilog里实现比较简单,可以通过控制流水线寄存器的写使能来冻结前级;在Logisim里实现气泡相对麻烦,常见做法是引入一个流水线暂停信号,统一控制各级流水线寄存器的使能端。
分支处理最简单的课设方案是“预测不跳转”:流水线照常取分支后面的两条指令,等分支指令在译码或执行阶段算出结果后,如果发现真的要跳转,就冲洗掉已经取进来但不该执行的指令。能耗是浪费了一两个周期,但在课设规模下完全可接受。如果你有余力,可以实现“延迟槽”方案,编译器负责在分支后面安排一条总是会执行的指令,这条指令不与分支判断冲突就行,这也是MIPS体系结构里经典的软件-硬件协同思路。
6. 报告与答辩:让你的工作量被老师看见
6.1 报告结构模板与画图建议
课设做得再好,报告写成一团浆糊也是白搭。计算机组成原理课设报告通常包含这几个部分:题目与要求、总体设计方案、各模块详细设计、系统验证与结果分析、问题与心得体会、参考文献与附录。如果学校给了模板,照模板走;没给模板的话,我建议就按这个结构来。
总体设计方案里,最重要的是三样东西:指令集编码表、整体数据通路图、控制信号真值表。指令集编码表说明你实现了哪些指令以及为什么是这些;整体数据通路图让别人一眼看清数据是怎么流动的;控制信号真值表是整个设计的“说明书”,也是老师判断你到底有没有搞懂控制器的主要依据。这三样东西放齐了,报告的基本盘就已经稳了。
画数据通路图不要用仿真工具的截图直接贴,截图太糊而且包含大量无关网格线。用draw.io、PPT甚至Visio重画一张,模块用矩形框,信号线用箭头,控制信号用不同的颜色标注出来。一张图塞不下就分两张,一张画数据通路,一张画控制信号分布。画完以后,每张图配三到五句话解释:数据从哪里来、经过什么部件、控制信号在哪里产生、最终写到哪里。图要配字,字要配图,这一点很多学生做不好。
6.2 答辩高频问题速答清单
答辩环节,老师问来问去其实就那么几类问题,提前准备好,能少很多临场的慌乱。
第一类:“这条ADD指令在你的CPU里执行,需要几个周期?”单周期答案是1个周期,多周期答案要说清楚是哪几个步骤,流水线答案是5级流水线在理想情况下每周期完成一条指令,但需要注意数据相关和结构相关带来的停顿。第二类:“你的ALU进位时延是多少?”至少要把行波进位和组间串行进位的区别讲清楚,能说出你采用的方案是为了在速度和电路规模之间做平衡,就及格了。第三类:“为什么要把指令存储器和数据存储器分开?”回答是避免结构相关,这在单周期CPU里尤为重要。
第四类:“如果我要增加一条新指令,你需要改动哪些地方?”经典问题是BGTZ分支指令。你要回答出:先定义指令编码,然后改控制信号真值表,增加译码逻辑,必要时在数据通路上增加多路选择器或修改ALU操作别,最后在测试程序里增加验证用例。第五类:“时钟频率最高能做到多少?”这个问题在Logisim里没法直接回答,但你的思路要对:时钟频率取决于关键路径的延迟,也就是最慢的那条路径,一般是LW指令经过的路径。你能说出“凡是要先写CV基础的,后面一定要配上验证波形图”这样的完整链条,老师就会满意。
答辩的时候还有一个隐形加分项:你是真的自己跑过调试的,还是从网上搬运的,老师问两个细节就能分辨。与其担心老师问倒你,不如在答辩前把你自己设计里最薄弱的那个模块再过一遍。绝大多数情况下,老师不会为难你,他们只是想确认“这个人真的懂自己的设计”。
课设做到最后,我个人体会最深的一点是:最值钱的不是最后跑通的那一瞬间,而是中间那个“看着波形不对,被迫把每条指令在每个时钟周期里做了什么都逼着自己画出来”的过程。那个过程很痛苦,但画完以后,整门计算机组成原理的知识就真的串起来了,甚至对你以后理解操作系统、编译原理、体系结构都有帮助。所以这份课设报告,别只当它是一个要交的作业,把它当成一次逼自己把“计算机怎么执行程序”这件事彻底搞明白的机会,你会有不一样的收获。