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!
评论





![2025 年数据库大作业 [BUAA-DB]](http://gitee.com/TheUHO/blog/raw/master/images/202407212255287.jpg)
![2026年算法设计与分析期末回忆版[BUAA-算法]](https://gitee.com/TheUHO/blog/raw/master/images/202407212255294.jpg)
![VLA模型技术代码调研学习 [VLA]](https://gitee.com/TheUHO/blog/raw/master/images/202409111007683.jpg)