一、流水线CPU
流水线CPU就是指将一条分解为多步,在同一周期内进行多条指令的同时执行。MIPS五级流水线就是将指令分为:取指(IF),译码(ID),执行(EX),访存(MEM),写回(WB)五个阶段。举个例子:
比如第二条指令lui $t2,0x2100
在流水线CPU中执行的就是
可以看到在200-300ns的周期里,IF阶段取到0x00400004处的指令,300-400ns,这条指令到了ID阶段,而IF阶段执行下一条指令。400-500ns,执行这条指令,ALU的结果为0x21000000,正是指令执行结果,500-600ns该指令不需要访存,所以MEM阶段不做什么事,600-700ns将结果写回寄存器。
在执行这条指令的同时,其它的指令也在被执行。而流水线CPU和单周期CPU的区别就在这里。
二、流水线冒险问题
我们知道,指令只有在执行到EX阶段才会得出结果,结果到了MEM阶段才会写回寄存器,到了WB阶段才会写回内存,在流水线CPU中,往往会出现前面的指令还未执行完成将结果写回寄存器,后面的指令就需要读取该寄存器的值来进行执行,那就出现了相关现象。
我们采取数据前推的方式来解决这一类问题。
(1)对于ALU操作数A和B,两个数在指令运行到EX阶段才需要访问,有如下情况:
①当MEM阶段指令是写回寄存器操作,且写回的寄存器不是0号寄存器,并且与EX阶段的指令所要访问的寄存器是同一个,则将MEM阶段的ALU运算结果进行转发。
举个例子:如下两条指令,20处的指令要将$t4寄存器的值加上$t7寄存器的值存到$t3中,而24处的指令要用$t3的值加上$t7的值放到$t5,所以$t3就出现了数据相关。
在1100-1200ns,EX阶段执行20处的指令,结果为0x00000004,而到了1200-1300ns,此结果还未写回寄存器,但是通过数据前推,将结果转发到ALU操作数处,执行24处的指令。
②当WB阶段指令是写寄存器操作,且写回的寄存器不是0号寄存器,并且与EX阶段的指令所要访问的寄存器是同一个,且不满足条件①,则将要写回寄存器的数据进行转发。
③不存在数据相关,直接转发从寄存器中读出的值即可。
(2)对于load-use数据冒险:当EX阶段的指令是load指令,并且load的数据存放将要存放的寄存器与ID阶段指令要访问的寄存器相同,这时需要插入一个气泡,即清空ID-EX流水段的控制信号,并且保持IF-ID流水段的值不变以及保持PC值不变。
(3)对于分支指令,首先我们采取分支预测的方式,在IF阶段读取到分支指令时,总是预测分支指令跳转成功,当指令执行到ID阶段,解码出分支指令的判断条件以及数据来源,我们依旧采取数据前推的方式,将正确的数据进行转发,来对分支指令是否跳转进行判断,所以需要将数据前推再提前一个阶段。
①当EX阶段指令是写回寄存器操作,且写回的寄存器不是0号寄存器,并且与ID阶段的指令所要访问的寄存器是同一个,则将EX阶段的ALU运算结果进行转发。
②当MEM阶段指令是写回寄存器操作,且写回的寄存器不是0号寄存器,并且与ID阶段的指令所要访问的寄存器是同一个,且不满足条件①则将MEM阶段的ALU运算结果进行转发。
③当WB阶段指令是写寄存器操作,且写回的寄存器不是0号寄存器,并且与ID阶段的指令所要访问的寄存器是同一个,且不满足条件②,则将要写回寄存器的数据进行转发。
④不存在数据相关,直接转发从寄存器中读出的值即可。
(4)对于跳转指令,情况与分支指令类似,只是不需要判断是否需要跳转而是直接跳转即可。
三、分支预测
对于分支指令,由于在单周期CPU中,判断分支指令是否跳转需要到EX阶段执行完成,而如果在流水线CPU中遇到分支指令,插入气泡等待分支指令执行完成再决定下一条指令无疑会浪费许多时间,所以我们采取分支预测的方式,在IF阶段取到指令后,判断若是分支指令,则默认预测分支指令跳转,而当分支指令执行到ID阶段后,通过解码获得分支指令的判断条件以及数据来源后,通过数据前推转发对应的数据进行判断,如果判断结果是跳转成功则说明预测成功,继续执行。如果判断结果是不应该跳转,则这时由于我们预测分支指令跳转成功,所以需要将已经取入IF阶段的指令进行清空。将此时ID阶段即分支指令的下一条指令PC传回NextPC。
3300-3400ns,IF阶段取004000a4处指令beq $t6,$0,l9(l9=0x004000ac)通过分支预测,我们总是预测分支指令跳转成功,更新NextPC=0x004000ac。WB阶段执行00400098处指令,更新寄存器$t1 = 0x0000000b。
3400-3500ns,IF阶段取004000ac处指令。ID阶段执行004000a4处指令beq $t6,$0,l9,由于EX阶段EX阶段执行004000a0处指令addi $t6,$0,100;aluOperandA=$0=0x00000000,aluOperandB=0x00000064, AluResult=0x00000064。验证正确。将AluResult=0x00000064转发到ID阶段,由于AluResult=0x00000064!=$0,所以分支预测错误,将IF-ID流水段信号清空,更新NextPC=004000a4+4=004000a8.
有些情况我就不一一举例了,报告中有详细的描述。
四、CPU设计
模块 | 功能描述 |
PC | 负责PC更新,仅在 clk 或者 rst 为 posedge 时更新 PC。 |
信号 | 描述 |
NextPC(NextInstAddress) | 从NextPC模块送来的下一条指令地址 |
PC(InstAddress) | 指令地址 |
clock(clock) | 时钟信号 |
reset(reset) | 复位信号 |
PCWrite(PCWrite) | 有效时暂停PC,保持指令不变 |
模块 | 功能描述 |
NextPC | 计算下一条指令地址 |
信号 | 描述 |
NextPC(NextInstAddress) | 计算出的PC值 |
PC(InstAddress) | 当前正在处理的指令的PC值 |
NextPCSignal(NextPCSignal) | 控制信号,选择哪一个作为下一个PC值 |
PC_ID(PC_ID+4) | 分支预测失败后,分支指令的下一条指令地址 |
JumpAddr_IF(JumpAddr) | IF阶段指令中的25位立即数,来计算分支指令跳转地址 |
JumpAddr_ID(JumpAddr_ID) | ID阶段的直接跳转指令的地址 |
JumpReg(ForwardEData) | ID阶段的寄存器跳转指令数据前推转发的地址 |
模块 | 功能描述 |
BranchTest | 判断分支指令是否满足条件跳转 |
信号 | 描述 |
JumpSignal(JumpSignal) | 解码后产生的信号,标记分支和跳转指令 |
BranchTestData1(ForwardCData) | 分支指令判断的操作数A,数据前推转发来的 |
BranchTestData2(ForwardDData) | 分支指令判断的操作数B,数据前推转发来的 |
Opcode_IF(Opcode) | IF阶段指令的opcode字段 |
Opcode_ID(Opcode_ID) | ID阶段指令的opcode字段 |
Func_ID(RegTarget_ID) | ID阶段指令的rt字段,来判断BLTZ,BLTZAL... |
NextPCSignal(NextPCSignal) | 控制信号,选择哪一个作为下一个PC值 |
IF_Flush(IF_Flush) | 控制是否清空IF阶段的指令 |
模块 | 功能描述 |
IF_ID | IF-ID流水段 |
信号 | 描述 |
clock(clock) | 时钟信号 |
PCWrite(PCWrite) | PC是否有效,无效时保持IF-ID阶段指令不变 |
IF_Flush(IF_Flush) | 控制是否清空IF阶段的指令 |
PC_IF(InstAddress) | IF阶段指令地址 |
Instruction_IF(instruction) | IF阶段指令 |
PC_ID(PC_ID) | ID阶段指令地址 |
Instruction_ID(Instruction_ID) | ID阶段指令 |
模块 | 功能描述 |
SRC_A | 选择ALU的操作数A |
信号 | 描述 |
DataIn0(ForwardAData) | 读出rs的数据,数据前推转发来 |
DataIn1(Shamt_EX) | EX阶段移位指令的位移量 |
Signal(AluSrcASignal_EX) | EX阶段指令ALU的操作数A选择信号 |
PC_EX(PC_EX+4) | BGEZAL,BLTZAL,JALR,JAL指令的下条指令地址作为返回地址写入31号寄存器 |
JumpSignal(JumpSignal_EX) | 解码后产生的信号,用于判断是否是BGEZAL,BLTZAL,JALR,JAL指令 |
DataOut(AluOperandA) | 操作数A |
模块 | 功能描述 |
SRC_B | 选择ALU的操作数B |
信号 | 描述 |
DataIn0(ForwardBData) | 读出rt的数据,数据前推转发来 |
DataIn1(Imm32_EX) | EX阶段指令中立即数扩展后的32位立即数 |
Signal(AluSrcBSignal_EX) | EX阶段指令ALU的操作数B选择信号 |
DataOut(AluOperandB) | 操作数B |
模块 | 功能描述 |
SignExtension | 扩展立即数 |
信号 | 描述 |
Imm16_ID | ID阶段指令解码后指令中的16位立即数 |
SignExt | 扩展信号,ID阶段解码后产生,表示零扩展还是符号扩展 |
Imm32 | ID阶段产生,扩展后的32位立即数 |
模块 | 功能描述 |
MemDataExtension | 扩展从内存中读出的数据 |
信号 | 描述 |
ReadMemData_WB | 读出的数据 |
ReadMemExtSignal_WB | 扩展信号 |
MemDataExt | 扩展后的数据 |
模块 | 功能描述 |
CU | 控制器模块,产生控制信号 |
信号 | 描述 |
Opcode(Opcode_ID) | 指令中的opcode字段 |
Func(Func_ID) | 指令中的function字段 |
Branch(RegTarget_ID) | 指令中的rt字段,(用于区分bltz,bltzal...) |
RegWrite(RegWrite) | 是否写寄存器 |
MemWrite(MemWrite_ID) | 是否写内存 |
SignExt(SignExt) | 是否扩展立即数 |
AluOpcode(AluOpcode) | ALU的操作符 |
JumpSignal(JumpSignal) | 标记分支指令和跳转指令 |
AluSrcASignal(AluSrcASignal) | 操作数A选择信号 |
AluSrcBSignal(AluSrcBSignal) | 操作数B选择信号 |
WriteRegDataSignal | 写入寄存器数据的选择信号 |
WriteRegSignal | 写入寄存器地址的选择信号 |
MemRead | 是否读内存 |
模块 | 功能描述 |
ID_EX | ID_EX流水段 |
信号 | 描述 |
clock(clock) | 时钟信号 |
stall(stall) | 控制是否清空ID阶段产生的控制信号,load-use冒险 |
WriteRegSignal_ID(WriteRegSignal) | ID阶段指令写入寄存器地址的选择信号 |
WriteRegDataSignal_ID(WriteRegDataSignal) | ID阶段指令写入寄存器数据的选择信号 |
AluSrc1Signal_ID(AluSrcASignal) | ID阶段指令操作数A选择信号 |
AluSrc2Signal_ID(AluSrcBSignal) | ID阶段指令操作数B选择信号 |
AluOpcode_ID(AluOpcode) | ID阶段指令ALU的操作符 |
MemWrite_ID(MemWrite_ID) | ID阶段指令是否写内存 |
MemRead_ID(MemRead) | ID阶段指令是否读内存 |
RegWrite_ID(RegWrite) | ID阶段指令是否写寄存器 |
ReadRegData1_ID(ReadRegData1_ID) | ID阶段指令从rs选择的寄存器读出的数据 |
ReadRegData2_ID(ReadRegData2_ID) | ID阶段指令从rt选择的寄存器读出的数据 |
Shamt_ID(Shamt_ID) | ID阶段指令移位指令的位移量 |
Imm32_ID(Imm32) | ID阶段指令扩展后的32位立即数 |
RegSource_ID(RegSource_ID) | ID阶段指令rs |
RegTarget_ID(RegTarget_ID) | ID阶段指令rt |
RegDst_ID(RegDst_ID) | ID阶段指令rd |
Instruction_ID(Instruction_ID) | ID阶段指令 |
PC_ID(PC_ID) | ID阶段指令地址 |
JumpSignal_ID(JumpSignal) | ID阶段指令标记分支指令和跳转指令信号 |
ReadRegData1_EX(ReadRegData1_EX) | EX阶段指令从rs选择的寄存器读出的数据 |
ReadRegData2_EX(ReadRegData2_EX) | EX阶段指令从rt选择的寄存器读出的数据 |
Shamt_EX(Shamt_EX) | EX阶段指令移位指令的位移量 |
Imm32_EX(Imm32_EX) | EX阶段指令扩展后的32位立即数 |
RegSource_EX(RegSource_EX) | EX阶段指令rs |
RegTarget_EX(RegTarget_EX) | EX阶段指令rt |
RegDst_EX(RegDst_EX) | EX阶段指令rd |
Instruction_EX(Instruction_EX) | EX阶段指令 |
PC_EX(PC_EX) | EX阶段指令地址 |
WriteRegSignal_EX(WriteRegSignal_EX) | EX阶段指令写入寄存器地址的选择信号 |
WriteRegDataSignal_EX(WriteRegDataSignal_EX) | EX阶段指令写入寄存器数据的选择信号 |
AluSrc1Signal_EX(AluSrcASignal_EX) | EX阶段指令操作数A选择信号 |
AluSrc2Signal_EX(AluSrcBSignal_EX) | EX阶段指令操作数B选择信号 |
AluOpcode_EX(AluOpcode_EX) | EX阶段指令ALU的操作符 |
MemWrite_EX(MemWrite_EX), | EX阶段指令是否写内存 |
MemRead_EX(MemRead_EX) | EX阶段指令是否读内存 |
RegWrite_EX(RegWrite_EX) | EX阶段指令是否写寄存器 |
JumpSignal_EX(JumpSignal_EX) | EX阶段指令标记分支指令和跳转指令信号 |
模块 | 功能描述 |
ALU | 运算器模块 |
信号 | 描述 |
AluOperandA(AluOperandA) | 操作数A |
AluOperandB(AluOperandB) | 操作数B |
AluOpcode(AluOpcode_EX) | ALU的操作符 |
MemRead(MemRead_EX) | 是否读内存 |
MemWrite(MemWrite_EX) | 是否写内存 |
AluResult(AluResult_EX) | 运算结果 |
AluOverflowSignal(AluOverflowSignal) | 判断运算结果是否溢出 |
WriteMemDataLength(WriteMemDataLength) | 表示写入内存的数据的位置,长度 |
ReadMemExtSignal(ReadMemExtSignal) | 表示从内存读出的数据如何拓展 |
模块 | 功能描述 |
Forwarding | 数据前推模块,产生5个转发信号 |
信号 | 描述 |
JumpSignal(JumpSignal) | 标记分支指令和跳转指令 |
RegSource_ID(RegSource_ID) | ID阶段指令的rs |
RegTarget_ID(RegTarget_ID) | ID阶段指令的rt |
RegSource_EX(RegSource_EX) | EX阶段指令的rs |
RegTarget_EX(RegTarget_EX) | EX阶段指令的rt |
WriteRegAddr_EX(WriteRegAddr), | EX阶段指令要写入的寄存器地址 |
WriteRegAddr_MEM(WriteRegAddr_MEM) | MEM阶段指令要写入的寄存器地址 |
WriteRegAddr_WB(WriteRegAddr_WB), | WB阶段指令要写入的寄存器地址 |
MemRead_MEM(MemRead_MEM), | MEM阶段的指令是否要读内存 |
RegWrite_EX(RegWrite_EX), | EX阶段指令是否要写寄存器 |
RegWrite_MEM(RegWrite_MEM), | MEM阶段指令是否要写寄存器 |
RegWrite_WB(RegWrite_WB), | WB阶段指令是否要写寄存器 |
ForwardASignal(ForwardASignal), | ALU操作数A的转发信号 |
ForwardBSignal(ForwardBSignal), | ALU操作数B的转发信号 |
ForwardCSignal(ForwardCSignal), | 分支判断操作数A的转发信号 |
ForwardDSignal(ForwardDSignal), | 分支判断操作数B的转发信号 |
ForwardESignal(ForwardESignal) | 跳转指令跳转地址的转发信号 |
模块 | 功能描述 |
HazardDetection | load-use冒险检测模块 |
信号 | 描述 |
RegSource_ID(RegSource_ID) | ID阶段指令的rs |
RegTarget_ID(RegTarget_ID) | ID阶段指令的rt |
WriteRegAddr_EX(WriteRegAddr), | EX阶段指令要写入的寄存器地址 |
MemRead_EX(MemRead_EX), | EX阶段的指令是否要读内存 |
PCWrite(PCWrite) | 有效时暂停PC,保持指令不变 |
stall(stall) | 控制是否清空ID阶段产生的控制信号 |
模块 | 功能描述 |
FORWARD_A | 转发ALU操作数A |
信号 | 描述 |
DataIn0(ReadRegData1_EX) | EX阶段指令从rs寄存器读出的值 |
DataIn1(WriteRegData), | WB阶段要写入寄存器的值 |
DataIn2(AluResult), | MEM阶段指令的运算结果 |
Signal(ForwardASignal) | ALU操作数A的转发信号 |
DataOut(ForwardAData) | 转发给ALU操作数A的数据 |
模块 | 功能描述 |
FORWARD_B | 转发ALU操作数B |
信号 | 描述 |
DataIn0(ReadRegData2_EX) | EX阶段指令从rt寄存器读出的值 |
DataIn1(WriteRegData), | WB阶段指令要写入寄存器的值 |
DataIn2(AluResult), | MEM阶段指令的运算结果 |
Signal(ForwardBSignal) | ALU操作数B的转发信号 |
DataOut(ForwardBData) | 转发给ALU操作数B的数据 |
模块 | 功能描述 |
FORWARD_C | 转发分支判断的操作数A |
信号 | 描述 |
DataIn0(ReadRegData1_ID) | ID阶段指令从rs寄存器读出的值 |
DataIn1(AluResult_EX) | EX阶段指令的运算结果 |
DataIn2(AluResult), | MEM阶段指令的运算结果 |
DataIn3(WriteRegData) | WB阶段指令要写入寄存器的值 |
Signal(ForwardCSignal) | 分支判断操作数A的转发信号 |
DataOut(ForwardCData) | 转发给分支判断操作数A的数据 |
模块 | 功能描述 |
FORWARD_D | 转发分支判断的操作数B |
信号 | 描述 |
DataIn0(ReadRegData2_ID) | ID阶段指令从rt寄存器读出的值 |
DataIn1(AluResult_EX) | EX阶段指令的运算结果 |
DataIn2(AluResult), | MEM阶段指令的运算结果 |
DataIn3(WriteRegData) | WB阶段指令要写入寄存器的值 |
Signal(ForwardDSignal) | 分支判断操作数B的转发信号 |
DataOut(ForwardDData) | 转发给分支判断操作数B的数据 |
模块 | 功能描述 |
FORWARD_E | 转发跳转指令的跳转地址 |
信号 | 描述 |
DataIn0(ReadRegData1_ID) | ID阶段指令从rs寄存器读出的值 |
DataIn1(AluResult_EX) | EX阶段指令的运算结果 |
DataIn2(AluResult), | MEM阶段指令的运算结果 |
DataIn3(WriteRegData) | WB阶段指令要写入寄存器的值 |
Signal(ForwardESignal) | 跳转指令的跳转地址的转发信号 |
DataOut(ForwardEData) | 跳转指令的跳转地址 |
模块 | 功能描述 |
WR_REG_ADDR | 选择写寄存器的地址 |
信号 | 描述 |
DataIn0(RegDst_EX) | 写入rd寄存器 |
DataIn1(RegTarget_EX) | 写入rt寄存器 |
.DataIn2(5'b11111) | 31号寄存器 |
Signal(WriteRegSignal_EX) | 选择信号 |
DataOut(WriteRegAddr) | 写寄存器的地址 |
模块 | 功能描述 |
WR_REG_DATA | 选择写寄存器的数据 |
信号 | 描述 |
DataIn0(AluResult_WB) | 运算器运算结果 |
DataIn1(MemDataExt) | 从内存读出并扩展后的数据 |
DataIn2(PC_WB + 4) | 当前指令的下一条指令地址,(JALR,JAL,BLTZAL...) |
Signal(WriteRegDataSignal_WB) | 选择信号 |
DataOut(WriteRegData) | 写寄存器的数据 |
模块 | 功能描述 |
EX_MEM | EX-MEM流水段 |
信号 | 描述 |
clock(clock) | 时钟信号 |
MemRead_EX | EX阶段是否要读内存 |
MemWrite_EX | EX阶段是否要写内存 |
RegWrite_EX | EX阶段是否写寄存器 |
WriteRegDataSignal_EX | EX阶段写寄存器数据的选择信号 |
AluResult_EX | EX阶段指令运算结果 |
WriteMemData_EX | EX阶段写内存数据 |
WriteRegAddr_EX | EX阶段写内存地址 |
Instruction_EX | EX阶段指令 |
WriteMemDataLength_EX | EX阶段写内存数据的长度和格式 |
ReadMemExtSignal_EX | EX阶段读内存数据如何扩展 |
PC_EX(PC_EX), | EX阶段指令地址 |
MemRead_MEM | MEM阶段是否要读内存 |
MemWrite_MEM | MEM阶段是否要写内存 |
RegWrite_MEM | MEM阶段是否写寄存器 |
WriteRegDataSignal_MEM | MEM阶段写寄存器数据的选择信号 |
AluResult_MEM | MEM阶段指令运算结果 |
WriteMemData_MEM | MEM阶段写内存数据 |
WriteRegAddr_MEM | MEM阶段写内存地址 |
Instruction_MEM | MEM阶段指令 |
WriteMemDataLength_MEM | MEM阶段写内存数据的长度和格式 |
ReadMemExtSignal_MEM | MEM阶段读内存数据如何扩展 |
PC_MEM(PC_MEM) | MEM阶段指令地址 |
模块 | 功能描述 |
MEM_WB | MEM_WB流水段 |
信号 | 描述 |
clock(clock) | 时钟信号 |
RegWrite_MEM | MEM阶段是否写寄存器 |
WriteRegDataSignal_MEM | MEM阶段写寄存器数据的选择信号 |
AluResult_MEM | MEM阶段指令运算结果 |
WriteRegAddr_MEM | MEM阶段写内存地址 |
Instruction_MEM | MEM阶段指令 |
ReadMemExtSignal_MEM | MEM阶段读内存数据如何扩展 |
PC_MEM(PC_MEM) | MEM阶段指令地址 |
RegWrite_WB | WB阶段是否写寄存器 |
WriteRegDataSignal_WB | WB阶段写寄存器数据的选择信号 |
AluResult_WB | WB阶段指令运算结果 |
WriteRegAddr_WB | WB阶段写内存地址 |
Instruction_WB | WB阶段指令 |
ReadMemExtSignal_WB | WB阶段读内存数据如何扩展 |
PC_WB(PC_WB) | WB阶段指令地址 |
模块 | 功能描述 |
Register | 通用寄存器组, |
信号 | 描述 |
RegWrite(RegWrite_WB) | 是否写寄存器 |
ReadRegAddr1(RegSource_ID) | 读rs的地址 |
ReadRegAddr2(RegTarget_ID) | 读rt的地址 |
WriteRegAddr(WriteRegAddr_WB) | 写寄存器的地址 |
WriteRegData(WriteRegData) | 写寄存器的数据 |
ReadRegData1(RegSourceData_ID) | 读出rs的数据 |
ReadRegData2(WriteMemData_ID) | 读出rt的数据 |
模块 | 功能描述 |
CPU | |
信号 | 描述 |
clock(clock) | 时钟信号 |
reset(rst) | 复位信号 |
instruction(Instruction) | 执行的指令 |
ReadMemData(ReadMemData) | 从内存中读出的数据 |
InstAddress(PC) | 指令地址 |
AluResult(MemDataAddr) | 从内存中读数据的地址 |
MemWrite(MemWrite) | 是否写内存 |
WriteMemData(WriteMemData) | 写入内存的数据 |
WriteMemDataLength(WriteMemDataLength) | 表示写入内存的数据的位置,长度 |
模块 | 功能描述 |
InstructionMemory | 指令存储器 |
信号 | 描述 |
PC[8:2] | 指令地址 |
Instruction | 指令 |
模块 | 功能描述 |
DataMemory | 数据存储器 |
信号 | 描述 |
clock | 时钟信号 |
MemDataAddr[8:2] | 写入/读出内存数据的地址 |
MemWrite | 是否写入内存 |
WriteMemData | 写入内存的数据 |
WriteMemDataLength | 表示写入内存的数据的位置,长度 |
ReadMemData | 从内存中读出的数据 |
五、控制逻辑
信号 | 含义 |
RegWrite | 是否需要将结果写回寄存器 |
1 | 是 |
0 | 否 |
信号 | 含义 |
MemWrite | 是否需要将结果写入内存 |
00 | 否 |
01 | 写入字节 |
10 | 写入半字 |
11 | 写入字 |
信号 | 含义 |
SignExt | 对指令中的16位立即数做什么扩展 |
1 | 符号扩展 |
0 | 零扩展 |
信号 | 含义 |
AluOpcode | alu操作符 |
00000 | NOP |
00001 | ADDU(not overflow) |
00010 | SUBU(not overflow) |
00011 | AND |
00100 | OR |
00101 | SLT |
00110 | SLTU |
00111 | NOR |
01000 | SLL |
01001 | SRL |
01010 | SRA |
01011 | SLLV |
01100 | SRLV |
01101 | LUI |
01111 | XOR |
10000 | SRAV |
10001 | SUB |
10010 | ADD |
信号 | 含义 |
JumpSignal | 分支指令和跳转指令的控制信号 |
000 | 顺序 |
001 | 分支指令 |
010 | J |
011 | JR |
101 | BGEZAL,BLTZAL(分支指令需要将返回地址写入寄存器) |
100 | JALR(寄存器跳转指令需要将返回地址写回寄存器) |
111 | JAL(直接跳转指令需要将返回地址写回寄存器) |
信号 | 含义 |
AluSrc1Signal | alu操作数A的选择信号 |
1 | 来源指令中的Shamt字段,移位指令 |
0 | 来源rs字段指定的寄存器数据 |
信号 | 含义 |
AluSrc2Signal | alu操作数B的选择信号 |
1 | 来源指令中的立即数字段,I-type |
0 | 来源rt字段指定的寄存器数据 |
信号 | 含义 |
WriteRegDataSignal | 写入寄存器的数据选择信号 |
00 | alu运算结果 |
01 | 从内存中加载的数据 |
10 | 某些跳转指令存储返回地址 |
信号 | 含义 |
WriteRegSignal | 写入寄存器的地址选择信号 |
00 | rd字段指定的寄存器 |
01 | rt字段指定的寄存器 |
10 | 31号寄存器存储某些跳转指令的返回地址 |
信号 | 含义 |
MemRead | 是否需要加载内存中的数据到寄存器 |
000 | 不需要 |
001 | 无符号加载字节 |
010 | 无符号加载半字 |
011 | 加载字 |
101 | 符号加载字节 |
110 | 符号加载半字 |
六、详细源码
chris-william0829/bit-mini-mips-single-cycle-cpu (github.com)