本CPU为logisim实现的单周期MIPS - CPU,支持的指令集包含{addu、subu、lui、ori、beq、lw、sw}。为了实现这些功能,CPU主要包含了IFU、GRF、ALU、DW、EXT、Conrroller。
(各模块会在文末附图)
1. GRF(寄存器堆)
表1.GRF端口定义
端口名 |
输入\输出 |
位宽 |
功能 |
clk |
Input |
1 |
时钟信号 |
reset |
Input |
1 |
复位信号 |
WE |
Input |
1 |
使能信号 |
A1 |
Input |
4:0 |
输入寄存器地址端口1,对应指令码25:21 |
A2 |
Input |
4:0 |
输入寄存器地址端口2,对应指令码20:16 |
A3 |
Input |
4:0 |
输入寄存器地址端口3,根据R型或I型指令分别对应指令码15:11和 20:16 |
WD |
Input |
31:0 |
数据输入端口,输入一个32位数据,存入编码为A3的寄存器中 |
RD1 |
Output |
31:0 |
输出编码为A1中输入的寄存器中的值 |
RD2 |
Output |
31:0 |
输出编码为A2中输入的寄存器中的值 |
1)寄存器部分
图1、GRF寄存器单元 |
编号为x的寄存器,输入端链接x_in 的标签,输出端链接x_out的标签,使能端、复位端、时钟端分别与对应信号链接
2)读出部分
图2、读出部分
使用五位选择信号、数据位宽为32的多路选择器,将寄存器输出端口连接到多路选择器的输入端,选择信号连接A1或A2输出连接
3)写入部分
图三、写入部分
WD连接DMX输入端口,输出端口连接对应编码的寄存器,选择信号为A3
4)注意
要将DMX设置为三态,不然写入的时候会将其他不需要的寄存器赋值为0
2. DM
图4、DM模块
使用一个32bit*32的RAM实现,str口连接MemWrite信号,ld口连接MemtoReg信号,输入数据为GRF模块的RD2口
我真傻,真的,忘记了DM中一个字是一个地址,地址端口应该连接ALU输出端的2~6位而不是0~5位,这个bug我de了两天qwq...
3. ALU
图5、ALU模块 |
表2、ALU端口说明
端口名 |
输入\输出 |
位宽 |
功能 |
A |
Input |
31:0 |
输入1 |
B |
Input |
31:0 |
输入2 |
C |
Output |
31:0 |
输出计算结果 |
F |
Input |
1:0 |
计算功能选择 |
ZERO |
Output |
1 |
判断A、B是否相等,相等为1,不相等为0 |
ALU实现了无符号加,无符号减,按位或,高十六位置立即数低十六位补0,分别对应的ALU_ctr为00、01、10、11,同时实现了相等判定,通过选择信号为F的多路选择器输出需要的计算结果
4. Controller
该CPU仅实现了七条指令及nop空指令,实际上,这些指令包括了R型,I型指令以及实现了跳转指令的数据通路,适当修改ALU和controller即可实现MIPS指令集中所有的指令(不包括扩展指令和syscall)
控制单元实现的功能为译码及输出相应控制信号,输入信号为func和op,分别连接指令码31:26位和5:0位,输出信号由以下真值表决定。
表3、controller真值表
执行指令 |
||||||||
信号名 |
addu |
subu |
lui |
ori |
sw |
lw |
beq |
nop |
func |
100001 |
100011 |
000000 |
|||||
op |
000000 |
000000 |
001111 |
001101 |
101011 |
100011 |
000100 |
000000 |
RegDst |
1 |
1 |
0 |
0 |
X |
0 |
X |
X |
ALUSrc |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
X |
MemToReg |
0 |
0 |
0 |
0 |
x |
1 |
X |
X |
RegWrite |
1 |
1 |
1 |
1 |
0 |
1 |
0 |
0 |
MemWrite |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
Npc_sel |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
X |
ALU_ctr1 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
X |
ALU_ctr2 |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
X |
各信号功能:
RegDst:被写入的寄存器的编码,由于MIPS中R型指令和I型指令被写入寄存器的编码对应的指令码位数不相同,故需要多路选择器对信号进行选择,多路选择器选择信号连接RegDst
ALUsrc:选择使用立即数还是使用GRF的RD2口输出数据,指令码为R型指令时置0,I型指令时置1
MemToReg:是否将数据存储器中的数据读入寄存器中,指令为lw时为1,其余情况为0
RegWrite:是否将数据写入寄存器堆中,连接GRF模块的使能端,需要向寄存器堆中写入数据时为1
MenWrite:是否将数据写入数据存储器中,连接数据存储器的写入使能端,需要向数据存储器中写入数据时为1
Npc_sel:跳转信号,当指令为beq且判定两寄存器的值相等时,该信号置1,指令存储器输入端选择输入信号为当前pc值加立即数
ALU_ctr:ALU计算结果选择信号,addu时为00,subu时为01,ori时为10,lui时为11
5. IFU
指令存储器使用32bit*32的ROM存储,输入端口前连接寄存器,受时钟控制,通过加法器实现pc自增
1. 跳转
Controller模块的npc_src信号与ALU的ZERO信号通过与运算后决定是否使用跳转地址,跳转地址的计算由位扩展器将指令码低16位扩展为32位数后,与当前的pc值相加得到
2. addu、subu指令数据通路
指令码26:21连接GRF的A1口,20:16连接A2口,ALUctr信号为00
经ALU计算结果后连接到WD口,RegWrite置1,选择15:11位连接A3口,将数据输入寄存器堆
3. 访存
DM地址接ALU输出结果的2至6位,输入数据为GRF模块的RD2输出,当指令为lw时,MemToReg信号为1,并将其同时连接到RAM数据存储器的ld信号口及多路选择器的选择信号上,多路选择器选择输出数据存储器的输出。寄存器的编码选择指令码的20:16位,将RegWrite信号置1;当指令为sw时,MemWrite信号置1,数据存储器数据输入端连接GRF的RD2端口,向数据存储器中写入数据
lw:
4. ori、lui实现
ori对应的ALU信号为10,lui对应的ALU信号为11,被写入寄存器地址为A3,A3口经多路选择器连接到指令码的20:16位
1. ALU功能测试
MIPS代码 操作码
ori $t0, $t0, 1 35080001
ori $t1, $t1, 2 35290002
addu $t2, $t0, $t1 01095021
subu $t3, $t1, $t0 01285823
lui $t4, 1 3c0c0001
期望结果
表4、ALU功能测试
$t0 |
$t1 |
$t2 |
$t3 |
$t4 |
0x00000001 |
0x00000002 |
0x00000003 |
0x00000001 |
0x00010000 |
测试结果:
2. DM功能测试
MIPS代码 操作码
ori $t0, $t0, 1 35080001
ori $t1, $t1, 2 35290002
sw $t1, ($t0) ad090000
lw $t2, ($t0) 8d0a0000
测试结果:
3. 跳转指令测试
MIPS代码 操作码
beq $t0, $t1, jump 11090001
ori $t0, $t0, 1 35080001
jump
ori $t1, $t1, 2 35290002
测试结果:
答:合理。RAM为随机存储,速度快于ROM,可以方便快捷地对RAM进行修改,在设备掉电后会清空RAM;ROM通常用作硬盘,用于存储指令,掉电后不会丢失,需要人为进行修改;而直接使用寄存器为效率最高的方法,每一条指令的实现均需要使用寄存器,故频繁调用的GRF模块应该使用Register
2.事实上,实现 nop 空指令,我们并不需要将它加入控制信号真值表,为什么?请给出你的理由。
答:寄存器写入信号RegWrite、数据存储器读写信号MemWrite、MemToReg均为0,接受nop信号时即使ALU在进行相关的计算,但并不会改变GRF和DM中的数值。
3.MARS 不能导出 PC 与 DM 起始地址均为 0 的机器码。实际上,可以通过为 DM 增添片选信号,来避免手工修改的麻烦,请查阅相关资料进行了解,并阐释为了解决这个问题,你最终采用的方法。
答:加一个模块,当地址大于0x3000时减去0x3000
4.除了编写程序进行测试外,还有一种验证 CPU 设计正确性的办法——形式验证。 形式验证的含义是根据某个或某些形式规范或属性,使用数学的方法证明其正确性或非正确性。请搜索“形式验证(Formal Verification)”了解相关内容后,简要阐述相比于测试,形式验证的优劣之处。
答:形式验证是一种IC设计的验证方法,它的主要思想是通过使用数学证明的方式来验证一个设计的功能是否正确。在处理一些模拟仿真时,可能会遇到一些不切实际的验证时间。而形式验证使用严格的数学推理来证明待测试设计的正确性,由于其静态、数学的特性,避免了对所有可能测试向量的枚举,而且能够达到100%无死角的检测。
四、最终成品
顶层模块:
GRF:
ALU:
controller:
本文是在原版实验报告上稍作修改后得到,后续可能会在描述不够具体的地方添加思路以及补充其他的指令实现,欢迎提出修改意见。
更新
具有更高可扩展性的controller实现方法(不对应原图,可尝试自行修改(万分推荐qwq))。