mips模型机在Sword板子部署在FPGA

单指令周期MIPS模型机系统结构示意图
image.png
MIPS指令格式
image.png

image.png
我是将模型机部署在sword板上,在FPGA实现模型机的运行。
BCD.V
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    10:53:22 06/28/2018 
// Design Name: 
// Module Name:    BCD 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module BCD(input [31:0]in,output reg[63:0]out);
  always@(in)
    begin
      case(in[3:0])
        4'b0000: out[7:0]=8'b00000011;
        4'b0001: out[7:0]=8'b10011111;
        4'b0010: out[7:0]=8'b00100101;
        4'b0011: out[7:0]=8'b00001101;
        4'b0100: out[7:0]=8'b10011001;
        4'b0101: out[7:0]=8'b01001001;
        4'b0110: out[7:0]=8'b01000001;
        4'b0111: out[7:0]=8'b00011111;
        4'b1000: out[7:0]=8'b00000001;
        4'b1001: out[7:0]=8'b00001001;
        4'b1010: out[7:0]=8'b00010001;
        4'b1011: out[7:0]=8'b11000001;
        4'b1100: out[7:0]=8'b01100011;
        4'b1101: out[7:0]=8'b10000101;
        4'b1110: out[7:0]=8'b01100001;
        4'b1111: out[7:0]=8'b01110001;
         default:out[7:0]=8'b11111111;
     endcase 
     case(in[7:4])
        4'b0000: out[15:8]=8'b00000011;
        4'b0001: out[15:8]=8'b10011111;
        4'b0010: out[15:8]=8'b00100101;
        4'b0011: out[15:8]=8'b00001101;
        4'b0100: out[15:8]=8'b10011001;
        4'b0101: out[15:8]=8'b01001001;
        4'b0110: out[15:8]=8'b01000001;
        4'b0111: out[15:8]=8'b00011111;
        4'b1000: out[15:8]=8'b00000001;
        4'b1001: out[15:8]=8'b00001001;
        4'b1010: out[15:8]=8'b00010001;
        4'b1011: out[15:8]=8'b11000001;
        4'b1100: out[15:8]=8'b01100011;
        4'b1101: out[15:8]=8'b10000101;
        4'b1110: out[15:8]=8'b01100001;
        4'b1111: out[15:8]=8'b01110001;
         default:out[15:8]=8'b11111111;
    endcase
     case(in[11:8])
        4'b0000: out[23:16]=8'b00000011;
        4'b0001: out[23:16]=8'b10011111;
        4'b0010: out[23:16]=8'b00100101;
        4'b0011: out[23:16]=8'b00001101;
        4'b0100: out[23:16]=8'b10011001;
        4'b0101: out[23:16]=8'b01001001;
        4'b0110: out[23:16]=8'b01000001;
        4'b0111: out[23:16]=8'b00011111;
        4'b1000: out[23:16]=8'b00000001;
        4'b1001: out[23:16]=8'b00001001;
        4'b1010: out[23:16]=8'b00010001;
        4'b1011: out[23:16]=8'b11000001;
        4'b1100: out[23:16]=8'b01100011;
        4'b1101: out[23:16]=8'b10000101;
        4'b1110: out[23:16]=8'b01100001;
        4'b1111: out[23:16]=8'b01110001;
         default:out[23:16]=8'b11111111;
    endcase
     case(in[15:12])
        4'b0000: out[31:24]=8'b00000011;
        4'b0001: out[31:24]=8'b10011111;
        4'b0010: out[31:24]=8'b00100101;
        4'b0011: out[31:24]=8'b00001101;
        4'b0100: out[31:24]=8'b10011001;
        4'b0101: out[31:24]=8'b01001001;
        4'b0110: out[31:24]=8'b01000001;
        4'b0111: out[31:24]=8'b00011111;
        4'b1000: out[31:24]=8'b00000001;
        4'b1001: out[31:24]=8'b00001001;
        4'b1010: out[31:24]=8'b00010001;
        4'b1011: out[31:24]=8'b11000001;
        4'b1100: out[31:24]=8'b01100011;
        4'b1101: out[31:24]=8'b10000101;
        4'b1110: out[31:24]=8'b01100001;
        4'b1111: out[31:24]=8'b01110001;
         default:out[31:24]=8'b11111111;
    endcase
    case(in[19:16])
        4'b0000: out[39:32]=8'b00000011;
        4'b0001: out[39:32]=8'b10011111;
        4'b0010: out[39:32]=8'b00100101;
        4'b0011: out[39:32]=8'b00001101;
        4'b0100: out[39:32]=8'b10011001;
        4'b0101: out[39:32]=8'b01001001;
        4'b0110: out[39:32]=8'b01000001;
        4'b0111: out[39:32]=8'b00011111;
        4'b1000: out[39:32]=8'b00000001;
        4'b1001: out[39:32]=8'b00001001;
        4'b1010: out[39:32]=8'b00010001;
        4'b1011: out[39:32]=8'b11000001;
        4'b1100: out[39:32]=8'b01100011;
        4'b1101: out[39:32]=8'b10000101;
        4'b1110: out[39:32]=8'b01100001;
        4'b1111: out[39:32]=8'b01110001;
         default:out[39:32]=8'b11111111;
    endcase
    case(in[23:20])
        4'b0000: out[47:40]=8'b00000011;
        4'b0001: out[47:40]=8'b10011111;
        4'b0010: out[47:40]=8'b00100101;
        4'b0011: out[47:40]=8'b00001101;
        4'b0100: out[47:40]=8'b10011001;
        4'b0101: out[47:40]=8'b01001001;
        4'b0110: out[47:40]=8'b01000001;
        4'b0111: out[47:40]=8'b00011111;
        4'b1000: out[47:40]=8'b00000001;
        4'b1001: out[47:40]=8'b00001001;
        4'b1010: out[47:40]=8'b00010001;
        4'b1011: out[47:40]=8'b11000001;
        4'b1100: out[47:40]=8'b01100011;
        4'b1101: out[47:40]=8'b10000101;
        4'b1110: out[47:40]=8'b01100001;
        4'b1111: out[47:40]=8'b01110001;
         default:out[47:40]=8'b11111111;
    endcase
    case(in[27:24])
        4'b0000: out[55:48]=8'b00000011;
        4'b0001: out[55:48]=8'b10011111;
        4'b0010: out[55:48]=8'b00100101;
        4'b0011: out[55:48]=8'b00001101;
        4'b0100: out[55:48]=8'b10011001;
        4'b0101: out[55:48]=8'b01001001;
        4'b0110: out[55:48]=8'b01000001;
        4'b0111: out[55:48]=8'b00011111;
        4'b1000: out[55:48]=8'b00000001;
        4'b1001: out[55:48]=8'b00001001;
        4'b1010: out[55:48]=8'b00010001;
        4'b1011: out[55:48]=8'b11000001;
        4'b1100: out[55:48]=8'b01100011;
        4'b1101: out[55:48]=8'b10000101;
        4'b1110: out[55:48]=8'b01100001;
        4'b1111: out[55:48]=8'b01110001;
         default:out[55:48]=8'b11111111;
    endcase
    case(in[31:28])
        4'b0000: out[63:56]=8'b00000011;
        4'b0001: out[63:56]=8'b10011111;
        4'b0010: out[63:56]=8'b00100101;
        4'b0011: out[63:56]=8'b00001101;
        4'b0100: out[63:56]=8'b10011001;
        4'b0101: out[63:56]=8'b01001001;
        4'b0110: out[63:56]=8'b01000001;
        4'b0111: out[63:56]=8'b00011111;
        4'b1000: out[63:56]=8'b00000001;
        4'b1001: out[63:56]=8'b00001001;
        4'b1010: out[63:56]=8'b00010001;
        4'b1011: out[63:56]=8'b11000001;
        4'b1100: out[63:56]=8'b01100011;
        4'b1101: out[63:56]=8'b10000101;
        4'b1110: out[63:56]=8'b01100001;
        4'b1111: out[63:56]=8'b01110001;
         default:out[63:56]=8'b11111111;
    endcase
  end
endmodule
clk_div.v
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:19:38 07/17/2012 
// Design Name: 
// Module Name:    clk_div 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module clk_div(input clk,
                    input rst,
                    input SW15,
                    output reg[31:0]clkdiv,
                    output Clk_CPU
                    );
                    
// Clock divider-时钟分频器


    always @ (posedge clk ) begin 
        if (rst) clkdiv <= 0; else clkdiv <= clkdiv + 1'b1; end
        
    assign Clk_CPU = clkdiv[24];
        
endmodule

defines.v
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:19:38 07/17/2012 
// Design Name: 
// Module Name:    defines
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
`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

`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
指令寄存器rom.v
`timescale 1ns / 1ps
`include "defines.v"

//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    08:36:20 07/03/2018 
// Design Name: 
// Module Name:    rom 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
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'h340200ff;//ori 0x00ff
         // inst_mem[1] = 32'hafc20004;
        inst_mem[1] = 32'h8fc50008;//key input
        inst_mem[2] = 32'hafc50004;//led output
        inst_mem[3] = 32'hafc50000;//seg output
          inst_mem[4] = 32'h08000001;//j
      end
    
    always@(*)
      if(ce == `ChipDisable)
        inst <= `ZeroWord;
      else
        inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
endmodule
top.v
`include "defines.v"
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:19:38 07/17/2012 
// Design Name: 
// Module Name:    top
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
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,
                     input wire [`KeyBus] key,
                     output [`SEGBus] SEG,
                     output [`KeyBus] LED
);
//ID to Pc
wire[`RegBus] branch_addr;
wire branch_flag;
      
                
//ID to 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 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 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;

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

/*
//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 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;
    
//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 iow1;
wire ice;
wire [`IOAddrBus] ioaddr;

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


wire rst_sig = !rst;

//pc_reg real
pc_reg pc_reg0(
    .clk(clk),
    .rst(rst_sig),
    .branch_addr_i(branch_addr),
    .branch_flag_i(branch_flag),
    .pc(rom_addr_o),
    .ce(rom_ce_o)
);
//ID real
id id0(
    .rst(rst_sig),  
    .pc_i(rom_addr_o), 
    .inst_i(rom_data_i),
    //Regfile - id input 
    .reg1_data_i(reg1_data),    .reg2_data_i(reg2_data),
    //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)
);
//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)
);
//EX real
ex ex0(
    .rst(rst_sig),
    //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),
    //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)
);

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_aluop),
    .memaddr_i(ex_memaddr),
    .rmemdata_i(rm_idata),
    .reg1data_i(ex_reg1data),
    .reg2data_i(ex_reg2data),
    // input
    .ex_wd(ex_wd),
    .ex_wreg(ex_wreg),
    .ex_wdata(ex_wdata),
    //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)
);

MIOC MIOC1(//wb to mioc input
    .rst(rst_sig),
    .ior_i(ior),
    .iow_i(iow),
    .rm_idata_o(rm_idata),
    .wm_idata_i(wm_idata),
    .m_iaddr_i(m_iaddr),
    .mw_i(mw),
    .mr_i(mr),
    .msel_i(msel),
     //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(iow1),
    .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(iow1),
    .rdata_o(riodata),
    .wdata_i(wiodata),
    .clk(clk),
    .rst(rst_sig),
    .key(key),
    .SEG(SEG),
    .LED(LED)
);

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,
              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
        pc <= pc + 4'h4;
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 @ (posedge clk) begin
        if (rst == `RstEnable) begin
                    hi_o <= `ZeroWord;
                    lo_o <= `ZeroWord;
        end else if((we == `WriteEnable)) begin
                    hi_o <= hi_i;
                    lo_o <= lo_i;
        end
    end

endmodule

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,
    
   
    //Regfile - id input
    input wire[`RegBus]         reg1_data_i,
    input wire[`RegBus]         reg2_data_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
);
    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;
    
    //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
    
    
    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;       
        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; 
            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; 
                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_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
        if(rst == `RstEnable) begin
            reg1_o <= `ZeroWord;    
            end 
      /*else if((reg1_read_o == 1'b1) && (wreg_o == 1'b1) && (wd_o == 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) && (wreg_o == 1'b1) && (wd_o == 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     
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,

    //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
);

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

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 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;      
          
        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;
          
            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
endmodule



//mem-io
module MIOC(
  input wire rst,
  //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,
    
    //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;
          
        end else begin
            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}; 
               //rdata_o <= 32'hffff000f;
            end
          `BUTTON_ADDR: begin
             //rdata_o <= Button;
             rdata_o <= 32'hffffffff;
            end
        endcase
      end 
    end
endmodule
顶层模块Prep_DEMO.v
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    10:50:10 11/03/2014 
// Design Name: 
// Module Name:    Output_2_Disp 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module   Prep_IO(input  wire clk_100mhz,
    // I/O:         
                        input  wire[15:0]SW,
                        
                        //input  wire OPENMIPS_rst;
                        output wire led_clk,
                        output wire led_clrn,
                        output wire led_sout,
                        output wire LED_PEN,
                
                        output wire seg_clk,
                        output wire seg_clrn,
                        output wire seg_sout,
                        output wire SEG_PEN,
                        output Buzzer
                        );
                


    
    wire [31:0] Div;
    wire CK;
    wire [15:0] LedData;
                                    
    wire [31:0] pc_1;   
    wire [31:0] rom_output_data;
    wire rom_ena;
    assign Buzzer = 1;
    wire [15:0] key;
    wire [31:0] SEG;
    wire [15:0] LED;
    
    wire[63:0] disp_data; 
    
   assign LedData = ~LED;   
    assign key = SW;
    


    
    clk_div       U8(clk_100mhz,1'b0,SW[0],Div,CK);

    P2S               #(.DATA_BITS(64),.DATA_COUNT_BITS(6)) 
                          P7SEG (clk_100mhz,
                                    1'b0,
                                    Div[20],
                                    disp_data,
                                    seg_clk,
                                    seg_clrn,
                                    seg_sout,
                                    SEG_PEN
                                    );
                                    
                                    
    LED_P2S               #(.DATA_BITS(16),.DATA_COUNT_BITS(4)) 
                          PLED (clk_100mhz,
                                    1'b0,
                                    Div[20],
                                    LedData,
                                    led_clk,
                                    led_clrn,
                                    led_sout,
                                    LED_PEN
                                    );
                                    

    BCD bcd(.in(SEG),.out(disp_data));
    OpenMIPS    OPEN01(.rst(SW[15]),.clk(CK),.rom_data_i(rom_output_data),
                       .rom_addr_o(pc_1),.rom_ce_o(rom_ena),.key(key),.SEG(SEG),.LED(LED));
    inst_rom(.ce(rom_ena),.addr(pc_1),.inst(rom_output_data));
    //rom01     rom0001(.clka(CK),.ena(rom_ena),.addra(pc_1),.douta(rom_output_data));
endmodule
运行效果:
方案一 使用FPGA模型机在FPGA开发板上进行按键输入输出测试
mips模型机在Sword板子部署在FPGA_第1张图片
image.png

mips模型机在Sword板子部署在FPGA_第2张图片
image.png
方案二 使用FPGA模型机在FPGA开发板上进行流水灯测试
mips模型机在Sword板子部署在FPGA_第3张图片
image.png

mips模型机在Sword板子部署在FPGA_第4张图片
image.png
测试分析与结论

根据上述测试数据,验证模型机在FPGA开发板上执行的正确性以及先前在modelsim上进行开发的所有过程、所有指令的准确性的测试,测试结果表明:FPGA模型机可以在实验箱上,实现正确IO端口操作,以及使用FPGA模型机设计的指令,进行了流水灯的设计,验证了系统开发的可行性与准确性,最终获得了模型机开发圆满结束。

你可能感兴趣的:(mips模型机在Sword板子部署在FPGA)