自己动手写CPU(6)——移动指令的实现

系统结构框图

hilo

代码模块

1. 宏定义defines.v
// 宏定义模块
// ***************  与具体指令有关的宏定义  ***************
`define EXE_MOVN        6'b001011
`define EXE_MOVZ        6'b001010
`define EXE_MFHI        6'b010000
`define EXE_MFLO        6'b010010
`define EXE_MTHI        6'b010001
`define EXE_MTLO        6'b010011
 
//AluOp   子类型
`define EXE_MOVN_OP     8'b00001011
`define EXE_MOVZ_OP     8'b00001010
`define EXE_MFHI_OP     8'b00010000
`define EXE_MFLO_OP     8'b00010010
`define EXE_MTHI_OP     8'b00010001
`define EXE_MTLO_OP     8'b00010011

//AluSel  类型
`define EXE_RES_MOVE    3'b011        // 移动

2. 译码id

添加新的移动指令MOVN、MOVZ、MFHI、MFLO、MTHI、MTLO的译码分支

// 对指令进行译码,得到最终运算的类型、子类型、源操作数1、源操作数2、要写入的目的寄存器地址信息等
`include "defines.v"

module id (
  // 输出到regfile的信息
  output  reg                   reg1_read_o,    // regfile模块第一个读寄存器端口的读使能信号
  output  reg                   reg2_read_o,    // regfile模块第二个读寄存器端口的读使能信号
  output  reg   [`RegAddrBus]   reg1_addr_o,    // regfile模块第一个读寄存器端口的读地址信号
  output  reg   [`RegAddrBus]   reg2_addr_o,    // regfile模块第二个读寄存器端口的读地址信号
  // 送到执行阶段的信息
  output  reg   [`AluOpBus]     aluop_o,        // 译码阶段的指令要进行的运算的子类型
  output  reg   [`AluSelBus]    alusel_o,       // 译码阶段的指令要进行的运算的类型
  output  reg   [`RegBus]       reg1_o,         // 译码阶段的指令要进行的运算的源操作数1
  output  reg   [`RegBus]       reg2_o,         // 译码阶段的指令要进行的运算的源操作数2
  output  reg   [`RegAddrBus]   wd_o,           // 译码阶段的指令要写入的目的寄存器地址
  output  reg                   wreg_o,         // 译码阶段的指令是否有要写入的目的寄存器
  
  input   wire                  rst,            // 复位
  input   wire  [`InstAddrBus]  pc_i,           // 译码阶段指令对应的地址
  input   wire  [`InstBus]      inst_i,         // 译码阶段的指令
  // 读取的regfile的值
  input   wire  [`RegBus]       reg1_data_i,    // 从regfile输入的第一个读寄存器端口的输出
  input   wire  [`RegBus]       reg2_data_i     // 从regfile输入的第一个读寄存器端口的输出  
);

  // 取得指令的指令码,功能码
  // 对于ori指令只需通过判断26-31bits的值,即可判断是否是ori指令,6'b00_1101
  wire  [5:0]     op  = inst_i[31:26];    // 指令码
  wire  [4:0]     op2 = inst_i[10:6];     
  wire  [5:0]     op3 = inst_i[5:0];      // 操作码
  wire  [4:0]     op4 = inst_i[20:16];
  
  // 保存指令执行需要的立即数
  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 <=  `InstValid;       // 指令有效
      reg1_read_o <=  1'b0;
      reg2_read_o <=  1'b0;
      reg1_addr_o <=  `NOPRegAddr;
      reg2_addr_o <=  `NOPRegAddr;
      imm         <=  32'h0;
    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];  // 默认通过regfile读端口1读取的寄存器地址,rs,源寄存器地址
      reg2_addr_o <=  inst_i[20:16];  // 默认通过regfile读端口2读取的寄存器地址,rt,源寄存器地址
      imm         <=  `ZeroWord;
      
      case (op)
        `EXE_SPECIAL_INST:  begin
          case  (op2)                 // [10:6]sa为0
            5'b00000: begin
              case (op3)              // [5:0]func
                `EXE_OR:  begin                   // or指令
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_OR_OP;     // 8'b 0010_0101
                  alusel_o    <=  `EXE_RES_LOGIC;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                end
                `EXE_AND: begin                   // and指令
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_AND_OP;    // 8'b 0010_0100
                  alusel_o    <=  `EXE_RES_LOGIC;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                end
                `EXE_XOR: begin                   // xor指令
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_XOR_OP ;   // 8'b 0010_0110
                  alusel_o    <=  `EXE_RES_LOGIC;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                end
                `EXE_NOR: begin                   // nor指令
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_NOR_OP;    // 8'b 0010_0111
                  alusel_o    <=  `EXE_RES_LOGIC;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                end
                `EXE_SLLV:  begin                 // sllv指令
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_SLL_OP;    // 8'b 0000_0100
                  alusel_o    <=  `EXE_RES_SHIFT; 
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                end
                `EXE_SRLV:  begin                 // srlv指令
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_SRL_OP;    // 8'b 0000_0110
                  alusel_o    <=  `EXE_RES_SHIFT;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                end
                `EXE_SRAV:  begin                 // srav指令
                  wreg_o      <=  `WriteEnable;
                  aluop_o 	   <=  `EXE_SRA_OP;    	// 8'b 0000_0111
                  alusel_o    <=  `EXE_RES_SHIFT;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                end
                `EXE_MFHI:  begin                 // mfhi rd <- hi
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_MFHI_OP;
                  alusel_o    <=  `EXE_RES_MOVE;
                  reg1_read_o <=  1'b0;
                  reg2_read_o <=  1'b0;
                  instvalid   <=  `InstValid;
                end
                `EXE_MFLO:  begin                 // mflo rd <- lo 
                  wreg_o      <=  `WriteEnable;
                  aluop_o     <=  `EXE_MFLO_OP;
                  alusel_o    <=  `EXE_RES_MOVE;
                  reg1_read_o <=  1'b0;
                  reg2_read_o <=  1'b0;
                  instvalid   <=  `InstValid;
                end
                `EXE_MTHI:  begin                 // mthi hi <- rs
                  wreg_o      <=  `WriteDisable;
                  aluop_o     <=  `EXE_MTHI_OP;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b0;
                  instvalid   <=  `InstValid;
                end
                `EXE_MTLO:  begin                 // mtlo lo <- rs
                  wreg_o      <=  `WriteDisable;
                  aluop_o     <=  `EXE_MTLO_OP;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b0;
                  instvalid   <=  `InstValid;
                end
                `EXE_MOVN:  begin                 // movn rd <- rs
                  aluop_o     <=  `EXE_MOVN_OP; 
                  alusel_o    <=  `EXE_RES_MOVE;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                  // reg2_o的值就是地址为rt的通用寄存器的值
                  if (reg2_o != `ZeroWord) begin
                    wreg_o    <=  `WriteEnable;
                  end else begin
                    wreg_o    <=  `WriteDisable;
                  end
                end
                `EXE_MOVZ:  begin
                  aluop_o     <=  `EXE_MOVZ_OP;
                  alusel_o    <=  `EXE_RES_MOVE;
                  reg1_read_o <=  1'b1;
                  reg2_read_o <=  1'b1;
                  instvalid   <=  `InstValid;
                  // reg2_o的值就是地址为rt的通用寄存器的值
                  if (reg2_o == `ZeroWord) begin
                    wreg_o    <=  `WriteEnable;
                  end else begin
                    wreg_o    <=  `WriteDisable;
                  end
                end                                  
                default:    begin
                end    
              endcase   // case (op3)
            end
            default:  begin
            end
          endcase   // case(op2)
        end  
        `EXE_ORI: begin               // 依据op的值判断指令是否为ori指令
          // ori指令需要将结果写入目的寄存器
          wreg_o      <=  `WriteEnable;
          // 运算子类型是逻辑'or'运算
          aluop_o     <=  `EXE_OR_OP;
          // 运算类型是逻辑运算
          alusel_o    <= `EXE_RES_LOGIC;
          // 需要通过regfile的读端口1读取寄存器
          reg1_read_o <=  `WriteEnable;
          // 不需要通过regfile的读端口2读取寄存器
          reg2_read_o <=  `WriteDisable;
          // 指令执行需要的立即数,无符号扩展
          imm         <=  {16'h0, inst_i[15:0]};
          // 指令执行要写的目的寄存器地址
          wd_o        <=  inst_i[20:16];
          // ori指令是有效指令
          instvalid   <=  `InstValid;
        end
        `EXE_ANDI:  begin                         // andi指令
          wreg_o      <=  `WriteEnable;
          aluop_o     <=  `EXE_AND_OP;            // 8'b 0000_1100
          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                         // xori指令
          wreg_o      <=  `WriteEnable;
          aluop_o     <=  `EXE_XOR_OP;            // 8'b 0010_0100
          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_LUI:   begin                         // lui指令
          wreg_o      <=  `WriteEnable;
          aluop_o     <=  `EXE_OR_OP;             // 8'b 0010_0101
          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
        default:    begin
        end
      endcase // case(op)
      if (inst_i[31:21] == 11'b000_0000_0000) begin
        if (op3 == `EXE_SLL)  begin               // sll指令
          wreg_o      <=  `WriteEnable;
          aluop_o     <=  `EXE_SLL_OP;            // 8'b 0000_0000
          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       // srl指令
          wreg_o      <=  `WriteEnable;
          aluop_o     <=  `EXE_SRL_OP;            // 8'b 0000_0010
          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       // sra指令
          wreg_o      <=  `WriteEnable;
          aluop_o     <=  `EXE_SRA_OP;            // 8'b 0000_0011
          alusel_o    <=  `EXE_RES_SHIFT;
          reg1_read_o <=  1'b0;
          reg2_read_o <=  1'b1;
          imm         <=  inst_i[10:6];
          wd_o        <=  inst_i[15:11];
          instvalid   <=  `InstValid;
        end
      end
    end //else
  end //always
  // ****************************************************************************
  // ********************第二阶段:确定进行运算的操作数1 ******************************
  // ****************************************************************************   
  always @ (*) begin
    if (rst == `RstEnable) begin
      reg1_o  <=  `ZeroWord;
    end else if (reg1_read_o == 1'b1) begin
      reg1_o  <=  reg1_data_i;    // regfile读端口1的输出值
    end else if (reg1_read_o == 1'b0) begin
      reg1_o  <=  imm;            // 立即数
    end else begin
      reg1_o  <=  `ZeroWord;
    end
  end
  // ****************************************************************************
  // ********************第三阶段:确定进行运算的操作数2 ******************************
  // ****************************************************************************   
  always @ (*) begin
    if (rst == `RstEnable) begin
      reg2_o  <=  `ZeroWord;
    end else if (reg2_read_o == 1'b1) begin
      reg2_o  <=  reg2_data_i;    // regfile读端口2的输出值
    end else if (reg2_read_o == 1'b0) begin
      reg2_o  <=  imm;            // 立即数
    end else begin
      reg2_o  <=  `ZeroWord;
    end
  end    

endmodule
 
3. 执行ex

为移动指令添加新的执行分支

// 从ID模块得到运算类型alusel_i、运算子类型aluse_i、源操作数reg1_i、源操作数reg2_i、要写入的目的寄存器地址wd_i
// EX模块依据这些数据进行运算
`include "defines.v"

module ex (
  // 执行的结果
  output  reg   [`RegAddrBus]   wd_o,         // 最终要写入的目的寄存器地址
  output  reg                   wreg_o,       // 最终是否有要写入的目的寄存器
  output  reg   [`RegBus]       wdata_o,      // 最终要写入目的寄存器的值
  // 处于执行阶段的指令对HI、LO寄存器的写操作请求
  output  reg                   whilo_o,
  output  reg   [`RegBus]       hi_o,
  output  reg   [`RegBus]       lo_o,
    
  input   wire                  rst,
  // 译码阶段送到执行阶段的信息
  input   wire  [`AluOpBus]     aluop_i,      // 执行阶段运算子类型
  input   wire  [`AluSelBus]    alusel_i,     // 执行阶段运算类型
  input   wire  [`RegBus]       reg1_i,       // 执行阶段源操作数1
  input   wire  [`RegBus]       reg2_i,       // 执行阶段源操作数2
  input   wire  [`RegAddrBus]   wd_i,         // 执行阶段要写入的目的寄存器地址
  input   wire                  wreg_i,       // 执行阶段是否有要写入的目的寄存器
  // HILO模块给出的HI、LO寄存器的值
  input   wire  [`RegBus]       hi_i,         // HILO模块给出的HI寄存器的值
  input   wire  [`RegBus]       lo_i          // HILO模块给出的LO寄存器的值 
);
  
  reg   [`RegBus]   logicout;         // 逻辑运算的结果
  reg   [`RegBus]   shiftres;         // 移位运算的结果
  reg   [`RegBus]   moveres;          // 移动操作的结果
  
reg   [`RegBus]   HI;               // 保存HI寄存器的最新值
  
reg  	[`RegBus]   LO;               // 保存LO寄存器的最新值
  

 
 // ****************************************************************************
  // ***************第一阶段:得到最新的HI、LO寄存器的值*********************
  // ****************************************************************************
  always @ (*) begin
    if (rst == `RstEnable) begin
      {HI, LO}  <=  {`ZeroWord, `ZeroWord};
    end else begin
      {HI, LO}  <=  {hi_i, lo_i};
    end
  end
  
  
  // ****************************************************************************
  // ***************第二阶段:依据aluop_i指示的运算子类型进行运算*********************
  // ****************************************************************************
  // ********** 逻辑运算 **********
  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_NOR_OP:  begin
          logicout  <=  ~(reg1_i | reg2_i);
        end
        `EXE_XOR_OP:  begin
          logicout  <=  reg1_i ^ reg2_i;
        end
        default:      begin
          logicout  <=  `ZeroWord;
        end
      endcase // case
    end // if
  end // always
  // ********** 移位运算 **********
  always @ (*) begin
    if (rst == `RstEnable) begin
      shiftres  <=  `ZeroWord;
    end else begin
      case (aluop_i)
        `EXE_SLL: begin
          shiftres  <=  reg2_i << reg1_i[4:0];
        end
        `EXE_SRL: begin
          shiftres  <=  reg2_i >> reg1_i[4:0];
        end
        `EXE_SRA: begin
          shiftres  <=  ({32{reg2_i[31]}} << (6'd32-{1'b0, reg1_i[4:0]})) | reg2_i >> reg1_i[4:0];
        end
      endcase
    end
  end
  // ********** 进行移位运算 MFHI、MFLO、MOVN、MOVZ **********
  always @ (*) begin
    if (rst == `RstEnable) begin
      moveres <=  `ZeroWord;
    end else begin
      moveres <=  `ZeroWord;
      case (aluop_i)
        `EXE_MFHI_OP: begin
          // 如果是mfhi指令,将HI的值作为移动操作的结果     rd <- hi
          moveres <=  HI;
        end
        `EXE_MFLO_OP: begin
          // 如果是mflo指令,将LO的值作为移动操作的结果     rd <- lo
          moveres <=  LO;
        end
        `EXE_MOVZ_OP: begin
          // 如果是movz指令,将reg1_i的值作为移动操作的结果 rd <- rs
          moveres <=  reg1_i;
        end
        `EXE_MOVN_OP: begin
          // 如果是movn指令,将reg1_i的值作为移动操作的结果 rd <- rs
          moveres <=  reg1_i;
        end
      endcase
    end   // else
  end
      
  // ****************************************************************************
  // **********第三阶段:依据alusel_i指示的运算类型,选择一个运算结果作为最终结果********
  // ****************************************************************************
  always @ (*) begin
    wd_o    <=  wd_i;     // 要写入的目的寄存器地址
    wreg_o  <=  wreg_i;   // 是否要写入目的寄存器
    case (alusel_i)
      `EXE_RES_LOGIC: begin
        wdata_o <=  logicout;   // wdata_o中存放运算结果
      end
      `EXE_RES_SHIFT: begin
        wdata_o <=  shiftres;
      end
      `EXE_RES_MOVE:  begin
        wdata_o <=  moveres;
      end
      default:        begin
        wdata_o <=  `ZeroWord;
      end
    endcase // case
  end // always 
  
  // ****************************************************************************
  // ***************************第四阶段:是否需要写HILO寄存器************************
  // ****************************************************************************
  always @ (*) begin
    if (rst == `RstEnable) begin
      whilo_o   <=  `WriteEnable;
      hi_o      <=  `ZeroWord;
      lo_o      <=  `ZeroWord;
    end else if (aluop_i == `EXE_MTHI_OP) begin       // hi <- rs
      whilo_o   <=  `WriteEnable;
      hi_o      <=  reg1_i;
      lo_o      <=  LO;
    end else if (aluop_i == `EXE_MTLO_OP) begin       // lo <- rs
      whilo_o   <=  `WriteEnable;
      hi_o      <=  HI;
      lo_o      <=  reg1_i;
    end
  end      

endmodule

4. 特殊寄存器hilo_reg
// HILO寄存器的实现
// 时钟上升沿,复位信号无效,当WriteEnable时,将输入作为HI、LO的新值,并通过hi_o、lo_o输出
`include "defines.v"

module hilo_reg (
  input  	wire              clk,
  input   wire              rst,
  // 写端口, 来自回写模块
  input   wire              we,         // HI、LO寄存器写使能信号
  input   wire  [`RegBus]   hi_i,       // 要写入HI寄存器的值
  input   wire  [`RegBus]   lo_i, 	     // 要写入LO寄存器的值
  
  // 读端口, 传送到执行模块
  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

5. 顶层模块OpenMIPS

增加新端口和新模块的顶层模块

// 顶层模块
`include "defines.v"

module openmips (
  output  wire     [`RegBus]   rom_addr_o,     // 输出到指令存储器的地址
  output  wire                 rom_ce_o,       // 指令寄存器使能信号
  
  input   wire    [`RegBus]   rom_data_i,     // 从指令寄存器取得的指令
  input   wire                rst,
  input   wire                clk
);

  // ****************************************************************************
  // **************************第一阶段:物理连线声明******************************
  // **************************************************************************** 
  
  // 连接ID模块和EX模块输入的变量
  wire  [`AluOpBus]     id_aluop;
  wire  [`AluSelBus]    id_alusel;
  wire  [`RegBus]       id_reg1;
  wire  [`RegBus]       id_reg2;
  wire                  id_wreg;
  wire  [`RegAddrBus]   id_wd;
  
  // 连接译码阶段ID模块和通用寄存器Regfile模块的变量
  wire                  reg1_read;
  wire                  reg2_read;
  wire  [`RegBus]       reg1_data;
  wire  [`RegBus]       reg2_data;
  wire  [`RegAddrBus]   reg1_addr;
  wire  [`RegAddrBus]   reg2_addr;

   // 连接EX模块输出和MEM模块的变量
  wire  [`RegAddrBus]   ex_wd;
  wire                  ex_wreg;
  wire  [`RegBus]       ex_wdata;  
  wire                  ex_whilo;
  wire  [`RegBus]       ex_hi;
  wire  [`RegBus]       ex_lo;
    
  // 连接MEM模块输出和WB模块的变量
  wire  [`RegAddrBus]   mem_wd;
  wire                  mem_wreg;
  wire  [`RegBus]       mem_wdata; 
  wire                  mem_whilo;
  wire  [`RegBus]       mem_hi;
  wire  [`RegBus]       mem_lo;
    
  // 连接WB模块和RegFIle模块输入的变量
  wire  [`RegAddrBus]   wb_wd;
  wire                  wb_wreg;
  wire  [`RegBus]       wb_wdata;
  
  // 连接WB模块和HILO模块的变量
  wire                  wb_whilo;
  wire  [`RegBus]       wb_hi;
  wire  [`RegBus]       wb_lo;
  
  // 连接HILO模块和EX模块的变量
  wire  [`RegBus]       hilo_hi;
  wire  [`RegBus]       hilo_lo;
  
  // ****************************************************************************
  // **********************第二阶段:对各个模块进行实例化*****************************
  // ****************************************************************************
  // pc_reg例化
  pc_reg  pc_reg0 (
          .pc(rom_addr_o), .ce(rom_ce_o),
          
          .clk(clk), .rst(rst)
  );
  // 译码阶段ID模块例化
  id      id0 (
          // 送到RegFile模块的信息
          .reg1_read_o(reg1_read), .reg2_read_o(reg2_read),
          .reg1_addr_o(reg1_addr), .reg2_addr_o(reg2_addr),
          // 送到EX模块的信息
          .aluop_o(id_aluop), .alusel_o(id_alusel),
          .reg1_o(id_reg1), .reg2_o(id_reg2),
          .wd_o(id_wd), .wreg_o(id_wreg),
          
          .rst(rst), .pc_i(rom_addr_o), .inst_i(rom_data_i),
          // 来自RegFile模块的输出
          .reg1_data_i(reg1_data), .reg2_data_i(reg2_data)
  ); 
  // 通用寄存器Regfile模块例化
  regfile regfile0 (
          .we(wb_wreg), .waddr(wb_wd), .wdata(wb_wdata),
          .re1(reg1_read), .raddr1(reg1_addr), .rdata1(reg1_data),
          .re2(reg2_read), .raddr2(reg2_addr), .rdata2(reg2_data),
          
          .clk(clk), .rst(rst)
  );
  // EX模块例化
  ex      ex0 (
          // 输出到MEM模块的信息
          .wd_o(ex_wd), .wreg_o(ex_wreg), .wdata_o(ex_wdata),
          .whilo_o(ex_whilo), .hi_o(ex_hi), .lo_o(ex_lo),
          
          .rst(rst),
          // 从ID模块传递过来的信息
          .aluop_i(id_aluop), .alusel_i(id_alusel),
          .reg1_i(id_reg1), .reg2_i(id_reg2),
          .wd_i(id_wd), .wreg_i(id_wreg),
          //  从HILO模块传递过来的信息
          .hi_i(hilo_hi), .lo_i(hilo_lo)
  );
  
  // MEM模块例化
  mem     mem0 (
          // 输出到WB模块的信息
          .wd_o(mem_wd), .wreg_o(mem_wreg), .wdata_o(mem_wdata),
          .whilo_o(mem_whilo), .hi_o(mem_hi), .lo_o(mem_lo),
          
          .rst(rst),
          // 从EX模块接收到的信息
          .wd_i(ex_wd), .wreg_i(ex_wreg), .wdata_i(ex_wdata),
          .whilo_i(ex_whilo), .hi_i(ex_hi), .lo_i(ex_lo)
  );
  
  // WB模块例化
  wb     wb0 (
          // 输出的regfile信息
          .wd_o(wb_wd), .wreg_o(wb_wreg), .wdata_o(wb_wdata),
          // 输出到HILO模块的信息
          .whilo_o(wb_whilo), .hi_o(wb_hi), .lo_o(wb_lo),
          
          .rst(rst),
          // 从MEM模块接收到的信息
          .wd_i(mem_wd), .wreg_i(mem_wreg), .wdata_i(mem_wdata),
          .whilo_i(mem_whilo), .hi_i(mem_hi), .lo_i(mem_lo)
  );
  
  // 特殊寄存器HILO模块的实例化
  hilo_reg  hilo_reg0 (
          // 输出到EX模块的信息
          .hi_o(hilo_hi), .lo_o(hilo_lo),
          
          .rst(rst), .clk(clk),
          // 从WB模块接收到的信息
          .we(wb_whilo), .hi_i(wb_hi), .lo_i(wb_lo)
  );

endmodule

测试模块

移动
仿真波形
测试_2

测试_1

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值