Skip to content

CPU 设计文档 - P3

CPU设计方案

各模块端口说明与功能规定

GRF

端口说明
信号名 方向
描述
clk I 时钟信号.
reset I 异步复位信号.
Reg1 [4:0] I 指定寄存器的5位地址,将目标寄存器的数据读出到 read1.
Reg2 [4:0] I 指定寄存器的5位地址,将目标寄存器的数据读出到 read2.
RegWrite I GRF写入使能信号:
0 : 不能向GRF中写入数据;
1 : 可以向GRF中写入数据.
RegAddr [4:0] I GRF写入目标寄存器的5位地址.
RedData [31:0] I GRF写入的32位数据.
read1 [31:0] O 输出Reg1指定的寄存器中的32位数据.
read2 [31:0] O 输出Reg2指定的寄存器中的32位数据.
$ra [31:0] O 输出寄存器$ra储存的32位数据.
功能规定
  • 异步复位:reset信号有效时将所有寄存器复位位0.
  • 读取数据:Reg1和Reg2信号可指定两个寄存器地址并读取其中数据,并通过端口read1,read2输出。
  • 储存数据:当写入使能信号RegWrite有效时,RedData输入的数据将在时钟信号上升沿时写入到RegAddr指定的寄存器中。
电路实现

GRF

ALU

端口说明
信号名 方向
描述
A [31:0] I 进行逻辑运算的第一个32位操作数.
B [31:0] I 进行逻辑运算的第二个32位操作数.
Shamt [4:0] I 当前指令的Shamt字段.
ALUoperation [3:0] I 由ALU控制单元输出的,指明ALU的运算类型.
详见功能规定
Zero O 表示输入的两个操作数是否相等:
0 : 不相等;
1 : 相等.
Greater O 表示输入的两个操作数的大小关系:
0 : A < B;
1 : A > B.
Result [31:0] O 输出逻辑运算后的32位结果.

功能规定
  • 根据ALU控制单元输出的ALUoperation信号对两个32位数据A、B进行算术逻辑运算。
ALUoperation [3:0] 功能
0000 执行+运算
0001 执行-运算
0010 执行&运算
0011 执行\|运算
0100 执行逻辑左移运算
0101 执行lui运算
0110 执行逻辑右移运算
0111 执行算术右移运算
电路实现

ALU

ALU Control

端口说明
信号名 方向
描述
Func [6:0] I 指令的Func字段(指令Func).
ALUop [3:0] I 由主控单元生成的ALUop,指明ALU的运算类型:
1111 : R型指令,具体运算类型由Func字段决定;
其他详见功能规定
ALUoperation [3:0] O 输出对ALU模块的控制信号,选择指定的运算结果.
功能规定
  • 根据指令的Func字段和ALUop信号控制ALU的逻辑运算结果。
指令 Func字段 ALUop ALU运算类型 ALUoperation
lw xxxxxx 0000 + 0000
sw xxxxxx 0000 + 0000
beq xxxxxx 0001 - 0001
ori xxxxxx 0011 \| 0011
lui xxxxxx 0101 <<16 0101
add 100 000 1111 + 0000
sub 100 010 1111 - 0001
and 100 100 1111 & 0010
or 100 101 1111 \| 0011
sll 000 000 1111 << 0100
电路实现

ALU_Control

IFU

端口说明
信号名 方向
描述
clk I 时钟信号.
reset I 异步复位信号.
Branch [1:0] I Controller输出的跳转类型.
详见Controller
Zero I ALU输出的判断值.
Greater I ALU输出的判断值.
Imm [31:0] I 经过符号扩展的32位立即数.
$ra [31:0] I 寄存器$ra的值.
Instruction [31:0] O 当前的32位指令码.
功能规定
  • 内部包括PC、IM及相关逻辑。
  • 通过相关逻辑将程序计数器与ROM地址联系起来。
  • 可以根据Controller输出的Branch控制信号、ALU输出的Zero判断结果执行跳转指令。
电路实现

IFU

DM

端口说明
信号名 方向
描述
clk I 时钟信号.
reset I 异步复位信号.
MemWrite I 写入使能信号:
0 : 不允许向RAM中写入数据;
1 : 允许向RAM中写入数据.
MemRead I 读取使能信号
0 : 不读取RAM中数据;
1 : 读取RAM中数据.
Address [31:0] I ALU输出的32位信号,当使能信号有效时作为数据读写的地址.
WriteData [31:0] I 使能信号有效时,要写入RAM中的32位数据.
ReadData [31:0] O 使能信号有效时,从RAM读取到的32位数据.
功能规定
  • 可以根据Controller输出的MemRead、MemWrite控制信号,对数据存储器DM进行读写。
电路实现

DM

Controller

端口说明
信号名 方向
描述
OpCode [5:0] I 指令的OpCode字段.
Branch [1:0] O 决定跳转类型.
00 : 不跳转;
01 : 执行beqbne类跳转指令;
10 : 执行jjal类跳转指令;
11 : 执行jrjalr类跳转指令.
MemtoReg O 决定寄存器堆写入端数据来源:
0 : 来自ALU输出;
1 : 来自DM输出.
MemWrite O DM写入使能信号.
MemRead O DM读取使能信号.
ALUop [3:0] O 指明ALU的运算类型.
详见功能规定
ALUSrc [1:0] O 决定ALU输入端B数据来源:
0 : 选择GRF输出read2;
1 : 选择signext输出.
RegWrite O GRF写入使能信号.
RegDst O 决定寄存器堆写入端地址:
0 : 选择rt字段;
1 : 选择rd字段.
电路实现

Controller

整体连接

CPU


思考题

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

对于单周期CPU,可以以 splitter 为界,将整个数据通路分成“上游”和“下游”两部分。

  • “上游”可看做一个 Moore 型 FSM PC寄存器发挥状态存储功能。
    NPC模块发挥状态转移功能。

  • “下游”可以看做一个 Mealy 型 FSM。 GRF、DM发挥状态存储功能。
    IFU、Splitter、Controller、ALU、MUX、EXT发挥状态转移功能。

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

合理
ROM是只读寄存器,且断电不会导致数据丢失。IM模块(指令存储器)只需读取寄存器中存储的指令,而不用修改其中的数据,因此选用ROM更安全稳定。
RAM是随机访问存储器,DM(数据存储器)需要在使用CPU过程中读写数据,并且还具有异步复位的功能,使用RAM符合要求。
GRF(通用寄存器组,也称为寄存器文件、寄存器堆)用具有写使能的寄存器实现,其作用类似于MIPS汇编中所使用的32个寄存器,作为进行逻辑运算的数据存储器,读写效率高。

3 . 在上述提示的模块之外,你是否在实际实现时设计了其他的模块?如果是的话,请给出介绍和设计的思路。

在实际电路搭建时,我设计了ALU Control模块,该模块用于通过Controller模块输出的ALUop信号和指令中的Func字段,输出对ALU模块的控制信号,指明ALU的逻辑运算方式。
其最重要的功能就是处理R型指令,通过Func字段将不同的指令运算进行区分。

4 . 事实上,实现 nop 空指令,我们并不需要将它加入控制信号真值表,为什么?

指令sll $0,$0,0的指令码即为0x0000_0000,该指令在CPU运行周期内不做任何行为,不改变寄存器和内存数据,相当于nop空指令。

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

从覆盖情况而言,其中给出的测试样例并不充分。例如,该测试样例中没有测试sub指令。此外,对于一些极端情况,该测试并没有测试完全。例如,题目中提到addsub按无符号加减法处理,但并没有具体测试溢出的情况;对于beq等跳转指令,没有测试向前跳转的情况。


测试方案

设计要求的指令,并同时在MARS和Logisim中单步运行,观察其中GRF,DM,PC模块中寄存器或RAM中数据的变化是否一致,如一致则证明无误。需要注意的是,设计指令时一定要多多考虑临界情况和特殊情况,因为在这些数据处更容易发生无法预料的错误。