
简介面向计算机组成原理课程设计的学习者这份文华学院个人课程作业文档围绕“基于Proteus简单模型计算机设计与实现”展开适合需要参考整机设计思路、微程序设计流程与调试记录的学生对照使用需注意其为个人作业仅供思路借鉴。文档从需求与总体设计入手依次梳理模型机逻辑图、运算器与存储器电路及其控制信号进而给出时序分析、指令数据流向、微指令与微代码设计、程序编制和调试结果验证较完整地呈现了从逻辑部件到整机运行的实现链路。压缩包仅含1个doc文件大小约2.79MB篇幅集中便于按目录快速定位运算器、存储器、控制器等模块的说明。目前已有537人学习可作为课程设计阶段梳理控制信号、区分脉冲与电平信号、检查微指令码点与时序安排的参考资料。1. 58H 加 58H 得 D0H凭什么说它对两片 74LS181 串成 8 位加法58H 加 58H 出 D0H在 Proteus 里跑出来只要几秒。但计算机组成原理课程设计这一关真正卡住人的不是那个 D0H而是答辩时老师随手抽一条 IN 指令问你这条指令占几个微地址、第三个微地址上 26 位微码里哪几位是 1、T2 和 T4 分别落在哪个节拍。这门课设要交的其实不是一张能跑通的图而是一套能自证的设计控制信号归纳得全不全、整机层次切得清不清、微指令码点排得对不对、开关拨动顺序记不记得住。下面这套基于 Proteus 的简单模型计算机方案从需求拆到验收学生可以照着交作业已经工作的也可以拿着改。2. 需求拆解与总体架构五个子电路怎么拼成一台模型机2.1 把试卷上的五条内容要求翻译成四件可交付物题目里列了五条内容读起来像五件事落到实际交付时其实是四件东西一张控制信号总表、一套层次化的整机电路、一份开关模拟调试记录、一份微指令码点与时序安排。第 3 条“用开关模拟控制信号调试二段汇编指令程序”和第 4 条“给出微指令码点以及脉冲信号的时序安排”看着是两件事实际共用同一张表——你拨开关的顺序就是微码里 T2、T4 两个节拍的展开顺序。所以我一般会先把交付物定死再动手画图交付物对应题目条目验收形式控制信号总表含有效电平第 1 条老师随机点一个信号能说出它什么时候有效层次化整机电路父图 5 个子图第 2 条子电路端口与主电路连线一一对上开关模拟调试记录第 3 条能现场复现一条 ADD 的完整拨动过程微指令码点 时序安排第 4、5 条微码表能与调试记录逐拍对应这四件东西的顺序不能颠倒。很多人上来就在 Proteus 里连运放、连寄存器连完发现控制信号列不全回头补表时又发现某个信号在自己的电路里根本没引出来只能拆了重连。先列表、后画图能少走一大截弯路。2.2 层次化划分主电路管总线子电路管选通与锁存整机切成父图和子图不是为了好看是为了让“改一处不牵动全局”。主电路上放按钮开关、显示灯、时序部分、指令寄存器 IR174LS273和控制器运算器单元、寄存器组、指令计数器部件、存储器单元各自做成子电路。子电路对外只暴露两类端口挂到 D[0..7] 数据总线和 AB[0..7] 地址总线上的线以及从控制器过来的控制端。按这个原则五个子电路的端口契约大致是这样子电路对外输入端口对外输出端口运算器单元D2CK、D1CK、/EDR1、/EDR2、S3、S2、S1、S0、CN、M、/ALU-OD[0..7]寄存器组单元SB、SA、/WR、RCK、/RDD[0..7]指令计数器部件CLR、PCK、PC1、ELP、PC-O、IR2CK、EIR2、IR2-OAB[0..7]、D[0..7]存储器单元/WM、EMCK、/RM、/CS、AB[0..7]、D[0..7]D[0..7]控制器单元CLR、SETWR、SETRD、T2、T4MD[0..25]、MB[0..5]这张表看着平淡实际是整篇设计的地基。我在做这类层次化拆分时有个习惯每画完一个子图就把它的端口名抄到父图上对应的引脚标签旁边两边的拼写必须一模一样。Proteus 对标签大小写和斜杠是敏感的/EDR1写成EDR1不会报错只会静静地不工作然后你在父图上找半天。2.3 器件选型两块 181 为什么走串行进位运算器用两片 74LS181 拼 8 位低 4 位那片的结果通过 CN 送给高 4 位那片本质是串行进位。选串行不选并行理由很实际模型机的时钟是人手拨开关拨出来的一个节拍几百毫秒进位延迟再多也无所谓而并行进位要多一片 74LS182 和一堆连线图一复杂调试时连哪根线接错了都看不出来。74LS181 的工作方式由 S3、S2、S1、S0 四位加 M 决定。M 为高电平做逻辑运算为低电平做算术运算CN 为高电平表示“无进位输入”做加法时它必须是高做减法时配合 S 端选择取反加一。这几位在微码里是电平信号一旦写进微指令就是整条指令执行期间保持不变的那部分。其余器件的分工也很清楚74LS6116 是 2K×8 的静态存储器挂 AB[0..7] 和 D[0..7]74LS193 两片级联做程序计数器74LS244 做三态缓冲负责把数据送上总线74LS273 锁存指令寄存器 IR1 和 IR2。选型上没有花样都是课设实验箱里现成的片子好处是网上资料多、引脚定义查得到坏处是 273 这类锁存器对脉冲沿敏感后面时序那一节会专门讲。2.4 两条总线怎么不打架整机只有两条总线8 位数据总线 D[0..7] 和 8 位地址总线 AB[0..7]。数据总线上同时挂着运算器输出、寄存器组输出、存储器输出、PC 输出和开关输入任何时刻只能有一个源在驱动其余全要高阻。地址总线相对干净主要来自 PC 和存储器地址锁存。控制信号里的 /ALU-O、/RD、PC-O、SW-BUS 这几个本质上都是“三态门的开关”。设计时要保证它们在同一个微地址上互斥——这条约束后面我会用一小段脚本做自动检查靠眼睛看 26 位二进制串是看不出来的。3. 控制信号全表从 11 个运算器信号到整机 30 多个控制端3.1 运算器单元的 11 个信号3 个脉冲、8 个电平运算器是整机里信号最密的一块。把所有控制端归纳出来是题目第 1 条明确要求的东西也是后面填微码表时的字段来源信号名作用有效电平/类型D2CKDR2 寄存器工作脉冲上升沿脉冲D1CKDR1 寄存器工作脉冲上升沿脉冲/EDR2选通 DR2 寄存器低电平电平/EDR1选通 DR1 寄存器低电平电平S3、S2、S1、S074LS181 工作方式选择低电平电平CN有无进位输入高电平电平M逻辑/算术运算选择高为逻辑低为算术电平/ALU-OALU 结果输出到总线低电平电平这块要分清“选通”和“打入”是两件事。数从总线进 DR1得先让 /EDR1 变低把门打开再给 D1CK 一个上升沿把数据锁进去只开 /EDR1 不给脉冲数据只在门口晃寄存器里还是旧值。这种“门开了但没敲钟”的错误在开关模拟阶段出现的频率最高。3.2 寄存器组与指令计数器选通、写入、读出三件事寄存器组的信号是 SB、SA、/WR、RCK、/RD。SB 和 SA 两位组合选出当前要操作的是 R0 还是 R1本例只有两个寄存器两位刚好够RCK 上升沿写入/RD 低电平把选中寄存器的内容送上总线。注意这里 /WR 和 RCK 也是一对/WR 是写允许这个“状态”RCK 才是那一下“动作”。指令计数器部件的端口多一些功能却更单一。CLR 清零PCK 是 PC 自己的打入脉冲PC1 让计数器加一ELP 把 PC 的低 8 位锁存到地址总线上PC-O 把 PC 内容送上数据总线用于某些需要把 PC 当数据处理的场合。IR2CK、EIR2、IR2-O 则服务于指令寄存器 IR2IR2CK 打入EIR2 是 IR2 的输出允许IR2-O 把 IR2 的内容送到总线。这里有个容易忽略的点PC1 是电平信号PCK 是脉冲信号。如果只把 PC1 拉高而不打 PCK193 计数器不会动。反过来只打 PCK 不给 PC1计数器会按当前置数方式工作。两个信号谁先谁后取决于你用的是同步置数还是异步置数接线时得对着 193 的真值表确认一遍。3.3 存储器单元四个信号锁死一次读或一次写6116 这块只有四个控制端但每一个都不能含糊信号名作用有效电平/类型/CS6116 片选低电平电平/RM6116 读允许低电平电平/WM6116 写允许低电平电平EMCK6116 写入脉冲上升沿脉冲一次完整的写存储过程是地址先稳定在 AB 上/CS 拉低选中片子/WM 拉低打开写通道然后给 EMCK 一个上升沿数据才真正落进存储单元。顺序反了写进去的就是地址还没稳定时的垃圾数据。读则简单些/CS 和 /RM 同时拉低数据直接出现在 D 总线上不需要脉冲。3.4 脉冲与电平的分工T2 打沿T4 保电平题目特意要求“区分脉冲信号和电平信号”这是整篇设计里最见功力的地方。模型机的时序部分只产生两个节拍T2 和 T4。它们不是两根时钟线而是两种“操作类型”的代号。T4 负责电平类动作开 /EDR1、开 /RD、选 SB/SA、置 S3~S0 和 M、开 /ALU-O。这些信号在 T4 有效期间一直保持给组合逻辑留出稳定时间。T2 负责脉冲类动作D1CK、D2CK、RCK、PCK、IR2CK、EMCK都是在 T4 建立好的电平环境上打一下沿把数据锁进目标器件。以 ADD R0,R1 的一个微步骤为例先给 T4让 /EDR1 和 SB/SA 选中的 R0 输出同时有效数据总线稳定再给 T2D1CK 上升沿把总线上的值锁进 DR1然后撤掉 T4 上的 /EDR1。这套“T4 铺路、T2 落锁、T4 收摊”的节奏贯穿了后面所有指令。开关模拟时你手里拨的那个开关本质上就是在手工产生 T2 和 T4。4. 微指令与微代码把 ADD R0,R1 拆成 4 个微地址4.1 先画信息流向再定每条指令占几个微地址微地址的数量不由指令长短决定由数据要转几手决定。IN R0,#DATA1 是双字节指令第一个微地址把开关数据送上总线并打开寄存器写第二个微地址关掉写。ADD R0,R1 要转四手R0 进 DR1、R1 进 DR2、ALU 做加法把结果放总线、结果写回 R0因此占 4 个微地址。先把流向画清楚微地址自然就数出来了。题目要求调试的两段程序一段只做运算一段带存储器存取; 程序一纯运算验证 ALU 与寄存器通路 IN R0, #DATA1 ; 从开关读第一个数例如 58H IN R1, #DATA2 ; 从开关读第二个数例如 58H ADD R0, R1 ; R0 - R0 R1 OUT R0 ; 结果送显示灯 ; 程序二加入存储器验证 STA / MOV 通路 IN R0, #DATA1 STA (01H), R0 ; R0 写入存储单元 01H IN R0, #DATA2 MOV R1, (01H) ; 存储单元 01H 读回 R1 ADD R0, R1 OUT R0程序一的意义是把 ALU、寄存器组、总线三者之间的通路跑通程序二多加了一次写存储和一次读存储把 6116 也拉进回路。两段都跑通才算把五个子电路全验证了一遍。这也是我建议的调试顺序先跑程序一跑通了再加程序二别一上来就上带存储器的版本。4.2 26 位微指令怎么排字段微指令宽度是 26 位记为 MD25 到 MD0微地址 6 位MB5 到 MB0理论上有 64 个微地址可用。字段顺序没有国家标准按自己电路上控制信号的排布定就行但一旦定下来整篇设计里不许再改。位字段类型位字段类型MD25SW-BUS电平MD12PC1电平MD24EDR1电平MD11ELP电平MD23EDR2电平MD10PC-O电平MD22M电平MD9EIR2电平MD21S3电平MD8IR2-O电平MD20S2电平MD7RM电平MD19S1电平MD6WM电平MD18S0电平MD5CS电平MD17CN电平MD4EIR1电平MD16ALU-O电平MD3R保留—MD15SB电平MD2R保留—MD14SA电平MD1R保留—MD13WR电平MD0R保留—表里 MD4 的 EIR1 是把 IR1 内容送上总线的输出允许MD3 到 MD0 留作扩展。这里要强调一点微码里存的是“信号是否有效”不是“引脚电平高低”。像 /EDR1 这种低电平有效的信号微码位写 1 表示“该信号有效”实际引脚输出是低。很多人在填表时把这两件事混了导出的微码看着对烧进去全反。4.3 微代码表ADD R0,R1 逐拍拆开以 ADD R0,R1 为例四个微地址对应四拍。下表里“有效信号”一栏写的是该拍需要置为有效的控制端微地址T4 保持的电平信号T2 打的脉冲数据流向M0SB/SA 选 R0、/EDR1、S3~S0 置送数方式D1CKR0 → 总线 → DR1M1SB/SA 选 R1、/EDR2D2CKR1 → 总线 → DR2M2S3~S0 置加法、M 置低、CN 置高、/ALU-O无DR1 DR2 → 总线M3SB/SA 选 R0、/WRRCK总线 → R0第一拍和第四拍最容易出错。第一拍里 /EDR1 和 SB/SA 必须同时有效否则总线上要么没数据要么数据来源不明第四拍里 /WR 是写允许、RCK 才是那一下写动作只给 /WR 不给 RCKR0 里躺着的还是老值屏幕上却看不出任何异常——它会一直显示上一次的结果让你误以为加法算错了。把这类表填完原始的 CM 文件就是一堆 DB 行每行一个二进制数对应一个微地址的 26 位微码。手写这些二进制串几乎必错我一般是先按上面这张表把“每拍需要哪些信号有效”写成文字再用脚本转成二进制最后人工抽查两三行。4.4 用一段脚本生成微码并做互斥检查手写 26 位 0/1 串的痛苦试过一次就够。下面这段脚本把位序固化成字典输入“这一拍哪些信号有效”输出 26 位串顺手检查几条互斥规则# 微码生成与互斥检查字段顺序必须与电路接线严格一致 FIELD_ORDER [ SW_BUS, EDR1, EDR2, M, S3, S2, S1, S0, CN, ALU_O, SB, SA, WR, PC_PLUS1, ELP, PC_O, EIR2, IR2_O, RM, WM, CS, EIR1, R0, R1, R2, R3, ] # 同一拍内不允许同时有效的信号组合理由是它们会抢同一条总线或同一片存储 EXCLUSIVE_GROUPS [ {EDR1, EDR2}, # 两个 ALU 暂存器不能同时往总线上送 {RM, WM}, # 同一次存储访问不能既读又写 {PC_O, ALU_O, SW_BUS}, # 三个总线源互斥 {SB, SA}, # 本例只用 R0/R1两位不做同时置位 ] def encode(active, total_bits26): 把这一拍有效的信号集合转成 26 位二进制串高位在左 for group in EXCLUSIVE_GROUPS: hit group set(active) if len(hit) 1: raise ValueError(f互斥冲突{hit} 不能同时有效) bits [1 if name in active else 0 for name in FIELD_ORDER] assert len(bits) total_bits, 字段数与微指令宽度不一致 return .join(bits), int(.join(bits), 2) if __name__ __main__: # ADD R0,R1 第四拍把总线上的运算结果写回 R0 word, value encode({SB, WR}) print(word, hex(value)) # 输出的串直接抄进 CM 文件脚本干三件事把信号名映射成位、把互斥规则变成断言、输出可直接抄进 CM 文件的字符串。FIELD_ORDER 的顺序必须和你电路上 MD25 到 MD0 的接线顺序一致改一位所有已生成的微码全废——所以这张表我会打印出来贴在屏幕边上改电路前先改它。互斥检查那几条规则看着简单实际能挡掉大半翻车事故。比如 /RM 和 /WM 同时有效6116 的数据线会同时被内部读出电路和写驱动占用仿真里表现是数据线出现 X 态或一个介于高低之间的怪值你盯着波形看半小时也未必想到是这两个信号打架。5. 联调避坑开关模拟调试里最容易翻车的五个点5.1 现象寄存器写不进去显示灯一直是旧值原因通常是“门开了但没敲钟”。/WR 或 /EDR 这类电平信号拉低了但 RCK、D1CK 这类脉冲没有给上升沿或者给了但时序在电平建立之前。在 Proteus 里脉冲源的初始状态也可能是高第一次“上升沿”根本没发生。解决的办法是把每一拍拆成固定三步先拨 T4 相关的电平开关等总线稳定仿真里大约几十毫秒再拨 T2 打脉冲最后撤 T4。三步写成检查清单贴在旁边别凭感觉拨。5.2 现象数据总线上出现怪值或者多个灯同时亮原因是总线冲突两个源同时驱动 D[0..7]。最常见的组合是 ALU 的 /ALU-O 还开着寄存器的 /RD 又开了或者开关输入的 SW-BUS 没关存储器已经在往总线上送数。解决上除了靠 4.4 那段脚本做静态检查调试时可以在总线上挂一个探针逐拍看是哪几个三态门处于打开状态。我一般会在微码表里给每个微地址加一列“本拍总线源”只允许填一个名字填两个就说明设计错了。5.3 现象运算结果对但换一组数据就不对原因多半是 CN 或 M 这两位被当成了“每条指令都要重新设”的信号。实际上在连续做加法时CN 应该保持高电平M 保持低电平如果某一拍把它们复位成默认值第一个数算对了第二个数就带进位错误。解决办法是把 S3~S0、CN、M 看成一组“运算方式配置”在进入 ALU 相关微地址之前统一设好中途不改。微码表里这几位连续几拍保持相同值是可以一眼看出来的。5.4 现象STA 指令执行完存储单元里读回来是 FF 或 00原因是写存储的顺序错了。地址还没稳定到 AB 上就给了 EMCK或者 /WM 和 /CS 拉低的时刻晚于 EMCK 的上升沿。6116 要求地址和片选在写脉冲之前建立写脉冲结束后还要保持一小段时间。解决是把 STA 拆成两拍第一拍把地址送到 AB、/CS 和 /WM 拉低第二拍给 EMCK 上升沿第三拍撤销 /WM。宁可多占一个微地址也别把三件事挤在一拍里。5.5 现象结果碰巧对了但换条指令就崩这是最隐蔽的一种。有人为了让显示灯亮出 D0H反复试微码试到某一组恰好出结果就交卷了。这种“凑答案”在答辩现场撑不过三分钟因为老师会换一组输入数据或者让你现场跑程序二。解决办法只有一个每一条指令都要能画出完整的数据流向图每一拍的总线源、目标器件、有效信号三样东西写清楚。写不清楚的那一拍就是设计里的黑匣子早晚要炸。6. 验收与答辩怎么用一条指令证明整机是对的验收不是把仿真跑一遍给老师看是一套有顺序的自证流程。我一般按“最小闭环 → 加重定位 → 现场抽考”三步走每一步都有明确的通过标准。第一步跑最小闭环就是程序一的 IN、IN、ADD、OUT 四条指令。通过标准不是“灯亮了”而是输入 58H 和 58H 得 D0H输入 01H 和 02H 得 03H输入 FFH 和 01H 得 00H验证进位溢出被丢弃。三组数据都过说明 ALU 通路和寄存器写回是正确的。第二步加重定位跑程序二。此时要观察的是 STA 写进去的值和 MOV 读出来的值是否一致以及读出来的值参与加法后结果是否正确。这一步通过说明地址总线、存储器、指令计数器都接对了。第三步是现场抽考也是答辩真正的分水岭。老师通常会做三件事随机指定一条指令让你说出它占几个微地址随机指一个微地址让你报出 26 位微码里哪几位是 1随机点一个控制信号问你它是脉冲还是电平。这三问对应三张表所以答辩前我会把控制信号总表、微码表、调试记录三张纸按顺序摆好问哪张翻哪张。下面这张验收表可以直接抄进报告的“结果”一节应得结果和实际结果并排写比只写一句“运行成功”有说服力得多验证项输入应得结果实际结果判定依据加法通路58H 58HD0HD0H显示灯 D7~D0加法进位丢弃FFH 01H00H00H8 位截断逻辑运算M158H AND 58H58H58H切换 S3~S0存储器写读STA 01H 后 MOV原值原值两次 OUT 对比时序正确性单拍 T2/T4每次只锁一个器件无总线冲突探针观察答辩时被问倒最多的不是原理是“你为什么这么接”。比如为什么 CN 接高、为什么串行进位、为什么 IR1 用 273 而不是 244——每个“为什么”背后都得有一句“因为我这样接之后某一拍的总线源就唯一了”。把设计的每个选择都归到“保证某一时刻只有一个驱动源”这条主线上回答起来就顺了。从那以后我每次做这类硬件课设都会在画第一根线之前先把控制信号总表和微码位序表写死哪怕当时还一张图都没有。这两张表一旦定下来后面画图、填码、拨开关全是有据可查的机械动作不再靠试。希望帮到你。本文还有配套的精品资源点击获取