mips单周期模型机设计与实现

单指令周期MIPS模型机系统结构示意图
mips单周期模型机设计与实现_第1张图片
image.png
MIPS指令格式
mips单周期模型机设计与实现_第2张图片
image.png

mips单周期模型机设计与实现_第3张图片
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


//OPCODE
`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_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_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 131071
`define InstMemNumLog2 17


//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     131071
`define DataMemNumLog2 17
top.v
`include "defines.v"

module OpenMIPS(input rst,
                input clk,
                input [`RegBus] rom_data_i,
                output [`RegBus] rom_addr_o,
                output rom_ce_o);
//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 RamMemdata
wire[`MemBus] mem_wmemdata;
wire[`MemAddrBus] mem_memaddr;
wire mem_wmem;
wire mem_mce;
wire[3:0] mem_msel;
wire[`MemBus] mem_rmemdata;//MEM input into WB



//pc_reg real
pc_reg pc_reg0(
    .clk(clk),
    .rst(rst),
    .branch_addr_i(branch_addr),
    .branch_flag_i(branch_flag),
    .pc(rom_addr_o),
    .ce(rom_ce_o)
);
//ID real
id id0(
    .rst(rst),  
    .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),
    //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),
    //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),
    // ex-WB output
    .aluop_o(ex_aluop),
    .memaddr_o(ex_memaddr),
    .reg1data_o(ex_reg1data),//auto
    .reg2data_o(ex_reg2data),
    .wd_o(ex_wd),
    .wreg_o(ex_wreg),
    .wdata_o(ex_wdata)
);
//WB real
wb wb0(
    .rst(rst),
    //ex - wb input
    .aluop_i(ex_aluop),
    .memaddr_i(ex_memaddr),
    .rmemdata_i(mem_rmemdata),
    .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(mem_wmemdata),
    .mem_memaddr_o(mem_memaddr),
    .mem_wmem_o(mem_wmem),
    .mem_mce_o(mem_mce),
    .mem_msel_o(mem_msel)
);
//MEM  real
mem mem1(
    .clk(clk),
    .mem_wmemdata_i(mem_wmemdata),
    .mem_memaddr_i(mem_memaddr),
    .mem_wmem_i(mem_wmem),
    .mem_msel_i(mem_msel),
    .mem_mce_i(mem_mce),
    .rmemdata_o(mem_rmemdata)
);
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 clk,
              input rst,
              input[`RegBus] branch_addr_i,
              input 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


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[10]=32'h00ff0000;
    regs[11]=32'h00ff0000;
  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_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                     
            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 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,

    //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;
    
  //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
      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
    
  always @ (*) begin
        if(rst == `RstEnable) begin
            arithmeticres <= `ZeroWord;
        end else begin
            case (aluop_i)
                `EXE_ADD_OP:        begin
                    arithmeticres <= reg1_i+reg2_i; 
                end
                `EXE_SUB_OP:        begin
                    arithmeticres <= reg1_i-reg2_i; 
                end     
                default:                begin
                    arithmeticres <= `ZeroWord;
                end
            endcase
        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))) begin
         wreg_o <= `WriteDisable;
     end else begin
      wreg_o <= wreg_i;
     end*/
     wreg_o <= wreg_i;
     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_JUMP_BRANCH:   begin
            wdata_o <= link_addr_i;
        end             
        default:                    begin
            wdata_o <= `ZeroWord;
        end
     endcase
 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]             reg2data_i,
  //mem-wb input
  input wire[`MemBus]             rmemdata_i,
    //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_mce_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_msel_o <= 4'b0000;
          mem_wmemdata_o <= `ZeroWord;
          mem_mce_o <= `ChipDisable;        
          
        end else begin
          wb_wd <= ex_wd;
            wb_wreg <= ex_wreg;
            wb_wdata <= ex_wdata;   
            mem_wmem_o <= `WriteDisable;
            mem_memaddr_o <= `ZeroWord;
            mem_msel_o <= 4'b1111;
            mem_mce_o <= `ChipDisable;
        
            case (aluop_i)
                `EXE_LW_OP:     begin
                    mem_memaddr_o <= memaddr_i;
                    mem_wmem_o <= `WriteDisable;
                    mem_wmemdata_o <= rmemdata_i;
                    mem_msel_o <= 4'b1111;      
                    mem_mce_o <= `ChipEnable;
                end
                `EXE_SW_OP:     begin
                    mem_memaddr_o <= memaddr_i;
                    mem_wmem_o <= `WriteEnable;
                    mem_wmemdata_o <= reg2data_i;
                    mem_msel_o <= 4'b1111;          
                    mem_mce_o <= `ChipEnable;
                end
    
                default:        begin
          //?????
                end
            endcase                         
        end    //if
    end      //always
    
/*
    always @ (*) begin
        if(rst == `RstEnable) begin
            wb_wd <= `NOPRegAddr;
            wb_wreg <= `WriteDisable;
          wb_wdata <= `ZeroWord;    
        end else begin
            wb_wd <= ex_wd;
            wb_wreg <= ex_wreg;
            wb_wdata <= ex_wdata;
        end    //if
    end      //always
    */
            
endmodule

text.v
`include "top.v"

module inst_rom(input ce,
                input [`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'h34011100;
        inst_mem[4] = 32'h34020020;
        inst_mem[8] = 32'h3403ff00;
        inst_mem[12] = 32'h3404ffff;
      end
    */
    always@(*)
      if(ce == `ChipDisable)
        inst <= `ZeroWord;
      else
        inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
endmodule

module openmips_min_sopc(input clk,
                         input 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 = `RstEnable;
        #195 rst = `RstDisable;
        #1000 $stop;  
      end
    
    openmips_min_sopc     openmips_min_sopc0(.clk(clk),
                                             .rst(rst));
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单周期模型机设计与实现)