CO_P4
CPU 设计文档
一、指令类型
- 解读:将指令按类型分类,并对指令按照功能划分
R类型指令
R类型指令 | Op(31~26) | Rs(25~21) | Rt(20~16) | Rd(15~11) | Shamt(10~6) | Func(5~0) |
---|---|---|---|---|---|---|
Add | 000000 | Rs | Rt | Rd | XXXXX | 100000 |
Sub | 000000 | Rs | Rt | Rd | XXXXX | 100010 |
Jr | 000000 | Rs | 00000 | 00000 | 00000 | 001000 |
add:
sub:
jr:
I类型指令
I类型指令 | Op(31~26) | Rs(25~21) | Rt(20~16) | immediate or address |
---|---|---|---|---|
Ori | 001101 | Rs | Rt | imm16 |
Lui | 001111 | 00000 | Rt | imm16 |
Lw | 100011 | Rs | Rt | imm16 |
Sw | 101011 | Rs | Rt | imm16 |
Beq | 000100 | Rs | Rt | imm16 |
ori:
lui:
lw:
sw:
beq:
J类型指令
J类型指令 | Op(31~26) | 26 address |
---|---|---|
j | 000010 | target |
jal | 000011 | target |
jal:
二、主要模块
mips(顶层模块)
端口 | 方向 | 描述 |
---|---|---|
clk | I | 时钟信号,控制所有需clk信号输入的模块 |
reset | I | 同步复位信号,控制所有需reset信号输入的模块 |
Conroller(控制器)
控制信号类型及含义
Branch
>
- Beq 1: 若Zero=1,PC输入选择加法器Nadd
- Jal 2: PC输入选择Jal_Adr
- Jr 3: PC输入选择Rdata1
- Other : 0,PC输入选择加法器Add输出(PC+4)
RegDst
>
- 0: 选择Rd
- 1: 选择Rt
- 2:选择31(jal指令)
RegWirte
>1: 表示寄存器堆可写入
MemtoReg
>
- R型指令 0: 选择 ALU 输出
- Lui 1 : 选择shift输出
- Lw 2: 选择数据存储器DM输出
- Jal 3:选择Adder(地址加法器)输出
ALUSrc
>
- R型指令 0: 选择寄存器堆的 Read data2 输出
- Ori 1: 选择zero_ext 输出
- Lw 2: 选择Signext的输出
- Sw 2: 选择Signext的输出
- Beq 0: 选择Read data2输出
ALUOp1 + ALUOp2
>
- 输入到ALU controller 控制单元
MemRead
>
- 0:表示DM不可写入
- 1:表示DM可写入
MemWrite
- 0:表示DM不可写入
- 1:表示DM可写入
shiftSrc
>
- 0: input(shift)选择Rdata2输出,shamt(shift)选择shamt输入
- 1:input(shift)选择imm16 输出,shamt(shift) 选择0x10输入
指令运算类型选择
指令 | Func字段 | ALUOp | ALU运算类型 | ALU Oper | ||
---|---|---|---|---|---|---|
Lw | XXXXXX | 00 | + | 000 | ||
Sw | XXXXXX | 00 | + | 000 | ||
Beq | XXXXXX | 01 | >/</= | 010 | ||
Ori | XXXXXX | 11 | \ | \ | 011 | |
Add | 100000 | 10 | + | 000 | ||
Sub | 100010 | 10 | - | 001 |
指令实现控制信号的转换
- x表示指令实现与该输入无关
指令 | Opcode | Branch | RegDst | RegWrite | MemtoReg | ALUSrc | ALUOp | MemWrite | MemCate | shiftSrc |
---|---|---|---|---|---|---|---|---|---|---|
Add/Sub | 000000 | 0 | 0 | 1 | 0 | 0 | 2 | 0 | x | x |
Lw | 100011 | 0 | 1 | 1 | 2 | 2 | 0 | 0 | x | x |
Sw | 101011 | 0 | x | 0 | x | 2 | 0 | 1 | 0 | x |
Beq | 000100 | 1 | x | 0 | x | 0 | 1 | 0 | x | x |
Ori | 001101 | 0 | 1 | 1 | 0 | 1 | 3 | 0 | x | x |
Lui | 001111 | 0 | 1 | 1 | 1 | x | x | 0 | x | 1 |
Nop | 000000 | 0 | x | 0 | x | x | x | 0 | x | 0 |
Jal | 000011 | 2 | 2 | 1 | 3 | x | x | 0 | x | x |
Jr | 000000 | 3 | x | 0 | x | x | x | 0 | x | x |
GRF(寄存器堆)
端口 | 方向 | 描述 |
---|---|---|
Clk | I | 时钟信号 |
Reset | I | 复位信号,将寄存器的值全部清零 1: 复位 0:无效 |
WE | I | 写使能信号 1: 可写入数据 0: 不可写入数据 |
ReadRes1 | I | 读出地址输入(5位),读出到Read Data1 |
ReadRes2 | I | 读出地址输入(5位),读出到Read Data2 |
WriteRes | I | 写入地址输入(5位) |
WriteData | I | 写入数据(32位) |
WPC | I | 输入当前pc地址 |
ReadData1 | O | Read register1地址对应寄存器的输出 |
ReadData2 | O | Read register2地址对应寄存器的输出 |
ALU(算数逻辑单位)
端口 | 方向 | 描述 |
---|---|---|
A | I | 操作数1(32位) |
B | I | 操作数2(32位) |
ALUOper | I | ALU功能选择(4位) |
Zero | O | 判断操作数1与操作数2是否相等(1位) |
Result | O | 结果输出(32位) |
ALU control(ALU控制单元)
端口 | 方向 | 描述 |
---|---|---|
ALUOp | I | 指令类型区分(4位) |
Func | I | 指令[5:0]位 |
ALUOper | O | ALU功能选择(4位) |
IFU (取指令单元)
端口 | 方向 | 描述 |
---|---|---|
Clk | I | 时钟信号 |
Reset | I | 指令存储器(im_reg)所有地址的存储值清零 1: 复位 0:无效 |
Branch | I | PC值分支跳转指令判断(4位) |
Zero | I | beq指令判断PC是否跳转条件(1位) |
index | I | 跳转指令的target中间值(26位) |
immSiExt | I | 16位立即数有符号扩展输入(32位) |
ReadData1 | O | GRF(寄存器堆)中Read register1地址对应寄存器的输出 |
pc | O | PC当前值(32位) |
instr | O | PC地址对应IM(指令存储器)的指令输出(32位) |
Adder | O | pc + 4 对应值(32位) |
DM(数据存储器)
端口 | 方向 | 描述 |
---|---|---|
Clk | I | 时钟信号 |
pc | O | PC当前值(32位) |
Reset | I | 数据存储器(RAM)所有地址的存储值清零 1: 复位 0:无效 |
MemWrite | I | 写使能信号, 1: 可写入数据 0: 不可写入数据 |
MemCate | I | 判断向数据储存器写入数据的操作指令类型(4位) |
Address | I | 读写地址(12位) |
WriteData | I | 写入数据(32位) |
ReadData | O | Address地址对应数据储存器(RAM)的储存值输出 |
shift(移位器)
端口 | 方向 | 描述 |
---|---|---|
input | I | 操作数 |
shamt | I | 偏移量(5位) |
output | I | 操作数移位后输出 |
三、数据通路
- 加粗表示该列存在分支
指令 | A | B | PC | IM Adr | Reg1 | Reg2 | Wreg | Wdata | A | B | DM Adr | DM Wdata | Sign-ext | A | B | shift | zero-ext | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Adder: | ALU: | Nadder: | / | |||||||||||||||
R型指令与访存 | PC | 4 | Adder | PC | Rs | Rt | Rd | ALU | Rdata1 | Rdata2 | / | / | / | / | / | /! | / | |
Lw | PC | 4 | Adder | PC | Rs | / | Rt | DM | Rdata1 | Sign_ext | ALU | / | imm16 | / | / | / | / | |
Sw | PC | 4 | Adder | PC | Rs | Rt | / | / | Rdata1 | Sign_ext | ALU | Rdata2 | imm16 | / | / | / | / | |
Beq | PC | 4 | Adder/Nadder | PC | Rs | Rt | / | / | Rdata1 | Rdata2 | / | / | imm16 | Adder | Sign-imm16(左移2) | / | / | |
Ori | PC | 4 | Adder | PC | Rs | / | Rt | ALU | Rdata1 | zero_ext | / | / | / | / | / | / | imm16 | |
Lui | PC | 4 | Adder | PC | / | / | Rt | shift | / | / | / | / | / | / | / | imm16 | / | / |
Nop | PC | 4 | Adder | PC | / | Rt | Rd | shift | / | / | / | / | / | / | / | Rdata2 | / | |
jal | PC | 4 | Jal_Adr | PC | / | / | 31 | Adder | / | / | / | / | / | / | / | / | / | |
jr | / | / | Rdata1 | PC | Rs | / | / | / | / | / | / | / | / | / | / | / | / |
四、测试
1 | ori $a1, $a0, 456 #$a0与立即数取或存入$a1 |
- Mars导出的机械码(储存在code.txt中的文件):
1 | 34040000 |
利用$readmemh指令读取code.txt中的机械码指令并储存在IFU_mips模块的指令存储器im_reg(4096个32位寄存器)当中,运行mips顶层模块,通过$display指令检测存入寄存器堆(GRF)和数据存储器(DM)时的pc地址,相应数据以及存入的寄存器或数据存储器地址,将结果与Mars对拍运行时的数据做比对,以此检测Verilog代码编写的单周期CPU是否正确。
五、思考题
Q1
- addr是从ALU计算结果输入
- 由于DM的一个地址对应一个字节的储存空间,同时存入数据的位数是32位(字),故为满足一次性存入32位数据,则需取出addr的[13:2],保证每次存入数据的地址都是4的倍数(32位数据存储的起始地址),即可完成一次性存入32位数据。
Q2
- 控制信号每种取值对应的控制信号
1 |
|
- 指令对应的控制信号的取值
1 |
|
优劣分析
- 记录每种控制信号对应的指令
- 优势:
- 通过assign语句实现,保证进入每一个新的时钟周期都对每一个控制信号赋值。
- 按照控制信号进行分类,可以方便查找每一个控制信号所对应的指令类型。
- 在添加指令时按照该指令所需的控制信号,对相应的控制信号进行添加指令即可,同时若要删减指令,删除所有控制信号中所出现的删减指令即可。
- 劣势:
- 不方便查找每一个指令所对应的控制信号。
- 对指令的控制信号进行修改时所需的调整过大。
- 直接控制指令对应的控制信号的取值
- 优势:
- 通过always语句块以及if-else语法实现,进入每一个时钟周期需要对指令进行判断,再对该指令所需的控制信号进行赋值。
- 按照指令类型进行分类,可以方便查找每一个指令所对应的控制信号。
- 在添加指令时加入新的else if语句块,添加判断条件以及赋值新的控制信号,若要删减指令,直接删除该else if语句块即可。
- 劣势:
- 不方便查找每一个控制信号所对应的指令类型
- 当需要对控制信号进行修改时所需的调整过大。
Q3
- 同步复位:clk的优先级大于reset的优先级。
只有clk处于上升沿(根据实际情况发生改变),reset信号才起作用。 - 异步复位: reset的优先级大于clk的优先级.
因为对于需要由clk和reset控制的组件,当reset信号处于高电平时,该部件一直处于复位状态,clk处于上升沿时该部件无法存入数据,只有当reset信号处于低电平时,clk处于上升沿时该部件方可存入数据。
Q4
addi 与 addiu
- addi指令和addiu指令正常运行(不存在溢出)时都是将寄存器Rs中值和符号扩展的16位立即数相加存入寄存器Rt当中,当寄存器Rs中值和符号扩展的16位立即数相加发生溢出(溢出判断,最高位进位和次高位进位不同),addi指令会发生溢出异常中断,发生报错。故在忽略溢出的前提下,addi 与 addiu 是等价的。
add 与 addu
- add指令和addu指令正常运行(不存在溢出)时都是将寄存器Rs和Rt中的值相加后存入寄存器Rd当中,当寄存器Rs和Rt中的值相加发生溢出(溢出判断,最高位进位和次高位进位不同),add指令会发生溢出异常中断,发生报错。故在忽略溢出的前提下,add 与 addu 是等价的。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ascendira!