P3-CPU设计文档[BUAA-CO]
P3单周期CPU设计文档
设计整体概述
- 预计实现指令集:add、sub、ori、Lui、lw、sw、beq、nop
- R型指令:add、sub、ori
opcode | rs | rt | rd | shamt | funct |
---|---|---|---|---|---|
6 | 5 | 5 | 5 | 5 | 6 |
- I型指令:lui、lw、sw、beq
opcode | rs | rt | offset |
---|---|---|---|
6 | 5 | 5 | 16 |
- J型指令:暂无
opcode | instr_inde |
---|---|
6 | 26 |
其中,nop指令为空指令,不执行任何操作,add、sub不考虑溢出,故实际执行addu和subu
- 实现功能:实现单周期CPU,能够执行上述指令集,采用模块化设计,顶层模块包含控制器
CU
和数据通路模块ALU
、IFU
、NPC
、GRF
、DM
、Ext
共七个子模块,预留了J型指令的NPC
接口 - 顶层设计图:
数据通路模块设计
IFU 指令单元
- 定义:模块内部包含
PC
程序计数器、IM
指令存储器子模块,负责根据PC的值从指令存储器中读取指令,输出到数据总线。 - 端口定义
信号名 | 方向 | 位宽 | 说明 |
---|---|---|---|
Next_PC | I | 32 | NPC 模块输出的下一条指令地址 |
clk | I | 1 | 时钟信号 |
reset | I | 1 | 复位信号 |
stop | I | 1 | 停机信号 |
RD | O | 32 | IM 取得的指令 |
PC | O | 32 | PC 模块输出地址,传入NPC 模块用于得到下一条指令地址 |
- 实现功能
序号 | 功能 | 描述 |
---|---|---|
1 | 复位 | 当reset信号为1时,PC 置0x00003000 |
2 | 停机 | 当stop信号为1时,PC 保持不变 |
3 | 取指 | 当stop信号为0时,根据PC 在clk上升沿得到的下一条指令地址,从IM 读取指令 |
PC
通过寄存器实现,初始化为0x00003000
IM`通过ROM实现,取PC[13:2]作为地址,减去0x00003000后读取指令
NPC 指令地址生成单元
- 定义:根据当前PC地址和控制信号,生成下一条指令地址。
- 端口定义
信号名 | 方向 | 位宽 | 说明 |
---|---|---|---|
PC | I | 32 | 当前指令地址 |
instr_index | I | 32 | J型指令的立即数 |
offset | I | 16 | I型指令的立即数 |
rs | I | 32 | jr指令的寄存器 |
branch | I | 1 | 是否执行I型指令跳转 |
jump | I | 1 | 是否执行J型指令跳转 |
jr | I | 1 | 是否执行jr指令跳转 |
Next_PC | O | 32 | 下一条指令地址 |
PC+4 | O | 32 | 当前指令地址+4,可用于拓展Jal指令 |
- 实现功能
序号 | 功能 | 描述 |
---|---|---|
1 | PC+4 | 当branch、jump、jr组成的control信号为3’b000时,Next_PC输出PC+4 |
2 | I型跳转 | 当branch、jump、jr组成的control信号为3’b100时,Next_PC输出PC_jump |
GRF 寄存器堆
- 定义:根据读写信号,对寄存器堆进行读写操作。
- 端口定义
信号名 | 方向 | 位宽 | 说明 |
---|---|---|---|
clk | I | 1 | 时钟信号 |
reset | I | 1 | 复位信号 |
WE | I | 1 | 写使能信号 |
A1 | I | 5 | 读寄存器1地址 |
A2 | I | 5 | 读寄存器2地址 |
A3 | I | 5 | 写寄存器地址 |
WD | I | 32 | 写数据 |
RD1 | O | 32 | 读寄存器1数据 |
RD2 | O | 32 | 读寄存器2数据 |
- 实现功能
序号 | 功能 | 描述 |
---|---|---|
1 | 复位 | 当reset为1时,将所有寄存器置为0 |
2 | 读 | 当WE为0时,将A1、A2对应的寄存器数据输出到RD1、RD2 |
3 | 写 | 当WE为1时,在时钟上升沿将A3对应的寄存器写入WD |
A1、A2分别读取Rs、Rt寄存器,A3写入RegAddress(根据RegDst选择Rt或Rd),WD写入RegData(根据MemRead选择ALU的运算结果或I型指令的立即数)
ALU 算术逻辑单元
- 定义:根据控制信号,对输入的两个数进行算术或逻辑运算。
- 端口定义
信号名 | 方向 | 位宽 | 说明 |
---|---|---|---|
A | I | 32 | 操作数1 |
B | I | 32 | 操作数2 |
ALU_Op | I | 3 | ALU控制信号 |
ALU_Res | O | 32 | ALU运算结果 |
cmp_equal | O | 1 | A、B是否相等 |
- 实现功能
序号 | 功能 | 描述 |
---|---|---|
1 | 加法 | 当ALU_Op为3’b000时,ALU_Res输出A+B |
2 | 减法 | 当ALU_Op为3’b001时,ALU_Res输出A-B |
3 | 与 | 当ALU_Op为3’b010时,ALU_Res输出A&B |
4 | 或 | 当ALU_Op为3’b011时,ALU_Res输出A丨B |
5 | 异或 | 当ALU_Op为3’b100时,ALU_Res输出A^B |
6 | 低位补0 | 当ALU_Op为3’b101时,ALU_Res输出B[15:0] + 016(实现lui指令) |
7 | 相等 | cmp_equal输出A是否等于B |
Ext 指令扩展单元
- 定义:根据控制信号,对输入的16位立即数进行零扩展或符号扩展。
- 端口定义
信号名 | 方向 | 位宽 | 说明 |
---|---|---|---|
offset | I | 16 | 16位立即数 |
sel | I | 1 | 扩展选择信号,0为零扩展,1为符号扩展 |
extend | O | 32 | 扩展后的32位立即数 |
- 实现功能
序号 | 功能 | 描述 |
---|---|---|
1 | 零扩展 | 当sel为0时,extend输出 016 + offset[15:0] |
2 | 符号扩展 | 当sel为1时,extend输出 offset[15] ? 116 + offset[15:0] : 016 + offset[15:0] |
DM 数据存储器
- 定义:使用RAM实现,根据控制信号,对输入的地址和数据进行读写操作。
- 端口定义
信号名 | 方向 | 位宽 | 说明 |
---|---|---|---|
address | I | 32 | 32位地址 |
WD | I | 32 | 32位数据 |
WE | I | 1 | 读/写控制信号,0为读,1为写 |
clk | I | 1 | 时钟信号 |
- 实现功能
序号 | 功能 | 描述 |
---|---|---|
1 | 读 | 当WE为0时,输出地址对应的32位数据 |
2 | 写 | 当WE为1时,将WD写入地址对应的32位数据 |
CU 控制单元
-
定义:利用
ANDLogic
和ORLogic
生成控制信号,控制其他模块的行为。 -
端口定义
控制单元需要读取指令的Op字段和Func字段,识别生成对应指令的控制信号。
信号名 | 方向 | 位宽 | 说明 |
---|---|---|---|
Op | I | 6 | instr[31:26] |
Func | I | 6 | instr[5:0] |
RegDst | O | 1 | GRF 写地址选择信号,0为Rt,1为Rd |
ALUSrc | O | 1 | ALU 源选择信号,0为RD2,1为拓展后的offset |
RegWrite | O | 1 | GRF 写使能信号 |
MemWrite | O | 1 | DM 写使能信号 |
is_Branch | O | 1 | I型跳转指令 |
ExtOp | O | 1 | 扩展操作选择信号, 0为零拓展,1为符号拓展 |
ALU_Op | O | 3 | 三位ALU操作码,3’b000为加法,3’b001为减法,3’b010为与,3’b011为或,3’b100为异或 |
- 实现功能
ANDLogic
模块- 定义:根据输入信号,识别对应指令。
- 端口定义
信号名 方向 位宽 说明 Op I 6 instr[31:26] Func I 6 instr[5:0] add O 1 add指令 sub O 1 sub指令 ori O 1 ori指令 lw O 1 lw指令 sw O 1 sw指令 beq O 1 beq指令 lui O 1 lui指令
指令 | Op | [25:21] | [20:16] | [15:11] | [10:6] | [5:0] |
---|---|---|---|---|---|---|
add | 000000 | rs | rt | rd | 00000 | 100000 |
sub | 000000 | rs | rt | rd | 00000 | 100010 |
ori | 001101 | rs | rt | immediate | immediate | immediate |
lw | 100011 | base | rt | offset | offset | offset |
sw | 101011 | base | rt | offset | offset | offset |
beq | 000100 | rs | rt | offset | offset | offset |
lui | 001111 | 00000 | rt | immediate | immediate | immediate |
ORLogic
模块- 定义:根据输入的对应指令,生成其他模块的操作信号。
- 端口定义
信号名 方向 位宽 说明 add I 1 add指令 sub I 1 sub指令 ori I 1 ori指令 lw I 1 lw指令 sw I 1 sw指令 RegDst O 1 GRF
写地址选择信号,0为Rt,1为RdALUSrc O 1 ALU
源选择信号,0为RD2,1为拓展后的offsetMemRead O 1 GRF
数据选择信号,0为ALU_Res,1为内存读取数据RegWrite O 1 GRF
写使能信号MemWrite O 1 DM
写使能信号is_Branch O 1 I型跳转指令 ExtOp O 1 扩展操作选择信号, 0为零拓展,1为符号拓展 ALU_Op O 3 三位ALU操作码,由真值表生成
- 功能实现:根据每种指令的对应操作,在输出前将指令信号进行或运算,得到其他模块的操作信号。
测试方案
思考题
- 上面我们介绍了通过 FSM 理解单周期 CPU 的基本方法。请大家指出单周期 CPU 所用到的模块中,哪些发挥状态存储功能,哪些发挥状态转移功能。
GRF、DM实现了状态存储功能,通过寄存器存储当前状态,IFU、Ext、NPC、ALU、CU实现了状态转移功能,利用组合逻辑电路实现状态转移。
- 现在我们的模块中 IM 使用 ROM, DM 使用 RAM, GRF 使用 Register,这种做法合理吗? 请给出分析,若有改进意见也请一并给出。
极为合理且正确,IM模块类比于是输入,应当是只读的,DM是内存部分,需要大量存储空间,因此使用RAM,GRF是通用寄存器堆,使用32个寄存器可以提高读写速度。
- 在上述提示的模块之外,你是否在实际实现时设计了其他的模块?如果是的话,请给出介绍和设计的思路。
添加了NPC模块,用于计PC的值,实现方法见上。
- 事实上,实现 nop 空指令,我们并不需要将它加入控制信号真值表,为什么?
由于nop并未对其他模块进行操作,因此不需要添加控制信号,只需要保证CU模块对于nop对应的Op和Func没有任何输出,就能保证不对其他模块进行操作。
- 阅读 Pre 的 “MIPS 指令集及汇编语言”一节中给出的测试样例,评价其强度(可从各个指令的覆盖情况,单一指令各种行为的覆盖情况等方面分析),并指出具体的不足之处。
测试样例代码
1 | ori $a0, $0, 123 |
显然强度是不够的(不够暴力),在代码数据量和覆盖率方面都有待提高,并没有测试到所有的通用寄存器和边界情况,测试数据也不够全面。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 theUHO!
评论