ARTICLE DETAIL

资讯详情

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

单总线CPU设计实验全解析:从指令集到微程序与仿真排错

单总线CPU设计实验全解析:从指令集到微程序与仿真排错 简介华中科技大学《计算机组成原理》课程CPU设计实验的完整实验报告面向计算机专业本科生、考研复试准备者以及正在学习MIPS体系结构与Logisim仿真平台的读者。报告系统记录了单周期与多周期两类32位MIPS CPU的设计全过程覆盖8条核心指令的硬布线控制器、微程序控制器实现并附有基于冒泡排序程序sort.hex的测试验证、故障调试及性能分析同时提供了数据通路示意图和控制信号功能表等关键设计资料。包体为1个docx文档共2.8MB内容包含设计要求、方案设计、实验步骤、故障与调试、测试与分析以及总结与心得等完整章节结构清晰可直接参考或作为课程设计模板。目前已有12110人浏览学习适合需要完成同类CPU设计实验、撰写实验报告或理解数据通路与控制器的读者下载使用。1. CPU设计实验这门课绕不过去的那份报告计算机组成原理这门课里CPU设计实验是压轴的大作业也是检验课本知识能不能兑现成硬件的试金石。华中科技大学的这份实验报告以docx存档真正的工作量却全在Logisim原理图或者Verilog代码里把MIPS指令子集翻译成一条条微命令让程序计数器、寄存器堆、ALU和存储器在限定拍节内协作完成取指、译码、执行、写回。这篇文章按指令集→数据通路→微程序→仿真排错→报告成稿的顺序把每一步的选型理由、关键参数和坑位讲清楚。适合正在做单总线或单周期CPU实验的学生也适合需要快速判断这类实验报告完成度的工程师。2. 单总线CPU的指令集与数据通路设计先订指令再挂总线数据通路和指令集是互相锁定的指令需要的操作决定总线怎么连反过来总线带宽又决定指令要拆成几拍。做实验不能一上来就连线先把指令子集和部件参数定下来。唐朔飞教材里的单总线CPU原型是这类实验的常见蓝本常见做法是先列一张指令功能表标注每条指令用到哪些部件再画数据通路框图。2.1 MIPS子集选多少条8条指令的覆盖逻辑大多数课程实验要求的指令在8到12条之间选型逻辑不是越多越好而是覆盖MIPS的三种基本格式R型、I型算数/访存、I型分支。典型配置是R型取add、sub、and、or、sltI型取addiu、lw、sw再加一条beq条件转移需要跳转时补j。这套子集能完整检验ALU的运算与零标志、寄存器堆的读写、存储器的按字访存、PC的顺序递增以及条件转移这五条关键路径。每增加一条指令代价不止是控制ROM多几行。在单总线结构里新指令如果有新的操作数来源就要给总线增加一个三态门微程序也要多一段执行序列。所以报告里写清为什么选这8条比只贴指令表得分高理由可以落在每个功能部件都被至少一条指令覆盖且没有冗余指令。2.2 单总线结构所有部件共享一根数据线意味着什么单总线CPU把所有部件的数据端并联到一条32位总线上任意时刻只能有一个驱动源在送数据其他驱动的三态缓冲器必须处于高阻态。这个约束直接决定了CPU必须多周期工作一次ALU运算至少四拍把源寄存器值送上总线到A锁存器把第二个操作数送B锁存器ALU结果回总线再从总线写入目的寄存器。与单周期CPU相比单总线把组合逻辑路径拆短了每个节拍只做一次总线传递或存储器访问时序约束更宽松但指令周期变长。华科实验路线通常就是单总线多周期微程序控制器因为连线规整、控制逻辑用ROM查表调试和写报告都直观。如果换成单周期MIPS CPU数据通路里会到处是多路选择器控制信号也变成纯组合逻辑两者选哪个要按课程要求的落点决定。2.3 关键部件参数表先定规格再画图部件常用规格设计要点寄存器堆8×32位或32×32位需要两个读地址口、一个写地址口单总线时两个读操作数分时送上总线ALU32位支持加、减、与、或、slt输出零标志ZA/B两侧各有一个锁存器暂存操作数程序计数器PC32位寄存器同步写入、异步清零支持输出到总线和自增1指令寄存器IR32位只在取指结束时刻写入其OP字段用于生成微程序入口主存储器128×32位按字寻址读在一个节拍内完成写受写使能和时钟控制MAR/MDR32位位于总线和存储器之间起隔离和暂存作用这里面最容易含糊的是寄存器堆的读端口。若寄存器堆只有一个数据输出口Rs和Rt必须分两拍读若用双读口设计可以把两个操作数同时打入ALU的两个锁存器执行段省掉一拍。写报告时建议把寄存器堆的端口图画清楚这经常是答辩时被追问的细节。关于存储器时序华科实验里强调现代时序即存储器读操作在一个节拍内直接返回有效数据不需要CPU等待应答。在Logisim里RAM的异步读输出天然满足这一要求写操作则由写使能和时钟沿共同限定。这一点与传统时序里需要MREQ握手信号的做法不同报告里把两种读写波形画出来能明显加分。3. 单总线CPU的微程序设计把指令拆成拍节和微命令微程序控制器的本质是用ROM内容代替逻辑电路每条指令的执行过程被拆成若干拍每拍对应一条微指令微指令里的控制字段直接就是各功能部件的使能信号。设计顺序是先写指令周期流程再定微指令格式最后填控制存储器内容。3.1 指令周期拆解从取指到写回要几拍取指微程序是公操作通常固定三段。第一拍把PC送上总线并写入MAR同时PC自增准备取下一条指令第二拍按MAR访问存储器读出内容锁存到MDR第三拍MDR送上总线写入IR同时把IR的OP字段送到微地址形成逻辑转到对应执行微程序。这三拍对所有指令完全一样。拍微命令数据流动T1PCOUT→MAR, PC1总线←PC, MAR←总线T2MEMREAD, MDRINMDR←M(MAR)T3MDROUT→IR, OP映射IR←总线, 生成执行段微地址执行段以add为例单总线下的分解是Rs→A、Rt→B、ALU(ADD)→总线、总线→Rd四拍。如果寄存器堆是双读口前两拍合并成一拍。lw的执行段要五拍Rs送A、立即数扩展送B、ALU求地址、访存到MDR、MDR写回Rt加上取指三拍整条lw约八拍。每多一拍控制ROM就多一条记录调试时多一个观察点。3.2 微指令格式控制字段、判别测试与下址微指令通常由三部分构成。控制字段每一位对应一个微命令同一拍互斥的命令在设计控制位时就要保证不会同时置1判别测试字段决定下一条微地址如何形成下址字段给出顺序情况下的下一微地址。字段宽度编码含义控制字段C16~20位每位对应一个微命令同一拍互斥的命令不会同时置1判别测试P2位00顺序执行01测试零标志Z10按OP映射下址NA8位判别不成立或无条件时的下一微地址微地址转移是微程序控制器里最容易写错的地方。按OP映射的做法是以指令OP字段作索引加到一个基地址上直接跳进该指令的执行微程序段起点。beq这类条件转移则测试ALU输出的零标志Z1时执行PC替换Z0时顺序取下址字段。教学CPU里转移目标常简化为PC符号扩展立即数字偏移省去左移、拼接和额外加法报告里写明这一语义即可。3.3 微程序代码示例取指、add、lw、beq四段下面这段是微程序表的文本表示左边微地址中间微命令右边下一微地址或转移条件。微地址只是为了讲清流动方向临时编的正式填表时按你的控制ROM布局重排。注意每行只能有一个→总线的微命令这是单总线的硬约束。; 取指公共段公操作 0x00: PC→MAR, PC1 NEXT0x01 0x01: M(MAR)→MDR NEXT0x02 0x02: MDR→IR, 按OP映射 NEXTMAP(OP) ; add $rd, $rs, $rt 执行段 0x04: Reg[Rs]→A NEXT0x05 0x05: Reg[Rt]→B NEXT0x06 0x06: ALU(ADD)→总线 NEXT0x07 0x07: 总线→Reg[Rd], 转取指 NEXT0x00 ; lw $rt, off($rs) 执行段 0x08: Reg[Rs]→A NEXT0x09 0x09: 符号扩展立即数→B NEXT0x0A 0x0A: ALU(ADD)→MAR NEXT0x0B 0x0B: M(MAR)→MDR NEXT0x0C 0x0C: MDR→Reg[Rt], 转取指 NEXT0x00 ; beq $rs, $rt, off 执行段 0x10: Reg[Rs]→A NEXT0x11 0x11: Reg[Rt]→B NEXT0x12 0x12: ALU(SUB), 测试Z Z1→0x13, Z0→0x00 0x13: PC←PCoff, 转取指 NEXT0x00lw段里A持有基地址B持有扩展后的偏移量ALU相加结果进MAR而不是寄存器堆这是访存指令和运算指令的主要差别。beq段做的是减法目的是设置零标志结果本身不进任何寄存器。多个R型指令的OP字段都是0只靠OP映射区分不了add和sub常见做法是让R型共用执行段入口段内再对funct字段做二次译码把运算类型送给ALU。3.4 硬布线控制器什么情况才值得换掉微程序硬布线控制器用状态机和组合逻辑取代控制ROM速度更快状态转换也直观。但它的缺点是可读性差每增加一条指令都要改状态转移表甚至状态编码实验中出错后从波形里反推状态很痛苦。微程序控制器的好处正好相反扩展指令只增加ROM条目调试时可以顺着微地址逐步查看。单总线CPU本来就以多拍换简单硬件ROM读出的时间开销完全可以接受。只有当课程要求做单周期CPU或流水线设计时硬布线才更贴近实际处理器的做法。4. 把单总线CPU跑起来Logisim搭建与仿真排错原理图阶段结束后剩下的工作就是让机器在仿真器里一格一格往前走。常见落地方式有两种用Logisim画原理图或者用Verilog写行为级模型。前者适合看信号流动后者适合批量回归验证。下面把两条路的关键步骤都过一遍。4.1 Logisim搭建的最小步骤子电路、总线与时钟启动Logisim后建议按子电路组织工程ALU、寄存器堆、微程序ROM、数据RAM各占一个子电路顶层只有总线、三态门和控制器。这样做的理由是总线上的三态门数量很多顶层如果堆成一张大图连线错误几乎没法查。java -jar logisim-evolution.jar # 新建工程后按 项目→添加电路 建 ALU / RegFile / ROM / RAM 四个子电路 # 顶层用32位导线连接所有三态门输出时钟信号统一接入各寄存器CLK搭建顺序建议这样走按2.3节参数表先把寄存器堆、ALU、RAM、ROM四个子电路做完每个子电路单独仿真验证一遍。顶层用Tunnel标签或直接导线把所有部件的数据端引向总线每个输出端加三态缓冲器使能端接微命令译码输出。时钟线接到PC、IR、MAR、MDR、寄存器堆写口和控制存储器的微地址寄存器上调试阶段全部用同一个时钟源。从手动时钟开始单拍推进观察PC、IR、MDR的变化确认取指三拍拍拍有反应。时钟配置上调试阶段强烈建议用手动时钟每次触发一个上升沿检查一个结果。如果一上来就跑自动时钟每个模块的动作太快根本看不清哪一拍出错。等整个程序能跑完后再改成自动时钟截图也来得及。4.2 Verilog参考骨架微程序控制器的三个字段如果课程允许用Verilog或者你想在写报告前用iverilog快速回归一遍微程序可以先只写控制器核心。下面的模块把控制ROM和微地址寄存器封装在一起C字段在顶层例化时接各三态门使能和寄存器写使能。// 微程序控制器参考骨架C字段接数据通路P字段决定下址来源 module ucontroller( input wire clk, input wire rst, input wire zero, // ALU零标志供beq测试 input wire [5:0] op, // 当前指令OP字段 output reg [7:0] uaddr // 微地址寄存器MPC ); reg [25:0] urom [0:255]; // {C[15:0], P[1:0], NA[7:0]} wire [15:0] C urom[uaddr][25:10]; wire [1:0] P urom[uaddr][9:8]; wire [7:0] NA urom[uaddr][7:0]; // 实际使用时用 $readmemh(microcode.hex, urom) 加载微程序 always (posedge clk) begin if (rst) uaddr 8h00; // 复位回到取指段起点 else case (P) 2b00: uaddr NA; // 顺序转移 2b01: uaddr zero ? NA : uaddr 8d1; // beq判别 2b10: uaddr {2b01, op}; // OP映射到0x40以上 default : uaddr uaddr; endcase end endmodule判别字段P取01时zero为1跳转到NA指定的分支微地址为0则顺序加1beq的不转移路径不用单独占ROM条目。P取10时把6位OP拼到微地址高两位后面入口落在0x40到0x7F区间避开0x00到0x3F的取指公共段。R型指令OP全是0会映射到同一个0x40入口段内再用funct字段选ALU运算类型这样控制ROM最省空间。4.3 指令与数据存储器的初始化文件在Logisim里指令存储器用ROM元件数据存储器用RAM元件两者都能从文件加载初始内容。下面给一个数组求和测试程序的汇编源码和对应机器码映像8条指令覆盖addiu、lw、add、sw、beq五类操作。# 数组求和S1 a[0] a[1]结果写回 a[2] addiu $s0, $zero, 0 # 数组基址字地址 0 addiu $s1, $zero, 0 # 累加器清零 lw $t0, 0($s0) # a[0] - $t0 add $s1, $s1, $t0 # sum a[0] lw $t0, 4($s0) # a[1] - $t0 add $s1, $s1, $t0 # sum a[1] sw $s1, 8($s0) # a[2] sum loop: beq $zero, $zero, loop # 自循环停机imm -1对应的指令ROM映像可以直接粘贴进Logisim的ROM编辑窗口或存成hex文件加载v2.0 raw 24100000 24110000 8e080000 02288820 8e080004 02288820 ae110008 1000ffff手工汇编时注意MIPS各字段顺序是OP在前rs、rt、rd依次排列。以add $s1,$s1,$t0为例字段是OP0、rs17、rt8、rd17、shamt0、funct0x20拼出来就是0x02288820。lw的OP是0x23sw是0x2Baddiu是0x09beq是0x04。初学阶段最大的坑是把OP和funct记混导致ROM里整条指令被译错。数据RAM把0号字和4号字分别填成5和88号字留0作结果位程序跑完后寄存器$s1和存储器8号字都应为0xD这就是验证CPU正确性的标准。4.4 单总线CPU三类高频故障与定位方法第一类是总线竞争症状是Logisim里总线上出现红叉原因是同一拍有两个→总线的微命令同时置位。定位方法很机械打开微程序表逐行检查确保每拍只有一个三态门使能调试器里用探针把三态门使能信号引出来能更快定位是哪一拍冲突。第二类是寄存器写入时序问题。寄存器堆的写使能如果和时钟沿配合不好会出现写进去的值是上一拍的总线值的怪现象。常见做法是让写操作发生在节拍末的上升沿数据在节拍内稳定到达寄存器的建立时间才有保证。排错时注意目标寄存器是否慢了一拍如果是先查时钟连接再查写使能是否在正确的微地址上有效。第三类是访存与写回的重叠问题。Logisim的RAM在WE有效时输出端行为可选输出旧值或输出新值如果你的设计里有读同一周期刚写过的字这类冒险必须固定RAM当前的读写语义否则对拍节时仿真结果和手工推导对不上。故障现象常见原因定位手段总线上出现红叉两个三态门同一拍打开查微程序表中同拍的→总线命令目标寄存器值慢一拍写使能与时钟沿不匹配用探针看RegWrite在哪个微地址有效lw结果恒为未知RAM写语义未固定在RAM属性面板固定写时输出选项提示在总线、PC、IR、MDR、微地址这五个位置上各加标签和探针Logisim仿真时就能实时追踪数据流动。大多数结果不对的问题顺着微地址和总线值的对应关系走一遍就找到了。5. CPU设计实验报告的成稿技巧从跑通到讲清楚老师看报告最关心两件事CPU是否真的按设计跑通了以及你懂不懂每一拍发生了什么。指令轨迹表比大段波形截图更直接每行记录一拍的主要微命令和总线值跑几条指令对齐几行。下面示例只列取指段三个节拍。拍微地址微命令PCIR总线值10x00PC→MAR, PC10X020x01M(MAR)→MDR1X高阻Z30x02MDR→IR10x241000000x24100000表里的PC、IR、总线值都要从仿真器里按拍抄出来和微程序表对照能证明每个控制信号确实在预期节拍有效。总线值在拍2记为高阻是因为访存数据先锁入MDR第三拍才经总线写入IR这一笔恰好能体现单总线的分时特性。PC用字地址表示若课程要求字节地址把表头改成PC×4即可。轨迹表覆盖add、lw、beq三条代表性指令就够不需要全程序逐行打印。docx报告按固定顺序组织即可实验目的、指令系统设计、数据通路框图、微指令格式与微程序表、仿真验证、问题与解决。截图至少三张数据通路全图、微程序ROM内容、带信号的波形或轨迹表每张图下面配两三行说明不要只贴图。答辩或审查时的常用追问有三个增加一条指令需要改哪些地方答案是控制ROM加一段执行微程序并扩展译码数据通路通常不用动最慢的是哪条指令答案是lw因为它要算地址、访存、写回拍数最多现代时序与传统时序的差别答现代时序下存储器读在一个节拍内完成无需等待应答即可过关。报告里把这几个问题的答案写进分析与讨论比最后硬凑一段心得体会实际得多。本文还有配套的精品资源点击获取
返回列表