均为R指令,靠func功能码判断
movn和movz实现很常规,执行时只需要多加个判断0
2的写HI、LO均在回写阶段;不写通用寄存器,所以wreg_o为disable,wd_o为0(这儿好像就明白了为什么$0一直为0)
3则需要写通用寄存器
需增加2个寄存器、执行阶段增加一个mux应对读HILO的指令、并处理新的数据相关
`include "defines.v"
module hilo_reg(
input wire clk,
input wire rst,
//写端口
input wire we,
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
//读端口1
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end
else if((we == `WriteEnable)) begin
hi_o <= hi_i;
lo_o <= lo_i;
end
end
endmodule
`EXE_MFHI: begin //NEW
wreg_o <= `WriteEnable; aluop_o <= `EXE_MFHI_OP;
alusel_o <= `EXE_RES_MOVE; reg1_read_o <= 1'b0; reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MFLO: begin
wreg_o <= `WriteEnable; aluop_o <= `EXE_MFLO_OP;
alusel_o <= `EXE_RES_MOVE; reg1_read_o <= 1'b0; reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MTHI: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_MTHI_OP;
reg1_read_o <= 1'b1; reg2_read_o <= 1'b0; instvalid <= `InstValid;
end
`EXE_MTLO: begin
wreg_o <= `WriteDisable; aluop_o <= `EXE_MTLO_OP;
reg1_read_o <= 1'b1; reg2_read_o <= 1'b0; instvalid <= `InstValid;
end
`EXE_MOVN: begin
aluop_o <= `EXE_MOVN_OP;
alusel_o <= `EXE_RES_MOVE; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
if(reg2_o != `ZeroWord) begin
wreg_o <= `WriteEnable;
end
else begin
wreg_o <= `WriteDisable;
end
end
`EXE_MOVZ: begin //NEW
aluop_o <= `EXE_MOVZ_OP;
alusel_o <= `EXE_RES_MOVE; reg1_read_o <= 1'b1; reg2_read_o <= 1'b1;
instvalid <= `InstValid;
if(reg2_o == `ZeroWord) begin
wreg_o <= `WriteEnable;
end
else begin
wreg_o <= `WriteDisable;
end
end
`include "defines.v"
module ex(
input wire rst,
//送到执行阶段的信息
input wire[`AluOpBus] aluop_i,
input wire[`AluSelBus] alusel_i,
input wire[`RegBus] reg1_i,
input wire[`RegBus] reg2_i,
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
//HI、LO寄存器的值 赋值给通用寄存器
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
//回写阶段的指令是否要写HI、LO,用于检测HI、LO的数据相关
input wire[`RegBus] wb_hi_i,
input wire[`RegBus] wb_lo_i,
input wire wb_whilo_i,
//访存阶段的指令是否要写HI、LO,用于检测HI、LO的数据相关
input wire[`RegBus] mem_hi_i,
input wire[`RegBus] mem_lo_i,
input wire mem_whilo_i,
//执行结果
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
output reg[`RegBus] wdata_o,
//执行阶段的指令对HI、LO寄存器的写操作请求 通用寄存器赋值给HILO
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o,
output reg whilo_o
);
//保存逻辑运算的结果
reg[`RegBus] logicout; //保存逻辑运算结果
reg[`RegBus] shiftres; //保存移位运算结果
reg[`RegBus] moveres; //保存移动操作结果
reg[`RegBus] HI; //保存HI最新值
reg[`RegBus] LO; //保存LO最新值
//根据大类型判断输出
always @ (*) begin
wd_o <= wd_i; //传递写目的寄存器地址
wreg_o <= wreg_i; //传递寄存器写使能信号
case ( alusel_i )
`EXE_RES_LOGIC: begin
wdata_o <= logicout;
end
`EXE_RES_SHIFT: begin
wdata_o <= shiftres;
end
`EXE_RES_MOVE: begin //移动操作指令的alusel_i
wdata_o <= moveres;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
//根据小类型作逻辑运算
always @ (*)
if(rst == `RstEnable) begin
logicout <= `ZeroWord;
end
else begin
case (aluop_i)
`EXE_OR_OP: begin
logicout <= reg1_i | reg2_i;
end
`EXE_AND_OP: begin
logicout <= reg1_i & reg2_i;
end
`EXE_NOR_OP: begin
logicout <= ~(reg1_i |reg2_i);
end
`EXE_XOR_OP: begin
logicout <= reg1_i ^ reg2_i;
end
default: begin
logicout <= `ZeroWord;
end
endcase
end
//根据小类型作移位运算
always @ (*)
if(rst == `RstEnable) begin
shiftres <= `ZeroWord;
end
else begin
case (aluop_i)
`EXE_SLL_OP: begin
shiftres <= reg2_i << reg1_i[4:0] ;
end
`EXE_SRL_OP: begin
shiftres <= reg2_i >> reg1_i[4:0];
end
`EXE_SRA_OP: begin //sra和srav都是这个指令
shiftres <= ({32{reg2_i[31]}} << (6'd32-{1'b0, reg1_i[4:0]}))
| reg2_i >> reg1_i[4:0];
end
default: begin
shiftres <= `ZeroWord;
end
endcase
end
//MFHI、MFLO、MOVN、MOVZ指令 移动操作
always @ (*) begin
if(rst == `RstEnable) begin
moveres <= `ZeroWord;
end
else begin
moveres <= `ZeroWord;
case (aluop_i)
`EXE_MFHI_OP: begin //将HI的值作为移动操作的结果
moveres <= HI;
end
`EXE_MFLO_OP: begin //将LO的值作为移动操作的结果
moveres <= LO;
end
`EXE_MOVZ_OP: begin //将reg1_i的值作为移动操作的结果
moveres <= reg1_i;
end
`EXE_MOVN_OP: begin //将reg1_i的值作为移动操作的结果
moveres <= reg1_i;
end
default : begin
end
endcase
end
end
//得到最新的HI、LO寄存器的值,此处要解决指令数据相关问题
always @ (*) begin
if(rst == `RstEnable) begin
{HI,LO} <= {`ZeroWord,`ZeroWord};
end
else if(mem_whilo_i == `WriteEnable) begin
{HI,LO} <= {mem_hi_i,mem_lo_i};
end
else if(wb_whilo_i == `WriteEnable) begin
{HI,LO} <= {wb_hi_i,wb_lo_i};
end
else begin
{HI,LO} <= {hi_i,lo_i};
end
end
//如果是MTHI MTLO 则需要给出whilo_o、hi_o、lo_o值
always @ (*) begin
if(rst == `RstEnable) begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end
else if(aluop_i == `EXE_MTHI_OP) begin
whilo_o <= `WriteEnable;
hi_o <= reg1_i;
lo_o <= LO;
end
else if(aluop_i == `EXE_MTLO_OP) begin
whilo_o <= `WriteEnable;
hi_o <= HI;
lo_o <= reg1_i;
end
else begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end
end
endmodule
`include "defines.v"
module ex_mem(
input wire clk,
input wire rst,
//来自执行阶段的信息
input wire[`RegAddrBus] ex_wd,
input wire ex_wreg,
input wire[`RegBus] ex_wdata,
input wire[`RegBus] ex_hi, //NEW
input wire[`RegBus] ex_lo, //NEW
input wire ex_whilo, //NEW
//送到访存阶段的信息
output reg[`RegAddrBus] mem_wd,
output reg mem_wreg,
output reg[`RegBus] mem_wdata,
output reg[`RegBus] mem_hi, //NEW
output reg[`RegBus] mem_lo, //NEW
output reg mem_whilo //NEW
);
always @ (posedge clk) begin
if(rst == `RstEnable) begin
mem_wd <= `NOPRegAddr;
mem_wreg <= `WriteDisable;
mem_wdata <= `ZeroWord;
mem_hi <= `ZeroWord;
mem_lo <= `ZeroWord;
mem_whilo <= `WriteDisable;
end else begin
mem_wd <= ex_wd;
mem_wreg <= ex_wreg;
mem_wdata <= ex_wdata;
mem_hi <= ex_hi;
mem_lo <= ex_lo;
mem_whilo <= ex_whilo;
end
end
endmodule
`include "defines.v"
module mem(
input wire rst,
//来自执行阶段的信息
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
input wire[`RegBus] wdata_i,
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
input wire whilo_i,
//送到回写阶段的信息
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
output reg[`RegBus] wdata_o,
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o,
output reg whilo_o
);
always @ (*) begin
if(rst == `RstEnable) begin
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
wdata_o <= `ZeroWord;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
whilo_o <= `WriteDisable;
end else begin
wd_o <= wd_i;
wreg_o <= wreg_i;
wdata_o <= wdata_i;
hi_o <= hi_i;
lo_o <= lo_i;
whilo_o <= whilo_i;
end
end
endmodule
`include "defines.v"
module mem_wb(
input wire clk,
input wire rst,
//来自访存阶段的信息
input wire[`RegAddrBus] mem_wd,
input wire mem_wreg,
input wire[`RegBus] mem_wdata,
input wire[`RegBus] mem_hi,
input wire[`RegBus] mem_lo,
input wire mem_whilo,
//送到回写阶段的信息
output reg[`RegAddrBus] wb_wd,
output reg wb_wreg,
output reg[`RegBus] wb_wdata,
output reg[`RegBus] wb_hi,
output reg[`RegBus] wb_lo,
output reg wb_whilo
);
always @ (posedge clk) begin
if(rst == `RstEnable) begin
wb_wd <= `NOPRegAddr;
wb_wreg <= `WriteDisable;
wb_wdata <= `ZeroWord;
wb_hi <= `ZeroWord;
wb_lo <= `ZeroWord;
wb_whilo <= `WriteDisable;
end else begin
wb_wd <= mem_wd;
wb_wreg <= mem_wreg;
wb_wdata <= mem_wdata;
wb_hi <= mem_hi;
wb_lo <= mem_lo;
wb_whilo <= mem_whilo;
end
end
endmodule