第4章 第一条指令ORI的实现

openMIPS结构图
以下进行模块化分析与代码实现

取指阶段模块实现:
1 PC模块:给出指令地址

`include "defines.v"

module pc_reg(
    input wire               clk,
    input wire               rst,
    output reg[`InstAddrBus] pc,    // program counter
    output reg               ce     
    );
    
    always @ (posedge clk) begin
        if (rst == `RstEnable) begin
            ce <= `ChipDisable;
        end else begin
            ce <= `ChipEnable;
        end
    end
    
     always @ (posedge clk) begin
        if (ce == `ChipDisable) begin
            pc <= 32'h00000000;
        end else begin
            pc <= pc + 1'h4;
        end
    end
endmodule

2 IF/ID模块:暂时保存取指阶段取得的指令以及对应的指令地址,并在下一个时钟传递到译码模块

`include "defines.v"

module if_id(
    input wire                  clk,
    input wire                  rst,
    input wire[`InstAddrBus]    if_pc,
    input wire[`InstBus]        if_inst,
    output reg[`InstAddrBus]    id_pc,
    output reg[`InstBus]        id_inst
    );
    
    always @ (posedge clk) begin
        if (rst == `RstDisable) begin
            id_pc <= `ZeroWord;
            id_inst <= `ZeroWord;
        end else begin
            id_pc <= if_pc;
            id_inst <= if_inst;
        end
    end
endmodule

译码阶段模块实现:
1 Regfile模块:同时经行两个寄存器的读操作和一个寄存器的写操作

`include "defines.v"

module regfile(
    input wire                  clk,
    input wire                  rst,
    
    input wire[`RegAddrBus]     waddr,  // write address
    input wire[`RegBus]         wdata,  // write data
    input wire                  we,     // write enable
    
    input wire[`RegAddrBus]     raddr1, // read address
    output reg[`RegBus]         rdata1, // read data
    input wire                  re1,    // read enable
    
    input wire[`RegAddrBus]     raddr2,
    output reg[`RegBus]         rdata2,
    input wire                  re2
    );
    
    reg[`RegBus] regs[0:`RegNum - 1];
    
    always @ (posedge clk) begin
        if (rst == `RstDisable) begin
            if (we == `WriteEnable && waddr != `RegNumLog2'h0) begin
                regs[waddr] <= wdata;
            end 
        end
    end 
    
    always @ (*) begin
        if (rst == `RstEnable) begin
            rdata1 <= `ZeroWord;
        end else if (raddr1 == `RegNumLog2'h0) begin
            rdata1 <= `ZeroWord;
        end else if (raddr1 == waddr && re1 == `ReadEnable && we == `WriteEnable) begin
            rdata1 <= wdata;
        end else if (re1 == `ReadEnable) begin
            rdata1 <= regs[raddr1];
        end begin
            rdata1 <= `ZeroWord;
        end 
    end
    
    always @ (*) begin
        if (rst == `RstEnable) begin
            rdata2 <= `ZeroWord;
        end else if (raddr2 == `RegNumLog2'h0) begin
            rdata2 <= `ZeroWord;
        end else if (raddr2 == waddr && re2 == `ReadEnable && we == `WriteEnable) begin
            rdata2 <= wdata;
        end else if (re2 == `ReadEnable) begin
            rdata2 <= regs[raddr2];
        end begin
            rdata2 <= `ZeroWord;
        end 
    end
endmodule

2 ID模块:对指令进行译码,得到指令的类型、子类型、操作数1、操作数2、目的寄存器地址

`include "defines.v"

module id(
    input wire                  rst,            // reset
    input wire[`InstAddrBus]    pc_i,           // order address
    input wire[`InstBus]        inst_i,         // order itself
    
    input wire[`RegBus]         reg1_data_i,
    input wire[`RegBus]         reg2_data_i,
    
    output reg[`RegBus]         reg1_read_o,
    output reg[`RegBus]         reg2_read_o,
    output reg[`RegAddrBus]     reg1_addr_o,
    output reg[`RegAddrBus]     reg2_addr_o,
    
    output reg[`AluOpBus]       aluop_o,        // order sub type
    output reg[`AluSelBus]      alusel_o,       // order type
    output reg[`RegBus]         reg1_o,         // first operator 
    output reg[`RegBus]         reg2_o,         // second operator 
    output reg[`RegAddrBus]     wd_o,           // write address
    output reg                  wreg_o          // weite register
    );
    
    wire[5:0] op = inst_i[31:26];
    reg[`RegBus] imm;
    reg instvalid;
    
    always @ (*) begin
        if (rst == `RstEnable) begin
            aluop_o     <= `EXE_NOP_OP;
            alusel_o    <= `EXE_RES_NOP;
            wd_o        <= `NOPRegAddr;
            wreg_o      <= `WriteDisable;
            instvalid   <= `InstInvalid;
            reg1_read_o <= 1'b0;
            reg2_read_o <= 1'b0;
            reg1_addr_o <= `NOPRegAddr;
            reg2_addr_o <= `NOPRegAddr;
            imm         <= `ZeroWord;
        end else 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         <= `ZeroWord;          
        end
        
        case (op) 
            `EXE_ORI: begin
                wreg_o <= `WriteEnable;
                aluop_o <= `EXE_OR_OP;
                alusel_o <= `EXE_RES_LOGIC;
                reg1_read_o <= 1'b1;
                reg2_read_o <= 1'b0;
                imm <= inst_i[15:0];
                wd_o <= inst_i[20:16];
                instvalid <= `InstValid;
            end
            
            default: begin
            end
        endcase        
    end
    
    always @ (*) begin
        if (rst == `RstEnable) begin
            reg1_o <= `ZeroWord;
        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) 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

3 ID/EX模块:将上述属性传递在下一个时钟阶段传递给流水线执行阶段

`include "defines.v"

module id_ex(
    input wire                  rst,        
    input wire                  clk,                   
    
    input wire[`AluOpBus]       id_aluop,      
    input wire[`AluSelBus]      id_alusel, 
    input wire[`RegBus]         id_reg1,     
    input wire[`RegBus]         id_reg2,      
    input wire[`RegAddrBus]     id_wd,        
    input wire                  id_wreg,       
    
    output reg[`AluOpBus]       ex_aluop,      
    output reg[`AluSelBus]      ex_alusel,    
    output reg[`RegBus]         ex_reg1,         
    output reg[`RegBus]         ex_reg2,      
    output reg[`RegAddrBus]     ex_wd,          
    output reg                  ex_wreg             
    );
    
    always @ (posedge clk) begin
        if (rst == `RstEnable) begin
            ex_aluop    <= `EXE_NOP_OP;
            ex_alusel   <= `EXE_RES_NOP;
            ex_reg1     <= `ZeroWord;
            ex_reg2     <= `ZeroWord;
            ex_wd       <= `NOPRegAddr;
            ex_wreg     <= `WriteDisable;
        end else begin
            ex_aluop    <= id_aluop;
            ex_alusel   <= id_alusel;
            ex_reg1     <= id_reg1;
            ex_reg2     <= id_reg2;
            ex_wd       <= id_wd;
            ex_wreg     <= id_wreg;           
        end
    end
endmodule

执行阶段模块实现
1 EX模块:判断指令的类型并给出运算的结果

`include "defines.v"

module ex(
    input wire                  rst,                      
    
    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,       
    
    output reg[`RegBus]         wdata_o,      
    output reg[`RegAddrBus]     wd_o,          
    output reg                  wreg_o    
    );
    
    reg[`RegBus] logicout;
    
    // logic type
    always @ (*) begin
        if (rst == `RstEnable) begin
            logicout <= `ZeroWord;
        end else begin
            case (aluop_i)
                 `EXE_OR_OP: begin
                    logicout <= reg1_i | reg2_i;
                 end
                 default : begin
                    logicout <= `ZeroWord;
                 end
            endcase
        end
    end
   
   // choose type
   always @ (*) begin
        wd_o <= wd_i;
        wreg_o <= wreg_i;
        case (alusel_i)
            `EXE_RES_LOGIC: begin
                wdata_o <= logicout;
            end
            default : begin
                wdata_o <= `ZeroWord;
            end
        endcase
    end
endmodule

2 EX/MEM模块:将指令阶段得到的运算结果在下一个时钟传递到流水线访存阶段

`include "defines.v"

module ex_mem(
    input wire                  rst,                      
    input wire                  clk,                      
    
    input wire[`RegBus]         ex_wdata,          
    input wire[`RegAddrBus]     ex_wd,        
    input wire                  ex_wreg,       
    
    output reg[`RegBus]         mem_wdata,    
    output reg[`RegAddrBus]     mem_wd,          
    output reg                  mem_wreg    
    );
    
    always @ (posedge clk) begin
        if (rst == `RstEnable) begin
            mem_wdata   <= `ZeroWord;
            mem_wd      <= `NOPRegAddr;
            mem_wreg    <= `WriteDisable;
        end else begin
            mem_wdata   <= ex_wdata;
            mem_wd      <= ex_wd;
            mem_wreg    <= ex_wreg;            
        end
    end 
endmodule

访存阶段模块实现
1 MEM模块:

`include "defines.v"

module mem(
    input wire                  rst,                                          
    
    input wire[`RegBus]         wdata_i,          
    input wire[`RegAddrBus]     wd_i,        
    input wire                  wreg_i,       
    
    output reg[`RegBus]         wdata_o,      
    output reg[`RegAddrBus]     wd_o,          
    output reg                  wreg_o   
    );
    
    always @ (*) begin
        if (rst == `RstEnable) begin
            wdata_o   <= `ZeroWord;
            wd_o      <= `NOPRegAddr;
            wreg_o    <= `WriteDisable;
        end else begin
            wdata_o   <= wdata_i;
            wd_o      <= wd_i;
            wreg_o    <= wreg_i;            
        end
    end 
endmodule

2 MEM/WB模块:将访存阶段的运算结果在下一个时钟传递到回写阶段

`include "defines.v"

module mem_wb(
    input wire                  rst,                      
    input wire                  clk,                      
    
    input wire[`RegBus]         mem_wdata,          
    input wire[`RegAddrBus]     mem_wd,        
    input wire                  mem_wreg,       
    
    output reg[`RegBus]         wb_wdata,      
    output reg[`RegAddrBus]     wb_wd,          
    output reg                  wb_wreg    
    );
    
    always @ (posedge clk) begin
        if (rst == `RstEnable) begin
            wb_wdata   <= `ZeroWord;
            wb_wd      <= `NOPRegAddr;
            wb_wreg    <= `WriteDisable;
        end else begin
            wb_wdata   <= mem_wdata;
            wb_wd      <= mem_wd;
            wb_wreg    <= mem_wreg;            
        end
    end 
endmodule

openMIPS顶层模块实现
openMIPS:对上述各个模块进行例化与连接

module openmips(
    input wire                  rst,                      
    input wire                  clk,                      
    
    input wire[`RegBus]         rom_data_i,               
    
    output wire[`RegBus]        rom_data_o,      
    output wire[`RegAddrBus]    rom_addr_o,          
    output wire                 rom_ce_o    
    );
    
    wire[`InstAddrBus]          pc;
    wire[`InstAddrBus]          id_pc_i;
    wire[`InstAddrBus]          id_inst_i;
    
    wire[`AluOpBus]             id_aluop_o; 
    wire[`AluSelBus]            id_alusel_o; 
    wire[`RegBus]               id_reg1_o;     
    wire[`RegBus]               id_reg2_o;      
    wire[`RegAddrBus]           id_wd_o;        
    wire                        id_wreg_o;
       
    wire[`AluOpBus]             ex_aluop_i; 
    wire[`AluSelBus]            ex_alusel_i; 
    wire[`RegBus]               ex_reg1_i;     
    wire[`RegBus]               ex_reg2_i;      
    wire[`RegAddrBus]           ex_wd_i;        
    wire                        ex_wreg_i;
    
    wire[`RegBus]               ex_wdata_o;      
    wire[`RegAddrBus]           ex_wd_o;          
    wire                        ex_wreg_o;

    wire[`RegBus]               mem_wdata_i;      
    wire[`RegAddrBus]           mem_wd_i;          
    wire                        mem_wreg_i;
    
    wire[`RegBus]               mem_wdata_o;      
    wire[`RegAddrBus]           mem_wd_o;          
    wire                        mem_wreg_o;   
    
    wire[`RegBus]               wb_wdata_i;      
    wire[`RegAddrBus]           wb_wd_i;          
    wire                        wb_wreg_i;   
    
    wire                        reg1_read;      
    wire                        reg2_read;      
    wire[`RegBus]               reg1_data;      
    wire[`RegBus]               reg2_data;      
    wire[`RegAddrBus]           reg1_addr; 
    wire[`RegAddrBus]           reg2_addr; 
    
    pc_reg pc_reg0(
        .clk(clk), .rst(rst), 
        
        .pc(pc), .ce(rom_ce_o)
    );
    
    if_id if_id0(
        .clk(clk), .rst(rst), 
        
        .if_pc(pc), .if_inst(rom_data_i),
        .id_pc(id_pc_i), .id_inst(id_inst_i)  
    );
    
    id id0(
        .rst(rst), .pc_i(id_pc), .inst_i(id_inst_i),
        
        .reg1_data_i(reg1_data), .reg2_data_i(reg2_data),
        .reg1_read_i(reg1_read), .reg2_read_i(reg2_read),
        .reg1_addr_i(reg1_addr), .reg2_addr_i(reg2_addr),
        
        .aluop_o(id_aluop_o), .alusel_o(id_alusel_o),
        .reg1_o(id_reg1_o), .reg2_o(id_reg2_o),
        .wd_o(id_wd_o), .wreg_o(id_wreg_o)
    );
    
    regfile regfile0(
        .clk(clk), .rst(rst), 
        
        .waddr(wb_wd), .wdata(wb_wdata), .we(wb_wreg),
        .raddr1(reg1_addr), .rdata1(reg1_data), .re1(reg1_read),
        .raddr2(reg2_addr), .rdata2(reg2_data), .re2(reg2_read)
    );
    
    id_ex id_ex0(
        .clk(clk), .rst(rst), 
        
        .id_aluop(id_aluop_o), .id_alusel(id_alusel_o),
        .id_reg1(id_reg1_o), .id_reg2(id_reg2_o),
        .id_wd(id_wd_o), .id_wreg(id_wreg_o),
        
        .ex_aluop(ex_aluop_i), .ex_alusel(ex_alusel_i),
        .ex_reg1(ex_reg1_i), .ex_reg2(ex_reg2_i),
        .ex_wd(ex_wd_i), .ex_wreg(ex_wreg_i)    
    );
    
    ex ex0(
        .rst(rst),
        
        .aluop_i(ex_aluop_i), .alusel_i(ex_alusel_i),
        .reg1_i(ex_reg1_i), .reg2_i(ex_reg2_i),
        .wd_i(ex_wd_i), .wreg_i(ex_wreg_i),
        
        .wdata_o(ex_wdata_o), .wd_o(ex_wd_o), .wreg_o(ex_wreg_o)
    );
    
    ex_mem ex_mem0(
        .clk(clk), .rst(rst), 
        
        .ex_wdata(ex_wdata_o), .ex_wd(ex_wd_o), .ex_wreg(ex_wreg_o),
                
        .mem_wdata(mem_wdata_i), .mem_wd(mem_wd_i), .mem_wreg(mem_wreg_i)
    );
    
    mem mem0(
        .rst(rst), 
          
        .wdata_i(mem_wdata_i), .wd_o(mem_wd_i), .wreg_o(mem_wreg_i),
        
        .wdata_o(mem_wdata_o), .wd_o(mem_wd_o), .wreg_o(mem_wreg_o)
    );
    
    mem_wb mem_wb0(
        .clk(clk), .rst(rst), 
                
        .mem_wdata(mem_wdata_o), .mem_wd(mem_wd_o), .mem_wreg(mem_wreg_o),

        .wb_wdata(wb_wdata_i), .wb_wd(wb_wd_i), .wb_wreg(wb_wreg_i)
    );
endmodule

宏定义参考

`define InstAddrBus     31:0
`define InstBus         31:0

`define RegAddrBus      4:0         // register address bus
`define RegBus          31:0        // register bus
`define RegWidth        32          
`define DoubleRegWidth  64
`define DoubleRegBus    63:0   
`define RegNum          32
`define RegNumLog2      5
`define NOPRegAddr      5'b000000   

`define RstEnable       1'b1        // reset enable
`define RstDisable      1'b0        // reset disable
`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'b1
`define InstInvalid     1'b0
`define True_v          1'b1
`define False_v         1'b0
`define ChipEnable      1'b1
`define ChipDisable     1'b0

`define EXE_ORI         6'b001101
`define EXE_NOP         6'b000000

`define EXE_OR_OP       8'b00100101
`define EXE_NOP_OP      8'b00000000

`define EXE_RES_LOGIC   3'b001
`define EXE_RES_NOP     6'b000
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值