MIPS 1字=4字节 1字节=8位 即:1字=32位
每一个时钟周期:IM取指令->译码->ALU执行->DM访存->回写Reg
addi 加立即数,支持溢出 addi $22,$24,6
格式: ADDI rt,rs,imm16
运算: rt<=rs+imm16
数据通路:
NPC:把当前指令地址传送给PC
PC:把当前PC地址传送给IM指令存储器
IM:把PC地址中的[11:2]addr截取,因为按字节寻址,而相邻指令相差4个字节,addr需要删除后两位(÷4)
//reg [31:0] dm[1023:0]表示有1024个地址,每个地址32bit //MIPS一条指令占32位
也就是1个字(4个字节) //比如相邻两条指令的address分别是: //0x00003000 0x00003004
//0011000000000000 0011000000000100
//实际上存储的时候是按照数组存储的,一个数组元素占4字节,相邻元素地址之差为4字节,也就是1字
//所以要在寻址的时候将PC指向的地址(字节)除以4,得到字地址,直接用字地址访问数组下标//P109 在字节寻址的机器中,连续的字地址相差为4,而不是1 //P46
为了得到正确的字节地址,lw指令中与基址存储器相加的偏移量必须输4×8=32,这样才能正确读到A[8]
//MIPS按字节编址,所以字的起始地址必须是4的倍数
IM取出地址按照字段分割,输入到CTRL等模块中
EXT:imm有符号16to32
ALU:add运算,判断溢出标志位overflow
CTRL:overflow高电平,使RegWrite无效
Reg:写寄存器
addiu 加立即数,不检测溢出 addiu $3,$0,0xababcdcd
格式: addiu rt,rs,imm16
运算: rt<=rs+imm16
数据通路:
IM取指令,译码
EXT imm16to32
ALU相加 溢出求模
Reg写寄存器
slt 小于置一指令 slt $20,$12,$4
格式: SLT rd,trs,rt
运算: rd<=(rs
jal 跳转至标签(Jump And Link) jal newadd
格式: JAL target
运算: gpr31<=PC+4
数据通路:
NPC始终输出 jalPC = PC + 4 NPC <= {PC[31:28], imm26, 2’b0}
IM取指令,译码
CTRL控制信号(MemtoReg=10 jalPC JAL跳转的PC+4)
将PC + 4的值写入31号寄存器(MUX32根据MemtoReg控制写入寄存器的数据,MUX5根据RegDst控制写寄存器的地址)
jr 跳转至寄存器中的指令地址 jr $31
格式:JR rs
运算:PC<-rs
数据通路:
当前指令是JR指令的时候
CRTL将jr_ctr设置为高电平
(GPR)根据rs[4:0]从31号寄存器中读出数据rd1[31:0],输出到NPC单元
NPC单元中检测到jr_ctr,于是将rd1[31:0]传送给NPC。(NPC <= rd1[31:0])
addu 加寄存器,不检测溢出 addu $4, $0,$16
格式:ADDU rd, rs, rt
运算:GPR[rd] ← GPR[rs] + GPR[rt]
数据通路:IM取指令->译码->ALU执行加法->运算结果回写Reg
subu 减寄存器,不检测溢出 subu $17,$17,$8
格式:SUBU rd, rs, rt
运算:GPR[rd] ← GPR[rs] - GPR[rt]
数据通路:IM取指令->译码->ALU执行减法->运算结果回写Reg
ori 或立即数 ori $8, $0,4
格式:ORI rt, rs, immediate
运算:GPR[rt] ← GPR[rs] or immediate
数据通路:IM取指令->译码->ALU执行或运算->运算结果回写Reg
lw 取字指令 将数据存储器中的字加载到寄存器中 lw $18, -4($8)
格式:LW rt, offset(base)
运算:GPR[rt] ← memory[GPR[base] + offset]
数据通路:IM取指令->译码->ALU执行加运算(计算地址)->DM访存->回写Reg
sw 取字指令 将寄存器的字存储到数据存储器中 sw $4, -4($8)
格式:SW rt, offset(base)
运算:memory[GPR[base] + offset] ← GPR[rt]
数据通路:IM取指令->译码->读Reg数据->ALU计算地址->写入DM
beq 相等则分支到标签 beq $25, $0,end2
格式:BEQ rs, rt, offset
运算:if GPR[rs] = GPR[rt] then branch
数据通路:IM取指令->译码->读Reg数据1数据2->ALU计算是否相等(0标志位)->CTRL(PCsrc判断是否分支)->NPC分支
lui 立即数加载至寄存器高16位 lui $19, 0xefef
格式:LUI rt, immediate
运算:GPR[rt] ← immediate || 016
数据通路:IM取指令->译码->MUX拓展16to32->ALU取低16to高16并补全32->回写Reg
j 无条件跳转 j end
格式:J target
运算:PC ← PCGPRLEN-1…28 || instr_index || 02
数据通路:当前指令是J指令的时候
CRTL将j_ctr设置为高电平
NPC根据imm26计算下一条指令地址
加载字节指令
在有效地址指定的存储器位置(基地址+16bit偏移地址,地址运算结果不一定非要是4的倍数)提取8位(1字节)的内容,扩展符号,存储到rt指定的寄存器中
lb指令,将从内存中取出的8bit字节(有符号)拓展至32bit(高位根据符号,补全0或全1),正如下图所说的:寄存器中高24位信息由符号拓展获取。
格式
lw指令的地址必须是4的倍数(数组下标*4
),因为一次取一个字
而lb指令的地址(基址+偏移)不一定是4的倍数,因为只取字节,地址可以是数组下标*4+1/2/3
具体操作如下图,把不是4的倍数的部分(最低两位)单独提取出来,作为片选信号,用来选择到底取一个字的哪个字节,也就是:先按字取出,然后再分离得到想要的那一个字节,这样变相达到了取字节的效果