目录
一 移动操作指令
移动操作指令的作用其实是用来实现乘除法,会对特殊寄存器HI和LO进行操作,具体如下:
HI、LO寄存器用于保存乘法、除法结果。当用于保存乘法结果时,HI寄存器保存结果
的高32位,LO寄存器保存结果的低32位;当用于保存除法结果时,HI寄存器保存余数,
LO寄存器保存商。
判断指令:可见都是R型指令,op都为0,根据后六位指令码即可判断
理解指令:movn和movz是根据rt的值来判断是否将rs寄存器的值赋值到rd中,后四个指令都是对hi和lo寄存器进行读写。
二 如何实现
我们先来理一下每条指令在五级流水线中的实现过程
1.movn和movz指令
此指令的只要功能是读取rs rt寄存器的值并把结果写回rd寄存器中,实现思路和之前的寄存器差不多,只是需要加一个判断条件rt是否为0来决定是否写入。
`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
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
执行阶段根据输入信号进行计算,把rs传递给rd即可,最后把这些信息一直传递到寄存器。
`EXE_MOVZ_OP: begin
moveres <= reg1_i;
end
`EXE_MOVN_OP: begin
moveres <= reg1_i
2.mthi,mtlo指令
(1)在译码阶段依据指令,给出运算类型alusel_ o、运算子类型aluop_ o的值,同时读出
地址为rs的通用寄存器的值。由于mthi、mtlo不写通用寄存器,所以wreg_ o为WriteDisable,
wdo为0。.
(2)在执行阶段确定要写HI、LO寄存器的情况,以及要写入的值,并将这些信息传递到访存阶段。
(3)访存阶段将这些信息再传递到回写阶段。
(4)回写阶段依据这些信息修改HI、LO寄存器的值。
3.mfhi,mflo指令
(1)在译码阶段依据指令,给出运算类型alusel_ o、 运算子类型aluop_ o的值,同时因为有要写入的目的寄存器,所以wreg. o为WriteEnable, wd o为指令中rd的值,也就是目的寄
存器地址。.
(2)在执行阶段获取HI或LO寄存器的值,作为要写入目的寄存器的数据,并将这些信息传递到访存阶段。因此系统结构中需要修改数据通路,将hilo寄存器的数据传递给执行阶段
(3)访存阶段将这些信息再传递到回写阶段。
(4)回写阶段依据这些信息修改目的寄存器。
新的数据相关问题:
当连续修改特殊寄存器时,会造成寄存器中的值更新不及时,如下图:
解决方法依然采用之前说过的数据前推,将回写和访存的hilo相关数据提前传递到执行阶段,如下图:
4.添加特殊寄存器模块
由于特殊寄存器的存在新增了一个模块放在回写阶段(类似之前的寄存器模块),此模块实现的功能用于读写hilo寄存器,故输入输出如下:
5.译码模块的实现
前两个指令和之前的指令一样,只需要判断是否写使能(需要根据rt寄存器的值去判断),写地址(默认rd)如何以及读哪些寄存器(都需要读)即可:
后四个指令由于是对hi lo寄存器进行操作,mf指令是吧特殊寄存器赋值给rd,是否写使能(需要写入目的寄存器),写地址(默认rd)如何以及读哪些寄存器(不需要读,因为是读特殊寄存器):
mt指令是将rs寄存器的值写给特殊寄存器,是否写使能(不需要因为不写通用寄存器)以及读哪些寄存器(读rs寄存器):
6.执行模块的实现
首先解决数据相关问题,如果处于访存和回写阶段的指令需要写入hilo寄存器,就把写入的最新值给到执行阶段(因为mthi/lo指令需要在执行阶段吧hilo的值赋给通用寄存器)
//得到最新的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
对于江将结果写入通用寄存器的指令如mo,mf开头的,执行阶段的操作和之前类似:
//MFHI、MFLO、MOVN、MOVZ指令
always @ (*) begin
if(rst == `RstEnable) begin
moveres <= `ZeroWord;
end else begin
moveres <= `ZeroWord;
case (aluop_i)
`EXE_MFHI_OP: begin
moveres <= HI;
end
`EXE_MFLO_OP: begin
moveres <= LO;
end
`EXE_MOVZ_OP: begin
moveres <= reg1_i;
end
`EXE_MOVN_OP: begin
moveres <= reg1_i;
end
default : begin
end
endcase
end
end
而对于mthi,mtlo指令,因为是需要把rs寄存器的值写入特殊寄存器,所以需要对hilo的相关信号*(hilo以及使能信号)进行赋值并且传输到hilo寄存器中:
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
对于EXE/MEM,MEM,MEM/WB模块,需要做的事情就是把hilo的相关信号一路传递到回写阶段即可,增添输入输出信号就可以了。
MEM/WB模块输出的对HI、LO寄存器的写信息将直接送到HILO模块,包括: wb_ whilo、 wb_ _hi、 wb_ lo,后者据此修改HI、LO寄存器的值。
至此新的sopc模块修改完成。