计算机组成原理课程设计

参考了这篇博客

课程设计步骤

功能和用途

通过该课程设计的学习,我们设计一台模型机,该模型机运行在FPGA平台上,可以模拟真正的计算机设备的一部分功能,通过微指令进行实现,使其可以完成一些基本操作,包括:最基本的,加法及其溢出、全零、进位、符号判断操作。除此之外对模型机进行了拓展,实现了条件指令JX,使用相对寻址完成了寻址,此外如果计算结果溢出则将相应的溢出标志存到特定的地址下。

调试过程中通过平台指示灯观察内部的数据流动情况,了解计算机的运行、计算过程和内部的时序问题并辅助修改。

指令系统

指令格式

基本字长:8位

  • 单字长指令:指令由高4位操作码、低4位全0构成。

  • 双字长指令:指令由第一字节高4位操作码、低4位为寄存器组操作码;第二字节由操作数、操作数地址、偏移量等构成。

  • 四字长指令:实验中唯一用到的四字长指令是是溢出标志存储指令。指令第一字节高4位为操作码,低4位为寄存器组操作码,第二字节为溢出标记值,第三字节为溢出写入地址,第四字节为指令的后继指令地址。

三种指令格式的高四位为操作码,支持16种不同的指令。实验中使用0001~1000作为九条指令的操作码。

寻址方式

立即数寻址:操作数在指令的第二个字节。如机器指令中的溢出标志存储指令,其溢出标记等就存储在后面相邻的字节中。再如JX指令,偏移量就存在下一个字节中。

直接寻址:操作数的地址在指令的第二个字节。如LOAD指令,其下一个字节为对应的操作数地址。

指令功能

指令指令功能
LOAD R0 A1读内存将A1地址的数存入寄存器R0
LOAD R1 A2读内存将A2地址的数存入寄存器R1
ADD R0 R1将寄存器R0、R1中的数相加,结果存入R0
STORE A3将寄存器R0所保存的计算结果存到内存地址A3
JX A4条件转移,若计算结果溢出则以A4为偏移量跳转执行STORE FF指令,否则执行停机指令
HALT停机
STORE FF从指令接下来的两个字节中依次读出溢出标记与溢出标记写入地址,并将溢出标记写入相应地址中。

总体结构与数据通路

总体结构

总体结构的设计参考课件中的设计方案。下面简要介绍一下各个部分。

ALU

ALU使用两片74181完成课程设计中的算数运算与直传功能,关键在于需要处理好两片74181之间的进位关系。

选择器

因为有时我们的数据来源有很多,所以需要设计数据选择器。

  • 连接算术运算器的两个选择器,左边的是数据选择器A,选择来自MDR或R0的数据。右边的是数据选择器B,选择来自R1或PC的数据
  • 连接uPC的选择器,选择无条件跳转或按操作码转移
  • 寄存器组中的选择器,选择将四片寄存器中哪一片寄存器的值作为数据输出。
寄存器组

核心是四片八位寄存器,输入输出端采用二四译码器进行片选,同时输出端使用两片四选一选择器进行数据输出控制。四片寄存器的数据可以作为选择器A、B任意一个的数据来源但在实验中我们约定R0的数据送入选择器A,R1的数据送入选择器B。

MDR

由于MDR既需要与总线进行数据交互,也需要与RAM进行数据交互,所以MDR设计了16位,其中8位负责与总线进行数据交换,另八位负责与RAM进行数据交换,以避免可能存在的数据冲突问题。MDR内部使用三态门进行控制数据的写入与读出,核心是一片八位寄存器。

数据通路

模型机的数据通路是以总线为基础,下面就机器指令分析其数据通路:

取指

(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(PC)+1\rightarrowPC

(RAM)\rightarrowMDR\rightarrowZ寄存器\rightarrowBUS\rightarrowIR

LOAD

(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(PC)+1\rightarrowPC

(RAM)\rightarrowMDR\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(RAM)\rightarrowMDR\rightarrowZ寄存器\rightarrowBUS\rightarrowR0

ADD

(R0)+(R1)\rightarrowZ寄存器\rightarrowBUS\rightarrowR0

STORE

(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(PC)+1\rightarrowPC

(RAM)\rightarrowMDR\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(R0)\rightarrowZ寄存器\rightarrowBUS\rightarrowMDR\rightarrowRAM

JX

(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(RAM)\rightarrowMDR

(MDR)+(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowPC

STORE FF

(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(PC)+1\rightarrowPC

(RAM)\rightarrowMDR\rightarrowZ寄存器\rightarrowBUS\rightarrowR0

(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(PC)+1\rightarrowPC

(RAM)\rightarrowMDR\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(R0)\rightarrowZ寄存器\rightarrowBUS\rightarrowMDR\rightarrowRAM

(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR

(RAM)\rightarrowMDR\rightarrowZ寄存器\rightarrowBUS\rightarrowPC

指令执行流程

首先分别执行两个操作数加载指令LOAD,通过立即数寻址将操作数分别存入R0、R1。

然后执行加法指令ADD,将存在寄存器中的两个操作数相加,结果存入R0中,并进行溢出、进位等判断。

然后执行存数指令STORE,从RAM中取出操作数存放地址,将加法的结果从R0取出,存入相应的地址。

然后执行条件转移指令JX,从RAM中取出偏移量并计算转移地址,送入PC输入端,根据加法指令时的判断结果,若溢出,则PC置数,以输入的值为PC值,否则,PC加一。

若加法溢出,即PC进行置数,则取指时会取出溢出标志存储指令STORE FF并执行,此时会依次从RAM中读出溢出标志与溢出写入地址,并将该标记值存入相应的地址,随后读出停机指令地址,再次进行条件转移到停机地址完成停机。

若加法未溢出则直接完成停机指令。

地址机器指令内容RAM#
00LOAD R0 A10001 000010
01A1操作数1地址0A
02LOAD R1 A20010 010024
03A2操作数2地址0B
04ADD R0 R10011 000131
05STORE A30100 000141
06A3结果存入地址0C
07JX0101 000050
08偏移量08
09HALT1000 000080
……
0A操作数1??
0B操作数2??
0C计算结果??
0D溢出写入00
……
10STORE FF0110 000161
11溢出标记值FF
12溢出写入地址OD
13停机地址09

微程序流程

取指

微操作微地址
(PC)->Z00
(Z)->MAR01
(PC)+1->PC02
(RAM)->MDR03
(MDR)->Z04
(Z)->IR05
QJP06

LOAD

微操作微地址
(PC)->Z10
(Z)->MAR11
(PC)+1->PC12
(RAM)->MDR13
(MDR)->Z14
(Z)->MAR15
(RAM)->MDR16
(MDR)->Z17
(Z)->R018
JP19

ADD

微操作微地址
A+B->Z30
A+B–>CR31
(Z)->R032
JP33

STORE

微操作微地址
(PC)->Z40
Z->MAR41
(PC)+1->PC42
(RAM)->MDR43
(MDR)->Z44
(Z)->MAR45
(R0)->Z46
(Z)->MDR47
(MDR)->RAM48
JP49

JX

微操作微地址
(PC)->Z50
(Z)->MAR51
(RAM)->MDR52
(MDR)+PC->Z53
Z->PC54
JP55

STORE FF

微操作微地址
(PC)->Z60
Z->MAR61
(PC)+1->PC62
(RAM)->MDR63
(MDR)->Z64
(Z)->R065
(PC)->Z66
(Z)->MAR67
(PC)+1->PC68
(RAM)->MDR69
(MDR)->Z6A
(Z)->MAR6B
(R0)->Z6C
(Z)->MDR6D
(MDR)->RAM6E
(PC)->Z6F
(Z)->MAR70
(RAM)->MDR71
(MDR)->Z72
(Z)->PC73
JP74

停机

微操作微地址
HTLT80

拓展部分的实现说明

实验中完成了拓展要求一条件指令JX,说明如下:

JX指令执行时,首先采用立即数寻址找到JX指令相对于STORE FF指令的偏移量A3,与当前PC的值相加后得出STORE FF的指令地址并送入PC输入端,此时PC根据溢出条件判断是否执行STORE FF指令。若溢出位为1,即计算结果溢出,则给PC置数使能,使其将PC值置为输入的地址,即STORE FF的地址,使整机下一步去执行溢出标志存储,否则不置数,继续执行后续指令。

若执行溢出标志存储指令,首先进行访存,在指令的下一字节获取到溢出标志位FF,将该标志位暂时存放到R0中,然后从再下一字节获取标志位存放的地址,输出到MAR,然后将R0中的标志位写入该地址,完成溢出标记后,再次将PC置数,跳到JX指令的下一条指令继续执行。

系统的调试、测试方法

单元测试部分

寄存器组测试

D0-D7、P、CPR、ENR、ENW、AC1、AC2、BC1、BC2接开关作为输入,A0-A7、B0-B7接指示灯。通过控制开关查看将不同数字存进不同寄存器组的情况,并在存放后检查不同寄存器组的输出情况,着重关注AC、BC对于输入输出的控制方式是否与预期相符。

软件自带2-4译码器测试

PPT上推荐可以使用软件自带的74139组件作为2-4译码器使用,由于不能确定A1、A2、B1、B2的关系以及输出情况,特对74139进行测试。将A1、A2、B1、B2接开关作为输入,所有YN端接指示灯作为输出。通过调整A、B的输入,观察指示灯的输出,最后确认A1、B1控制是一对译码输入,A2、B2是一对译码输入,译码的输出是3个1和1个0。

累加器测试

D0-D7、LD接开关作为输入,CK接单脉冲,Q0-Q7接指示灯。通过控制开关和单脉冲,观察指示灯闪烁情况,分别验证累加器的自增加一、置数功能。

ALU测试

A、B输入、CN、M、S0-S3接开关,F输出和CN2接指示灯。通过控制开关,观察指示灯闪烁情况,分别验证ALU加法、直传功能,并观察CN2的进位情况。

整机测试部分

  1. 指令经过检查无误后,通过软件以十六进制的形式写入RAM的相应单元。
  2. 微程序经过检查无误后,通过软件以十六进制的形式写入ROM的相应单元。
  3. 拨清零开关使所有寄存器、累加器清零,按复位键。
  4. 不断点击单脉冲,每次点击后观察ROM的当前微指令值,并根据提前连接的指示灯观察MDR、寄存器Z、寄存器组、IR、状态寄存器的输出情况。
  5. 运行到停机指令后通过软件读取RAM的值,验证结果。
  6. 单脉冲确保运行结果无误后,将单脉冲替换为连续脉冲,并将除状态寄存器的指示灯外的所有指示灯断开连接,以免影响连续脉冲。
  7. 按一次脉冲键发单脉冲使启动器发送连续脉冲,开始运行程序,并通过指示灯观察状态寄存器的值。
  8. 等到程序运行结束后通过软件读取RAM的值,验证结果。

小组成员各自的任务和完成情况

各部件设计、整机实验中,两人曾尝试具体分工,在检查时发现单独完成部分效果不佳,出现器件连线出错、设计理念不一致、编码不完善的问题,因而选择两人一起边讨论边思考完成实验。

组中赵炜宁主要负责整机结构与电路绘制、微指令逻辑设计,王浩聪主要负责设计寄存器组并编写实现整机的微代码,最终进行汇总并完成实验。

课程设计总结

收获与体会

这次实验加深了我对课本知识的认知,也增强了动手能力。

  1. 经过这次实验加深了对CPU工作原理的认识,对于CPU的数据传输以及工作方式有了更进一步的了解。学会了简单指令系统的设计以及微程序工作原理。

  2. 通过课程设计掌握了模型机的设计流程。并从模型及设计流程中学会了解决实际问题,体会到了设计与实际实现之间的不同。

  3. 通过实验过程更加熟悉了实验平台的使用,以及模型及设计流程。同时也锻炼了在实验中锻炼自己的动手能力和解决问题的能力。

  4. 总线结构有利也有弊,好处在于电路结构清晰、数据通路简单、组合多样,弊端在于容易发生读写冲突、总线上只能传输一组数据。

  5. 通过与队友的沟通交流发现、弥补了自己在一些知识上的欠缺,也使我团队协作能力有了进一步提升。

遇到的问题和解决的方法

读写冲突

起初由于不理解RAM的单数据通路而发生读写冲突报错,后来将MDR与总线的数据交互和MDR与RAM的数据交互进行分离解决了这一问题。

时序问题

初始时寄存器组采用即写即读的策略,即:每次存入数据后立即将数据读出,但发现在时序上出现了先读后写的问题,导致读出的数据错误,后来将寄存器组读写拆开,这样在逻辑上进行了清晰的划分,也避免了读写的时序问题。

另外Z寄存器也存在相同的问题,在组件通过ALU直传以及总线向另一组件传递数据时,发现有时数据不对,比如(PC)\rightarrowMAR,实验时发现读出的RAM总是错的,思考后发现,我们认为的这一步脉冲后的数据通路是理想化的(PC)\rightarrowZ寄存器\rightarrowBUS\rightarrowMAR,但实际上,在脉冲时MAR先读入了Z寄存器的值,然后才完成了Z寄存器的置数,导致时序错误,针对这个问题我们对实验中涉及的微指令进行拆分,保证在通过总线进行组件间的数据传输时,先将数据送入Z寄存器,然后再控制Z寄存器的使能将数据送入目标组件。

ALU直传

ALU器件设计功能只能直传A输入端的数据,无法直传B输入端的数据,通过使用加法0+B输入端数据实现B输入端数据的直传。

寄存器组的控制问题

初始时采用微指令控制寄存器片选与输出,但后来发现这种方式占用大量微指令位数,而且大多数时间中并不需要寄存器组的片选与输出控制,所以我改用机器指令对寄存器组进行控制,将第四位规定为寄存器组的控制位,同时四位中的高两位同时也是片选控制位,这样就大大简化了微代码。

附录

附录一

总体结构图

ALU

二选一选择器

寄存器组

MDR

带置数功能的计数器

启停电路

附录二

附录三

地址机器指令指令值/指令解释十六进制格式
00LOAD R0 A10001 000010
01A1操作数1地址0A
02LOAD R1 A20010 010024
03A2操作数2地址0B
04ADD R0 R10011 000131
05STORE0100 000141
06A3结果存入地址0C
07JO0101 000050
08偏移量08
09HALT1000 000080
……
0A操作数1??
0B操作数2??
0C计算结果??
0D溢出写入00
……
10STORE FF0110 000161
11溢出标记值FF
12溢出写入地址OD
13停机地址09