Mini MIPS 32-bits CPU

32位单周期MIPS指令集CPU,仅仅支持10条指令:

  • lw, sw
  • lui, ori, addiu
  • addu, slt
  • beq, bne, j

具体实现可见:Mini-Mips32

部件构成

顶层模块:

CPU模块:

控制单元:

数据通路:

控制信号

指令 reg_write reg_dst alu_src branch mem_write mem_to_reg aluop jump select_imm
R-type 1 1 0 00 0 0 100 0 0
beq 0 x 0 01 0 x 010 0 0
bne 0 x 0 10 0 x 010 0 0
j 0 x x 00 0 x xxx 1 0
addiu 1 0 1 00 0 0 000 0 0
ori 1 0 1 00 0 0 011 0 0
lui 1 0 1 00 0 0 100 0 1
lw 1 0 1 00 0 1 000 0 0
sw 0 x 1 00 1 x 000 0 0
invalid_op x x x xx x x xxx 0 x

指令流程

lw

lw指令为访存指令,当CPU根据instr解析其为lw指令的时候,首先将instr送入控制单元将其解析并将其控制信号输入数据通路。到达数据通路,首先经过reg_file,在reg_filea1读入base寄存器的值作为src_a,将instr[15 : 0]符号扩展作为src_bsrc_asrc_b经过ALU进行运算,这时alu_control表明进行加法运算,进行运算后作为读内存地址送入RAM并读取该地址的值,在之后将读到的值作为write_reg_data根据instr[20 : 16]作为写入寄存器的编号写到目标寄存器中,随后等下一个时钟沿到来的时候将pc+4并送给iaddr并进行下条指令的取指。

sw

sw指令大体与lw指令相同,不同之处在于从rt的寄存器中取出值将其写入base寄存器加上offset的内存地址中。

lui

lui指令将立即数imm写入寄存器rt的高16位,寄存器rt的低16位置0。在我的实现中,设计了一个select_imm的控制位,当select_imm为1时,将imm放在高16位,低16位置0作为sign_imm。此时ALU不做任何事,仅仅返回src_b。随后将值写入rt寄存器中。

ori

ori指令较为简单,只需从rs中取出值并与sign_imm进行或运算写入rt寄存器即可。

addiu

addiu指令将从rs寄存器中取出的值与sign_imm的值送入ALU相加并写入rt寄存器中。

addu

addu为R类型指令,根据funct来判断其alu_control。此时分别从rsrd寄存器中取出的值进行相加并将其写入rt寄存器中。

slt

slt寄存器将rs寄存器中的值与rt寄存器中的值进行有符号数比较(此时将通过ALU的比较进行),若rs中的值较小,则将rd寄存器写入1,否则写入0。

beq

beq指令将rs寄存器与rt的寄存器进行比较,若相等则进行分支跳转。此时比较是通过ALU的减法操作来进行的,当zero为0时,则进入分支指令,此时分支指令的地址由offset左移两位进行符号扩展加上该分支指令对应的延迟槽的PC计算得到。

bne

beq指令大体相同,只不过变为了不相等则跳转。我们branch由两位组成。计算式为alu_res = (zero & branch[0]) | (~zero & branch[1])

j

无条件跳转,设置jump控制位,任何条件下都进行分支跳转。