BUAA_CO_P4
P4_Verilog实现10指令单周期CPU
需求分析
实现10指令:add, sub, ori, lw, sw, beq, lui, jal, jr, nop
在8指令的基础上增量开发实现10指令,我们首先分析新增指令的功能
jal:将pc + 4写入31号寄存器 + 跳转到指定地址jr:从31号寄存器中读出 + 跳转到指定地址
思路分析
由于
jal要求写入31号寄存器,所以的RegAddr需要至少3种编码,也就是说RegDst至少需要2位,分别对应写入寄存器编号来自rtrd和 31号1
2
3[1:0] RegDst // RegDst == 2'b00 RegAddr是rt对应的寄存器 (默认)
// RegDst == 2'b01 RegAddr是rd对应的寄存器
// RegDst == 2'b10 RegAddr是31号寄存器同时要回写的内容
WriteBack也要发生变化,WriteBack的取值有4种可能,所以WBSource至少需要2位,分别对应WriteBack来自ALU_ans,WD,imm_ext,和pc + 41
2
3
4
5
6
7
8
9[1:0] WBSource // WBSource == 2'b00 WriteBack = ALU_ans (默认)
// WBSource == 2'b01 WriteBack = WD
// WBSource == 2'b10 WriteBack = imm_ext
// WBSource == 2'b11 WriteBack = pc + 4
/* 2'b01 对应 lw
2'b10 对应 lui
2'b11 对应 jal
*/接下来要实现的是跳转功能,输入
IFU的32位shift可能有两种情况,分别是分支指令时的imm_ext和j指令时的jumpAddr。jumpAddr是pc要跳转到的地址,而imm_ext还要在IFU的npc模块里完成进一步的处理才能成为分支指令时的npc。
顶层电路


控制信号
1 | [1:0] RegDst // RegDst == 2'b00 写入rt对应的寄存器 (默认) |
| add | sub | nop | ori | lw | sw | lui | beq | jal | jr | |
|---|---|---|---|---|---|---|---|---|---|---|
| [1:0] RegDst | 01 | 01 | 00 | 00 | 00 | 00 | 00 | 00 | 10 | 00 |
| Branch | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| MemRead | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
| MemtoReg | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| [1:0] ALUOp | 00 | 01 | 00 | 11 | 00 | 00 | 00 | 01 | 00 | 00 |
| MemWrite | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
| ALUSrc | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
| RegWrite | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 |
| isLui | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
| isJal | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
| isJr | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| jump | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
思考题
Q1:阅读下面给出的
DM的输入示例中,根据你的理解回答,这个addr信号是从哪里来的?地址信号addr位数为什么是[11:2]而不是[9:0] ?A1:
addr是访存地址,来自于ALU的输出。在DM中数据按字储存,故需要将addr除以4。
Q2:在设计控制器时可以记录下指令对应的控制信号如何取值,也可以记录下控制信号每种取值所对应的指令。请分析两种做法各自的优劣。
Q2:
指令对应信号:优点是分析简单,只需要思考每条指令的数据通路即可获得控制信号取值;缺点是码量大,对于每个指令都要设置所有信号的取值。不够简洁。
信号对应指令:优点是简洁清晰(为每个信号设置默认值为0,在当前指令需要改变信号值时再更改);缺点是不够直观,容易出错。
Q3:在相应的部件中,复位信号的设计都是同步复位,这与
P3中的设计要求不同。请对比同步复位与异步复位这两种方式的reset信号与clk信号优先级的关系。A3:同步复位时
clk优先级高于reset,只有在clk处于上升沿时才考虑reset信号。异步复位时reset优先级高于clk,只有reset为低电平时才考虑时钟变化带来的影响。
Q4:C 语言是一种弱类型程序设计语言。C 语言中不对计算结果溢出进行处理,这意味着 C 语言要求程序员必须很清楚计算结果是否会导致溢出。因此,如果仅仅支持 C 语言,MIPS 指令的所有计算指令均可以忽略溢出。 请说明为什么在忽略溢出的前提下,addi 与 addiu 是等价的,add 与 addu 是等价的。
A4:这里通过
add和addu来说明。addu的操作是简单的,我们考虑add的操作:1
2
3
4
5
6temp = (GPR[rs][31] || GPR[rs]) + (GPR[rt][31] || GPR[rt])
if temp[32] ≠ temp[31] then
SignalException(IntegerOverflow)
else
GPR[rd] ← temp31..0
endif在上述操作中,我们将32位加数
A1和A2符号拓展至33位,他们的和记为temp。temp的低32位事实上就是A1+A2在不考虑溢出时的的结果(因为有溢出时这个溢出会被向上进位至33位)。











