体系结构

指令集: add, sub, ori, lw, sw, beq, lui, nop 端口:

信号方向描述
CLKI时钟信号
RSTI异步复位信号

基本模块

IFU

PC & NPC

此处尚未要求 J 类型指令和 jr 指令, 留出扩展空间

  • Moore 状态机:
    • 下一状态:NPC
      • PC + 4
      • PC + 4 + Offset
      • Jump
    • 输出:PC

PC

  • 端口:

    信号方向描述
    CLKI时钟信号
    RSTI异步复位信号
    NPC[31:0]I下一指令地址
    PC[31:0]O取指令地址

NPC

  • 端口:

    信号方向描述
    PC[31:0]I当前指令地址
    IN[31:0]I跳转地址 (offset[15:0], jump_address[25:0], ra[31:0])
    NPCSel[2:0]I下一 PC 选择信号
    ZeroIrs 和 rt 相等标志 (1=相等, 0=不等)
    PCPlus4[31:0]O当前指令地址+4
    NPC[31:0]O下一指令地址
  • NPCSel 编码:

    NPCSel含义
    00顺序执行
    01分支跳转
    10J 型跳转
    11JR 寄存器跳转

IM

  • 元件: ROM

  • 地址范围: 0 x 00003000 ~ 0 x 00006 FFF

  • 实际地址宽度:

    • 0x00006FFF - 0x00003000 + 1 = 0x3FFF + 1 = 0x4000
    • 0x4000 -> 16384Byte
    • 16384 / 4 = 4096 = 2 ** 12
  • 按照指令寻址: ROM_addr = (PC - 0x00003000) >> 2

  • 端口:

    信号方向描述
    A[31:0]I取指令地址
    RD[31:0]O取出指令

RF

已经在 P 0 课下完成, 直接复用模块

信号名方向描述
CLKI时钟信号
RSTI异步复位信号
WEI写使能信号
A1[4:0]I地址输入信号, 读出到 RD 1
A2[4:0]I地址输入信号, 读出到 RD 2
A3[4:0]I地址输入信号,写入的目标寄存器
WD[31:0]I32 位数据输入信号
RD1[31:0]O输出 A 1 指定的寄存器数据
RD2[31:0]O输出 A 2 指定的寄存器数据

ALU

目前运算共三种, 但留出三位以供扩展

ALUControl编码:

运算编码
or001
add010
sub110

端口:

信号方向描述
SrcAI操作数 1
SrcBI操作数 2
ALUControl[2:0]I运算种类控制信号
ZeroO使用 ALU 进行比较时, 做减法运算,
判断结果是否为 0
Result[31:0]O运算结果

DM

  • 元件: RAM, 读写双端口分离

  • 地址范围: 0 x 00000000 ~ 0 x 00002 FFF

  • 端口:

    信号方向描述
    CLKI时钟信号
    RSTI异步复位信号
    WEI写使能信号
    A[31:0]I读写地址
    WD[31:0]I写入数据
    RD[31:0]O读出数据

EXT

信号方向描述
imm[15:0]I指令中的立即数
OpI扩展控制信号 (0=无符号扩展,1=符号扩展)
Out[31:0]O扩展后的结果

Controller

Main Decoder

端口:

信号方向描述
Opcode[5:0]I指令的[31:26], op 部分
MemtoRegO寄存器回写的数据来源 (0=ALU 结果, 1=内存数据)
MemWriteODM 写使能信号
NPCSel[2:0]O下一 PC 选择信号
ALUOp[1:0]O传入 ALU 译码器计算ALUControl(00=加法, 01=减法, 10=根据 funct 字段)
ALUSrcOALU 第二操作数选择(0=寄存器, 1=立即数)
RegDstO寄存器写入目标(0=rt, 1=rd)
RegWriteO寄存器写使能信号

ALU Decoder

端口:

信号方向描述
Funct[5:0]IR 指令[5:0], funct 部分
ALUOp[1:0]IFunct配合计算ALUControl
ALUControl[2:0]O选择 ALU 的具体运算功能

真值表:

ALUOpFunctALUControl
00X010
X 1X110
1 X100000 (add)010
1 X100010 (sub)110
1 X100101 (or)001

指令

指令集: add, sub, ori, lw, sw, beq, lui, nop

  • 数据通路:
部件IMRFEXTALUDM
输入AA 1A 2A 3WDABA
addPC. PCIM. RD[25:21]IM. RD[20:16]IM. RD[15:11]ALU. ResultRF. RD 1RF. RD 2
subPC. PCIM. RD[25:21]IM. RD[20:16]IM. RD[15:11]ALU. ResultRF. RD 1RF. RD 2
oriPC. PCIM. RD[25:21]IM. RD[20:16]IM. RD[15:0]RF. RD 1EXT. Out
lwPC. PCIM. RD[25:21]IM. RD[20:16]DM. RDIM. RD[15:0]RF. RD 1EXT. OutALU. Result
swPC. PCIM. RD[25:21]IM. RD[20:16]IM. RD[15:0]RF. RD 1EXT. OutALU. Result
beqPC. PCIM. RD[25:21]IM. RD[20:16]RF. RD 1RF. RD 2
jalPC. PC0 x 1 FPC. PCPlus 4
jrPC. PCIM. RD[25:21]
TotalPC. PCIM. RD[25:21]IM. RD[20:16]IM. RD[15:11]ALU. Result
DM. RD
PC. PCPlus 4
IM. RD[15:0]RF. RD 1RF. RD 2
EXT. Out
ALU. Result

P 3 思考题

  1. 上面我们介绍了通过 FSM 理解单周期 CPU 的基本方法。请大家指出单周期 CPU 所用到的模块中,哪些发挥状态存储功能,哪些发挥状态转移功能。

上游的 Moore 状态机部分, PC 寄存器起到状态存储功能, NPC 内部的逻辑起到的是状态转移功能; 下游的 Mealy 状态机部分, GF 起到的是状态存储功能, 其余的 IM, ALU, EXT, DM 的各个输出做各类组合逻辑运算, 计算内容再次存储到寄存器内, 发挥了状态转移功能.

  1. 现在我们的模块中 IM 使用 ROM, DM 使用 RAM, GRF 使用 Register,这种做法合理吗? 请给出分析,若有改进意见也请一并给出。

我认为比较合理.

  • IM 中的指令在运行时不可变, 因此用 ROM 存放.
  • DM 中的数据在运行时可读写, 因此用 RAM 存放.
  • GRF for Global Register File, 顾名思义, 负责在运行过程中存储状态, 参与计算. 并且在运行过程中要反复读写, 而寄存器读写速度快于存储器. 因此采用 Register.

但是有些地方存在着简化, 即 IM 使用 ROM, 实际的处理器其应该可读写, 否则无法使操作系统载入新的程序到 IM 中, 使用 RAM 可能更适合实际使用.

  1. 在上述提示的模块之外,你是否在实际实现时设计了其他的模块?如果是的话,请给出介绍和设计的思路。
  • 我在 IFU 设计中, 分离了 PC 和 NPC 的设计, 使得职责单一化, PC 只负责输出当前指令的地址给 IM, 用以取出指令, 而复杂的下一条指令地址计算被封装进了 NPC.
  • 我在 Controller 设计中, 我将控制单元分为两部分组合逻辑 首先是 Main Decoder, 负责根据指令的 Opcode 字段计算大部分控制信号, 包括读写使能, 寄存器选择等, 并且输出一个两位的 ALUOp 控制信号给 ALU Decoder 部分. ALU Decoder 结合 Funct 字段, 计算出 ALUControl 信号, 控制 ALU 计算行为, 使得设计更加清晰且结构化. 因为一些计算指令如addaddi都会用到 ALU, 前者有 Funct 字段而后者无; 一些非计算指令也会用到 ALU, 例如beq, lw, sw指令. 因此把计算行为的选择分离出来是有必要的, 这样可以综合 Opcode 和 Funct 考虑所用的运算, 并且两个模块都不会同时接入两个输入, 更简洁. 并且运算种类较多, 涉及到的计算的选择, 电路更复杂, 分离出来使得两个模块复杂度都降低了.
  1. 事实上,实现 nop 空指令,我们并不需要将它加入控制信号真值表,为什么?

nop空指令的机器码为 0 x 00000000, opcode 字段为 000000, 因此会被解读是 R 型指令, 即为sll $zero, $zero, 0指令. 我们目前没有实现sll指令, 但是控制器根据逻辑生成的控制信号, 使得其仍旧不会真正进行有效的读写, 而是空转一周期, 因此无需纳入真值表单独考虑.

  1. 阅读 Pre 的 “MIPS 指令集及汇编语言” 一节中给出的测试样例,评价其强度(可从各个指令的覆盖情况,单一指令各种行为的覆盖情况等方面分析),并指出具体的不足之处。