mips五级流水线模型机设计与实现

五级流水线MIPS模型机系统结构示意图
image.png
MIPS指令格式
image.png

image.png
defines.v
//GlobalFlag
`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 InterruptAssert 1'b1
`define InterruptNotAssert 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 IOBase 32'hfffff000


//MipsAluOp
`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_ADDI 6'b001000
`define EXE_ADD  6'b100000
`define EXE_SUB  6'b100010

`define EXE_SLL  6'b000000
`define EXE_SRL  6'b000010
`define EXE_SRA  6'b000011

`define EXE_MULT  6'b011000
`define EXE_MUL  6'b000010

`define EXE_LW  6'b100011
`define EXE_SW  6'b101011

`define EXE_J  6'b000010
`define EXE_JAL  6'b000011
`define EXE_JR  6'b001000
`define EXE_BEQ  6'b000100
`define EXE_BNE  6'b000101

`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

//AluOp
`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_ADDI_OP  8'b01001000   
`define EXE_ADD_OP  8'b00100000
`define EXE_SUB_OP  8'b00100010


`define EXE_SLL_OP  8'b01111100
`define EXE_SRL_OP  8'b00000010
`define EXE_SRA_OP  8'b00000011


`define EXE_MULT_OP  8'b00011000
`define EXE_MUL_OP  8'b10101001

`define EXE_LW_OP  8'b11100011
`define EXE_SW_OP  8'b11101011


`define EXE_J_OP  8'b01001111
`define EXE_JAL_OP  8'b01010000
`define EXE_JR_OP  8'b00001000
`define EXE_BEQ_OP  8'b01010001
`define EXE_BNE_OP  8'b01010010

`define EXE_NOP_OP    8'b00000000

//AluSel
`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


//inst_rom
`define InstAddrBus 31:0
`define InstBus 31:0
`define InstMemNum   511//131071
`define InstMemNumLog2 10//17

`define KeyBus 15:0
`define SEGBus 31:0


//regfile
`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

//mem
`define MemBus         31:0
`define MemAddrBus     31:0
`define MemWidth       32
`define DataMemNum     511 //131071
`define DataMemNumLog2 10 //17

//IO
`define IONum 511//4095
`define IOWidth       32
`define IOBus         31:0
`define IOAddrBus     31:0
`define IONumLog2      10//12

//IO _ Addr
`define SEG_ADDR 32'hFFFFF000
`define LED_ADDR 32'hFFFFF004
`define KEY_ADDR 32'hFFFFF008
`define BUTTON_ADDR 32'hFFFFF00c

test.v

`include "top.v"

module inst_rom(input wire ce,
                input wire [`InstAddrBus] addr,
                output reg [`InstBus] inst);
                
    reg [`InstBus] inst_mem [`InstMemNum-1:0];    
    initial $readmemh ("G:\init_h.txt",inst_mem);
    /*
    initial
      begin
        inst_mem[0] = 32'h8fc50008;
        inst_mem[1] = 32'hafc20004;
        inst_mem[2] = 32'h8fc6000c;
        inst_mem[3] = 32'hafc40000;
      end
      */
    
    always@(*)
      if(ce == `ChipDisable)
        inst <= `ZeroWord;
      else
        inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
endmodule

module openmips_min_sopc(input wire clk,
                         input wire rst);
    wire [`InstAddrBus] inst_addr;
    wire [`InstBus] inst;
    wire rom_ce;
    
    OpenMIPS OpenMIPS0(.clk(clk),
                       .rst(rst),
                       .rom_addr_o(inst_addr),
                       .rom_data_i(inst),
                       .rom_ce_o(rom_ce));
                       
    inst_rom inst_rom0(.ce(rom_ce),
                       .addr(inst_addr),
                       .inst(inst));
endmodule

module OpenMIPS_tb;
    reg clk;
    reg rst;
    initial
      begin
        clk = 1'b0;
        forever #10 clk = ~clk; 
      end
    initial
      begin
        rst = `RstDisable;
        #195 rst = `RstEnable;
        #1000 $stop;  
      end
    
    openmips_min_sopc     openmips_min_sopc0(.clk(clk),
                                             .rst(rst));
endmodule

top.v

`include "defines.v"

module OpenMIPS(input wire rst,
                input wire clk,
                input wire [`RegBus] rom_data_i,
                output wire [`RegBus] rom_addr_o,
                output wire rom_ce_o);
//if_id to id input
wire[`RegBus] rom_data_i1;
wire[`RegBus] rom_addr_i1;                


//ID to ID_EX
wire[`RegBus] branch_addr;
wire branch_flag;

//ID_EX to pc
wire[`RegBus] branch_addr1;
wire branch_flag1;    
                
//ID to ID_EX
wire[`AluOpBus] id_aluop;
wire[`AluSelBus] id_alusel;

wire[`RegBus] id_reg1;
wire[`RegBus] id_reg2;
wire          id_wreg;
wire[`RegAddrBus] id_wd;
wire[`RegBus] link_addr;
wire[`InstAddrBus] inst;

//ID_EX to EX
wire[`AluOpBus] id_aluop1;
wire[`AluSelBus] id_alusel1;
wire[`RegBus] id_reg11;
wire[`RegBus] id_reg21;
wire          id_wreg1;
wire[`RegAddrBus] id_wd1;
wire[`RegBus] link_addr1;
wire[`InstAddrBus] inst1;




//ID to Regfile
wire reg1_read;
wire reg2_read;
wire[`RegBus] reg1_data;
wire[`RegBus] reg2_data;
wire[`RegAddrBus] reg1_addr;
wire[`RegAddrBus] reg2_addr;

//EX to EX_WB
wire ex_wreg;
wire[`RegAddrBus] ex_wd;
wire[`RegBus] ex_wdata;
wire[`AluOpBus] ex_aluop;
wire[`MemAddrBus]  ex_memaddr;
wire[`MemBus] ex_reg1data;
wire[`MemBus] ex_reg2data;

//EX_WB to WB
wire ex_wreg1;
wire[`RegAddrBus] ex_wd1;
wire[`RegBus] ex_wdata1;
wire[`AluOpBus] ex_aluop1;
wire[`MemAddrBus]  ex_memaddr1;
wire[`MemBus] ex_reg1data1;
wire[`MemBus] ex_reg2data1;



//WB to wb_moic
wire[`RegAddrBus] wb_wd;
wire wb_wreg;
wire[`RegBus] wb_wdata;

//wb to wb_mioc
wire[`RegAddrBus] wb_wd1;
//MIOC to id input
wire[`RegAddrBus] wb_wd2;

//wb to id
wire[`RegAddrBus] wb_wd_id;
wire wb_wreg_id;
wire[`RegBus] wb_wdata_id;


//ex to id
wire[`RegAddrBus] ex_wd_id;
wire ex_wreg_id;
wire[`RegBus] ex_wdata_id;

/*
//WB to MIOC
wire[`MemBus] mem_wmemdata;
wire[`MemAddrBus] mem_memaddr;
wire mem_wmem;
wire mem_mce;
wire[3:0] mem_msel;
wire[`MemBus] mem_rm_idata;//MEM input into WB
*/

//HILO to ex
wire[`RegBus]           ex_hi;
wire[`RegBus]           ex_lo;
//HI - LO to ex input     
wire[`RegBus]           HILO_hi;
wire[`RegBus]           HILO_lo;
wire                    HILO_whilo;


//wb to wb_mioc input
wire ior;
wire iow;
wire [`MemBus]  rm_idata;
wire [`MemBus]  wm_idata;
wire [`MemAddrBus] m_iaddr;
wire mw;
wire mr;
wire [3:0] msel;


//wb_mioc to mioc input
wire ior1;
wire iow1;
wire [`MemBus]  rm_idata1;
wire [`MemBus]  wm_idata1;
wire [`MemAddrBus] m_iaddr1;
wire mw1;
wire mr1;
wire [3:0] msel1;
    
//MIOC to Mem output
wire[`MemBus]  rmdata;
wire[`MemBus] wmdata;
wire[`MemAddrBus] maddr;
wire memw;
wire mce;
wire[3:0] MI_msel;
    
    
//MIOC to IO output
wire [`IOBus] wiodata;
wire [`IOBus]  riodata;
wire iow2;
wire ice;
wire [`IOAddrBus] ioaddr;

//IO to FPGA
wire [`KeyBus] key;
wire [`SEGBus] SEG;
wire [`KeyBus] LED;


// id to ctrl req
wire stallreq_from_id;
//wire stallreq_from_mem;
//ctrl signal
wire [5:0] stall_ctrl;

//deal with load data relation
wire[`AluOpBus] ex_aluop_to_id;
wire[`AluOpBus] wb_aluop_to_id;
wire[`AluOpBus] MIOC_aluop_to_id;

wire[`AluOpBus] wb_MIOC_aluop;
wire[`AluOpBus] wb_MIOC_aluop1;

wire rst_sig = !rst;


assign wb_wd1 = wb_wd;
assign ex_aluop_to_id = ex_aluop;
assign wb_aluop_to_id = wb_MIOC_aluop;


ctrl ctrl1(
    .rst(rst_sig),
    //from ex stop req
    .stallreq_from_id(stallreq_from_id),
    //.stallreq_from_mem(stallreq_from_mem),
    .stall(stall_ctrl)       
    
);

//pc_reg real
pc_reg pc_reg0(
    .clk(clk),
    .rst(rst_sig),
    .stall(stall_ctrl),
    .branch_addr_i(branch_addr),
    .branch_flag_i(branch_flag),
    .pc(rom_addr_o),
    .ce(rom_ce_o)
);

//IF_ID real
IF_ID if_id1(
    .clk(clk),
    .rst(rst_sig),
    .stall(stall_ctrl),
    //rom to IF-ID input
    .inst_i(rom_data_i),
    //pc to IF-ID input
    .pc_i(rom_addr_o),
    //IF-ID to id output
    .inst_o(rom_data_i1),
    .pc_o(rom_addr_i1)
);
//ID real
id id0(
    .rst(rst_sig),  
    .pc_i(rom_addr_i1), 
    .inst_i(rom_data_i1),
    //deal with data relation
    .ex_aluop_i(ex_aluop_to_id),
    .wb_aluop_i(wb_aluop_to_id),
    .MIOC_aluop_i(MIOC_aluop_to_id),
   
    //Regfile - id input 
    .reg1_data_i(reg1_data),    .reg2_data_i(reg2_data),
    
    //MIOC to id 
    .MIOC_wd_to_id_i(wb_wd2),
    //wb to id input
    .wb_wd_to_id_i(wb_wd_id),
    .wb_wreg_to_id_i(wb_wreg_id),
    .wb_wdata_to_id_i(wb_wdata_id),
    //ex to id input
    .ex_wd_to_id_i(ex_wd_id),
    .ex_wreg_to_id_i(ex_wreg_id),
    .ex_wdata_to_id_i(ex_wdata_id),
    //id - Regfile output
    .reg1_read_o(reg1_read),    .reg2_read_o(reg2_read),
    .reg1_addr_o(reg1_addr),    .reg2_addr_o(reg2_addr),
    //id - EX output
    .link_addr_o(link_addr),
    .inst_o(inst),
    .aluop_o(id_aluop),   .alusel_o(id_alusel),
    .reg1_o(id_reg1),     .reg2_o(id_reg2),
    .wd_o(id_wd),         .wreg_o(id_wreg),
    //id - pc output
    .branch_addr_o(branch_addr),
    .branch_flag_o(branch_flag),
    .stallreq(stallreq_from_id)
);
//Regfile real
regfile regfile1(
    .clk(clk),
    .rst(rst_sig),
    //WB-regfile input
    .we(wb_wreg), .waddr(wb_wd),
    .wdata(wb_wdata),
    //ID-regfile input
    .re1(reg1_read),    .raddr1(reg1_addr), 
    .rdata1(reg1_data),
    .re2(reg2_read),    .raddr2(reg2_addr),
    .rdata2(reg2_data)
);
//ID_EX real
ID_EX id_ex1(
    .clk(clk),
    .rst(rst_sig),
    .stall(stall_ctrl),
    // id to ID_EX input
    .branch_addr_i(branch_addr),
    .branch_flag_i(branch_flag),
    //id to ID_EX input 
    .link_addr_i(link_addr),
    .inst_i(inst),
    .aluop_i(id_aluop),
    .alusel_i(id_alusel),
    .reg1_i(id_reg1),
    .reg2_i(id_reg2),
    .wd_i(id_wd),
    .wreg_i(id_wreg),
    //ID_EX to pc output
    .branch_addr_o(branch_addr1),
    .branch_flag_o(branch_flag1),
    //ID_EX to Ex output
    .link_addr_o(link_addr1),
    .inst_o(inst1),
    .aluop_o(id_aluop1),
    .alusel_o(id_alusel1),
    .reg1_o(id_reg11),
    .reg2_o(id_reg21),
    .wd_o(id_wd1),
    .wreg_o(id_wreg1)
);

//EX real
ex ex0(
    .rst(rst_sig),
    //ID-ex input
    .link_addr_i(link_addr1),
    .inst_i(inst1),
    .aluop_i(id_aluop1),   .alusel_i(id_alusel1),
    .reg1_i(id_reg11),     .reg2_i(id_reg21),
    .wd_i(id_wd1),         .wreg_i(id_wreg1),
    //ex_to_id output
    .ex_wd_to_id_o(ex_wd_id),
    .ex_wreg_to_id_o(ex_wreg_id),
    .ex_wdata_to_id_o(ex_wdata_id),
    //HI?LO?????
      .hi_i(ex_hi),
      .lo_i(ex_lo),
      .hi_o(HILO_hi),
      .lo_o(HILO_lo),
      .whilo_o(HILO_whilo),
    // ex-WB output
    .aluop_o(ex_aluop),
    .memaddr_o(ex_memaddr),
    .reg1data_o(ex_reg1data),//
    .reg2data_o(ex_reg2data),
    .wd_o(ex_wd),
    .wreg_o(ex_wreg),
    .wdata_o(ex_wdata)
);

// EX_WB real
EX_WB ex_wb1(
  .clk(clk),
  .rst(rst_sig),
  .stall(stall_ctrl),
  //ex to EX_WB input
  .aluop_i(ex_aluop),
  .memaddr_i(ex_memaddr),
  .reg1data_i(ex_reg1data),
  .reg2data_i(ex_reg2data),
  .wd_i(ex_wd),
  .wreg_i(ex_wreg),
  .wdata_i(ex_wdata),
  //EX_WB to wb output
  .aluop_o(ex_aluop1),
  .memaddr_o(ex_memaddr1),
  .reg1data_o(ex_reg1data1),
  .reg2data_o(ex_reg2data1),
  .wd_o(ex_wd1),
  .wreg_o(ex_wreg1),
  .wdata_o(ex_wdata1)
);

hilo_reg hilo_reg1(
    .clk(clk),
    .rst(rst_sig),
    .we(HILO_whilo),
    .hi_i(HILO_hi),
    .lo_i(HILO_lo),
    .hi_o(ex_hi),
    .lo_o(ex_lo)
);

//WB real
wb wb0(
    .rst(rst_sig),
    //ex - wb input
    .aluop_i(ex_aluop1),
    .memaddr_i(ex_memaddr1),
    .rmemdata_i(rm_idata),
    .reg1data_i(ex_reg1data1),
    .reg2data_i(ex_reg2data1),
    // input
    .ex_wd(ex_wd1),
    .ex_wreg(ex_wreg1),
    .ex_wdata(ex_wdata1),
    .aluop_o(wb_MIOC_aluop),
    //wb_to_id  output
    .wb_wd_to_id_o(wb_wd_id),
    .wb_wreg_to_id_o(wb_wreg_id),
    .wb_wdata_to_id_o(wb_wdata_id),
    //Wb-regfile output
    .wb_wd(wb_wd),  .wb_wreg(wb_wreg),
    .wb_wdata(wb_wdata),
    //wb - mem-ram output
    .mem_wmemdata_o(wm_idata),
    .mem_memaddr_o(m_iaddr),
    .mem_wmem_o(mw),
    .mem_rmem_o(mr),
    .mem_msel_o(msel),
    .iow(iow),
    .ior(ior)
);


WB_MIOC wb_mioc1(
  .clk(clk),
  .rst(rst_sig),
  .stall(stall_ctrl),
  .aluop_i(wb_MIOC_aluop),
  .aluop_o(wb_MIOC_aluop1),
  //wb to WB_MIOC input
  .rmemdata_o(rm_idata),
  .iow_i(iow),
  .ior_i(ior),    
    .mem_wmemdata_i(wm_idata),
    .mem_memaddr_i(m_iaddr),
    .mem_wmem_i(mw),
    .mem_rmem_i(mr),
    .mem_msel_i(msel),
    //wb-wb-moic input
    .wb_wd_i(wb_wd1),
    //.wb_wreg_i(wb_wreg),
    //.wb_wdata_i(wb_wdata), 
  //WB_MIOC to MIOC output
  .ior_o(ior1),
  .iow_o(iow1),
  .rm_idata_i(rm_idata1),
  .wm_idata_o(wm_idata1),
    .m_iaddr_o(m_iaddr1),
    .mw_o(mw1),
    .mr_o(mr1),
    .msel_o(msel1),
    //WB_MIOC-Regfile output
    .wb_wd_o(wb_wd2)
    //.wb_wreg_o(wb_wreg1),
    //.wb_wdata_o(wb_wdata1),
    //.stallreq_from_mem(stallreq_from_mem)
);

MIOC MIOC1(//wb to mioc input
    .rst(rst_sig),
    .aluop_i(wb_MIOC_aluop1), 
    .ior_i(ior1),
    .iow_i(iow1),
    .rm_idata_o(rm_idata1),
    .wm_idata_i(wm_idata1),
    .m_iaddr_i(m_iaddr1),
    .mw_i(mw1),
    .mr_i(mr1),
    .msel_i(msel1),
    
    .aluop_o(MIOC_aluop_to_id),
    
     //MIOC to Mem output
    .rmdata_i(rmdata),
    .wmdata_o(wmdata),
    .maddr_o(maddr),
    .memw_o(memw),
    .mce_o(mce),
    .msel_o(MI_msel),

     //MIOC to IO output
    .wiodata_o(wiodata),
    .riodata_i(riodata),
    .iow_o(iow2),
    .ice_o(ice),
    .ioaddr_o(ioaddr)
);

//MEM  real
mem mem1(
    .clk(clk),
    .mem_wmemdata_i(wmdata),
    .mem_memaddr_i(maddr),
    .mem_wmem_i(memw),
    .mem_msel_i(MI_msel),
    .mem_mce_i(mce),
    .rmemdata_o(rmdata)
);

IO IO1(
    .addr_i(ioaddr),
    .ce_i(ice),
    .iow_i(iow2),
    .rdata_o(riodata),
    .wdata_i(wiodata),
    .clk(clk),
    .rst(rst_sig),
    .key(key),
    .SEG(SEG),
    .LED(LED)
);

endmodule


module IF_ID(
  input wire clk,
  input wire rst,
    //?????????
    input wire[5:0]               stall,    
  //rom to IF-ID input
  input wire [`InstBus]     inst_i,
  //pc to IF-ID input
  input wire [`InstAddrBus] pc_i,
  //IF-ID to id output
  output reg [`InstBus]     inst_o,
  output reg [`InstAddrBus] pc_o
);
   always@(posedge clk)
    begin
      if(rst == `RstEnable)
        begin
         inst_o <= `ZeroWord;
         pc_o <= `ZeroWord;
      end else if(stall[1] == `Stop && stall[2] == `NoStop) begin
               inst_o <= `ZeroWord;
               pc_o <= `ZeroWord;   
        end else if(stall[1] == `NoStop) begin
         inst_o <= inst_i;
         pc_o <= pc_i;
      end
    end
endmodule 


module ID_EX(
    input wire clk,
    input wire rst,
    //?????????
      input wire[5:0]                            stall,
    // id to ID_EX input
    input wire[`RegBus]         branch_addr_i,
    input wire                  branch_flag_i,
    //id to ID_EX input 
    input wire[`RegBus]            link_addr_i,
    input wire[`InstAddrBus]       inst_i,
    
    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,
    //ID_EX to pc output
    output reg[`RegBus]         branch_addr_o,
    output reg                  branch_flag_o,
    //ID_EX to Ex output
    output reg[`RegBus]            link_addr_o,
    output reg[`InstAddrBus]       inst_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
);
   always@(posedge clk)
    begin
      if(rst == `RstEnable)
        begin
          aluop_o <= `EXE_NOP_OP;
          alusel_o <= `EXE_RES_NOP;
          wd_o <= `NOPRegAddr;
          wreg_o <= `WriteDisable;
            link_addr_o <= `ZeroWord;
            inst_o <= `ZeroWord;
                branch_addr_o <= `ZeroWord;
                branch_flag_o <= `NotBranch;
          reg1_o <= `ZeroWord;
          reg2_o <= `ZeroWord;
      end else if(stall[2] == `Stop && stall[3] == `NoStop) begin
                aluop_o <= `EXE_NOP_OP;
          alusel_o <= `EXE_RES_NOP;
          wd_o <= `NOPRegAddr;
          wreg_o <= `WriteDisable;
            link_addr_o <= `ZeroWord;
            inst_o <= `ZeroWord;
                branch_addr_o <= `ZeroWord;
                branch_flag_o <= `NotBranch;
          reg1_o <= `ZeroWord;
          reg2_o <= `ZeroWord;      
          end else if(stall[2] == `NoStop) begin
          branch_addr_o <= branch_addr_i;
          branch_flag_o<= branch_flag_i;
          link_addr_o<= link_addr_i;
          inst_o<= inst_i;
          aluop_o<= aluop_i;
          alusel_o<= alusel_i;
          reg1_o<= reg1_i;
          reg2_o<= reg2_i;
          wd_o<= wd_i;
          wreg_o<= wreg_i;
      end
    end
endmodule 

module EX_WB(
  input wire clk,
  input wire rst,
    //?????????
    input wire[5:0]                          stall, 
  //ex to EX_WB input
  input wire[`AluOpBus]           aluop_i,
  input wire[`MemAddrBus]         memaddr_i,
  input wire[`MemBus]             reg1data_i,
  input wire[`MemBus]             reg2data_i,
  input wire[`RegAddrBus]         wd_i,
  input wire                      wreg_i,
  input wire[`RegBus]             wdata_i,
  //EX_WB to wb output
  output reg[`AluOpBus]           aluop_o,
  output reg[`MemAddrBus]         memaddr_o,
  output reg[`MemBus]             reg1data_o,
  output reg[`MemBus]             reg2data_o,
  output reg[`RegAddrBus]         wd_o,
  output reg                      wreg_o,
  output reg[`RegBus]             wdata_o
 
  
);
   always@(posedge clk)
    begin
      if(rst == `RstEnable)
        begin
         aluop_o <= `EXE_NOP_OP;
         memaddr_o <= `ZeroWord;
         reg1data_o <= `ZeroWord;
         reg2data_o <= `ZeroWord;
         wd_o <= `NOPRegAddr;
         wreg_o <= `WriteDisable;
         wdata_o <= `ZeroWord;
      end else if(stall[3] == `Stop && stall[4] == `NoStop) begin
                aluop_o <= `EXE_NOP_OP;
         memaddr_o <= `ZeroWord;
         reg1data_o <= `ZeroWord;
         reg2data_o <= `ZeroWord;
         wd_o <= `NOPRegAddr;
         wreg_o <= `WriteDisable;
         wdata_o <= `ZeroWord;              
        end else if(stall[3] == `NoStop) begin
         aluop_o <= aluop_i;
         memaddr_o <= memaddr_i;
         reg1data_o <= reg1data_i;
         reg2data_o <= reg2data_i;
         wd_o <= wd_i;
         wreg_o <= wreg_i;
         wdata_o <= wdata_i;
      end
    end
endmodule 


module WB_MIOC(
  input wire clk,
  input wire rst,
  //?????????
    input wire[5:0]               stall,    
  
  input wire[`AluOpBus]        aluop_i,
  //wb to WB_MIOC input
  output reg[`MemBus]     rmemdata_o,
  input wire iow_i,
  input wire ior_i,    
    input wire[`MemBus] mem_wmemdata_i,
    input wire[`MemAddrBus] mem_memaddr_i,
    input wire mem_wmem_i,
    input wire mem_rmem_i,
    input wire[3:0] mem_msel_i,
    //wb - WB_MIOC input
    input wire[`RegAddrBus]      wb_wd_i,
    input wire                   wb_wreg_i,
    input wire[`RegBus]                  wb_wdata_i, 
    output reg[`AluOpBus]           aluop_o,
  //WB_MIOC to MIOC output
  output reg ior_o,
  output reg iow_o,
  input wire [`MemBus]  rm_idata_i,
  output reg [`MemBus]  wm_idata_o,
    output reg [`MemAddrBus] m_iaddr_o,
    output reg mw_o,
    output reg mr_o,
    output reg [3:0] msel_o,
    //WB_MIOC-Regfile output
    output reg[`RegAddrBus]      wb_wd_o,
    output reg                   wb_wreg_o,
    output reg[`RegBus]                  wb_wdata_o       
);
   always@(posedge clk)
    begin
      if(rst == `RstEnable)
        begin
         rmemdata_o <= `ZeroWord;
         ior_o <= `ReadDisable;
         iow_o <= `WriteDisable;
         wm_idata_o <= `ZeroWord;
         m_iaddr_o <= `ZeroWord;
         mw_o <= `WriteDisable;
         mr_o <= `ReadDisable;
         msel_o <= 4'b0000;
         wb_wd_o <= `NOPRegAddr;
         wb_wreg_o <= `WriteDisable;
         wb_wdata_o <= `ZeroWord;
         aluop_o <= `EXE_NOP_OP;
      end else if(stall[4] == `Stop && stall[5] == `NoStop) begin
               rmemdata_o <= `ZeroWord;
         ior_o <= `ReadDisable;
         iow_o <= `WriteDisable;
         wm_idata_o <= `ZeroWord;
         m_iaddr_o <= `ZeroWord;
         mw_o <= `WriteDisable;
         mr_o <= `ReadDisable;
         msel_o <= 4'b0000;
         wb_wd_o <= `NOPRegAddr;
         wb_wreg_o <= `WriteDisable;
         wb_wdata_o <= `ZeroWord;
         aluop_o <= `EXE_NOP_OP;          
          end else if(stall[4] == `NoStop) begin
                 rmemdata_o <= rm_idata_i;
         ior_o <= ior_i;
         iow_o <= iow_i;
         wm_idata_o <= mem_wmemdata_i;
         m_iaddr_o <= mem_memaddr_i;
         mw_o <= mem_wmem_i;
         mr_o <=mem_rmem_i;
         msel_o <= mem_msel_i;
         wb_wd_o <= wb_wd_i;
         wb_wreg_o <= wb_wreg_i;
         wb_wdata_o <= wb_wdata_i;
         aluop_o <= aluop_i;
          end
    end
endmodule 

module ctrl(
    input wire                                      rst,
    //from ex stop req
    input wire                   stallreq_from_id,
    //input wire                   stallreq_from_mem,
    output reg[5:0]              stall       
    
);
    always @ (*) begin
        if(rst == `RstEnable) begin
            stall <= 6'b000000;
        end /*else if(stallreq_from_mem == `Stop) begin
            stall <= 6'b000011;         
        end*/ else if(stallreq_from_id == `Stop) begin
            stall <= 6'b110000;         
        end else begin
            stall <= 6'b000000;
        end    //if
    end      //always
            

endmodule

module mem(
    input wire clk,
    input wire [`MemBus] mem_wmemdata_i,
    input wire [`MemAddrBus] mem_memaddr_i,
    input wire mem_wmem_i,
    input wire [3:0] mem_msel_i,
    input wire mem_mce_i,
    
    output reg[`MemBus] rmemdata_o
    
);
  reg [`MemBus] ram [`DataMemNum-1:0];
  
  always@(*)
    begin
      if(mem_mce_i == `ChipDisable)//ce=0 read
        begin
        rmemdata_o <= `ZeroWord;
      end
    else   
        begin
            rmemdata_o<=ram[mem_memaddr_i[`DataMemNumLog2+1:2]];
      end
    end
  always@(posedge clk)
    begin
      if(mem_mce_i == `ChipEnable && mem_wmem_i == `WriteEnable)
        begin
          ram[mem_memaddr_i[`DataMemNumLog2+1:2]]<=mem_wmemdata_i;
      end
    end
endmodule

module pc_reg(input wire clk,
              input wire rst,
                //from ctrl info
                input wire[5:0]               stall,
              input wire [`RegBus] branch_addr_i,
              input wire branch_flag_i,
              output reg [`InstAddrBus] pc,
              output reg ce);
    always@(posedge clk)
      if(rst == `RstEnable)
        ce <= `ChipDisable;
      else
        ce <= `ChipEnable;
        
    always@(posedge clk)
      if(ce == `ChipDisable)
        pc <= `ZeroWord;
      else if(branch_flag_i == `Branch)
        pc <= branch_addr_i;
      else if(stall[0] == `NoStop)
        pc <= pc + 3'b100;
endmodule

// HI-LO
module hilo_reg(

    input   wire                                        clk,
    input wire                                      rst,
    
    //???
    input wire                                      we,
    input wire[`RegBus]                 hi_i,
    input wire[`RegBus]                       lo_i,
    
    //???1
    output reg[`RegBus]           hi_o,
    output reg[`RegBus]           lo_o
    
);

    always @ (*) begin
        if (rst == `RstEnable) begin
                    hi_o <= `ZeroWord;
                    lo_o <= `ZeroWord;
        end else if((we == `WriteEnable)) begin
                    hi_o <= hi_i;
                    lo_o <= lo_i;
        end
    end

endmodule

module regfile(
  
    input wire clk,
    input wire rst,

    //wb-reg input
    input wire                  we,
    input wire[`RegAddrBus]     waddr,
    input wire[`RegBus]         wdata,

    //id-reg 1 
    input wire                  re1,
    input wire[`RegAddrBus]     raddr1,
    output reg[`RegBus]         rdata1,

    //id-reg 2
    input wire                  re2,
    input wire[`RegAddrBus]     raddr2,
    output reg[`RegBus]         rdata2
);

//32 bit 32 depth
reg[`RegBus] regs[0:`RegNum-1];

initial
  begin 
    regs[1]=32'hffff0000;
    regs[2]=32'h0000ffff;
    regs[3]=32'h0fff0000;
    regs[4]=32'h00ff0000;
    regs[30]=32'hfffff000;
    
  end
//???
always @ (posedge clk) begin
    if(rst==`RstDisable)begin
        if((we==`WriteEnable) && (waddr != `RegNumLog2'h0))begin
            regs[waddr]<=wdata;
        end
    end
end

//read reg1
always @ (*) begin
    if(rst==`RstEnable) begin
        rdata1<=`ZeroWord;
    end
    else if(raddr1==`RegNumLog2'h0) begin
        rdata1<=`ZeroWord;
    end
    else if(re1==`ReadEnable) begin
        rdata1<=regs[raddr1];
    end
    else begin
        rdata1<=`ZeroWord;
    end
end

//read reg2
always @ (*) begin
    if(rst==`RstEnable) begin
        rdata2<=`ZeroWord;
    end
    else if(raddr2==`RegNumLog2'h0) begin
        rdata2<=`ZeroWord;
    end
    else if(re2==`ReadEnable) begin
        rdata2<=regs[raddr2];
    end
    else begin
        rdata2<=`ZeroWord;
    end
end

endmodule

module id(
    input wire                  rst,
    input wire[`InstAddrBus]    pc_i,
    input wire[`InstBus]        inst_i,
    
    //deal with load data relation
    input wire[`AluOpBus]                   ex_aluop_i,
    input wire[`AluOpBus]                wb_aluop_i,
    input wire[`AluOpBus]                MIOC_aluop_i,
   
    //Regfile - id input
    input wire[`RegBus]         reg1_data_i,
    input wire[`RegBus]         reg2_data_i,
    
    //MIOC to id 
    input wire[`RegAddrBus] MIOC_wd_to_id_i,
    
    //wb to id
    input wire[`RegAddrBus] wb_wd_to_id_i,
    input wire              wb_wreg_to_id_i,
    input wire[`RegBus]     wb_wdata_to_id_i,


    //ex to id
    input wire[`RegAddrBus] ex_wd_to_id_i,
    input wire              ex_wreg_to_id_i,
    input wire[`RegBus]     ex_wdata_to_id_i,
    
    //Id - pc output
    output reg[`RegBus]         branch_addr_o,
    output reg                  branch_flag_o,
    
    //Id - Regfile output
    output reg                     reg1_read_o,
    output reg                     reg2_read_o,
    output reg[`RegAddrBus]        reg1_addr_o,
    output reg[`RegAddrBus]        reg2_addr_o,

    //ID- Ex output
    output reg[`RegBus]            link_addr_o,
    output reg[`InstAddrBus]       inst_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,
    output reg                     stallreq 
);
    
    wire [5:0] op = inst_i[31:26];//I!=0 _  R=000000 
    wire [4:0] op2 = inst_i[10:6];
    wire [5:0] op3 = inst_i[5:0];
    wire [4:0] op4 = inst_i[20:16];//wregaddr  rt
    
    reg[`RegBus] imm;
    reg instvalid;
    wire[`RegBus] pc_plus_4;
    wire[`RegBus] pc_plus_8;
    wire[`RegBus] imm_sll2_signedext;
    
    
    reg stallreq_for_reg1_loadrelate;
    reg stallreq_for_reg2_loadrelate;
    wire pre_inst_is_load;
    wire pre2_inst_is_load;
    wire pre3_inst_is_load;
    
    assign pre_inst_is_load = (ex_aluop_i == `EXE_LW_OP)? 1'b1 : 1'b0;
    assign pre2_inst_is_load = (wb_aluop_i == `EXE_LW_OP)? 1'b1 : 1'b0;
    assign pre3_inst_is_load = (MIOC_aluop_i == `EXE_LW_OP)? 1'b1 : 1'b0;
    
    //jump attribute
    assign pc_plus_4 = pc_i + 3'b100;//j inst nextinst adress
    assign pc_plus_8 = pc_i + 4'b1000;//save jal inst return inst adress
    assign imm_sll2_signedext = {{14{inst_i[15]}}, inst_i[15:0], 2'b00 }; //imm extend jump address
    
    //stream stop
    always@(*)begin 
      stallreq = stallreq_for_reg1_loadrelate | stallreq_for_reg2_loadrelate;
    end
    
    always@(*)      
      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;
            inst_o <= `ZeroWord;
                branch_addr_o <= `ZeroWord;
                branch_flag_o <= `NotBranch;
                //SW need inst
          inst_o <= inst_i;  
          stallreq <= `NoStop;     
        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;
         inst_o <= `ZeroWord;
               branch_addr_o <= `ZeroWord;
               branch_flag_o <= `NotBranch;
               //SW need inst
         inst_o <= inst_i;
         stallreq <= `NoStop; 
            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_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_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_MULT: begin
                                wreg_o <= `WriteDisable;        aluop_o <= `EXE_MULT_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;
                                link_addr_o <= `ZeroWord;
                                branch_addr_o <= reg1_o;
                      branch_flag_o <= `Branch;
                instvalid <= `InstValid;    
                                end
                         default:   begin
                            end
                        endcase
                    end
                    default: begin
                        end
                endcase 
                end                                   
            `EXE_ORI:           begin                        //ORI??
                  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_ADDI:          begin               //addi 
                 wreg_o <= `WriteEnable;        aluop_o <= `EXE_ADD_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_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_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; //stallreq <= `Stop;
                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; // stallreq <= `Stop;
                 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_addr_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};
                branch_flag_o <= `Branch;   
                instvalid <= `InstValid;    
                end
                `EXE_JAL:           begin
                  wreg_o <= `WriteEnable;//write back 31 register
                  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;//save return address register   
                  link_addr_o <= pc_plus_4 ;//return instr address
                branch_addr_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};
                branch_flag_o <= `Branch;   
                instvalid <= `InstValid;    
                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_addr_o <= pc_plus_4 + imm_sll2_signedext;
                    branch_flag_o <= `Branch;   
                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_addr_o <= pc_plus_4 + imm_sll2_signedext;
                    branch_flag_o <= `Branch;           
                end
                end
                `EXE_SPECIAL2_INST:     begin
                    case ( op3 )
                        `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 
                        default:    begin
                        end
                    endcase      //EXE_SPECIAL_INST2 case
                end                                         
            default:            begin
                  aluop_o <= `EXE_NOP_OP;
              alusel_o <= `EXE_RES_NOP;
              wd_o <= inst_i[15:11];
              wreg_o <= `WriteDisable;
              instvalid <= `InstValid;
              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 <= 32'h0;
              link_addr_o <= `ZeroWord;
              inst_o <= `ZeroWord;
                    branch_addr_o <= `ZeroWord;
                    branch_flag_o <= `NotBranch; 
            end
          endcase         //case op
          
          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
       end         //always  
                
  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_to_id_i == reg1_addr_o && reg1_read_o == 1'b1 ) begin
          stallreq_for_reg1_loadrelate <= `Stop;                            
        end 
        else if(pre2_inst_is_load == 1'b1 && wb_wd_to_id_i == reg1_addr_o && reg1_read_o == 1'b1 ) begin
          stallreq_for_reg1_loadrelate <= `Stop;                            
        end
        else if(pre3_inst_is_load == 1'b1 && MIOC_wd_to_id_i == reg1_addr_o && reg1_read_o == 1'b1  ) begin
          stallreq_for_reg1_loadrelate <= `Stop;                            
        end
      else if((reg1_read_o == 1'b1) && (ex_wreg_to_id_i == 1'b1) && (ex_wd_to_id_i == reg1_addr_o)) begin
            reg1_o <= ex_wdata_to_id_i; 
        end 
      else if((reg1_read_o == 1'b1) && (wb_wreg_to_id_i == 1'b1) && (wb_wd_to_id_i == reg1_addr_o)) begin
            reg1_o <= wb_wdata_to_id_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
      stallreq_for_reg2_loadrelate <= `NoStop;  
        if(rst == `RstEnable) begin
            reg2_o <= `ZeroWord;
        end
        else if(pre_inst_is_load == 1'b1 && ex_wd_to_id_i == reg2_addr_o && reg2_read_o == 1'b1 ) begin
          stallreq_for_reg2_loadrelate <= `Stop;            
        end 
        else if(pre2_inst_is_load == 1'b1 && wb_wd_to_id_i == reg2_addr_o && reg2_read_o == 1'b1 ) begin
          stallreq_for_reg2_loadrelate <= `Stop;            
        end
        else if(pre3_inst_is_load == 1'b1 && MIOC_wd_to_id_i == reg2_addr_o && reg2_read_o == 1'b1  ) begin
          stallreq_for_reg2_loadrelate <= `Stop;            
        end
      else if((reg2_read_o == 1'b1) && (ex_wreg_to_id_i == 1'b1) && (ex_wd_to_id_i == reg2_addr_o)) begin
            reg2_o <= ex_wdata_to_id_i; 
        end 
        else if((reg2_read_o == 1'b1) && (wb_wreg_to_id_i == 1'b1) && (wb_wd_to_id_i == reg2_addr_o)) begin
            reg2_o <= wb_wdata_to_id_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     
endmodule

module ex(
    input wire rst,
    //ID-EX input
    input wire[`RegBus]             link_addr_i,
    input wire[`InstAddrBus]        inst_i,
    input wire[`AluOpBus]           aluop_i,
    input wire[`AluSelBus]          alusel_i,
    input wire[`RegBus]             reg1_i,
    input wire[`RegBus]             reg2_i,
    input wire[`RegAddrBus]         wd_i,
    input wire                      wreg_i,
    
    //HI?LO?????
      input wire[`RegBus]           hi_i,
      input wire[`RegBus]           lo_i,
    
      output reg[`RegBus]           hi_o,
      output reg[`RegBus]           lo_o,
      output reg                    whilo_o,
    
    output reg[`RegAddrBus] ex_wd_to_id_o,
    output reg              ex_wreg_to_id_o,
    output reg[`RegBus]     ex_wdata_to_id_o,
    
    //EX-WB output
    output reg[`AluOpBus]           aluop_o,
    output reg[`MemAddrBus]         memaddr_o,
    output reg[`MemBus]             reg1data_o,
    output reg[`MemBus]             reg2data_o,
    output reg[`RegAddrBus]         wd_o,
    output reg                      wreg_o,
    output reg[`RegBus]             wdata_o
  //  output reg                     stallreq   
    
);

  //logic result 
    reg[`RegBus] logicout;
    reg[`RegBus] shiftres;
    reg[`RegBus] arithmeticres;
    reg[`DoubleRegBus] mulres;
    
    reg[`RegBus] HI;
    reg[`RegBus] LO;
    wire[`RegBus] reg2_i_mux;
    wire[`RegBus] reg1_i_not;   
    wire[`RegBus] result_sum;
    wire ov_sum;

    wire[`RegBus] opdata1_mult;
    wire[`RegBus] opdata2_mult;
    wire[`DoubleRegBus] hilo_temp;

  //LW SW mem
    always @ (*) begin
      //op
    aluop_o <= aluop_i;
    //mem_addr
    memaddr_o <= reg1_i + {{16{inst_i[15]}},inst_i[15:0]};
       //sw save reg2value to memaddr
      reg1data_o <= reg1_i; 
      reg2data_o <= reg2_i; 
    end
      
    
    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 & reg2_i;
                end
                `EXE_XOR_OP:        begin
                    logicout <= reg1_i ^ reg2_i;
                end
                
                default:                begin
                    logicout <= `ZeroWord;
                end
            endcase
        end    //if
    end      //always

    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    //if
    end      //always
    
    //add?sub op2
    assign reg2_i_mux = (aluop_i == `EXE_SUB_OP)  
                                             ? (~reg2_i)+1 : reg2_i;
  //add?sub result
    assign result_sum = reg1_i + reg2_i_mux;                                         
  
  //overflag
    assign ov_sum = ((!reg1_i[31] && !reg2_i_mux[31]) && result_sum[31]) ||
                                    ((reg1_i[31] && reg2_i_mux[31]) && (!result_sum[31]));  
                                    

  
  always @ (*) begin
        if(rst == `RstEnable) begin
            arithmeticres <= `ZeroWord;
        end else begin
            case (aluop_i)
                `EXE_ADD_OP:        begin
                    arithmeticres <= result_sum; 
                end
                `EXE_SUB_OP:        begin
                    arithmeticres <= result_sum; 
                end     
                default:                begin
                    arithmeticres <= `ZeroWord;
                end
            endcase
        end
    end

  //mul two op
    assign opdata1_mult = (((aluop_i == `EXE_MUL_OP) || (aluop_i == `EXE_MULT_OP))
                                                    && (reg1_i[31] == 1'b1)) ? (~reg1_i + 1) : reg1_i;

  assign opdata2_mult = (((aluop_i == `EXE_MUL_OP) || (aluop_i == `EXE_MULT_OP))
                                                    && (reg2_i[31] == 1'b1)) ? (~reg2_i + 1) : reg2_i;  
    //mul result
    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))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

  //ex to mem?wb 
    always @ (*) begin
        if(rst == `RstEnable) begin
            {HI,LO} <= {`ZeroWord,`ZeroWord};
        end else begin
            {HI,LO} <= {hi_i,lo_i};         
        end
    end 
    
 //output
 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;
     end else begin
      wreg_o <= wreg_i;
     end
     aluop_o <= aluop_i;
     reg1data_o <= reg1_i;
     reg2data_o <=  reg2_i;
     case ( alusel_i ) 
        `EXE_RES_LOGIC:     begin
            wdata_o <= logicout;
        end
        `EXE_RES_SHIFT:     begin
            wdata_o <= shiftres;
        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_addr_i;
        end             
        default:                    begin
            wdata_o <= `ZeroWord;
        end
     endcase
 end    
 
 //HI _ LO
 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_MUL_OP) begin
            whilo_o <= `WriteEnable;
            hi_o <= mulres[63:32];
            lo_o <= mulres[31:0];           
        end else begin
            whilo_o <= `WriteDisable;
            hi_o <= `ZeroWord;
            lo_o <= `ZeroWord;
        end             
    end     
    //ex - id
    always @ (*) begin
     ex_wd_to_id_o <= wd_o;
     ex_wreg_to_id_o <= wreg_o;
     ex_wdata_to_id_o <= wdata_o;
    end 
endmodule


module wb(
    input wire  rst,

    //EX-WB input   
    input wire[`RegAddrBus]       ex_wd,
    input wire                    ex_wreg,
    input wire[`RegBus]                 ex_wdata,
    input wire[`AluOpBus]           aluop_i,
  input wire[`MemAddrBus]         memaddr_i,
  input wire[`MemBus]             reg1data_i,
  input wire[`MemBus]             reg2data_i,
  //mem-wb input
  input wire[`MemBus]             rmemdata_i,
  
  output reg[`AluOpBus]           aluop_o,
  output reg[`RegAddrBus]     wb_wd_to_id_o,
  output reg                  wb_wreg_to_id_o,
  output reg[`RegBus]         wb_wdata_to_id_o,
  //
  output reg iow,
  output reg ior,
    //wb-Regfile output
    output reg[`RegAddrBus]      wb_wd,
    output reg                   wb_wreg,
    output reg[`RegBus]                  wb_wdata,       
    //wb-mem output
    output reg[`MemBus] mem_wmemdata_o,
    output reg[`MemAddrBus] mem_memaddr_o,
    output reg mem_wmem_o,
    output reg mem_rmem_o,
    output reg[3:0] mem_msel_o
);
  
  always @ (*) begin
        if(rst == `RstEnable) begin
            wb_wd <= `NOPRegAddr;
            wb_wreg <= `WriteDisable;
          wb_wdata <= `ZeroWord;    
          mem_memaddr_o <= `ZeroWord;
          mem_wmem_o <= `WriteDisable;
          mem_rmem_o <= `ReadDisable;
          mem_msel_o <= 4'b0000;
          mem_wmemdata_o <= `ZeroWord;
          iow <= `WriteDisable;
          ior <= `ReadDisable;
          //mem_mce_o <= `ChipDisable;
          aluop_o   <= `EXE_NOP_OP;
          
        end else begin
          wb_wd <= ex_wd;
            wb_wreg <= ex_wreg;
            wb_wdata <= ex_wdata;   
            mem_memaddr_o <= `ZeroWord;
            mem_wmem_o <= `WriteDisable;
            mem_rmem_o <= `ReadDisable;
            mem_msel_o <= 4'b1111;
            mem_wmemdata_o <= `ZeroWord;
            //mem_mce_o <= `ChipDisable;
          iow <= `WriteDisable;
          ior <= `ReadDisable;
          aluop_o   <= aluop_i;
          
            case (aluop_i)
                `EXE_LW_OP:     begin
                  mem_rmem_o <= ((memaddr_i & `IOBase)!=`IOBase)?1:0;
                  ior <= ((memaddr_i & `IOBase)==`IOBase)?1:0;
                  if(ior == `ReadEnable) begin
                     mem_memaddr_o <= memaddr_i;
                       //mem_rmem_o <= `ReadEnable;
                       wb_wdata <= rmemdata_i;
                      //    mem_mce_o <= `ChipEnable;
                  end else if (mem_rmem_o == `ReadEnable) begin
                       mem_memaddr_o <= memaddr_i;
                       //mem_rmem_o <= `ReadEnable;
                       wb_wdata <= rmemdata_i;
                      //    mem_mce_o <= `ChipEnable;
                  end
                end
                `EXE_SW_OP:     begin
                  mem_wmem_o <= ((memaddr_i & `IOBase)!=`IOBase)?1:0;
                  iow <= ((memaddr_i & `IOBase)==`IOBase)?1:0;
                  if(iow == `WriteEnable)begin 
                     mem_memaddr_o <= memaddr_i;
                       //mem_wmem_o <= `WriteEnable;
                       mem_wmemdata_o <= reg2data_i;
                  end else if(mem_wmem_o == `WriteEnable) begin
                       mem_memaddr_o <= memaddr_i;
                       //mem_wmem_o <= `WriteEnable;
                       mem_wmemdata_o <= reg2data_i;
                    //  mem_mce_o <= `ChipEnable;
                    end
                end
    
                default:        begin
          //?????
                end
            endcase                         
        end    //if
    end      //always
    
    //wb - id
    always @ (*) begin
      wb_wd_to_id_o <= wb_wd;
      wb_wreg_to_id_o <= wb_wreg;
      wb_wdata_to_id_o <= wb_wdata;
    end 
endmodule



//mem-io
module MIOC(
  input wire rst,
  input wire[`AluOpBus]  aluop_i,
  //wb to mioc input
  input wire ior_i,
  input wire iow_i,
  output reg [`MemBus]  rm_idata_o,
  input wire [`MemBus]  wm_idata_i,
    input wire [`MemAddrBus] m_iaddr_i,
    input wire mw_i,
    input wire mr_i,
    input wire [3:0] msel_i,
    
    output reg [`AluOpBus]  aluop_o,
    
    //MIOC to Mem output
    input wire[`MemBus]  rmdata_i,
    output reg [`MemBus] wmdata_o,
    output reg [`MemAddrBus] maddr_o,
    output reg memw_o,
    output reg mce_o,
    output reg [3:0] msel_o,
    
    //MIOC to IO output
    output reg [`IOBus] wiodata_o,
    input wire [`IOBus]  riodata_i,
    output reg iow_o,
  output reg ice_o,
    output reg [`IOAddrBus] ioaddr_o
);          

  always @ (*) begin
        if(rst == `RstEnable) begin
          //output to wb
          rm_idata_o <= `ZeroWord;
          
          wmdata_o <= `ZeroWord;
          maddr_o <= `ZeroWord;
          memw_o <= `WriteDisable;
          mce_o <= `ChipDisable;
          msel_o <= 4'b0000;    
          
          wiodata_o <= `ZeroWord;
          iow_o <= `WriteDisable;
          ice_o <= `ChipDisable;
          ioaddr_o <= `ZeroWord;
          aluop_o <= `EXE_NOP_OP;
        end else begin
          aluop_o <= aluop_i;
            if(ior_i == `ReadEnable) begin
                rm_idata_o <= riodata_i;
            iow_o <= `WriteDisable;
            ice_o <= `ChipEnable;
            ioaddr_o <= m_iaddr_i;
            end else if (iow_i == `WriteEnable) begin
                ioaddr_o <= m_iaddr_i;
                iow_o <= `WriteEnable;
                ice_o <= `ReadEnable;
                wiodata_o <= wm_idata_i;
            end else if(mr_i == `ReadEnable)begin 
                rm_idata_o <= rmdata_i;
            maddr_o <= m_iaddr_i;
            memw_o <= `WriteDisable;
            mce_o <= `ChipEnable;
            msel_o <= 4'b1111;  
            end else if(mw_i == `WriteEnable) begin
                maddr_o <= m_iaddr_i;
                memw_o <= `WriteEnable;
                wmdata_o <= wm_idata_i;
                mce_o <= `ChipEnable;
                msel_o <= 4'b1111;          
            end
        end    //if
    end      //always
  
endmodule

module IO(
  //MIOC to IO input
  input wire [`IOAddrBus] addr_i,
  input wire ce_i,
  input wire iow_i,
  output reg [`IOBus]  rdata_o,
  input wire [`IOBus] wdata_i,
  
  input wire clk,
  input wire rst,
  input wire [`KeyBus] key,//0xFFFFF008
  input wire [`RegBus] Button,//0xFFFFF00c
  output reg [`SEGBus] SEG,//0xFFFFF000
  output reg [`KeyBus] LED//0xFFFFF004
);
  //IO model
  reg [`IOBus] IO [`IONum-1:0];

  always@(posedge clk)
    begin
      if(rst == `RstEnable) begin
        LED <= `ZeroWord;
            SEG <= `ZeroWord;
      end else begin
        case(addr_i)
              `LED_ADDR: begin
                   LED <= wdata_i[15:0];    
                 end
              `SEG_ADDR: begin
                 SEG <= wdata_i;
              end
            endcase
      end
  end 
  
  always@(*)
    begin
      if(ce_i == `ChipDisable) begin
           rdata_o <= `ZeroWord;
      end else begin
        case(addr_i)
          `KEY_ADDR: begin
               //rdata_o <= {{16{1'b0}},key[15:0]}; 
               rdata_o <= 32'hffff000f;
            end
          `BUTTON_ADDR: begin
             //rdata_o <= Button;
             rdata_o <= 32'hffffffff;
            end
        endcase
      end 
    end
endmodule
测试文件代码:
   .org 0x0
   .set noat
   .set noreorder
   .set nomacro
   .global _start
_start:
   
   ori  $1,$0,0x0001    # $1 = 0x01
   ori  $2,$0,0x0003 
   j    0x20
   andi $2,$2,0x0001    #if this instruction exed  $2=0x01
   
   .org 0x20
   addi $3,$1,0x0003  # $3  = $1+0x0003               
   
   jal  0x40   # $31 = 0x2c 
   add  $5,$31,$1 
   
   j  0x80
   .org 0x40
   ori  $5,$0,0x0001
   jr   $31
   .org 0x80 
   #è®؟ه�ک
   ori  $6,$0,0x4455
   sll  $6,$6,0x10
   ori  $6,$6,0x6677     
   sw   $6,0x8($0)       # [0x8] = 0x44, [0x9]= 0x55, [0xa]= 0x66, [0xb] = 0x77
   lw   $7,0x8($0)       # $1 = 0x4455667
   beq  $10,$11,s1
   or   $1,$0,$0
   ori  $1,$0,0x0001    # $1 = 0x01
   ori  $2,$0,0x0003
   .org 0x00b0
s1:
   ori  $1,$0,0x1111
   nop
   bne  $10,$1,_start
_loop:
   j _loop

生成的机器码:
34010001
34020003
08000008
30420001
00000000
00000000
00000000
00000000
20230003
0c000010
03e12820
08000020
00000000
00000000
00000000
00000000
34050001
03e00008
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
34064455
00063400
34c66677
ac060008
8c070008
114b0006
00000825
34010001
34020003
00000000
00000000
00000000
34011111
00000000
1541ffd1
0800002f
00000000

以上为mips五级流水线模型机的设计代码,仅供参考!!!

你可能感兴趣的:(mips五级流水线模型机设计与实现)