美文网首页
mips单周期模型机设计与实现

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

作者: 黎涛note | 来源:发表于2018-07-25 15:45 被阅读0次
    单指令周期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
    
    
    //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单周期模型机设计与实现

          本文链接:https://www.haomeiwen.com/subject/wzupmftx.html