MIPS架构中定义的异常类型
MIPS32架构中,有些事情打断程序的正常的执行流程,这些事情称为中断、陷阱、系统调用以及其他打断程序执行流程的情况,统称为异常 。
此处的OpenMIPS处理器只实现了其中6中异常情况的处理:
- 硬件复位
- 中断(软中断、硬中断)
- syscall系统调用
- 无效指令
- 溢出
- 自陷指令引发的异常
异常发生后,进入异常处理例程进行具体处理,处理结束后,返回到异常发生前的状态继续执行。`硬件复位是一种特殊的异常,在于不用从异常处理例程返回,不需要保护现场,不用保存返回地址,此处的处理方法简单粗暴:全部寄存器清零,从地址0x0处取指执行,即复位。所以此处置详细论述其他5种异常的处理过程。
精确异常
当一个异常发生时,系统的顺序执行会被中断,此时,若干条指令处于流水线上的不同阶段,处理器会转到异常处理例程,异常处理结束后返回原程序继续执行。当异常发生时,因为不希望异常处理例程破坏原程序的正常执行,对于没有执行完的指令,必须记住它处于流水线的哪个阶段,以便异常处理结束后能恢复执行,这就是精确异常 当异常发生时,被异常打断的指令称为异常受害者 ,该指令前面的所有指令都要被执行到流水线的最后一个阶段,即正常完成。但是该指令及该指令之后的指令都要被取消。
for example
e.g.1
第二条指令add执行阶段发生溢出异常,在这种情况下,指令1ori指令会顺利完成,指令2,3,4都会被取消。为了实现精确异常,必须要求异常发生的顺序与指令的顺序相同。流水线处理器上,异常会在流水线的不同阶段发生,带来问题。
e.g.2
加载指令lw会在流水线的访存阶段发生地址未对齐的异常 ,该异常会在第四 个时钟周期发生,后一条指令di是无效指令mips32架构并没有这条指令,所以是无效的 ,在流水线阶段引发无效指令异常,也就是第三 个周期,此时上一条加载指令lw还处于执行阶段,没有进入访存阶段,所以先发生的异常是无效指令异常。 从而不满足异常发生的顺序与指令的顺序相同 这一要求。
为了避免 上述情况,先发生的异常并不立即处理 ,异常事件只是被标记,并继续运行流水线 ,大多数处理器中,会设计一个特殊的流水线阶段 ,专门用于处理异常 ,如果某一条指令的异常事件达到流水线的这个阶段 ,就会被进行异常处理 ,并且当前处于流水线其余阶段的指令的异常事件都会被忽略 。
以上图为例,假设处理器会在访存阶段处理异常情况 ,那么di指令虽然在第三个周期发生异常 ,但并不处理 ,只是一个保存一个异常标记 ,等到了第五个时钟周期该指令进入访存阶段时再处理 。但是在第四个时钟周期 ,上一条指令lw进入访存阶段 ,并发生地址未对齐异常 ,因为已经处于访存阶段 ,所以会处理该异常 ,包括无效指令异常在内的流水线其余阶段的异常都被忽略 。
通过上述方法,实现在流水线处理器中实现按指令执行的顺序处理异常,而不是按异常发生的顺序处理异常处理 。
异常处理过程
EXL为1,表示当前已经处于异常处理过程,如果当前发生的异常类型是中断,那么不处理,忽略,因为异常处理过程中会禁止中断。如果当前发生的异常类型不是中断,那么将异常原因保存到CP0中的Cause寄存器的ExCode字段 如果EXL为0 ,那么将异常原因保存到CP0中的Cause寄存器的ExCode字段 ,进入步骤二
检查发生异常的指令是否在延迟槽中 ,如果在延迟槽中,那么设置EPC寄存器的值为该指令的地址减4,同时设置Cause寄存器的BD字段为1 ,反之,设置EPC寄存器的值就位该指令的地址,同时设置Cause寄存器的BD字段为0 。
设置Status寄存器EXL字段为1 ,表示进入异常处理过程 ,禁止中断
处理器转移到事先定义好的一个地址 ,在那个地址中往往有异常处理例程 ,在其中进行异常处理,这个地址称为异常处理例程入口地址 OpenMIPS定义的异常处理例程入口地址表如下。此处对系统调用、无效指令、溢出、自陷这四类异常都设置为相同的处理例程入口地址,也可以设置为不同的地址。
在异常处理例程中会进行具体的异常处理,处理结束后,需要返回到异常发生前的状态继续执行。异常返回指令eret来完成此项工作,eret指令既要清除Status寄存器的EXL字段,从而使能中断,还要将EPC寄存器保存的地址恢复到PC中,从而返回到异常发生处继续执行
引延迟槽后,处理器执行转移指令的顺序: 转移指令->延迟槽指令->转移目标指令地址
流程图(我懒得画)
异常相关指令介绍
自陷指令
按照指令中是否包含立即数,分为2类
不包含立即数的自陷指令
31-26 | 25-21 | 20-16 | 15-6 | 5-0 | useage | function |
---|
SPECIAL(000000) | rs | rt | code | TEQ(110100) | teq rs,rt | if GPR[rs]=GPR[rt] then trap将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值比较,如果两者相等,发生自陷异常 | SPECIAL(000000) | rs | rt | code | TGE(110000) | tge rs,rt | if GPR[rs] >= GPR[rt] then trap将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数比较,如果前者大于后者,那么引发自陷异常 | SPECIAL(000000) | rs | rt | code | TGEU(110001) | tgeu rs,rt | if GPR[rs] >= GPR[rt] then trap将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为无 符号数比较,如果前者大于后者,那么引发自陷异常 | SPECIAL(000000) | rs | rt | code | TLT(110010) | tlt rs,rt | if GPR[rs] < GPR[rt] then trap将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数比较,如果前者小 于后者,那么引发自陷异常 | SPECIAL(000000) | rs | rt | code | TLTU(110011) | tltu rs,rt | if GPR[rs] >= GPR[rt] then trap将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作无· 符号数比较,如果前者小 于后者,那么引发自陷异常 | SPECIAL(000000) | rs | rt | code | TNE(110110) | tne rs,rt | if GPR[rs] != GPR[rt] then trap将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值比较,如果两者不相等,那么引发自陷异常 |
包含立即数的自陷指令
31-26 | 25-21 | 20-16 | 15-0 | useage | function |
---|
REGIMM(000001) | rs | TEQI(01100) | immediate | teqi rs ,immediate | if GPR[rs]=sign_extended(immediate) then trap 将地址为rs 的通用寄存器的值与指令中16位立即数符号扩展至32位 后的值比较,如果两者相等,那引发自陷异常 | REGIMM(000001) | rs | TGEI(01000) | immediate | tgei rs ,immediate | if GPR[rs]=sign>=extended(immediate) then trap 将地址为rs 的通用寄存器的值与指令中16位立即数符号扩展至32位 后的值比较,如果前者大于等于后者,那么引发自陷异常 | REGIMM(000001) | rs | TGEIU(01001) | immediate | tgeiu rs ,immediate | if GPR[rs]>=sign_extended(immediate) then trap 将地址为rs 的通用寄存器的值与指令中16位立即数符号扩展至32位后的值作为无符号数进行比较 ,如果前者大于等于后者,那么引发自陷异常 | REGIMM(000001) | rs | TLTI(01010) | immediate | tlti rs ,immediate | if GPR[rs]<sign_extended(immediate) then trap 将地址为rs 的通用寄存器的值与指令中16位立即数符号扩展至32位后的值作为有符号数进行比较 ,如果前者小于后者,那么引发自陷异常、REGIMM(000001) | REGIMM(000001) | rs | TNEI(01110) | immediate | tnei rs ,immediate | if GPR[rs]!=sign_extended(immediate) then trap 将地址为rs 的通用寄存器的值与指令中16位立即数符号扩展至32位后的值进行比较 ,如果两者不相等,那么引发自陷异常 |
异常返回指令eret
31-26 | 25 | 24-6 | 5-0 | useage | function |
---|
COP0(010000) | CO(1) | 0000 0000 0000 0000 000 | ERET(011000) | eret | 从异常处理例程返回,执行该指令(1)是EPC寄存器的值称为新的取指地址(2)设置Status寄存器的EXL字段为0,表示不再处于异常级 |
系统调用指令syscall
31-26 | 25-6 | 5-0 | useage | function |
---|
SPECIAL(000000) | code | SYSCALL(001100) | syscall | 引发系统调用异常。用户模式下的程序为了执行一些在内核模式下才能进行的操作,可以调用syscall指令,引发系统调用异常,进入异常处理例程,从而进入内核模式 |
实现思路
在流水线各个阶段手机异常信息,并传递到流水线访存阶段,在访存阶段同一处理异常信息。流水线各个阶段需要收集的异常信息:
译码
判断是否系统调用异常、是否返回指令、无效指令
执行
判断是否有自陷异常、溢出异常
访存
检查是否有中断发生。访存阶段,处理器结合CP0中相关寄存器的值,判断异常是否需要处理,如果需要处理,那么转移到该异常对应的处理例程入口地址,清除流水线上除回写阶段外的全部信息,同时修改协处理器CP0中相关寄存器的值 。eret指令,转移到EPC寄存器保存的地址处,同时清除流水线上除回写阶段外的全部信息,修改协处理器CP0中相关寄存器的值。所谓清除流水线上某个阶段的信息,其实就是将该阶段中所有寄存器设置为初始值即可
数据流图的修改
确定自陷指令、syscall质量、eret指令的过程
id
系统结构的修改
id
id模块判断是否调用指令syscall,异常返回指令eret,无效指令,将这些信息通过excepttype_o 接口传递到ex模块,同时将指令地址通过current_inst_addr_o 接口传递到执行阶段。
ex
ex模块进一步判断是否有自陷异常,或溢出异常。这些信息会融合到id模块的异常信息中,excepttype_i 传入,通过excepttype_o 传递到mem模块。同时current_inst_addr_o 接口将指令地址传递到mem模块,通过is_delayslot_o 指出指令是否位于延迟槽中,该信息也会传入mem模块。
mem
mem模块依据传递来的异常类型excepttype_i ,Cause寄存器的值cp0_cause_i ,Status寄存器的值cp0_status_i ,综合判断是否需要处理异常,如果需要处理,最终的异常类型会跳过excepttype_o 接口送入到CTRL 模块,CTRL模块据此给出异常处理的入口地址new_pc 传递到PC。
cp0_reg
处理异常时,需要修改CP0中的EPC,Status,Cause等寄存器的值,所以mem模块给出的最终的异常类型还要通过excepttype_o 接口送入CP0模块,同时送入的异常指令是否在延迟槽中is_in_delayslot_i 接口送入,发生异常指令的地址current_inst_address_o 接口送入。CP0模块根据这些信息修改相应寄存器的值。
CTRL
如果要处理异常,需要清除流水线上除回写阶段 外寄存器的值,CTRL模块通过送出flush 实现。flush 模块送到PC,IF/ID,ID/EX,EX/MEM,MEM/WB 等模块,将这些模块中的寄存器置为初始值。
LLbit
ll执行时设置LLbit为1,sc执行时,检测该寄存器是否为1,如果为1就正常运行,如果为0,说明出现了干扰,不进行存储操作。出现干扰的原因之一就是ll,sc指令之间产生了异常,所以在异常处理过程中会多进行一步操作,将LLbit寄存器设置为0 。
代码
因为这是自己动手写cpu基础版的最后一章了,所以把完整的代码放上来。
pc_reg.v
`include "define.v"
module pc_reg(
input wire clk,
input wire rst,
input wire[5:0] stall,
input wire flush,
input wire[`RegBus] new_pc,
input wire branch_flag_i,
input wire[`RegBus] branch_target_address_i,
output reg[`InstAddrBus] pc,
output reg ce
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
ce <= `ChipDisable;
end else begin
ce <= `ChipEnable;
end
end
always @ (posedge clk)begin
if(ce == `ChipDisable)begin
pc <= 32'h00000000;
end else begin
if(flush == 1'b1)begin
pc <= new_pc;
end else if(stall[0] == `NoStop)begin
end
end
end
end
endmodule
inst_rom.v
`include "define.v"
module inst_rom(
input wire ce,
input wire[`InstAddrBus] addr,
output reg[`InstBus] inst
);
reg[`InstBus] inst_mem[0:`InstMemNum-1];
initial $readmemh ("D:/test_2/inst_rom_11_3.data",inst_mem);
always @ (*)
begin
if(ce == `ChipDisable)
begin
inst <= `ZeroWord;
end
else begin
inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
end
end
endmodule
if_id.v
`include "define.v"
module if_id(
input wire clk,
input wire rst,
input wire[`InstAddrBus] if_pc,
input wire[`InstBus] if_inst,
input wire[5:0] stall,
input wire flush,
output reg[`InstAddrBus] id_pc,
output reg[`InstBus] id_inst
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
id_pc <= `ZeroWord;
id_inst <= `ZeroWord;
end else if(flush== 1'b1)begin
id_pc <= `ZeroWord;
id_inst <= `ZeroWord;
end else if(stall[1] == `Stop && stall[2] == `NoStop)begin
id_pc <= `ZeroWord;
id_inst <= `ZeroWord;
end else if(stall[1] == `NoStop)begin
id_pc <= if_pc;
id_inst <= if_inst;
end
end
endmodule
ctrl.v
`include "define.v"
module ctrl(
input wire rst,
input wire stallreq_from_id,
input wire stallreq_from_ex,
input wire[31:0] excepttype_i,
input wire[`RegBus] cp0_epc_i,
output reg[5:0] stall,
output reg[`RegBus] new_pc,
output reg flush
);
always @ (*) begin
if(rst == `RstEnable) begin
stall <= 6'b000000;
flush <= 1'b0;
new_pc <= `ZeroWord;
end else if(excepttype_i != `ZeroWord) begin
flush <= 1'b1;
stall <= 6'b000000;
case (excepttype_i)
32'h00000001: begin
new_pc <= 32'h00000020;
end
32'h00000008: begin
new_pc <= 32'h00000040;
end
32'h0000000a: begin
new_pc <= 32'h00000040;
end
32'h0000000d: begin
new_pc <= 32'h00000040;
end
32'h0000000c: begin
new_pc <= 32'h00000040;
end
32'h0000000e: begin
new_pc <= cp0_epc_i;
end
default : begin
end
endcase
end else if(stallreq_from_ex == `Stop) begin
stall <= 6'b001111;
flush <= 1'b0;
end else if(stallreq_from_id == `Stop) begin
stall <= 6'b000111;
flush <= 1'b0;
end else begin
stall <= 6'b000000;
flush <= 1'b0;
new_pc <= `ZeroWord;
end
end
endmodule
data_ram.v
`include "define.v"
module data_ram(
input wire clk,
input wire ce,
input wire we,
input wire[`DataAddrBus] addr,
input wire[3:0] sel,
input wire[`DataBus] data_i,
output reg[`DataBus] data_o
);
reg[`ByteWidth] data_mem0[0:`DataMemNum-1];
reg[`ByteWidth] data_mem1[0:`DataMemNum-1];
reg[`ByteWidth] data_mem2[0:`DataMemNum-1];
reg[`ByteWidth] data_mem3[0:`DataMemNum-1];
always @ (posedge clk)begin
if(ce == `ChipDisable) begin
end else if(we == `WriteEnable)begin
if(sel[3] == 1'b1)begin
data_mem3[addr[`DataMemNumLog2+1:2]] <= data_i[31:24];
end
if(sel[2] == 1'b1)begin
data_mem2[addr[`DataMemNumLog2+1:2]] <= data_i[23:16];
end
if(sel[1] == 1'b1)begin
data_mem1[addr[`DataMemNumLog2+1:2]] <= data_i[15:8];
end
if(sel[0 == 1'b1])begin
data_mem0[addr[`DataMemNumLog2+1:2]] <= data_i[7:0];
end
end
end
always @ (*) begin
if(ce == `ChipDisable)begin
data_o <= `ZeroWord;
end else if(we == `WriteDisable)begin
data_o <= {data_mem3[addr[`DataMemNumLog2+1:2]],data_mem2[addr[`DataMemNumLog2+1:2]],data_mem1[addr[`DataMemNumLog2+1:2]],data_mem0[addr[`DataMemNumLog2+1:2]]};
end else begin
data_o <= `ZeroWord;
end
end
endmodule
define.v
`define RstEnable 1'b1
`define RstDisable 1'b0
`define ZeroWord 32'h00000000
`define WriteEnable 1'b1
`define WriteDisable 1'b0
`define ReadEnable 1'b1
`define ReadDisable 1'b0
`define AluOpBus 7:0
`define AluSelBus 2:0
`define InstValid 1'b0
`define InstInvalid 1'b1
`define Stop 1'b1
`define NoStop 1'b0
`define InDelaySlot 1'b1
`define NotInDelaySlot 1'b0
`define Branch 1'b1
`define NotBranch 1'b0
`define InterruputAssert 1'b1
`define InterruputNotAssert 1'b0
`define TrapAssert 1'b1
`define TrapNotAssert 1'b0
`define True_v 1'b1
`define False_v 1'b0
`define ChipEnable 1'b1
`define ChipDisable 1'b0
`define EXE_AND 6'b100100
`define EXE_OR 6'b100101
`define EXE_XOR 6'b100110
`define EXE_NOR 6'b100111
`define EXE_ANDI 6'b001100
`define EXE_ORI 6'b001101
`define EXE_XORI 6'b001110
`define EXE_LUI 6'b001111
`define EXE_SLL 6'b000000
`define EXE_SLLV 6'b000100
`define EXE_SRL 6'b000010
`define EXE_SRLV 6'b000110
`define EXE_SRA 6'b000011
`define EXE_SRAV 6'b000111
`define EXE_SYNC 6'b001111
`define EXE_PREF 6'b110011
`define EXE_MOVZ 6'b001010
`define EXE_MOVN 6'b001011
`define EXE_MFHI 6'b010000
`define EXE_MTHI 6'b010001
`define EXE_MFLO 6'b010010
`define EXE_MTLO 6'b010011
`define EXE_SLT 6'b101010
`define EXE_SLTU 6'b101011
`define EXE_SLTI 6'b001010
`define EXE_SLTIU 6'b001011
`define EXE_ADD 6'b100000
`define EXE_ADDU 6'b100001
`define EXE_SUB 6'b100010
`define EXE_SUBU 6'b100011
`define EXE_ADDI 6'b001000
`define EXE_ADDIU 6'b001001
`define EXE_CLZ 6'b100000
`define EXE_CLO 6'b100001
`define EXE_MULT 6'b011000
`define EXE_MULTU 6'b011001
`define EXE_MUL 6'b000010
`define EXE_MADD 6'b000000
`define EXE_MADDU 6'b000001
`define EXE_MSUB 6'b000100
`define EXE_MSUBU 6'b000101
`define EXE_DIV 6'b011010
`define EXE_DIVU 6'b011011
`define EXE_J 6'b000010
`define EXE_JAL 6'b000011
`define EXE_JALR 6'b001001
`define EXE_JR 6'b001000
`define EXE_BEQ 6'b000100
`define EXE_BGEZ 5'b00001
`define EXE_BGEZAL 5'b10001
`define EXE_BGTZ 6'b000111
`define EXE_BLEZ 6'b000110
`define EXE_BLTZ 5'b00000
`define EXE_BLTZAL 5'b10000
`define EXE_BNE 6'b000101
`define EXE_LB 6'b100000
`define EXE_LBU 6'b100100
`define EXE_LH 6'b100001
`define EXE_LHU 6'b100101
`define EXE_LL 6'b110000
`define EXE_LW 6'b100011
`define EXE_LWL 6'b100010
`define EXE_LWR 6'b100110
`define EXE_SB 6'b101000
`define EXE_SC 6'b111000
`define EXE_SH 6'b101001
`define EXE_SW 6'b101011
`define EXE_SWL 6'b101010
`define EXE_SWR 6'b101110
`define EXE_SYSCALL 6'b001100
`define EXE_TEQ 6'b110100
`define EXE_TEQI 5'b01100
`define EXE_TGE 6'b110000
`define EXE_TGEI 5'b01000
`define EXE_TGEIU 5'b01001
`define EXE_TGEU 6'b110001
`define EXE_TLT 6'b110010
`define EXE_TLTI 5'b01010
`define EXE_TLTIU 5'b01011
`define EXE_TLTU 6'b110011
`define EXE_TNE 6'b110110
`define EXE_TNEI 5'b01110
`define EXE_ERET 32'b01000010000000000000000000011000
`define EXE_NOP 6'b000000
`define SSNOP 32'b00000000000000000000000001000000
`define EXE_SPECIAL_INST 6'b000000
`define EXE_REGIMM_INST 6'b000001
`define EXE_SPECIAL2_INST 6'b011100
`define EXE_AND_OP 8'b00100100
`define EXE_OR_OP 8'b00100101
`define EXE_XOR_OP 8'b00100110
`define EXE_NOR_OP 8'b00100111
`define EXE_ANDI_OP 8'b01011001
`define EXE_ORI_OP 8'b01011010
`define EXE_XORI_OP 8'b01011011
`define EXE_LUI_OP 8'b01011100
`define EXE_SLL_OP 8'b01111100
`define EXE_SLLV_OP 8'b00000100
`define EXE_SRL_OP 8'b00000010
`define EXE_SRLV_OP 8'b00000110
`define EXE_SRA_OP 8'b00000011
`define EXE_SRAV_OP 8'b00000111
`define EXE_MOVZ_OP 8'b00001010
`define EXE_MOVN_OP 8'b00001011
`define EXE_MFHI_OP 8'b00010000
`define EXE_MTHI_OP 8'b00010001
`define EXE_MFLO_OP 8'b00010010
`define EXE_MTLO_OP 8'b00010011
`define EXE_SLT_OP 8'b00101010
`define EXE_SLTU_OP 8'b00101011
`define EXE_SLTI_OP 8'b01010111
`define EXE_SLTIU_OP 8'b01011000
`define EXE_ADD_OP 8'b00100000
`define EXE_ADDU_OP 8'b00100001
`define EXE_SUB_OP 8'b00100010
`define EXE_SUBU_OP 8'b00100011
`define EXE_ADDI_OP 8'b01010101
`define EXE_ADDIU_OP 8'b01010110
`define EXE_CLZ_OP 8'b10110000
`define EXE_CLO_OP 8'b10110001
`define EXE_MULT_OP 8'b00011000
`define EXE_MULTU_OP 8'b00011001
`define EXE_MUL_OP 8'b10101001
`define EXE_MADD_OP 8'b10100110
`define EXE_MADDU_OP 8'b10101000
`define EXE_MSUB_OP 8'b10101010
`define EXE_MSUBU_OP 8'b10101011
`define EXE_DIV_OP 8'b00011010
`define EXE_DIVU_OP 8'b00011011
`define EXE_J_OP 8'b01001111
`define EXE_JAL_OP 8'b01010000
`define EXE_JALR_OP 8'b00001001
`define EXE_JR_OP 8'b00001000
`define EXE_BEQ_OP 8'b01010001
`define EXE_BGEZ_OP 8'b01000001
`define EXE_BGEZAL_OP 8'b01001011
`define EXE_BGTZ_OP 8'b01010100
`define EXE_BLEZ_OP 8'b01010011
`define EXE_BLTZ_OP 8'b01000000
`define EXE_BLTZAL_OP 8'b01001010
`define EXE_BNE_OP 8'b01010010
`define EXE_LB_OP 8'b11100000
`define EXE_LBU_OP 8'b11100100
`define EXE_LH_OP 8'b11100001
`define EXE_LHU_OP 8'b11100101
`define EXE_LL_OP 8'b11110000
`define EXE_LW_OP 8'b11100011
`define EXE_LWL_OP 8'b11100010
`define EXE_LWR_OP 8'b11100110
`define EXE_PREF_OP 8'b11110011
`define EXE_SB_OP 8'b11101000
`define EXE_SC_OP 8'b11111000
`define EXE_SH_OP 8'b11101001
`define EXE_SW_OP 8'b11101011
`define EXE_SWL_OP 8'b11101010
`define EXE_SWR_OP 8'b11101110
`define EXE_SYNC_OP 8'b00001111
`define EXE_MFC0_OP 8'b01011101
`define EXE_MTC0_OP 8'b01100000
`define EXE_SYSCALL_OP 8'b00001100
`define EXE_TEQ_OP 8'b00110100
`define EXE_TEQI_OP 8'b01001000
`define EXE_TGE_OP 8'b00110000
`define EXE_TGEI_OP 8'b01000100
`define EXE_TGEIU_OP 8'b01000101
`define EXE_TGEU_OP 8'b00110001
`define EXE_TLT_OP 8'b00110010
`define EXE_TLTI_OP 8'b01000110
`define EXE_TLTIU_OP 8'b01000111
`define EXE_TLTU_OP 8'b00110011
`define EXE_TNE_OP 8'b00110110
`define EXE_TNEI_OP 8'b01001001
`define EXE_ERET_OP 8'b01101011
`define EXE_NOP_OP 8'b00000000
`define EXE_RES_LOGIC 3'b001
`define EXE_RES_SHIFT 3'b010
`define EXE_RES_MOVE 3'b011
`define EXE_RES_ARITHMETIC 3'b100
`define EXE_RES_MUL 3'b101
`define EXE_RES_JUMP_BRANCH 3'b110
`define EXE_RES_LOAD_STORE 3'b111
`define EXE_RES_NOP 3'b000
`define InstAddrBus 31:0
`define InstBus 31:0
`define InstMemNum 131071
`define InstMemNumLog2 17
`define DataAddrBus 31:0
`define DataBus 31:0
`define DataMemNum 131071
`define DataMemNumLog2 17
`define ByteWidth 7:0
`define RegAddrBus 4:0
`define RegBus 31:0
`define RegWidth 32
`define DoubleRegWidth 64
`define DoubleRegBus 63:0
`define RegNum 32
`define RegNumLog2 5
`define NOPRegAddr 5'b00000
`define DivFree 2'b00
`define DivByZero 2'b01
`define DivOn 2'b10
`define DivEnd 2'b11
`define DivResultReady 1'b1
`define DivResultNotReady 1'b0
`define DivStart 1'b1
`define DivStop 1'b0
`define CP0_REG_COUNT 5'b01001
`define CP0_REG_COMPARE 5'b01011
`define CP0_REG_STATUS 5'b01100
`define CP0_REG_CAUSE 5'b01101
`define CP0_REG_EPC 5'b01110
`define CP0_REG_PrId 5'b01111
`define CP0_REG_CONFIG 5'b10000
div.v
`include "define.v"
module div(
input wire clk,
input wire rst,
input wire signed_div_i,
input wire[31:0] opdata1_i,
input wire[31:0] opdata2_i,
input wire start_i,
input wire annul_i,
output reg[63:0] result_o,
output reg ready_o
);
wire[32:0] div_temp;
reg[5:0] cnt;
reg[64:0] dividend;
reg[1:0] state;
reg[31:0] divisor;
reg[31:0] temp_op1;
reg[31:0] temp_op2;
assign div_temp = {1'b0,dividend[63:32]} - {1'b0,divisor};
always @ (posedge clk) begin
if (rst == `RstEnable) begin
state <= `DivFree;
ready_o <= `DivResultNotReady;
result_o <= {`ZeroWord,`ZeroWord};
end else begin
case (state)
`DivFree: begin
if(start_i == `DivStart && annul_i == 1'b0) begin
if(opdata2_i == `ZeroWord) begin
state <= `DivByZero;
end else begin
state <= `DivOn;
cnt <= 6'b000000;
if(signed_div_i == 1'b1 && opdata1_i[31] == 1'b1 ) begin
temp_op1 = ~opdata1_i + 1;
end else begin
temp_op1 = opdata1_i;
end
if(signed_div_i == 1'b1 && opdata2_i[31] == 1'b1 ) begin
temp_op2 = ~opdata2_i + 1;
end else begin
temp_op2 = opdata2_i;
end
dividend <= {`ZeroWord,`ZeroWord};
dividend[32:1] <= temp_op1;
divisor <= temp_op2;
end
end else begin
ready_o <= `DivResultNotReady;
result_o <= {`ZeroWord,`ZeroWord};
end
end
`DivByZero: begin
dividend <= {`ZeroWord,`ZeroWord};
state <= `DivEnd;
end
`DivOn: begin
if(annul_i == 1'b0) begin
if(cnt != 6'b100000) begin
if(div_temp[32] == 1'b1) begin
dividend <= {dividend[63:0] , 1'b0};
end else begin
dividend <= {div_temp[31:0] , dividend[31:0] , 1'b1};
end
cnt <= cnt + 1;
end else begin
if((signed_div_i == 1'b1) && ((opdata1_i[31] ^ opdata2_i[31]) == 1'b1)) begin
dividend[31:0] <= (~dividend[31:0] + 1);
end
if((signed_div_i == 1'b1) && ((opdata1_i[31] ^ dividend[64]) == 1'b1)) begin
dividend[64:33] <= (~dividend[64:33] + 1);
end
state <= `DivEnd;
cnt <= 6'b000000;
end
end else begin
state <= `DivFree;
end
end
`DivEnd: begin
result_o <= {dividend[64:33], dividend[31:0]};
ready_o <= `DivResultReady;
if(start_i == `DivStop) begin
state <= `DivFree;
ready_o <= `DivResultNotReady;
result_o <= {`ZeroWord,`ZeroWord};
end
end
endcase
end
end
endmodule
id.v
`include "define.v"
module id(
input wire rst,
input wire[`InstAddrBus] pc_i,
input wire[`InstBus] inst_i,
input wire[`RegBus] reg1_data_i,
input wire[`RegBus] reg2_data_i,
input wire is_in_delayslot_i,
output reg reg1_read_o,
output reg reg2_read_o,
output reg[`RegAddrBus] reg1_addr_o,
output reg[`RegAddrBus] reg2_addr_o,
output reg[`AluOpBus] aluop_o,
output reg[`AluSelBus] alusel_o,
output reg[`RegBus] reg1_o,
output reg[`RegBus] reg2_o,
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
input wire ex_wreg_i,
input wire[`RegBus] ex_wdata_i,
input wire[`RegAddrBus] ex_wd_i,
input wire[`AluOpBus] ex_aluop_i,
input wire mem_wreg_i,
input wire[`RegBus] mem_wdata_i,
input wire[`RegAddrBus] mem_wd_i,
output wire stallreq,
output reg next_inst_in_delayslot_o,
output reg branch_flag_o,
output reg[`RegBus] branch_target_address_o,
output reg[`RegBus] link_addr_o,
output reg is_in_delayslot_o,
output wire[`RegBus] inst_o ,
output wire[31:0] excepttype_o,
output wire[`RegBus] current_inst_address_o
);
wire[5:0] op = inst_i[31:26];
wire[4:0] op2 = inst_i[10:6];
wire[5:0] op3 = inst_i[5:0];
wire[4:0] op4 = inst_i[20:16];
wire[`RegBus] pc_plus_8;
wire[`RegBus] pc_plus_4;
wire[`RegBus] imm_sll2_signedext;
reg[`RegBus] imm;
reg instvalid;
reg excepttype_is_syscall;
reg excepttype_is_eret;
assign excepttype_o = {19'b0,excepttype_is_eret,2'b0,instvalid,excepttype_is_syscall,8'b0};
assign current_inst_address_o = pc_i;
assign stallreq = `NoStop;
assign imm_sll2_signedext = {{14{inst_i[15]}},inst_i[15:0],2'b00};
assign pc_plus_8 = pc_i+8;
assign pc_plus_4 = pc_i+4;
assign stallreq = `NoStop;
assign inst_o = inst_i;
reg stallreq_for_reg1_loadrelate;
reg stallreq_for_reg2_loadrelate;
wire pre_inst_is_load;
assign pre_inst_is_load = ((ex_aluop_i == `EXE_LB_OP)||
(ex_aluop_i == `EXE_LBU_OP)||
(ex_aluop_i == `EXE_LH_OP)||
(ex_aluop_i==`EXE_LHU)||
(ex_aluop_i==`EXE_LW_OP)||
(ex_aluop_i==`EXE_LWR_OP)||
(ex_aluop_i==`EXE_LWL_OP)||
(ex_aluop_i==`EXE_LL_OP)||
(ex_aluop_i==`EXE_SC_OP)) ? 1'b1 : 1'b0;
always @(*)begin
stallreq_for_reg1_loadrelate <= `NoStop;
if(rst == `RstEnable)begin
reg1_o <= `ZeroWord;
end else if(pre_inst_is_load == 1'b1 && ex_wd_i == reg1_addr_o && reg1_read_o == 1'b1)begin
stallreq_for_reg1_loadrelate <= `Stop;
end
end
always @(*)begin
stallreq_for_reg2_loadrelate <= `NoStop;
if(rst == `RstEnable)begin
reg2_o <= `ZeroWord;
end else if(pre_inst_is_load == 1'b1 && ex_wd_i == reg2_addr_o && reg2_read_o == 1'b1)begin
stallreq_for_reg2_loadrelate <= `Stop;
end
end
assign stallreq = stallreq_for_reg1_loadrelate | stallreq_for_reg2_loadrelate;
always @ (*) begin
if (rst == `RstEnable) begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
instvalid <= `InstValid;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= `NOPRegAddr;
reg2_addr_o <= `NOPRegAddr;
imm <= 32'h0;
link_addr_o <= `ZeroWord;
branch_target_address_o <= `ZeroWord;
branch_flag_o <= `NotBranch;
next_inst_in_delayslot_o <= `NotInDelaySlot;
end else begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= inst_i[15:11];
wreg_o <= `WriteDisable;
instvalid <= `InstInvalid;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= inst_i[25:21];
reg2_addr_o <= inst_i[20:16];
imm <= `ZeroWord;
link_addr_o <= `ZeroWord;
branch_target_address_o <= `ZeroWord;
branch_flag_o <= `NotBranch;
next_inst_in_delayslot_o <= `NotInDelaySlot;
excepttype_is_syscall <= `False_v;
excepttype_is_eret <= `False_v;
instvalid <= `InstInvalid;
case (op)
`EXE_SPECIAL_INST: begin
case(op2)
5'b00000: begin
case(op3)
`EXE_OR: begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_OR_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_AND:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_AND_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_XOR:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_XOR_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_NOR:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_NOR_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SLLV:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLL_OP;
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SRLV:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRLV_OP;
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SRAV:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRAV_OP;
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SYNC:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MFHI:begin
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 <= `WriteEnable;
aluop_o <= `EXE_MTHI_OP;
alusel_o <= `EXE_RES_MOVE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MTLO:begin
wreg_o <= `WriteEnable;
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
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
`EXE_SLT:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLT_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SLTU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLTU_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_ADD:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_ADD_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_ADDU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_ADDU_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SUB:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SUB_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SUBU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SUBU_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MULT:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_MULT_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MULTU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_MULTU_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_DIV:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_DIV_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_DIVU:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_DIVU_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_JR:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_JR_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[15:11];
link_addr_o <= pc_plus_8;
branch_target_address_o <= reg1_o;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
instvalid <= `InstValid;
end
`EXE_JALR:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_JALR_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[15:11];
link_addr_o <= pc_plus_8;
branch_target_address_o <= reg1_o;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
instvalid <= `InstValid;
end
`EXE_TEQ:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_SYSCALL_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_TGE:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TGE_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_TGEU:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TGEU_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_TLT:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TLT_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_TLTU:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TLTU_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_TNE:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TNE_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SYSCALL:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_SYSCALL_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
excepttype_is_syscall <= `True_v;
end
default:begin
end
endcase
end
default:begin
end
endcase
end
`EXE_J:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_J_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
link_addr_o <= `ZeroWord;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
instvalid <= `InstValid;
branch_target_address_o <= {pc_plus_4[31:28],inst_i[25:0],2'b00};
end
`EXE_JAL:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_JAL_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
wd_o <= 5'b11111;
link_addr_o <= pc_plus_8;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
instvalid <= `InstValid;
branch_target_address_o <= {pc_plus_4[31:28],inst_i[25:0],2'b00};
end
`EXE_BEQ:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BEQ_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
if(reg1_o == reg2_o)begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_BGTZ:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BGTZ_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
if((reg1_o[31] == 1'b0)&&(reg1_o != `ZeroWord))begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_BLEZ:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BLEZ_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
if((reg1_o[31] == 1'b1)&&(reg1_o != `ZeroWord))begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_BNE:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BNE_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
if(reg1_o != reg2_o)begin
branch_target_address_o <= pc_plus_4+imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_REGIMM_INST:begin
case(op4)
`EXE_BLTZAL:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_BGEZAL_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
link_addr_o <= pc_plus_8;
wd_o <= 5'b11111;
instvalid <= `InstValid;
if(reg1_o[31] == 1'b1) begin
branch_target_address_o <= pc_plus_4+imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_BLTZ:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BGEZAL_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
if(reg1_o[31] == 1'b1)begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_BGEZ:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BGEZ_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
if(reg1_o[31] == 1'b0)begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_BGEZAL:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_BGEZAL_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
link_addr_o <= pc_plus_8;
wd_o <= 5'b11111;
instvalid <= `InstValid;
if(reg1_o[31] == 1'b0)begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
next_inst_in_delayslot_o <= `InDelaySlot;
end
end
`EXE_TEQI:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TEQI_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
instvalid <= `InstValid;
end
`EXE_TGEI:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TGEI_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
instvalid <= `InstValid;
end
`EXE_TGEIU:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TGEIU_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
instvalid <= `InstValid;
end
`EXE_TLTI:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TLTI_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
instvalid <= `InstValid;
end
`EXE_TLTIU:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TLTIU_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
instvalid <= `InstValid;
end
`EXE_TNEI:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_TNEI_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
instvalid <= `InstValid;
end
default:begin
end
endcase
end
`EXE_ORI:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_OR_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {16'h0, inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_ANDI:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_AND_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {16'h0,inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid = `InstValid;
end
`EXE_XORI:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_XOR_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {16'h0,inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid = `InstValid;
end
`EXE_LUI:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_OR_OP;
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {inst_i[15:0],16'h0};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_SLTI:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLT_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_SLTIU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLTU_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_ADDI:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_ADDI_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_ADDIU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_ADDIU_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {{16{inst_i[15]}},inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LB:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LB_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LBU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LBU_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LH:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LH_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LHU:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LHU_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LW:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LW_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LWL:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LWL_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LWR:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LWR_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_SB:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_SB_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
alusel_o <= `EXE_RES_LOAD_STORE;
end
`EXE_SH:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_SH_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
alusel_o <= `EXE_RES_LOAD_STORE;
end
`EXE_SW:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_SW_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
alusel_o <= `EXE_RES_LOAD_STORE;
end
`EXE_SWL:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_SWL_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
alusel_o <= `EXE_RES_LOAD_STORE;
end
`EXE_SWR:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_SWR_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
alusel_o <= `EXE_RES_LOAD_STORE;
end
`EXE_LL:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_LL_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_SC:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SC_OP;
alusel_o <= `EXE_RES_LOAD_STORE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_SPECIAL2_INST:begin
case(op3)
`EXE_CLZ:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_CLZ_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_CLO:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_CLO_OP;
alusel_o <= `EXE_RES_ARITHMETIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MUL:begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_MUL_OP;
alusel_o <= `EXE_RES_MUL;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MADD:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_MADD_OP;
alusel_o <= `EXE_RES_MUL;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MADDU:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_MADDU_OP;
alusel_o <= `EXE_RES_MUL;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MSUB:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_MSUB_OP;
alusel_o <= `EXE_RES_MUL;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MSUBU:begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_MSUBU_OP;
alusel_o <= `EXE_RES_MUL;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
default:begin
end
endcase
end
default:begin
end
endcase
if(inst_i == `EXE_ERET)begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_ERET_OP;
alusel_o <= `EXE_RES_NOP;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
excepttype_is_eret <= `True_v;
end
if(inst_i[31:21] == 11'b00000000000)begin
if(op3 == `EXE_SLL) begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLL_OP;
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6];
wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end else if(op3 == `EXE_SRL)begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRL_OP;
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6];
wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end else if(op3 == `EXE_SRA) begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRA_OP;
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6];
wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end
end
if(inst_i[31:21]==11'b010_0000_0000&&inst_i[10:0]==11'b000_0000_0000)
begin
aluop_o <= `EXE_MFC0_OP;
alusel_o <= `EXE_RES_MOVE;
wd_o <= inst_i[20:16];
wreg_o <= `WriteEnable;
instvalid <= `InstValid;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
end else if(inst_i[31:21]==11'b010_0000_0100&&inst_i[10:0]==11'b00000000000)
begin
aluop_o <= `EXE_MTC0_OP;
alusel_o <= `EXE_RES_MOVE;
wreg_o <= `WriteDisable;
instvalid <= `InstValid;
reg1_read_o <= 1'b1;
reg1_addr_o <= inst_i[20:16];
reg2_read_o <= 1'b0;
end
end
end
always @ (*) begin
if(rst == `RstEnable) begin
reg1_o <= `ZeroWord;
end else if((reg1_read_o == 1'b1) && (ex_wreg_i == 1'b1)
&& (ex_wd_i == reg1_addr_o)) begin
reg1_o <= ex_wdata_i;
end else if((reg1_read_o == 1'b1) && (mem_wreg_i == 1'b1)
&& (mem_wd_i == reg1_addr_o)) begin
reg1_o <= mem_wdata_i;
end else if(reg1_read_o == 1'b1) begin
reg1_o <= reg1_data_i;
end else if(reg1_read_o == 1'b0) begin
reg1_o <= imm;
end else begin
reg1_o <= `ZeroWord;
end
end
always @ (*) begin
if(rst == `RstEnable) begin
reg2_o <= `ZeroWord;
end else if((reg2_read_o == 1'b1) && (ex_wreg_i == 1'b1)
&& (ex_wd_i == reg2_addr_o)) begin
reg2_o <= ex_wdata_i;
end else if((reg2_read_o == 1'b1) && (mem_wreg_i == 1'b1)
&& (mem_wd_i == reg2_addr_o)) begin
reg2_o <= mem_wdata_i;
end else if(reg2_read_o == 1'b1) begin
reg2_o <= reg2_data_i;
end else if(reg2_read_o == 1'b0) begin
reg2_o <= imm;
end else begin
reg2_o <= `ZeroWord;
end
end
always @ (*)begin
if(rst == `RstEnable)begin
is_in_delayslot_o <= `NotInDelaySlot;
end else begin
is_in_delayslot_o <= is_in_delayslot_i;
end
end
endmodule
id_ex.v
`include "define.v"
module id_ex(
input wire clk,
input wire rst,
input wire flush,
input wire[`RegBus] id_current_inst_address,
input wire[31:0] id_excepttype,
input wire[`AluOpBus] id_aluop,
input wire[`AluSelBus] id_alusel,
input wire[`RegBus] id_reg1,
input wire[`RegBus] id_reg2,
input wire[`RegAddrBus] id_wd,
input wire id_wreg,
input wire[5:0] stall ,
input wire[`RegBus] id_link_address,
input wire id_is_in_delayslot,
input wire next_inst_in_delayslot_i,
input wire[`RegBus] id_inst,
output reg[`AluOpBus] ex_aluop,
output reg[`AluSelBus] ex_alusel,
output reg[`RegBus] ex_reg1,
output reg[`RegBus] ex_reg2,
output reg[`RegAddrBus] ex_wd,
output reg ex_wreg,
output reg[`RegBus] ex_link_address,
output reg ex_is_in_delayslot,
output reg is_in_delayslot_o,
output reg[`RegBus] ex_inst ,
output reg[`RegBus] ex_current_inst_address,
output reg[31:0] ex_excepttype
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
ex_aluop <= `EXE_NOP_OP;
ex_alusel <= `EXE_RES_NOP;
ex_reg1 <= `ZeroWord;
ex_reg2 <= `ZeroWord;
ex_wd <= `NOPRegAddr;
ex_wreg <= `WriteDisable;
ex_link_address <= `ZeroWord;
ex_is_in_delayslot <= `NotInDelaySlot;
ex_inst <= `ZeroWord;
ex_excepttype <= `ZeroWord;
ex_current_inst_address <= `ZeroWord;
end else if(flush == 1'b1) begin
ex_aluop <= `EXE_NOP_OP;
ex_alusel <= `EXE_RES_NOP;
ex_reg1 <= `ZeroWord;
ex_reg2 <= `ZeroWord;
ex_wd <= `NOPRegAddr;
ex_wreg <= `WriteDisable;
ex_excepttype <= `ZeroWord;
ex_link_address <= `ZeroWord;
ex_inst <= `ZeroWord;
ex_is_in_delayslot <= `NotInDelaySlot;
is_in_delayslot_o <= `NotInDelaySlot;
ex_current_inst_address <= `ZeroWord;
end else if(stall[2] == `Stop && stall[3] == `NoStop)begin
ex_aluop <= `EXE_NOP_OP;
ex_alusel <= `EXE_RES_NOP;
ex_reg1 <= `ZeroWord;
ex_reg2 <= `ZeroWord;
ex_wd <= `NOPRegAddr;
ex_wreg <= `WriteDisable;
ex_link_address <= `ZeroWord;
ex_is_in_delayslot <= `NotInDelaySlot;
ex_inst <= `ZeroWord;
ex_excepttype <= `ZeroWord;
ex_current_inst_address <= `ZeroWord;
end else if(stall[2] == `NoStop)begin
ex_aluop <= id_aluop;
ex_alusel <= id_alusel;
ex_reg1 <= id_reg1;
ex_reg2 <= id_reg2;
ex_wd <= id_wd;
ex_wreg <= id_wreg;
ex_link_address <= id_link_address;
ex_is_in_delayslot <= id_is_in_delayslot;
ex_inst <= id_inst;
is_in_delayslot_o <= next_inst_in_delayslot_i;
ex_excepttype <= id_excepttype;
ex_current_inst_address <= id_current_inst_address;
end
end
endmodule
ex.v
`include "define.v"
module ex(
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,
input wire rst,
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
input wire[`RegBus] wb_hi_i,
input wire[`RegBus] wb_lo_i,
input wire wb_whilo_i,
input wire[`RegBus] mem_hi_i,
input wire[`RegBus] mem_lo_i,
input wire mem_whilo_i,
input wire[`DoubleRegBus] hilo_temp_i,
input wire[1:0] cnt_i,
input wire[`DoubleRegBus] div_result_i,
input wire div_ready_i,
input wire[`RegBus] link_address_i,
input wire is_in_delayslot_i,
input wire[`RegBus] inst_i,
input wire mem_cp0_reg_we,
input wire[4:0] mem_cp0_reg_write_addr,
input wire[`RegBus] mem_cp0_reg_data,
input wire wb_cp0_reg_we,
input wire[4:0] wb_cp0_reg_write_addr,
input wire[`RegBus] wb_cp0_reg_data,
input wire[`RegBus] cp0_reg_data_i,
input wire[31:0] excepttype_i,
input wire[`RegBus] current_inst_address_i,
output reg[4:0] cp0_reg_read_addr_o,
output reg cp0_reg_we_o,
output reg[4:0] cp0_reg_write_addr_o,
output reg[`RegBus] cp0_reg_data_o,
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o,
output reg whilo_o,
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
output reg[`RegBus] wdata_o,
output reg stallreq,
output reg[`DoubleRegBus] hilo_temp_o,
output reg[1:0] cnt_o,
output reg[`RegBus] div_opdata1_o,
output reg[`RegBus] div_opdata2_o,
output reg div_start_o,
output reg signed_div_o,
output wire[`AluOpBus] aluop_o,
output wire[`RegBus] mem_addr_o,
output wire[`RegBus] reg2_o,
output wire[31:0] excepttype_o,
output wire[`RegBus] current_inst_address_o,
output wire is_in_delayslot_o
);
reg[`RegBus] logicout;
reg[`RegBus] shiftres;
reg[`RegBus] moveres;
reg[`RegBus] HI;
reg[`RegBus] LO;
reg stallreq_for_div;
wire ov_sum;
wire reg1_eq_reg2;
wire reg1_lt_reg2;
reg[`RegBus] arithmeticres;
reg[`DoubleRegBus] mulres;
wire[`RegBus] reg2_i_mux;
wire[`RegBus] reg1_i_not;
wire[`RegBus] result_sum;
wire[`RegBus] opdata1_mult;
wire[`RegBus] opdata2_mult;
wire[`DoubleRegBus] hilo_temp;
reg [`DoubleRegBus] hilo_temp1;
reg stallreq_for_madd_msub;
reg trapassert;
reg ovassert;
assign aluop_o = aluop_i;
assign mem_addr_o = reg1_i + {{16{inst_i[15]}},inst_i[15:0]};
assign reg2_o = reg2_i;
assign excepttype_o={excepttype_i[31:12],ovassert,trapassert,excepttype_i[9:8],8'h00};
assign is_in_delayslot_o = is_in_delayslot_i;
assign current_inst_address_o = current_inst_address_i;
always @ (*)
begin
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®2_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
end
always @ (*) begin
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
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
end
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
end
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_MOVN_OP:begin
moveres <= reg1_i;
end
`EXE_MOVZ_OP:begin
moveres <= reg1_i;
end
`EXE_MFC0_OP:begin
cp0_reg_read_addr_o <= inst_i[15:11];
moveres <= cp0_reg_data_i;
if(mem_cp0_reg_we == `WriteEnable && mem_cp0_reg_write_addr == inst_i[15:11])
begin
moveres <= mem_cp0_reg_data;
end else if(wb_cp0_reg_we == `WriteEnable && wb_cp0_reg_write_addr == inst_i[15:11])
begin
moveres <= wb_cp0_reg_data;
end
end
default:begin
end
endcase
end
end
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
assign reg2_i_mux = ((aluop_i == `EXE_SUB_OP)||(aluop_i == `EXE_SUBU_OP)||(aluop_i == `EXE_SLT_OP)||
(aluop_i == `EXE_TLT_OP)||(aluop_i == `EXE_TLTI_OP)||(aluop_i == `EXE_TGE_OP)||(aluop_i == `EXE_TGE_OP)||(aluop_i == `EXE_TGEI_OP))?(~reg2_i)+1:reg2_i;
assign result_sum = reg1_i + reg2_i_mux;
assign ov_sum = ((!reg1_i[31] && !reg2_i_mux[31]) && result_sum[31])||((reg1_i[31] && reg2_i_mux[31])&&(!result_sum[31]));
assign reg1_lt_reg2 = ((aluop_i == `EXE_SLT_OP)
||(aluop_i == `EXE_TLT_OP)||
(aluop_i == `EXE_TLTI_OP)||
(aluop_i == `EXE_TGE_OP)||
(aluop_i == `EXE_TGEI_OP))?((reg1_i[31]&&!reg2_i[31])||(!reg1_i[31]&&!reg2_i[31]&&result_sum[31])||(reg1_i[31]&®2_i[31]&&result_sum[31])):(reg1_i<reg2_i);
assign reg1_i_not = ~reg1_i;
always @ (*) begin
if(rst == `RstEnable)begin
arithmeticres <= `ZeroWord;
end else begin
case(aluop_i)
`EXE_SLT_OP,`EXE_SLTU_OP:begin
arithmeticres <= reg1_lt_reg2;
end
`EXE_ADD_OP,`EXE_ADDU_OP,`EXE_ADDI_OP,`EXE_ADDIU_OP:begin
arithmeticres <= result_sum;
end
`EXE_SUB_OP,`EXE_SUBU_OP:begin
arithmeticres <= result_sum;
end
`EXE_CLZ_OP:begin
arithmeticres <= reg1_i[31]?0:reg1_i[30]?1:
reg1_i[29]?2:reg1_i[28]?3:
reg1_i[27]?4:reg1_i[26]?5:
reg1_i[25]?6:reg1_i[24]?7:
reg1_i[23]?8:reg1_i[22]?9:
reg1_i[21]?10:reg1_i[20]?11:
reg1_i[19]?12:reg1_i[18]?13:
reg1_i[17]?14:reg1_i[16]?15:
reg1_i[15]?16:reg1_i[14]?17:
reg1_i[13]?18:reg1_i[12]?19:
reg1_i[11]?20:reg1_i[10]?21:
reg1_i[9]?22:reg1_i[8]?23:
reg1_i[7]?24:reg1_i[6]?25:
reg1_i[5]?26:reg1_i[4]?27:
reg1_i[3]?28:reg1_i[2]?29:
reg1_i[1]?20:reg1_i[0]?31:32;
end
`EXE_CLO_OP:begin
arithmeticres <= (reg1_i_not[31]?0:
reg1_i_not[30]?1:
reg1_i_not[29]?2:
reg1_i_not[28]?3:
reg1_i_not[27]?4:
reg1_i_not[26]?5:
reg1_i_not[25]?6:
reg1_i_not[24]?7:
reg1_i_not[23]?8:
reg1_i_not[22]?9:
reg1_i_not[21]?10:
reg1_i_not[20]?11:
reg1_i_not[19]?12:
reg1_i_not[18]?13:
reg1_i_not[17]?14:
reg1_i_not[16]?15:
reg1_i_not[15]?16:
reg1_i_not[14]?17:
reg1_i_not[13]?18:
reg1_i_not[12]?19:
reg1_i_not[11]?20:
reg1_i_not[10]?21:
reg1_i_not[9]?22:
reg1_i_not[8]?23:
reg1_i_not[7]?24:
reg1_i_not[6]?25:
reg1_i_not[5]?26:
reg1_i_not[4]?27:
reg1_i_not[3]?28:
reg1_i_not[2]?29:
reg1_i_not[1]?30:
reg1_i_not[0]?31:32);
end
default:begin
arithmeticres <= `ZeroWord;
end
endcase
end
end
assign opdata1_mult = (((aluop_i == `EXE_MUL_OP)||(aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MSUB_OP))&&(reg1_i[31] == 1'b1)) ? (~reg1_i+1):reg1_i;
assign opdata2_mult = (((aluop_i == `EXE_MUL_OP)||(aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MSUB_OP))&&(reg2_i[31] == 1'b1)) ? (~reg2_i+1):reg2_i;
assign hilo_temp = opdata1_mult * opdata2_mult;
always @ (*) begin
if(rst == `RstEnable) begin
mulres <= {`ZeroWord,`ZeroWord};
end else if((aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MUL_OP)||(aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MSUB_OP))begin
if(reg1_i[31]^reg2_i[31] == 1'b1)begin
mulres <= ~hilo_temp+1;
end else begin
mulres <= hilo_temp;
end
end else begin
mulres <= hilo_temp;
end
end
always @ (*)begin
wd_o <= wd_i;
if(((aluop_i == `EXE_ADD_OP)||(aluop_i == `EXE_ADDI_OP)||(aluop_i == `EXE_SUB_OP))&&(ov_sum == 1'b1))begin
wreg_o <= `WriteDisable;
ovassert <= 1'b1;
end else begin
wreg_o <= wreg_i;
ovassert <= 1'b0;
end
case(alusel_i)
`EXE_RES_LOGIC:begin
wdata_o <= logicout;
end
`EXE_RES_SHIFT:begin
wdata_o <= shiftres;
end
`EXE_RES_MOVE:begin
wdata_o <= moveres;
end
`EXE_RES_ARITHMETIC:begin
wdata_o <= arithmeticres;
end
`EXE_RES_MUL:begin
wdata_o <= mulres[31:0];
end
`EXE_RES_JUMP_BRANCH:begin
wdata_o <= link_address_i;
end
default:begin
wdata_o <= `ZeroWord;
end
endcase
end
always @ (*) begin
if(rst == `RstEnable) begin
hilo_temp_o <= {`ZeroWord,`ZeroWord};
cnt_o <= 2'b00;
stallreq_for_madd_msub <= `NoStop;
end else begin
case(aluop_i)
`EXE_MADD_OP,`EXE_MADDU_OP:begin
if(cnt_i == 2'b00) begin
hilo_temp_o <= mulres;
cnt_o <= 2'b01;
hilo_temp1 <= {`ZeroWord,`ZeroWord};
stallreq_for_madd_msub <= `Stop;
end else if(cnt_i == 2'b01) begin
hilo_temp_o <= {`ZeroWord,`ZeroWord};
cnt_o <= 2'b10;
hilo_temp1 <= hilo_temp_i+{HI,LO};
stallreq_for_madd_msub <= `NoStop;
end
end
`EXE_MSUB_OP,`EXE_MSUBU_OP:begin
if(cnt_i == 2'b00) begin
hilo_temp_o <= ~mulres+1;
cnt_o <= 2'b01;
stallreq_for_madd_msub <= `Stop;
end else if(cnt_i == 2'b01) begin
hilo_temp_o <= {`ZeroWord,`ZeroWord};
cnt_o <= 2'b10;
hilo_temp1 <= hilo_temp_i +{HI,LO};
stallreq_for_madd_msub <= `NoStop;
end
end
default:begin
hilo_temp_o <= {`ZeroWord,`ZeroWord};
cnt_o <= 2'b00;
stallreq_for_madd_msub <= `NoStop;
end
endcase
end
end
always @ (*) begin
if(rst == `RstEnable)begin
stallreq_for_div <= `NoStop;
div_opdata1_o <= `ZeroWord;
div_opdata2_o <= `ZeroWord;
div_start_o <= `DivStop;
signed_div_o <= 1'b0;
end else begin
stallreq_for_div <= `NoStop;
div_opdata1_o <= `ZeroWord;
div_opdata2_o <= `ZeroWord;
div_start_o <= `DivStop;
signed_div_o <= 1'b0;
case(aluop_i)
`EXE_DIV_OP:begin
if(div_ready_i == `DivResultNotReady) begin
div_opdata1_o <= reg1_i;
div_opdata2_o <= reg2_i;
div_start_o <= `DivStart;
signed_div_o <= 1'b1;
stallreq_for_div <= `Stop;
end else if(div_ready_i == `DivResultReady) begin
div_opdata1_o <= reg1_i;
div_opdata2_o <= reg2_i;
div_start_o <= `DivStop;
signed_div_o <= 1'b1;
stallreq_for_div <= `NoStop;
end else begin
div_opdata1_o <= `ZeroWord;
div_opdata2_o <= `ZeroWord;
div_start_o <= `DivStop;
signed_div_o <= 1'b0;
stallreq_for_div <= `NoStop;
end
end
`EXE_DIVU_OP:begin
if(div_ready_i == `DivResultNotReady) begin
div_opdata1_o <= reg1_i;
div_opdata2_o <= reg2_i;
div_start_o <= `DivStart;
signed_div_o <= 1'b0;
stallreq_for_div <= `Stop;
end else if(div_ready_i == `DivResultReady) begin
div_opdata1_o <= reg1_i;
div_opdata2_o <= reg2_i;
div_start_o <= `DivStop;
signed_div_o <= 1'b0;
stallreq_for_div <= `NoStop;
end else begin
div_opdata1_o <= `ZeroWord;
div_opdata2_o <= `ZeroWord;
div_start_o <= `DivStop;
signed_div_o <= 1'b0;
stallreq_for_div <= `NoStop;
end
end
default:begin
end
endcase
end
end
always @ (*) begin
stallreq = stallreq_for_madd_msub || stallreq_for_div;
end
always @ (*)begin
if(rst == `RstEnable) begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end else if((aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MULTU_OP))begin
whilo_o <= `WriteEnable;
hi_o <= mulres[63:32];
lo_o <= mulres[31:0];
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 if((aluop_i == `EXE_MSUB_OP)||(aluop_i == `EXE_MSUBU_OP))begin
whilo_o <= `WriteEnable;
hi_o <= hilo_temp1[63:32];
lo_o <= hilo_temp1[31:0];
end else if((aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MADDU_OP))begin
whilo_o <= `WriteEnable;
hi_o <= hilo_temp1[63:32];
lo_o <= hilo_temp1[31:0];
end else if((aluop_i == `EXE_DIV_OP)||(aluop_i == `EXE_DIVU_OP))begin
whilo_o <= `WriteEnable;
hi_o <= div_result_i[63:32];
lo_o <= div_result_i[31:0];
end else begin
whilo_o <= `WriteDisable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end
end
always @ (*) begin
if(rst == `RstEnable)begin
cp0_reg_write_addr_o <= 5'b00000;
cp0_reg_we_o <= `WriteDisable;
cp0_reg_data_o <= `ZeroWord;
end else if(aluop_i == `EXE_MTC0_OP)begin
cp0_reg_write_addr_o <= inst_i[15:11];
cp0_reg_we_o <= `WriteEnable;
cp0_reg_data_o <= reg1_i;
end else begin
cp0_reg_write_addr_o <= 5'b00000;
cp0_reg_we_o <= `WriteDisable;
cp0_reg_data_o <= `ZeroWord;
end
end
always @ (*) begin
if(rst == `RstEnable)begin
trapassert <= `TrapNotAssert;
end else begin
trapassert <= `TrapNotAssert;
case(aluop_i)
`EXE_TEQ_OP,`EXE_TEQI_OP:begin
if(reg1_i == reg2_i)begin
trapassert <= `TrapAssert;
end
end
`EXE_TGE_OP,`EXE_TGEI_OP,`EXE_TGEIU_OP,`EXE_TGEU_OP:
begin
if(~reg1_lt_reg2)begin
trapassert <= `TrapAssert;
end
end
`EXE_TLT_OP,`EXE_TLTI_OP,`EXE_TLTIU_OP,`EXE_TLTU_OP:
begin
if(reg1_lt_reg2)begin
trapassert <= `TrapAssert;
end
end
`EXE_TNE_OP,`EXE_TNEI_OP:begin
if(reg1_i!=reg2_i)begin
trapassert <= `TrapAssert;
end
end
default:begin
trapassert <= `TrapNotAssert;
end
endcase
end
end
endmodule
ex_mem.v
`include "define.v"
module ex_mem(
input wire clk,
input wire rst,
input wire[5:0] stall,
input wire flush,
input wire[`RegAddrBus] ex_wd,
input wire ex_wreg,
input wire[`RegBus] ex_wdata,
input wire[`RegBus] ex_hi,
input wire[`RegBus] ex_lo,
input wire ex_whilo,
input wire[`AluOpBus] ex_aluop,
input wire[`RegBus] ex_mem_addr,
input wire[`RegBus] ex_reg2,
input wire[`DoubleRegBus] hilo_i,
input wire[1:0] cnt_i,
input wire ex_cp0_reg_we,
input wire[4:0] ex_cp0_reg_write_addr,
input wire[`RegBus] ex_cp0_reg_data,
input wire[31:0] ex_excepttype,
input wire ex_is_in_delayslot,
input wire[`RegBus] ex_current_inst_address,
output reg[`RegAddrBus] mem_wd,
output reg mem_wreg,
output reg[`RegBus] mem_wdata,
output reg[`RegBus] mem_hi,
output reg[`RegBus] mem_lo,
output reg mem_whilo,
output reg[`AluOpBus] mem_aluop,
output reg[`RegBus] mem_mem_addr,
output reg[`RegBus] mem_reg2,
output reg mem_cp0_reg_we,
output reg[4:0] mem_cp0_reg_write_addr,
output reg[`RegBus] mem_cp0_reg_data,
output reg[`DoubleRegBus] hilo_o,
output reg[1:0] cnt_o ,
output reg[31:0] mem_excepttype,
output reg mem_is_in_delayslot,
output reg[`RegBus] mem_current_inst_address
);
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;
hilo_o <= {`ZeroWord, `ZeroWord};
cnt_o <= 2'b00;
mem_aluop <= `EXE_NOP_OP;
mem_mem_addr <= `ZeroWord;
mem_reg2 <= `ZeroWord;
mem_cp0_reg_we <= `WriteDisable;
mem_cp0_reg_write_addr <= 5'b00000;
mem_cp0_reg_data <= `ZeroWord;
mem_excepttype <= `ZeroWord;
mem_is_in_delayslot <= `NotInDelaySlot;
mem_current_inst_address <= `ZeroWord;
end else if(flush == 1'b1)begin
mem_wd <= `NOPRegAddr;
mem_wreg <= `WriteDisable;
mem_wdata <= `ZeroWord;
mem_hi <= `ZeroWord;
mem_lo <= `ZeroWord;
mem_whilo <= `WriteDisable;
mem_aluop <= `EXE_NOP_OP;
mem_mem_addr <= `ZeroWord;
mem_reg2 <= `ZeroWord;
mem_cp0_reg_we <= `WriteDisable;
mem_cp0_reg_write_addr <= 5'b00000;
mem_cp0_reg_data <= `ZeroWord;
mem_excepttype <= `ZeroWord;
mem_is_in_delayslot <= `NotInDelaySlot;
mem_current_inst_address <= `ZeroWord;
hilo_o <= {`ZeroWord,`ZeroWord};
cnt_o <= 2'b00;
end else if(stall[3] == `Stop && stall[4] == `NoStop) begin
mem_wd <= `NOPRegAddr;
mem_wreg <= `WriteDisable;
mem_wdata <= `ZeroWord;
mem_hi <= `ZeroWord;
mem_lo <= `ZeroWord;
mem_whilo <= `WriteDisable;
hilo_o <= hilo_i;
cnt_o <= cnt_i;
mem_aluop <= `EXE_NOP_OP;
mem_mem_addr <= `ZeroWord;
mem_reg2 <= `ZeroWord;
mem_cp0_reg_we <= `WriteDisable;
mem_cp0_reg_write_addr <= 5'b00000;
mem_cp0_reg_data <= `ZeroWord;
mem_excepttype <= `ZeroWord;
mem_is_in_delayslot <= `NotInDelaySlot;
mem_current_inst_address <= `ZeroWord;
end else if(stall[3] == `NoStop) 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;
hilo_o <= {`ZeroWord, `ZeroWord};
cnt_o <= 2'b00;
mem_aluop <= ex_aluop;
mem_mem_addr <= ex_mem_addr;
mem_reg2 <= ex_reg2;
mem_cp0_reg_we <= ex_cp0_reg_we;
mem_cp0_reg_write_addr <= ex_cp0_reg_write_addr;
mem_cp0_reg_data <= ex_cp0_reg_data;
mem_excepttype <= ex_excepttype;
mem_is_in_delayslot <= ex_is_in_delayslot;
mem_current_inst_address <= ex_current_inst_address;
end else begin
hilo_o <= hilo_i;
cnt_o <= cnt_i;
end
end
endmodule
mem.v
`include "define.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,
input wire[`AluOpBus] aluop_i,
input wire[`RegBus] mem_addr_i,
input wire[`RegBus] reg2_i,
input wire[`RegBus] mem_data_i,
input wire LLbit_i,
input wire wb_LLbit_we_i,
input wire wb_LLbit_value_i,
input wire cp0_reg_we_i,
input wire[4:0] cp0_reg_write_addr_i,
input wire[`RegBus] cp0_reg_data_i,
input wire[31:0] excepttype_i,
input wire is_in_delayslot_i,
input wire[`RegBus] current_inst_address_i,
input wire[`RegBus] cp0_status_i,
input wire[`RegBus] cp0_cause_i,
input wire[`RegBus] cp0_epc_i,
input wire wb_cp0_reg_we,
input wire[4:0] wb_cp0_reg_write_addr,
input wire[`RegBus] wb_cp0_reg_data,
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,
output reg LLbit_we_o,
output reg LLbit_value_o,
output reg cp0_reg_we_o,
output reg[4:0] cp0_reg_write_addr_o,
output reg[`RegBus] cp0_reg_data_o,
output reg[`RegBus] mem_addr_o,
output wire mem_we_o,
output reg[3:0] mem_sel_o,
output reg[`RegBus] mem_data_o,
output reg mem_ce_o,
output reg[31:0] excepttype_o,
output wire[`RegBus] cp0_epc_o,
output wire is_in_delayslot_o,
output wire[`RegBus] current_inst_address_o
);
reg LLbit;
wire[`RegBus] zero32;
reg[`RegBus] cp0_status;
reg[`RegBus] cp0_cause;
reg[`RegBus] cp0_epc;
reg mem_we;
assign mem_we_o = mem_we & (~(|excepttype_o));
assign zero32 = `ZeroWord;
assign is_in_delayslot_o = is_in_delayslot_i;
assign current_inst_address_o = current_inst_address_i;
assign cp0_epc_o = cp0_epc;
always @ (*) begin
if(rst == `RstEnable) begin
LLbit <= 1'b0;
end else begin
if(wb_LLbit_we_i == 1'b1) begin
LLbit <= wb_LLbit_value_i;
end else begin
LLbit <= LLbit_i;
end
end
end
always @ (*) begin
if(rst == `RstEnable) begin
wd_o <= `NOPRegAddr;
wreg_o <= `WriteDisable;
wdata_o <= `ZeroWord;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
whilo_o <= `WriteDisable;
mem_addr_o <= `ZeroWord;
mem_we <= `WriteDisable;
mem_sel_o <= 4'b0000;
mem_data_o <= `ZeroWord;
mem_ce_o <= `ChipDisable;
LLbit_we_o <= 1'b0;
LLbit_value_o <= 1'b0;
cp0_reg_we_o <= `WriteDisable;
cp0_reg_write_addr_o <= 5'b00000;
cp0_reg_data_o <= `ZeroWord;
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;
mem_we <= `WriteDisable;
mem_addr_o <= `ZeroWord;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipDisable;
LLbit_we_o <= 1'b0;
LLbit_value_o <= 1'b0;
cp0_reg_we_o <= cp0_reg_we_i;
cp0_reg_write_addr_o <= cp0_reg_write_addr_i;
cp0_reg_data_o <= cp0_reg_data_i;
case (aluop_i)
`EXE_LB_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {{24{mem_data_i[31]}},mem_data_i[31:24]};
mem_sel_o <= 4'b1000;
end
2'b01: begin
wdata_o <= {{24{mem_data_i[23]}},mem_data_i[23:16]};
mem_sel_o <= 4'b0100;
end
2'b10: begin
wdata_o <= {{24{mem_data_i[15]}},mem_data_i[15:8]};
mem_sel_o <= 4'b0010;
end
2'b11: begin
wdata_o <= {{24{mem_data_i[7]}},mem_data_i[7:0]};
mem_sel_o <= 4'b0001;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LBU_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {{24{1'b0}},mem_data_i[31:24]};
mem_sel_o <= 4'b1000;
end
2'b01: begin
wdata_o <= {{24{1'b0}},mem_data_i[23:16]};
mem_sel_o <= 4'b0100;
end
2'b10: begin
wdata_o <= {{24{1'b0}},mem_data_i[15:8]};
mem_sel_o <= 4'b0010;
end
2'b11: begin
wdata_o <= {{24{1'b0}},mem_data_i[7:0]};
mem_sel_o <= 4'b0001;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LH_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {{16{mem_data_i[31]}},mem_data_i[31:16]};
mem_sel_o <= 4'b1100;
end
2'b10: begin
wdata_o <= {{16{mem_data_i[15]}},mem_data_i[15:0]};
mem_sel_o <= 4'b0011;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LHU_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {{16{1'b0}},mem_data_i[31:16]};
mem_sel_o <= 4'b1100;
end
2'b10: begin
wdata_o <= {{16{1'b0}},mem_data_i[15:0]};
mem_sel_o <= 4'b0011;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LW_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
wdata_o <= mem_data_i;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end
`EXE_LWL_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00};
mem_we <= `WriteDisable;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= mem_data_i[31:0];
end
2'b01: begin
wdata_o <= {mem_data_i[23:0],reg2_i[7:0]};
end
2'b10: begin
wdata_o <= {mem_data_i[15:0],reg2_i[15:0]};
end
2'b11: begin
wdata_o <= {mem_data_i[7:0],reg2_i[23:0]};
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LWR_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00};
mem_we <= `WriteDisable;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
wdata_o <= {reg2_i[31:8],mem_data_i[31:24]};
end
2'b01: begin
wdata_o <= {reg2_i[31:16],mem_data_i[31:16]};
end
2'b10: begin
wdata_o <= {reg2_i[31:24],mem_data_i[31:8]};
end
2'b11: begin
wdata_o <= mem_data_i;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase
end
`EXE_LL_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteDisable;
wdata_o <= mem_data_i;
LLbit_we_o <= 1'b1;
LLbit_value_o <= 1'b1;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end
`EXE_SB_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable;
mem_data_o <= {reg2_i[7:0],reg2_i[7:0],reg2_i[7:0],reg2_i[7:0]};
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
mem_sel_o <= 4'b1000;
end
2'b01: begin
mem_sel_o <= 4'b0100;
end
2'b10: begin
mem_sel_o <= 4'b0010;
end
2'b11: begin
mem_sel_o <= 4'b0001;
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
`EXE_SH_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable;
mem_data_o <= {reg2_i[15:0],reg2_i[15:0]};
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
mem_sel_o <= 4'b1100;
end
2'b10: begin
mem_sel_o <= 4'b0011;
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
`EXE_SW_OP: begin
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable;
mem_data_o <= reg2_i;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end
`EXE_SWL_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00};
mem_we <= `WriteEnable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
mem_sel_o <= 4'b1111;
mem_data_o <= reg2_i;
end
2'b01: begin
mem_sel_o <= 4'b0111;
mem_data_o <= {zero32[7:0],reg2_i[31:8]};
end
2'b10: begin
mem_sel_o <= 4'b0011;
mem_data_o <= {zero32[15:0],reg2_i[31:16]};
end
2'b11: begin
mem_sel_o <= 4'b0001;
mem_data_o <= {zero32[23:0],reg2_i[31:24]};
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
`EXE_SWR_OP: begin
mem_addr_o <= {mem_addr_i[31:2], 2'b00};
mem_we <= `WriteEnable;
mem_ce_o <= `ChipEnable;
case (mem_addr_i[1:0])
2'b00: begin
mem_sel_o <= 4'b1000;
mem_data_o <= {reg2_i[7:0],zero32[23:0]};
end
2'b01: begin
mem_sel_o <= 4'b1100;
mem_data_o <= {reg2_i[15:0],zero32[15:0]};
end
2'b10: begin
mem_sel_o <= 4'b1110;
mem_data_o <= {reg2_i[23:0],zero32[7:0]};
end
2'b11: begin
mem_sel_o <= 4'b1111;
mem_data_o <= reg2_i[31:0];
end
default: begin
mem_sel_o <= 4'b0000;
end
endcase
end
`EXE_SC_OP: begin
if(LLbit == 1'b1) begin
LLbit_we_o <= 1'b1;
LLbit_value_o <= 1'b0;
mem_addr_o <= mem_addr_i;
mem_we <= `WriteEnable;
mem_data_o <= reg2_i;
wdata_o <= 32'b1;
mem_sel_o <= 4'b1111;
mem_ce_o <= `ChipEnable;
end else begin
wdata_o <= 32'b0;
end
end
default: begin
end
endcase
end
end
always @ (*) begin
if(rst == `RstEnable) begin
cp0_status <= `ZeroWord;
end else if((wb_cp0_reg_we == `WriteEnable) &&
(wb_cp0_reg_write_addr == `CP0_REG_STATUS ))begin
cp0_status <= wb_cp0_reg_data;
end else begin
cp0_status <= cp0_status_i;
end
end
always @ (*) begin
if(rst == `RstEnable) begin
cp0_epc <= `ZeroWord;
end else if((wb_cp0_reg_we == `WriteEnable) &&
(wb_cp0_reg_write_addr == `CP0_REG_EPC ))begin
cp0_epc <= wb_cp0_reg_data;
end else begin
cp0_epc <= cp0_epc_i;
end
end
always @ (*) begin
if(rst == `RstEnable) begin
cp0_cause <= `ZeroWord;
end else if((wb_cp0_reg_we == `WriteEnable) &&
(wb_cp0_reg_write_addr == `CP0_REG_CAUSE ))begin
cp0_cause[9:8] <= wb_cp0_reg_data[9:8];
cp0_cause[22] <= wb_cp0_reg_data[22];
cp0_cause[23] <= wb_cp0_reg_data[23];
end else begin
cp0_cause <= cp0_cause_i;
end
end
always @ (*) begin
if(rst == `RstEnable) begin
excepttype_o <= `ZeroWord;
end else begin
excepttype_o <= `ZeroWord;
if(current_inst_address_i != `ZeroWord) begin
if(((cp0_cause[15:8] & (cp0_status[15:8])) != 8'h00) && (cp0_status[1] == 1'b0) &&
(cp0_status[0] == 1'b1)) begin
excepttype_o <= 32'h00000001;
end else if(excepttype_i[8] == 1'b1) begin
excepttype_o <= 32'h00000008;
end else if(excepttype_i[9] == 1'b1) begin
excepttype_o <= 32'h0000000a;
end else if(excepttype_i[10] ==1'b1) begin
excepttype_o <= 32'h0000000d;
end else if(excepttype_i[11] == 1'b1) begin
excepttype_o <= 32'h0000000c;
end else if(excepttype_i[12] == 1'b1) begin
excepttype_o <= 32'h0000000e;
end
end
end
end
endmodule
mem_wb.v
`include "define.v"
module mem_wb(
input wire clk,
input wire rst,
input wire[5:0] stall,
input wire flush,
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,
input wire mem_LLbit_we,
input wire mem_LLbit_value,
input wire mem_cp0_reg_we,
input wire[4:0] mem_cp0_reg_write_addr,
input wire[`RegBus] mem_cp0_reg_data,
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,
output reg wb_LLbit_we,
output reg wb_LLbit_value,
output reg wb_cp0_reg_we,
output reg[4:0] wb_cp0_reg_write_addr,
output reg[`RegBus] wb_cp0_reg_data
);
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;
wb_LLbit_we <= 1'b0;
wb_LLbit_value <= 1'b0;
wb_cp0_reg_we <= `WriteDisable;
wb_cp0_reg_write_addr <= 5'b00000;
wb_cp0_reg_data <= `ZeroWord;
end else if(flush == 1'b1 ) begin
wb_wd <= `NOPRegAddr;
wb_wreg <= `WriteDisable;
wb_wdata <= `ZeroWord;
wb_hi <= `ZeroWord;
wb_lo <= `ZeroWord;
wb_whilo <= `WriteDisable;
wb_LLbit_we <= 1'b0;
wb_LLbit_value <= 1'b0;
wb_cp0_reg_we <= `WriteDisable;
wb_cp0_reg_write_addr <= 5'b00000;
wb_cp0_reg_data <= `ZeroWord;
end else if(stall[4] == `Stop && stall[5] == `NoStop) begin
wb_wd <= `NOPRegAddr;
wb_wreg <= `WriteDisable;
wb_wdata <= `ZeroWord;
wb_hi <= `ZeroWord;
wb_lo <= `ZeroWord;
wb_whilo <= `WriteDisable;
wb_LLbit_we <= 1'b0;
wb_LLbit_value <= 1'b0;
wb_cp0_reg_we <= `WriteDisable;
wb_cp0_reg_write_addr <= 5'b00000;
wb_cp0_reg_data <= `ZeroWord;
end else if(stall[4] == `NoStop) 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;
wb_LLbit_we <= mem_LLbit_we;
wb_LLbit_value <= mem_LLbit_value;
wb_cp0_reg_we <= mem_cp0_reg_we;
wb_cp0_reg_write_addr <= mem_cp0_reg_write_addr;
wb_cp0_reg_data <= mem_cp0_reg_data;
end
end
endmodule
regfile.v
`include "define.v"
module regfile(
input wire clk,
input wire rst,
input wire we,
input wire[`RegAddrBus] waddr,
input wire[`RegBus] wdata,
input wire re1,
input wire[`RegAddrBus] raddr1,
output reg[`RegBus] rdata1,
input wire re2,
input wire[`RegAddrBus] raddr2,
output reg[`RegBus] rdata2
);
reg[`RegBus] regs[0:`RegNum-1];
always @ (posedge clk)
begin
if(rst==`RstDisable)
begin
if((we==`WriteEnable)&&(waddr!=`RegNumLog2'h0))
begin
regs[waddr]<=wdata;
end
end
end
always @(*)
begin
if(rst==`RstEnable)
begin
rdata1 <= `ZeroWord;
end
else if(raddr1==`RegNumLog2'h0)
begin
rdata1<=`ZeroWord;
end
else if((raddr1==waddr)&&(we==`WriteEnable)&&(re1==`ReadEnable))
begin
rdata1<=wdata;
end
else if(re1==`ReadEnable)
begin
rdata1<=regs[raddr1];
end
else
begin
rdata1<=`ZeroWord;
end
end
always @ (*)
begin
if(rst==`RstEnable)
begin
rdata2<=`ZeroWord;
end
else if(raddr2==`RegNumLog2'h0)
begin
rdata2<=`ZeroWord;
end
else if((raddr2==waddr)&&(we==`WriteEnable)&&(re2==`ReadEnable))
begin
rdata2<=wdata;
end
else if(re2==`ReadEnable)
begin
rdata2<=regs[raddr2];
end
else
begin
rdata2<=`ZeroWord;
end
end
endmodule
cp_reg.v
`include "define.v"
module cp0_reg(
input wire clk,
input wire rst,
input wire we_i,
input wire[4:0] waddr_i,
input wire[4:0] raddr_i,
input wire[`RegBus] data_i,
input wire[31:0] excepttype_i,
input wire[5:0] int_i,
input wire[`RegBus] current_inst_addr_i,
input wire is_in_delayslot_i,
output reg[`RegBus] data_o,
output reg[`RegBus] count_o,
output reg[`RegBus] compare_o,
output reg[`RegBus] status_o,
output reg[`RegBus] cause_o,
output reg[`RegBus] epc_o,
output reg[`RegBus] config_o,
output reg[`RegBus] prid_o,
output reg timer_int_o
);
always @ (posedge clk) begin
if(rst == `RstEnable) begin
count_o <= `ZeroWord;
compare_o <= `ZeroWord;
status_o <= 32'b00010000000000000000000000000000;
cause_o <= `ZeroWord;
epc_o <= `ZeroWord;
config_o <= 32'b00000000000000001000000000000000;
prid_o <= 32'b00000000010011000000000100000010;
timer_int_o <= `InterruputNotAssert;
end else begin
count_o <= count_o + 1 ;
cause_o[15:10] <= int_i;
if(compare_o != `ZeroWord && count_o == compare_o) begin
timer_int_o <= `InterruputAssert;
end
if(we_i == `WriteEnable) begin
case (waddr_i)
`CP0_REG_COUNT: begin
count_o <= data_i;
end
`CP0_REG_COMPARE: begin
compare_o <= data_i;
timer_int_o <= `InterruputNotAssert;
end
`CP0_REG_STATUS: begin
status_o <= data_i;
end
`CP0_REG_EPC: begin
epc_o <= data_i;
end
`CP0_REG_CAUSE: begin
cause_o[9:8] <= data_i[9:8];
cause_o[23] <= data_i[23];
cause_o[22] <= data_i[22];
end
endcase
end
case (excepttype_i)
32'h00000001: begin
if(is_in_delayslot_i == `InDelaySlot ) begin
epc_o <= current_inst_addr_i - 4 ;
cause_o[31] <= 1'b1;
end else begin
epc_o <= current_inst_addr_i;
cause_o[31] <= 1'b0;
end
status_o[1] <= 1'b1;
cause_o[6:2] <= 5'b00000;
end
32'h00000008: begin
if(status_o[1] == 1'b0) begin
if(is_in_delayslot_i == `InDelaySlot ) begin
epc_o <= current_inst_addr_i - 4 ;
cause_o[31] <= 1'b1;
end else begin
epc_o <= current_inst_addr_i;
cause_o[31] <= 1'b0;
end
end
status_o[1] <= 1'b1;
cause_o[6:2] <= 5'b01000;
end
32'h0000000a: begin
if(status_o[1] == 1'b0) begin
if(is_in_delayslot_i == `InDelaySlot ) begin
epc_o <= current_inst_addr_i - 4 ;
cause_o[31] <= 1'b1;
end else begin
epc_o <= current_inst_addr_i;
cause_o[31] <= 1'b0;
end
end
status_o[1] <= 1'b1;
cause_o[6:2] <= 5'b01010;
end
32'h0000000d: begin
if(status_o[1] == 1'b0) begin
if(is_in_delayslot_i == `InDelaySlot ) begin
epc_o <= current_inst_addr_i - 4 ;
cause_o[31] <= 1'b1;
end else begin
epc_o <= current_inst_addr_i;
cause_o[31] <= 1'b0;
end
end
status_o[1] <= 1'b1;
cause_o[6:2] <= 5'b01101;
end
32'h0000000c: begin
if(status_o[1] == 1'b0) begin
if(is_in_delayslot_i == `InDelaySlot ) begin
epc_o <= current_inst_addr_i - 4 ;
cause_o[31] <= 1'b1;
end else begin
epc_o <= current_inst_addr_i;
cause_o[31] <= 1'b0;
end
end
status_o[1] <= 1'b1;
cause_o[6:2] <= 5'b01100;
end
32'h0000000e: begin
status_o[1] <= 1'b0;
end
default: begin
end
endcase
end
end
always @ (*) begin
if(rst == `RstEnable) begin
data_o <= `ZeroWord;
end else begin
case (raddr_i)
`CP0_REG_COUNT: begin
data_o <= count_o ;
end
`CP0_REG_COMPARE: begin
data_o <= compare_o ;
end
`CP0_REG_STATUS: begin
data_o <= status_o ;
end
`CP0_REG_CAUSE: begin
data_o <= cause_o ;
end
`CP0_REG_EPC: begin
data_o <= epc_o ;
end
`CP0_REG_PrId: begin
data_o <= prid_o ;
end
`CP0_REG_CONFIG: begin
data_o <= config_o ;
end
default: begin
end
endcase
end
end
endmodule
LLbit_reg.v
`include "define.v"
module LLbit_reg(
input wire clk,
input wire rst,
input wire flush,
input wire LLbit_i,
input wire we,
output reg LLbit_o
);
always @ (posedge clk) begin
if(rst == `RstEnable)begin
LLbit_o <= 1'b0;
end else if((flush == 1'b1))begin
LLbit_o <= 1'b0;
end else if((we == `WriteEnable))begin
LLbit_o <= LLbit_i;
end
end
endmodule
openmips.v
`include "define.v"
module openmips(
input wire clk,
input wire rst,
input wire[5:0] int_i,
input wire[`RegBus] rom_data_i,
output wire[`RegBus] rom_addr_o,
output wire rom_ce_o,
input wire[`RegBus] ram_data_i,
output wire[`RegBus] ram_addr_o,
output wire[`RegBus] ram_data_o,
output wire ram_we_o,
output wire[3:0] ram_sel_o,
output wire[3:0] ram_ce_o,
output wire timer_int_o
);
wire[`InstAddrBus] pc;
wire[`InstAddrBus] id_pc_i;
wire[`InstBus] id_inst_i;
wire[`AluOpBus] id_aluop_o;
wire[`AluSelBus] id_alusel_o;
wire[`RegBus] id_reg1_o;
wire[`RegBus] id_reg2_o;
wire id_wreg_o;
wire[`RegAddrBus] id_wd_o;
wire id_is_in_delayslot_o;
wire[`RegBus] id_link_address_o;
wire[`RegBus] id_inst_o;
wire[31:0] id_excepttype_o;
wire[`RegBus] id_current_inst_address_o;
wire[`AluOpBus] ex_aluop_i;
wire[`AluSelBus] ex_alusel_i;
wire[`RegBus] ex_reg1_i;
wire[`RegBus] ex_reg2_i;
wire ex_wreg_i;
wire[`RegAddrBus] ex_wd_i;
wire ex_is_in_delayslot_i;
wire[`RegBus] ex_link_address_i;
wire[`RegBus] ex_inst_i;
wire[31:0] ex_excepttype_i;
wire[`RegBus] ex_current_inst_address_i;
wire ex_wreg_o;
wire[`RegAddrBus] ex_wd_o;
wire[`RegBus] ex_wdata_o;
wire[`RegBus] ex_hi_o;
wire[`RegBus] ex_lo_o;
wire ex_whilo_o;
wire[`AluOpBus] ex_aluop_o;
wire[`RegBus] ex_mem_addr_o;
wire[`RegBus] ex_reg2_o;
wire ex_cp0_reg_we_o;
wire[4:0] ex_cp0_reg_write_addr_o;
wire[`RegBus] ex_cp0_reg_data_o;
wire[31:0] ex_excepttype_o;
wire[`RegBus] ex_current_inst_address_o;
wire ex_is_in_delayslot_o;
wire mem_wreg_i;
wire[`RegAddrBus] mem_wd_i;
wire[`RegBus] mem_wdata_i;
wire[`RegBus] mem_hi_i;
wire[`RegBus] mem_lo_i;
wire mem_whilo_i;
wire[`AluOpBus] mem_aluop_i;
wire[`RegBus] mem_mem_addr_i;
wire[`RegBus] mem_reg2_i;
wire mem_cp0_reg_we_i;
wire[4:0] mem_cp0_reg_write_addr_i;
wire[`RegBus] mem_cp0_reg_data_i;
wire[31:0] mem_excepttype_i;
wire mem_is_in_delayslot_i;
wire[`RegBus] mem_current_inst_address_i;
wire mem_wreg_o;
wire[`RegAddrBus] mem_wd_o;
wire[`RegBus] mem_wdata_o;
wire[`RegBus] mem_hi_o;
wire[`RegBus] mem_lo_o;
wire mem_whilo_o;
wire mem_LLbit_value_o;
wire mem_LLbit_we_o;
wire mem_cp0_reg_we_o;
wire[4:0] mem_cp0_reg_write_addr_o;
wire[`RegBus] mem_cp0_reg_data_o;
wire[31:0] mem_excepttype_o;
wire mem_is_in_delayslot_o;
wire[`RegBus] mem_current_inst_address_o;
wire wb_wreg_i;
wire[`RegAddrBus] wb_wd_i;
wire[`RegBus] wb_wdata_i;
wire[`RegBus] wb_hi_i;
wire[`RegBus] wb_lo_i;
wire wb_whilo_i;
wire wb_LLbit_value_i;
wire wb_LLbit_we_i;
wire wb_cp0_reg_we_i;
wire[4:0] wb_cp0_reg_write_addr_i;
wire[`RegBus] wb_cp0_reg_data_i;
wire[31:0] wb_excepttype_i;
wire wb_is_in_delayslot_i;
wire[`RegBus] wb_current_inst_address_i;
wire reg1_read;
wire reg2_read;
wire[`RegBus] reg1_data;
wire[`RegBus] reg2_data;
wire[`RegAddrBus] reg1_addr;
wire[`RegAddrBus] reg2_addr;
wire[`RegBus] hi;
wire[`RegBus] lo;
wire[`DoubleRegBus] hilo_temp_o;
wire[1:0] cnt_o;
wire[`DoubleRegBus] hilo_temp_i;
wire[1:0] cnt_i;
wire[`DoubleRegBus] div_result;
wire div_ready;
wire[`RegBus] div_opdata1;
wire[`RegBus] div_opdata2;
wire div_start;
wire div_annul;
wire signed_div;
wire is_in_delayslot_i;
wire is_in_delayslot_o;
wire next_inst_in_delayslot_o;
wire id_branch_flag_o;
wire[`RegBus] branch_target_address;
wire[5:0] stall;
wire stallreq_from_id;
wire stallreq_from_ex;
wire LLbit_o;
wire[`RegBus] cp0_data_o;
wire[4:0] cp0_raddr_i;
wire flush;
wire[`RegBus] new_pc;
wire[`RegBus] cp0_count;
wire[`RegBus] cp0_compare;
wire[`RegBus] cp0_status;
wire[`RegBus] cp0_cause;
wire[`RegBus] cp0_epc;
wire[`RegBus] cp0_config;
wire[`RegBus] cp0_prid;
wire[`RegBus] latest_epc;
pc_reg pc_reg0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.new_pc(new_pc),
.branch_flag_i(id_branch_flag_o),
.branch_target_address_i(branch_target_address),
.pc(pc),
.ce(rom_ce_o)
);
assign rom_addr_o = pc;
if_id if_id0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.if_pc(pc),
.if_inst(rom_data_i),
.id_pc(id_pc_i),
.id_inst(id_inst_i)
);
id id0(
.rst(rst),
.pc_i(id_pc_i),
.inst_i(id_inst_i),
.ex_aluop_i(ex_aluop_o),
.reg1_data_i(reg1_data),
.reg2_data_i(reg2_data),
.ex_wreg_i(ex_wreg_o),
.ex_wdata_i(ex_wdata_o),
.ex_wd_i(ex_wd_o),
.mem_wreg_i(mem_wreg_o),
.mem_wdata_i(mem_wdata_o),
.mem_wd_i(mem_wd_o),
.is_in_delayslot_i(is_in_delayslot_i),
.reg1_read_o(reg1_read),
.reg2_read_o(reg2_read),
.reg1_addr_o(reg1_addr),
.reg2_addr_o(reg2_addr),
.aluop_o(id_aluop_o),
.alusel_o(id_alusel_o),
.reg1_o(id_reg1_o),
.reg2_o(id_reg2_o),
.wd_o(id_wd_o),
.wreg_o(id_wreg_o),
.excepttype_o(id_excepttype_o),
.inst_o(id_inst_o),
.next_inst_in_delayslot_o(next_inst_in_delayslot_o),
.branch_flag_o(id_branch_flag_o),
.branch_target_address_o(branch_target_address),
.link_addr_o(id_link_address_o),
.is_in_delayslot_o(id_is_in_delayslot_o),
.current_inst_address_o(id_current_inst_address_o),
.stallreq(stallreq_from_id)
);
regfile regfile1(
.clk (clk),
.rst (rst),
.we (wb_wreg_i),
.waddr (wb_wd_i),
.wdata (wb_wdata_i),
.re1 (reg1_read),
.raddr1 (reg1_addr),
.rdata1 (reg1_data),
.re2 (reg2_read),
.raddr2 (reg2_addr),
.rdata2 (reg2_data)
);
id_ex id_ex0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.id_aluop(id_aluop_o),
.id_alusel(id_alusel_o),
.id_reg1(id_reg1_o),
.id_reg2(id_reg2_o),
.id_wd(id_wd_o),
.id_wreg(id_wreg_o),
.id_link_address(id_link_address_o),
.id_is_in_delayslot(id_is_in_delayslot_o),
.next_inst_in_delayslot_i(next_inst_in_delayslot_o),
.id_inst(id_inst_o),
.id_excepttype(id_excepttype_o),
.id_current_inst_address(id_current_inst_address_o),
.ex_aluop(ex_aluop_i),
.ex_alusel(ex_alusel_i),
.ex_reg1(ex_reg1_i),
.ex_reg2(ex_reg2_i),
.ex_wd(ex_wd_i),
.ex_wreg(ex_wreg_i),
.ex_link_address(ex_link_address_i),
.ex_is_in_delayslot(ex_is_in_delayslot_i),
.is_in_delayslot_o(is_in_delayslot_i),
.ex_inst(ex_inst_i),
.ex_excepttype(ex_excepttype_i),
.ex_current_inst_address(ex_current_inst_address_i)
);
ex ex0(
.rst(rst),
.aluop_i(ex_aluop_i),
.alusel_i(ex_alusel_i),
.reg1_i(ex_reg1_i),
.reg2_i(ex_reg2_i),
.wd_i(ex_wd_i),
.wreg_i(ex_wreg_i),
.hi_i(hi),
.lo_i(lo),
.inst_i(ex_inst_i),
.wb_hi_i(wb_hi_i),
.wb_lo_i(wb_lo_i),
.wb_whilo_i(wb_whilo_i),
.mem_hi_i(mem_hi_o),
.mem_lo_i(mem_lo_o),
.mem_whilo_i(mem_whilo_o),
.hilo_temp_i(hilo_temp_i),
.cnt_i(cnt_i),
.div_result_i(div_result),
.div_ready_i(div_ready),
.link_address_i(ex_link_address_i),
.is_in_delayslot_i(ex_is_in_delayslot_i),
.excepttype_i(ex_excepttype_i),
.current_inst_address_i(ex_current_inst_address_i),
.mem_cp0_reg_we(mem_cp0_reg_we_o),
.mem_cp0_reg_write_addr(mem_cp0_reg_write_addr_o),
.mem_cp0_reg_data(mem_cp0_reg_data_o),
.wb_cp0_reg_we(wb_cp0_reg_we_i),
.wb_cp0_reg_write_addr(wb_cp0_reg_write_addr_i),
.wb_cp0_reg_data(wb_cp0_reg_data_i),
.cp0_reg_data_i(cp0_data_o),
.cp0_reg_read_addr_o(cp0_raddr_i),
.cp0_reg_we_o(ex_cp0_reg_we_o),
.cp0_reg_write_addr_o(ex_cp0_reg_write_addr_o),
.cp0_reg_data_o(ex_cp0_reg_data_o),
.wd_o(ex_wd_o),
.wreg_o(ex_wreg_o),
.wdata_o(ex_wdata_o),
.hi_o(ex_hi_o),
.lo_o(ex_lo_o),
.whilo_o(ex_whilo_o),
.hilo_temp_o(hilo_temp_o),
.cnt_o(cnt_o),
.div_opdata1_o(div_opdata1),
.div_opdata2_o(div_opdata2),
.div_start_o(div_start),
.signed_div_o(signed_div),
.aluop_o(ex_aluop_o),
.mem_addr_o(ex_mem_addr_o),
.reg2_o(ex_reg2_o),
.excepttype_o(ex_excepttype_o),
.is_in_delayslot_o(ex_is_in_delayslot_o),
.current_inst_address_o(ex_current_inst_address_o),
.stallreq(stallreq_from_ex)
);
ex_mem ex_mem0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.ex_wd(ex_wd_o),
.ex_wreg(ex_wreg_o),
.ex_wdata(ex_wdata_o),
.ex_hi(ex_hi_o),
.ex_lo(ex_lo_o),
.ex_whilo(ex_whilo_o),
.ex_aluop(ex_aluop_o),
.ex_mem_addr(ex_mem_addr_o),
.ex_reg2(ex_reg2_o),
.ex_cp0_reg_we(ex_cp0_reg_we_o),
.ex_cp0_reg_write_addr(ex_cp0_reg_write_addr_o),
.ex_cp0_reg_data(ex_cp0_reg_data_o),
.ex_excepttype(ex_excepttype_o),
.ex_is_in_delayslot(ex_is_in_delayslot_o),
.ex_current_inst_address(ex_current_inst_address_o),
.hilo_i(hilo_temp_o),
.cnt_i(cnt_o),
.mem_wd(mem_wd_i),
.mem_wreg(mem_wreg_i),
.mem_wdata(mem_wdata_i),
.mem_hi(mem_hi_i),
.mem_lo(mem_lo_i),
.mem_whilo(mem_whilo_i),
.mem_cp0_reg_we(mem_cp0_reg_we_i),
.mem_cp0_reg_write_addr(mem_cp0_reg_write_addr_i),
.mem_cp0_reg_data(mem_cp0_reg_data_i),
.mem_aluop(mem_aluop_i),
.mem_mem_addr(mem_mem_addr_i),
.mem_reg2(mem_reg2_i),
.mem_excepttype(mem_excepttype_i),
.mem_is_in_delayslot(mem_is_in_delayslot_i),
.mem_current_inst_address(mem_current_inst_address_i),
.hilo_o(hilo_temp_i),
.cnt_o(cnt_i)
);
mem mem0(
.rst(rst),
.wd_i(mem_wd_i),
.wreg_i(mem_wreg_i),
.wdata_i(mem_wdata_i),
.hi_i(mem_hi_i),
.lo_i(mem_lo_i),
.whilo_i(mem_whilo_i),
.aluop_i(mem_aluop_i),
.mem_addr_i(mem_mem_addr_i),
.reg2_i(mem_reg2_i),
.mem_data_i(ram_data_i),
.LLbit_i(LLbit_o),
.wb_LLbit_we_i(wb_LLbit_we_i),
.wb_LLbit_value_i(wb_LLbit_value_i),
.cp0_reg_we_i(mem_cp0_reg_we_i),
.cp0_reg_write_addr_i(mem_cp0_reg_write_addr_i),
.cp0_reg_data_i(mem_cp0_reg_data_i),
.excepttype_i(mem_excepttype_i),
.is_in_delayslot_i(mem_is_in_delayslot_i),
.current_inst_address_i(mem_current_inst_address_i),
.cp0_status_i(cp0_status),
.cp0_cause_i(cp0_cause),
.cp0_epc_i(cp0_epc),
.wb_cp0_reg_we(wb_cp0_reg_we_i),
.wb_cp0_reg_write_addr(wb_cp0_reg_write_addr_i),
.wb_cp0_reg_data(wb_cp0_reg_data_i),
.LLbit_we_o(mem_LLbit_we_o),
.LLbit_value_o(mem_LLbit_value_o),
.cp0_reg_we_o(mem_cp0_reg_we_o),
.cp0_reg_write_addr_o(mem_cp0_reg_write_addr_o),
.cp0_reg_data_o(mem_cp0_reg_data_o),
.wd_o(mem_wd_o),
.wreg_o(mem_wreg_o),
.wdata_o(mem_wdata_o),
.hi_o(mem_hi_o),
.lo_o(mem_lo_o),
.whilo_o(mem_whilo_o),
.mem_addr_o(ram_addr_o),
.mem_we_o(ram_we_o),
.mem_sel_o(ram_sel_o),
.mem_data_o(ram_data_o),
.mem_ce_o(ram_ce_o),
.excepttype_o(mem_excepttype_o),
.cp0_epc_o(latest_epc),
.is_in_delayslot_o(mem_is_in_delayslot_o),
.current_inst_address_o(mem_current_inst_address_o)
);
mem_wb mem_wb0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.mem_wd(mem_wd_o),
.mem_wreg(mem_wreg_o),
.mem_wdata(mem_wdata_o),
.mem_hi(mem_hi_o),
.mem_lo(mem_lo_o),
.mem_whilo(mem_whilo_o),
.mem_LLbit_we(mem_LLbit_we_o),
.mem_LLbit_value(mem_LLbit_value_o),
.mem_cp0_reg_we(mem_cp0_reg_we_o),
.mem_cp0_reg_write_addr(mem_cp0_reg_write_addr_o),
.mem_cp0_reg_data(mem_cp0_reg_data_o),
.wb_wd(wb_wd_i),
.wb_wreg(wb_wreg_i),
.wb_wdata(wb_wdata_i),
.wb_hi(wb_hi_i),
.wb_lo(wb_lo_i),
.wb_whilo(wb_whilo_i),
.wb_LLbit_we(wb_LLbit_we_i),
.wb_LLbit_value(wb_LLbit_value_i),
.wb_cp0_reg_we(wb_cp0_reg_we_i),
.wb_cp0_reg_write_addr(wb_cp0_reg_write_addr_i),
.wb_cp0_reg_data(wb_cp0_reg_data_i)
);
hilo_reg hilo_reg0(
.clk(clk),
.rst(rst),
.we(wb_whilo_i),
.hi_i(wb_hi_i),
.lo_i(wb_lo_i),
.hi_o(hi),
.lo_o(lo)
);
ctrl ctrl0(
.rst(rst),
.excepttype_i(mem_excepttype_o),
.cp0_epc_i(latest_epc),
.stallreq_from_id(stallreq_from_id),
.stallreq_from_ex(stallreq_from_ex),
.new_pc(new_pc),
.flush(flush),
.stall(stall)
);
div div0(
.clk(clk),
.rst(rst),
.signed_div_i(signed_div),
.opdata1_i(div_opdata1),
.opdata2_i(div_opdata2),
.start_i(div_start),
.annul_i(flush),
.result_o(div_result),
.ready_o(div_ready)
);
LLbit_reg LLbit_reg0(
.clk(clk),
.rst(rst),
.flush(flush),
.LLbit_i(wb_LLbit_value_i),
.we(wb_LLbit_we_i),
.LLbit_o(LLbit_o)
);
cp0_reg cp0_reg0(
.clk(clk),
.rst(rst),
.we_i(wb_cp0_reg_we_i),
.waddr_i(wb_cp0_reg_write_addr_i),
.raddr_i(cp0_raddr_i),
.data_i(wb_cp0_reg_data_i),
.excepttype_i(mem_excepttype_o),
.int_i(int_i),
.current_inst_addr_i(mem_current_inst_address_o),
.is_in_delayslot_i(mem_is_in_delayslot_o),
.data_o(cp0_data_o),
.count_o(cp0_count),
.compare_o(cp0_compare),
.status_o(cp0_status),
.cause_o(cp0_cause),
.epc_o(cp0_epc),
.config_o(cp0_config),
.prid_o(cp0_prid),
.timer_int_o(timer_int_o)
);
endmodule
openmips_min_sopc.v
`include "define.v"
module openmips(
input wire clk,
input wire rst,
input wire[5:0] int_i,
input wire[`RegBus] rom_data_i,
output wire[`RegBus] rom_addr_o,
output wire rom_ce_o,
input wire[`RegBus] ram_data_i,
output wire[`RegBus] ram_addr_o,
output wire[`RegBus] ram_data_o,
output wire ram_we_o,
output wire[3:0] ram_sel_o,
output wire[3:0] ram_ce_o,
output wire timer_int_o
);
wire[`InstAddrBus] pc;
wire[`InstAddrBus] id_pc_i;
wire[`InstBus] id_inst_i;
wire[`AluOpBus] id_aluop_o;
wire[`AluSelBus] id_alusel_o;
wire[`RegBus] id_reg1_o;
wire[`RegBus] id_reg2_o;
wire id_wreg_o;
wire[`RegAddrBus] id_wd_o;
wire id_is_in_delayslot_o;
wire[`RegBus] id_link_address_o;
wire[`RegBus] id_inst_o;
wire[31:0] id_excepttype_o;
wire[`RegBus] id_current_inst_address_o;
wire[`AluOpBus] ex_aluop_i;
wire[`AluSelBus] ex_alusel_i;
wire[`RegBus] ex_reg1_i;
wire[`RegBus] ex_reg2_i;
wire ex_wreg_i;
wire[`RegAddrBus] ex_wd_i;
wire ex_is_in_delayslot_i;
wire[`RegBus] ex_link_address_i;
wire[`RegBus] ex_inst_i;
wire[31:0] ex_excepttype_i;
wire[`RegBus] ex_current_inst_address_i;
wire ex_wreg_o;
wire[`RegAddrBus] ex_wd_o;
wire[`RegBus] ex_wdata_o;
wire[`RegBus] ex_hi_o;
wire[`RegBus] ex_lo_o;
wire ex_whilo_o;
wire[`AluOpBus] ex_aluop_o;
wire[`RegBus] ex_mem_addr_o;
wire[`RegBus] ex_reg2_o;
wire ex_cp0_reg_we_o;
wire[4:0] ex_cp0_reg_write_addr_o;
wire[`RegBus] ex_cp0_reg_data_o;
wire[31:0] ex_excepttype_o;
wire[`RegBus] ex_current_inst_address_o;
wire ex_is_in_delayslot_o;
wire mem_wreg_i;
wire[`RegAddrBus] mem_wd_i;
wire[`RegBus] mem_wdata_i;
wire[`RegBus] mem_hi_i;
wire[`RegBus] mem_lo_i;
wire mem_whilo_i;
wire[`AluOpBus] mem_aluop_i;
wire[`RegBus] mem_mem_addr_i;
wire[`RegBus] mem_reg2_i;
wire mem_cp0_reg_we_i;
wire[4:0] mem_cp0_reg_write_addr_i;
wire[`RegBus] mem_cp0_reg_data_i;
wire[31:0] mem_excepttype_i;
wire mem_is_in_delayslot_i;
wire[`RegBus] mem_current_inst_address_i;
wire mem_wreg_o;
wire[`RegAddrBus] mem_wd_o;
wire[`RegBus] mem_wdata_o;
wire[`RegBus] mem_hi_o;
wire[`RegBus] mem_lo_o;
wire mem_whilo_o;
wire mem_LLbit_value_o;
wire mem_LLbit_we_o;
wire mem_cp0_reg_we_o;
wire[4:0] mem_cp0_reg_write_addr_o;
wire[`RegBus] mem_cp0_reg_data_o;
wire[31:0] mem_excepttype_o;
wire mem_is_in_delayslot_o;
wire[`RegBus] mem_current_inst_address_o;
wire wb_wreg_i;
wire[`RegAddrBus] wb_wd_i;
wire[`RegBus] wb_wdata_i;
wire[`RegBus] wb_hi_i;
wire[`RegBus] wb_lo_i;
wire wb_whilo_i;
wire wb_LLbit_value_i;
wire wb_LLbit_we_i;
wire wb_cp0_reg_we_i;
wire[4:0] wb_cp0_reg_write_addr_i;
wire[`RegBus] wb_cp0_reg_data_i;
wire[31:0] wb_excepttype_i;
wire wb_is_in_delayslot_i;
wire[`RegBus] wb_current_inst_address_i;
wire reg1_read;
wire reg2_read;
wire[`RegBus] reg1_data;
wire[`RegBus] reg2_data;
wire[`RegAddrBus] reg1_addr;
wire[`RegAddrBus] reg2_addr;
wire[`RegBus] hi;
wire[`RegBus] lo;
wire[`DoubleRegBus] hilo_temp_o;
wire[1:0] cnt_o;
wire[`DoubleRegBus] hilo_temp_i;
wire[1:0] cnt_i;
wire[`DoubleRegBus] div_result;
wire div_ready;
wire[`RegBus] div_opdata1;
wire[`RegBus] div_opdata2;
wire div_start;
wire div_annul;
wire signed_div;
wire is_in_delayslot_i;
wire is_in_delayslot_o;
wire next_inst_in_delayslot_o;
wire id_branch_flag_o;
wire[`RegBus] branch_target_address;
wire[5:0] stall;
wire stallreq_from_id;
wire stallreq_from_ex;
wire LLbit_o;
wire[`RegBus] cp0_data_o;
wire[4:0] cp0_raddr_i;
wire flush;
wire[`RegBus] new_pc;
wire[`RegBus] cp0_count;
wire[`RegBus] cp0_compare;
wire[`RegBus] cp0_status;
wire[`RegBus] cp0_cause;
wire[`RegBus] cp0_epc;
wire[`RegBus] cp0_config;
wire[`RegBus] cp0_prid;
wire[`RegBus] latest_epc;
pc_reg pc_reg0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.new_pc(new_pc),
.branch_flag_i(id_branch_flag_o),
.branch_target_address_i(branch_target_address),
.pc(pc),
.ce(rom_ce_o)
);
assign rom_addr_o = pc;
if_id if_id0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.if_pc(pc),
.if_inst(rom_data_i),
.id_pc(id_pc_i),
.id_inst(id_inst_i)
);
id id0(
.rst(rst),
.pc_i(id_pc_i),
.inst_i(id_inst_i),
.ex_aluop_i(ex_aluop_o),
.reg1_data_i(reg1_data),
.reg2_data_i(reg2_data),
.ex_wreg_i(ex_wreg_o),
.ex_wdata_i(ex_wdata_o),
.ex_wd_i(ex_wd_o),
.mem_wreg_i(mem_wreg_o),
.mem_wdata_i(mem_wdata_o),
.mem_wd_i(mem_wd_o),
.is_in_delayslot_i(is_in_delayslot_i),
.reg1_read_o(reg1_read),
.reg2_read_o(reg2_read),
.reg1_addr_o(reg1_addr),
.reg2_addr_o(reg2_addr),
.aluop_o(id_aluop_o),
.alusel_o(id_alusel_o),
.reg1_o(id_reg1_o),
.reg2_o(id_reg2_o),
.wd_o(id_wd_o),
.wreg_o(id_wreg_o),
.excepttype_o(id_excepttype_o),
.inst_o(id_inst_o),
.next_inst_in_delayslot_o(next_inst_in_delayslot_o),
.branch_flag_o(id_branch_flag_o),
.branch_target_address_o(branch_target_address),
.link_addr_o(id_link_address_o),
.is_in_delayslot_o(id_is_in_delayslot_o),
.current_inst_address_o(id_current_inst_address_o),
.stallreq(stallreq_from_id)
);
regfile regfile1(
.clk (clk),
.rst (rst),
.we (wb_wreg_i),
.waddr (wb_wd_i),
.wdata (wb_wdata_i),
.re1 (reg1_read),
.raddr1 (reg1_addr),
.rdata1 (reg1_data),
.re2 (reg2_read),
.raddr2 (reg2_addr),
.rdata2 (reg2_data)
);
id_ex id_ex0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.id_aluop(id_aluop_o),
.id_alusel(id_alusel_o),
.id_reg1(id_reg1_o),
.id_reg2(id_reg2_o),
.id_wd(id_wd_o),
.id_wreg(id_wreg_o),
.id_link_address(id_link_address_o),
.id_is_in_delayslot(id_is_in_delayslot_o),
.next_inst_in_delayslot_i(next_inst_in_delayslot_o),
.id_inst(id_inst_o),
.id_excepttype(id_excepttype_o),
.id_current_inst_address(id_current_inst_address_o),
.ex_aluop(ex_aluop_i),
.ex_alusel(ex_alusel_i),
.ex_reg1(ex_reg1_i),
.ex_reg2(ex_reg2_i),
.ex_wd(ex_wd_i),
.ex_wreg(ex_wreg_i),
.ex_link_address(ex_link_address_i),
.ex_is_in_delayslot(ex_is_in_delayslot_i),
.is_in_delayslot_o(is_in_delayslot_i),
.ex_inst(ex_inst_i),
.ex_excepttype(ex_excepttype_i),
.ex_current_inst_address(ex_current_inst_address_i)
);
ex ex0(
.rst(rst),
.aluop_i(ex_aluop_i),
.alusel_i(ex_alusel_i),
.reg1_i(ex_reg1_i),
.reg2_i(ex_reg2_i),
.wd_i(ex_wd_i),
.wreg_i(ex_wreg_i),
.hi_i(hi),
.lo_i(lo),
.inst_i(ex_inst_i),
.wb_hi_i(wb_hi_i),
.wb_lo_i(wb_lo_i),
.wb_whilo_i(wb_whilo_i),
.mem_hi_i(mem_hi_o),
.mem_lo_i(mem_lo_o),
.mem_whilo_i(mem_whilo_o),
.hilo_temp_i(hilo_temp_i),
.cnt_i(cnt_i),
.div_result_i(div_result),
.div_ready_i(div_ready),
.link_address_i(ex_link_address_i),
.is_in_delayslot_i(ex_is_in_delayslot_i),
.excepttype_i(ex_excepttype_i),
.current_inst_address_i(ex_current_inst_address_i),
.mem_cp0_reg_we(mem_cp0_reg_we_o),
.mem_cp0_reg_write_addr(mem_cp0_reg_write_addr_o),
.mem_cp0_reg_data(mem_cp0_reg_data_o),
.wb_cp0_reg_we(wb_cp0_reg_we_i),
.wb_cp0_reg_write_addr(wb_cp0_reg_write_addr_i),
.wb_cp0_reg_data(wb_cp0_reg_data_i),
.cp0_reg_data_i(cp0_data_o),
.cp0_reg_read_addr_o(cp0_raddr_i),
.cp0_reg_we_o(ex_cp0_reg_we_o),
.cp0_reg_write_addr_o(ex_cp0_reg_write_addr_o),
.cp0_reg_data_o(ex_cp0_reg_data_o),
.wd_o(ex_wd_o),
.wreg_o(ex_wreg_o),
.wdata_o(ex_wdata_o),
.hi_o(ex_hi_o),
.lo_o(ex_lo_o),
.whilo_o(ex_whilo_o),
.hilo_temp_o(hilo_temp_o),
.cnt_o(cnt_o),
.div_opdata1_o(div_opdata1),
.div_opdata2_o(div_opdata2),
.div_start_o(div_start),
.signed_div_o(signed_div),
.aluop_o(ex_aluop_o),
.mem_addr_o(ex_mem_addr_o),
.reg2_o(ex_reg2_o),
.excepttype_o(ex_excepttype_o),
.is_in_delayslot_o(ex_is_in_delayslot_o),
.current_inst_address_o(ex_current_inst_address_o),
.stallreq(stallreq_from_ex)
);
ex_mem ex_mem0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.ex_wd(ex_wd_o),
.ex_wreg(ex_wreg_o),
.ex_wdata(ex_wdata_o),
.ex_hi(ex_hi_o),
.ex_lo(ex_lo_o),
.ex_whilo(ex_whilo_o),
.ex_aluop(ex_aluop_o),
.ex_mem_addr(ex_mem_addr_o),
.ex_reg2(ex_reg2_o),
.ex_cp0_reg_we(ex_cp0_reg_we_o),
.ex_cp0_reg_write_addr(ex_cp0_reg_write_addr_o),
.ex_cp0_reg_data(ex_cp0_reg_data_o),
.ex_excepttype(ex_excepttype_o),
.ex_is_in_delayslot(ex_is_in_delayslot_o),
.ex_current_inst_address(ex_current_inst_address_o),
.hilo_i(hilo_temp_o),
.cnt_i(cnt_o),
.mem_wd(mem_wd_i),
.mem_wreg(mem_wreg_i),
.mem_wdata(mem_wdata_i),
.mem_hi(mem_hi_i),
.mem_lo(mem_lo_i),
.mem_whilo(mem_whilo_i),
.mem_cp0_reg_we(mem_cp0_reg_we_i),
.mem_cp0_reg_write_addr(mem_cp0_reg_write_addr_i),
.mem_cp0_reg_data(mem_cp0_reg_data_i),
.mem_aluop(mem_aluop_i),
.mem_mem_addr(mem_mem_addr_i),
.mem_reg2(mem_reg2_i),
.mem_excepttype(mem_excepttype_i),
.mem_is_in_delayslot(mem_is_in_delayslot_i),
.mem_current_inst_address(mem_current_inst_address_i),
.hilo_o(hilo_temp_i),
.cnt_o(cnt_i)
);
mem mem0(
.rst(rst),
.wd_i(mem_wd_i),
.wreg_i(mem_wreg_i),
.wdata_i(mem_wdata_i),
.hi_i(mem_hi_i),
.lo_i(mem_lo_i),
.whilo_i(mem_whilo_i),
.aluop_i(mem_aluop_i),
.mem_addr_i(mem_mem_addr_i),
.reg2_i(mem_reg2_i),
.mem_data_i(ram_data_i),
.LLbit_i(LLbit_o),
.wb_LLbit_we_i(wb_LLbit_we_i),
.wb_LLbit_value_i(wb_LLbit_value_i),
.cp0_reg_we_i(mem_cp0_reg_we_i),
.cp0_reg_write_addr_i(mem_cp0_reg_write_addr_i),
.cp0_reg_data_i(mem_cp0_reg_data_i),
.excepttype_i(mem_excepttype_i),
.is_in_delayslot_i(mem_is_in_delayslot_i),
.current_inst_address_i(mem_current_inst_address_i),
.cp0_status_i(cp0_status),
.cp0_cause_i(cp0_cause),
.cp0_epc_i(cp0_epc),
.wb_cp0_reg_we(wb_cp0_reg_we_i),
.wb_cp0_reg_write_addr(wb_cp0_reg_write_addr_i),
.wb_cp0_reg_data(wb_cp0_reg_data_i),
.LLbit_we_o(mem_LLbit_we_o),
.LLbit_value_o(mem_LLbit_value_o),
.cp0_reg_we_o(mem_cp0_reg_we_o),
.cp0_reg_write_addr_o(mem_cp0_reg_write_addr_o),
.cp0_reg_data_o(mem_cp0_reg_data_o),
.wd_o(mem_wd_o),
.wreg_o(mem_wreg_o),
.wdata_o(mem_wdata_o),
.hi_o(mem_hi_o),
.lo_o(mem_lo_o),
.whilo_o(mem_whilo_o),
.mem_addr_o(ram_addr_o),
.mem_we_o(ram_we_o),
.mem_sel_o(ram_sel_o),
.mem_data_o(ram_data_o),
.mem_ce_o(ram_ce_o),
.excepttype_o(mem_excepttype_o),
.cp0_epc_o(latest_epc),
.is_in_delayslot_o(mem_is_in_delayslot_o),
.current_inst_address_o(mem_current_inst_address_o)
);
mem_wb mem_wb0(
.clk(clk),
.rst(rst),
.stall(stall),
.flush(flush),
.mem_wd(mem_wd_o),
.mem_wreg(mem_wreg_o),
.mem_wdata(mem_wdata_o),
.mem_hi(mem_hi_o),
.mem_lo(mem_lo_o),
.mem_whilo(mem_whilo_o),
.mem_LLbit_we(mem_LLbit_we_o),
.mem_LLbit_value(mem_LLbit_value_o),
.mem_cp0_reg_we(mem_cp0_reg_we_o),
.mem_cp0_reg_write_addr(mem_cp0_reg_write_addr_o),
.mem_cp0_reg_data(mem_cp0_reg_data_o),
.wb_wd(wb_wd_i),
.wb_wreg(wb_wreg_i),
.wb_wdata(wb_wdata_i),
.wb_hi(wb_hi_i),
.wb_lo(wb_lo_i),
.wb_whilo(wb_whilo_i),
.wb_LLbit_we(wb_LLbit_we_i),
.wb_LLbit_value(wb_LLbit_value_i),
.wb_cp0_reg_we(wb_cp0_reg_we_i),
.wb_cp0_reg_write_addr(wb_cp0_reg_write_addr_i),
.wb_cp0_reg_data(wb_cp0_reg_data_i)
);
hilo_reg hilo_reg0(
.clk(clk),
.rst(rst),
.we(wb_whilo_i),
.hi_i(wb_hi_i),
.lo_i(wb_lo_i),
.hi_o(hi),
.lo_o(lo)
);
ctrl ctrl0(
.rst(rst),
.excepttype_i(mem_excepttype_o),
.cp0_epc_i(latest_epc),
.stallreq_from_id(stallreq_from_id),
.stallreq_from_ex(stallreq_from_ex),
.new_pc(new_pc),
.flush(flush),
.stall(stall)
);
div div0(
.clk(clk),
.rst(rst),
.signed_div_i(signed_div),
.opdata1_i(div_opdata1),
.opdata2_i(div_opdata2),
.start_i(div_start),
.annul_i(flush),
.result_o(div_result),
.ready_o(div_ready)
);
LLbit_reg LLbit_reg0(
.clk(clk),
.rst(rst),
.flush(flush),
.LLbit_i(wb_LLbit_value_i),
.we(wb_LLbit_we_i),
.LLbit_o(LLbit_o)
);
cp0_reg cp0_reg0(
.clk(clk),
.rst(rst),
.we_i(wb_cp0_reg_we_i),
.waddr_i(wb_cp0_reg_write_addr_i),
.raddr_i(cp0_raddr_i),
.data_i(wb_cp0_reg_data_i),
.excepttype_i(mem_excepttype_o),
.int_i(int_i),
.current_inst_addr_i(mem_current_inst_address_o),
.is_in_delayslot_i(mem_is_in_delayslot_o),
.data_o(cp0_data_o),
.count_o(cp0_count),
.compare_o(cp0_compare),
.status_o(cp0_status),
.cause_o(cp0_cause),
.epc_o(cp0_epc),
.config_o(cp0_config),
.prid_o(cp0_prid),
.timer_int_o(timer_int_o)
);
endmodule
opemmips_min_sopc_tb.v
`include "define.v"
`timescale 1ns/1ps
module openmips_min_sopc_tb();
reg CLOCK_50;
reg rst;
initial begin
CLOCK_50 = 1'b0;
forever #10 CLOCK_50 = ~CLOCK_50;
end
initial begin
rst = `RstEnable;
#195 rst = `RstDisable;
#1000 $stop;
end
openmips_min_sopc openmips_min_sopc0(
.clk(CLOCK_50),
.rst(rst)
);
endmodule
测试文件和结果
测试文件分为3个,分别对系统调用异常 ,自陷异常 ,时钟和中断 进行测试,结果就是看各个寄存器的值是否和指令中的相符。测试文件和结果就不放出来了。
完结撒花
|