【【深入浅出TinyRisc-v】】

深入浅出TinyRisc-v

本代码参考于 https://gitee.com/liangkangnan/tinyriscv 自己理解之后又重新写了一遍

tinyriscv.v

// 涓嬮潰鏄鏁翠釜top妯″潡鐨勪功鍐?
module  tinyriscv(
    input                     clk             ,
    input                     rst_n           ,
    //澶栬鐨勪俊鎭鍙?
    input       [31 : 0]      rib_ex_data_i   , // 浠庡璁捐鍙栫殑鏁版嵁
    output      [31 : 0]      rib_ex_addr_o   , // 璇诲啓澶栬鐨勫湴鍧?
    output      [31 : 0]      rib_ex_data_o   , // 鍐欏叆澶栬鐨勬暟鎹?
    output                    rib_ex_req_o    ,
    output                    rib_ex_we_o     ,

    // 鍙栨寚浠? 浠? ROM涓?
    input       [31 : 0]      rib_pc_data_i   ,
    output      [31 : 0]      rib_pc_addr_o   ,  // 鍙栨寚鍦板潃

    // jtag浜や簰鐨勬帴鍙?
    input       [4  : 0]      jtag_reg_addr_i ,   // jtag妯″潡璇汇?佸啓瀵勫瓨鍣ㄧ殑鍦板潃 4:0
    input       [31 : 0]      jtag_reg_data_i ,       // jtag妯″潡鍐欏瘎瀛樺櫒鏁版嵁 31 : 0
    input                     jtag_reg_we_i   ,                  // jtag妯″潡鍐欏瘎瀛樺櫒鏍囧織
    output      [31 : 0]      jtag_reg_data_o ,      // jtag妯″潡璇诲彇鍒扮殑瀵勫瓨鍣ㄦ暟鎹?

    input                     rib_hold_flag_i    ,                // 鎬荤嚎鏆傚仠鏍囧織
    input                     jtag_halt_flag_i   ,               // jtag鏆傚仠鏍囧織
    input                     jtag_reset_flag_i  ,              // jtag澶嶄綅PC鏍囧織

    input       [7  : 0]      int_i                 // 涓柇淇″彿 7:0
  );


  // -------------------------------------------------------- //
  //           internal signal  and deffine                  //
  // -----------------------------------------------------  //

  wire   [31 : 0]   pc_pc_o  ;
  assign    rib_pc_addr_o   =  pc_pc_o  ;  // 杩欐槸鍙栨寚浠ゅ湴鍧?
  wire   [2  : 0]   ctrl_hold_flag_o    ;
  wire              ctrl_jump_flag_o    ;
  wire   [31 : 0]   ctrl_jump_addr_o    ;
  wire   [7  : 0]   if_int_flag_o       ;
  wire   [31 : 0]   if_inst_o           ;
  wire   [31 : 0]   if_inst_addr_o      ;

  wire   [31 : 0]   regs_rdata1_o       ;
  wire   [31 : 0]   regs_rdata2_o       ;

  wire   [4  : 0]   id_reg1_raddr_o     ;
  wire   [4  : 0]   id_reg2_raddr_o     ;
  wire   [31 : 0]   id_inst_o           ;
  wire   [31 : 0]   id_inst_addr_o      ;
  wire   [31 : 0]   id_reg1_rdata_o     ;
  wire   [31 : 0]   id_reg2_rdata_o     ;
  wire              id_reg_we_o         ;
  wire   [4  : 0]   id_reg_waddr_o      ;
  wire   [31 : 0]   id_csr_raddr_o      ;
  wire              id_csr_we_o         ;
  wire   [31 : 0]   id_csr_rdata_o      ;
  wire   [31 : 0]   id_csr_waddr_o      ;
  wire   [31 : 0]   id_op1_o            ;
  wire   [31 : 0]   id_op2_o            ;
  wire   [31 : 0]   id_op1_jump_o       ;
  wire   [31 : 0]   id_op2_jump_o       ;

  // id_ex妯″潡杈撳嚭淇″彿
  wire   [31 : 0]   ie_inst_o           ;
  wire   [31 : 0]   ie_inst_addr_o      ;
  wire              ie_reg_we_o         ;
  wire   [4 : 0]    ie_reg_waddr_o      ;
  wire   [31 : 0]   ie_reg1_rdata_o     ;
  wire   [31 : 0]   ie_reg2_rdata_o     ;
  wire              ie_csr_we_o         ;
  wire   [31 : 0]   ie_csr_waddr_o      ;
  wire   [31 : 0]   ie_csr_rdata_o      ;
  wire   [31 : 0]   ie_op1_o            ;
  wire   [31 : 0]   ie_op2_o            ;
  wire   [31 : 0]   ie_op1_jump_o       ;
  wire   [31 : 0]   ie_op2_jump_o       ;

  // ex妯″潡杈撳嚭淇″彿
  wire   [31 : 0]   ex_mem_wdata_o      ;
  wire   [31 : 0]   ex_mem_raddr_o      ;
  wire   [31 : 0]   ex_mem_waddr_o      ;
  wire              ex_mem_we_o         ;
  wire              ex_mem_req_o        ;
  wire   [31 : 0]   ex_reg_wdata_o      ;
  wire              ex_reg_we_o         ;
  wire   [4 : 0]   ex_reg_waddr_o      ;
  wire              ex_hold_flag_o      ;
  wire              ex_jump_flag_o      ;
  wire   [31 : 0]   ex_jump_addr_o      ;
  wire              ex_div_start_o      ;
  wire   [31 : 0]   ex_div_dividend_o   ;
  wire   [31 : 0]   ex_div_divisor_o    ;
  wire   [2  : 0]   ex_div_op_o         ;
  wire   [4  : 0]   ex_div_reg_waddr_o  ;
  wire   [31 : 0]   ex_csr_wdata_o      ;
  wire              ex_csr_we_o         ;
  wire   [31 : 0]   ex_csr_waddr_o      ;

  wire   [31 : 0]   csr_data_o          ;
  wire   [31 : 0]   csr_clint_data_o    ;
  wire              csr_global_int_en_o ;
  wire   [31 : 0]   csr_clint_csr_mtvec ;
  wire   [31 : 0]   csr_clint_csr_mepc  ;
  wire   [31 : 0]   csr_clint_csr_mstatus;


  wire   [31 : 0]   div_result_o        ;
  wire              div_ready_o         ;
  wire              div_busy_o          ;
  wire   [4  : 0]   div_reg_waddr_o     ;

  wire              clint_we_o          ;
  wire   [31 : 0]   clint_waddr_o       ;
  wire   [31 : 0]   clint_raddr_o       ;
  wire   [31 : 0]   clint_data_o        ;
  wire   [31 : 0]   clint_int_addr_o    ;
  wire              clint_int_assert_o  ;
  wire              clint_hold_flag_o   ;


  assign rib_ex_addr_o = (ex_mem_we_o == 1)? ex_mem_waddr_o: ex_mem_raddr_o;
  assign rib_ex_data_o = ex_mem_wdata_o   ;
  assign rib_ex_req_o  = ex_mem_req_o     ;
  assign rib_ex_we_o   = ex_mem_we_o      ;









  // -----------------------------------------------------  //
  //               渚嬪寲 浠嬬粛                                 //
  // -----------------------------------------------------  //

  pc_reg u_pc_reg(
           .clk                ( clk                ),
           .rst_n              ( rst_n              ),
           .jtag_reset_flag_i(jtag_reset_flag_i),
           .pc_o(pc_pc_o),
           .hold_flag_i(ctrl_hold_flag_o),
           .jump_flag_i(ctrl_jump_flag_o),
           .jump_addr_i(ctrl_jump_addr_o)
         );


  // 鎸夐『搴忎笅涓?涓槸 if_id
  if_id u_if_id(
          .clk          ( clk          ),
          .rst_n        ( rst_n        ),
          .inst_i(rib_pc_data_i),
          .inst_addr_i(pc_pc_o),
          .int_flag_i(int_i),
          .int_flag_o(if_int_flag_o),
          .hold_flag_i(ctrl_hold_flag_o),
          .inst_o(if_inst_o),
          .inst_addr_o(if_inst_addr_o)
        );

  //鎺ヤ笅鏉ユ槸 id妯″潡
  id u_id(
       .rst_n         ( rst_n         ),
       .inst_i(if_inst_o),
        .inst_addr_i(if_inst_addr_o),
        .reg1_rdata_i(regs_rdata1_o),
        .reg2_rdata_i(regs_rdata2_o),
       
        .reg1_raddr_o(id_reg1_raddr_o),
        .reg2_raddr_o(id_reg2_raddr_o),
        .inst_o(id_inst_o),
        .inst_addr_o(id_inst_addr_o),
        .reg1_rdata_o(id_reg1_rdata_o),
        .reg2_rdata_o(id_reg2_rdata_o),
        .reg_we_o(id_reg_we_o),
        .reg_waddr_o(id_reg_waddr_o),
        .op1_o(id_op1_o),
        .op2_o(id_op2_o),
        .op1_jump_o(id_op1_jump_o),
        .op2_jump_o(id_op2_jump_o),
        .csr_rdata_i(csr_data_o),
        .csr_raddr_o(id_csr_raddr_o),
        .csr_we_o(id_csr_we_o),
        .csr_rdata_o(id_csr_rdata_o),
        .csr_waddr_o(id_csr_waddr_o)
     );
  // 杩欓噷闈㈠苟娌℃湁鍗忓晢ex_jump_flag

  // 鐢ㄧ殑鏄? id_ex
  id_ex u_id_ex(
          .clk(clk                      ),
          .rst_n(rst_n                  ),
          .inst_i(id_inst_o),
          .inst_addr_i(id_inst_addr_o),
          .reg_we_i(id_reg_we_o),
          .reg_waddr_i(id_reg_waddr_o),
          .reg1_rdata_i(id_reg1_rdata_o),
          .reg2_rdata_i(id_reg2_rdata_o),
          .hold_flag_i(ctrl_hold_flag_o),
          .inst_o(ie_inst_o),
          .inst_addr_o(ie_inst_addr_o),
          .reg_we_o(ie_reg_we_o),
          .reg_waddr_o(ie_reg_waddr_o),
          .reg1_rdata_o(ie_reg1_rdata_o),
          .reg2_rdata_o(ie_reg2_rdata_o),
          .op1_i(id_op1_o),
          .op2_i(id_op2_o),
          .op1_jump_i(id_op1_jump_o),
          .op2_jump_i(id_op2_jump_o),
          .op1_o(ie_op1_o),
          .op2_o(ie_op2_o),
          .op1_jump_o(ie_op1_jump_o),
          .op2_jump_o(ie_op2_jump_o),
          .csr_we_i(id_csr_we_o),
          .csr_waddr_i(id_csr_waddr_o),
          .csr_rdata_i(id_csr_rdata_o),
          .csr_we_o(ie_csr_we_o),
          .csr_waddr_o(ie_csr_waddr_o),
          .csr_rdata_o(ie_csr_rdata_o)
        );

  // ex妯″潡

  ex u_ex(
       .rst_n(rst_n ),
       .inst_i(ie_inst_o),
       .inst_addr_i(ie_inst_addr_o),
       .reg_we_i(ie_reg_we_o),
       .reg_waddr_i(ie_reg_waddr_o),
       .reg1_rdata_i(ie_reg1_rdata_o),
       .reg2_rdata_i(ie_reg2_rdata_o),
       .op1_i(ie_op1_o),
       .op2_i(ie_op2_o),
       .op1_jump_i(ie_op1_jump_o),
       .op2_jump_i(ie_op2_jump_o),
       .mem_rdata_i(rib_ex_data_i),
       .mem_wdata_o(ex_mem_wdata_o),
       .mem_raddr_o(ex_mem_raddr_o),
       .mem_waddr_o(ex_mem_waddr_o),
       .mem_we_o(ex_mem_we_o),
       .mem_req_o(ex_mem_req_o),
       .reg_wdata_o(ex_reg_wdata_o),
       .reg_we_o(ex_reg_we_o),
       .reg_waddr_o(ex_reg_waddr_o),
       .hold_flag_o(ex_hold_flag_o),
       .jump_flag_o(ex_jump_flag_o),
       .jump_addr_o(ex_jump_addr_o),
       .int_assert_i(clint_int_assert_o),
       .int_addr_i(clint_int_addr_o),
       .div_ready_i(div_ready_o),
       .div_result_i(div_result_o),
       .div_busy_i(div_busy_o),
       .div_reg_waddr_i(div_reg_waddr_o),
       .div_start_o(ex_div_start_o),
       .div_dividend_o(ex_div_dividend_o),
       .div_divisor_o(ex_div_divisor_o),
       .div_op_o(ex_div_op_o),
       .div_reg_waddr_o(ex_div_reg_waddr_o),
       .csr_we_i(ie_csr_we_o),
       .csr_waddr_i(ie_csr_waddr_o),
       .csr_rdata_i(ie_csr_rdata_o),
       .csr_wdata_o(ex_csr_wdata_o),
       .csr_we_o(ex_csr_we_o),
       .csr_waddr_o(ex_csr_waddr_o)
     );


  ctrl u_ctrl(
         .jump_flag_i(ex_jump_flag_o),
         .jump_addr_i(ex_jump_addr_o),
         .hold_flag_ex_i(ex_hold_flag_o),
         .hold_flag_rib_i(rib_hold_flag_i),
         .hold_flag_o(ctrl_hold_flag_o),
         .hold_flag_clint_i(clint_hold_flag_o),
         .jump_flag_o(ctrl_jump_flag_o),
         .jump_addr_o(ctrl_jump_addr_o),
         .jtag_halt_flag_i(jtag_halt_flag_i)
       );

  regs u_regs(
         .clk(clk),
         .rst_n(rst_n),
         .we_i(ex_reg_we_o),
         .waddr_i(ex_reg_waddr_o),
         .wdata_i(ex_reg_wdata_o),
         .raddr1_i(id_reg1_raddr_o),
         .rdata1_o(regs_rdata1_o),
         .raddr2_i(id_reg2_raddr_o),
         .rdata2_o(regs_rdata2_o),
         .jtag_we_i(jtag_reg_we_i),
         .jtag_addr_i(jtag_reg_addr_i),
         .jtag_data_i(jtag_reg_data_i),
         .jtag_data_o(jtag_reg_data_o)
       );


  csr_reg u_csr_reg(
            .clk(clk),
            .rst_n(rst_n),
            .we_i(ex_csr_we_o),
            .raddr_i(id_csr_raddr_o),
            .waddr_i(ex_csr_waddr_o),
            .data_i(ex_csr_wdata_o),
            .data_o(csr_data_o),
            .global_int_en_o(csr_global_int_en_o),
            .clint_we_i(clint_we_o),
            .clint_raddr_i(clint_raddr_o),
            .clint_waddr_i(clint_waddr_o),
            .clint_data_i(clint_data_o),
            .clint_data_o(csr_clint_data_o),
            .clint_csr_mtvec(csr_clint_csr_mtvec),
            .clint_csr_mepc(csr_clint_csr_mepc),
            .clint_csr_mstatus(csr_clint_csr_mstatus)
          );


  div u_div(
        .clk(clk),
        .rst_n(rst_n),
        .dividend_i(ex_div_dividend_o),
        .divisor_i(ex_div_divisor_o),
        .start_i(ex_div_start_o),
        .op_i(ex_div_op_o),
        .reg_waddr_i(ex_div_reg_waddr_o),
        .result_o(div_result_o),
        .ready_o(div_ready_o),
        .busy_o(div_busy_o),
        .reg_waddr_o(div_reg_waddr_o)
      );

  clint u_clint(
          .clk(clk),
          .rst_n(rst_n),
          .int_flag_i(if_int_flag_o),
          .inst_i(id_inst_o),
          .inst_addr_i(id_inst_addr_o),
          .jump_flag_i(ex_jump_flag_o),
          .jump_addr_i(ex_jump_addr_o),
          .div_started_i(ex_div_start_o),
          .csr_mtvec(csr_clint_csr_mtvec),
          .csr_mepc(csr_clint_csr_mepc),
          .csr_mstatus(csr_clint_csr_mstatus),
          .we_o(clint_we_o),
          .waddr_o(clint_waddr_o),
          .raddr_o(clint_raddr_o),
          .data_o(clint_data_o),
          .hold_flag_o(clint_hold_flag_o),
          .global_int_en_i(csr_global_int_en_o),
          .int_addr_o(clint_int_addr_o),
          .int_assert_o(clint_int_assert_o)
        );

endmodule

pc_reg.v

// PC寄存器模块
module  pc_reg(
    input   wire            clk                ,
    input   wire            rst_n              ,  // 低电平复位

    input   wire            jump_flag_i        ,  // 跳转标志
    input   wire  [31:0]    jump_addr_i        ,  // 跳转地址
    input   wire  [2 :0]    hold_flag_i        ,  // 流水线暂停标志
    input   wire            jtag_reset_flag_i  ,  // 复位标志

    output  reg   [31:0]    pc_o
  );

  always@(posedge clk )
  begin
    // 复位
    if(rst_n == 0 || jtag_reset_flag_i == 1)
    begin
      pc_o  <= 32'h0 ;
    end
    else if(jump_flag_i == 1)
    begin
      pc_o  <= jump_addr_i  ;
    end
    else if(hold_flag_i >= 3'b001 )
    begin
      pc_o  <= pc_o ; // 这就是暂停保持的
    end
    else
    begin
      pc_o <= pc_o + 4'h4 ;
    end
  end
endmodule

if_id.v

// 将指令向译码模块传递
module if_id(
    input    wire             clk          ,
    input    wire             rst_n        ,

    input    wire   [31 : 0]  inst_i       ,
    output   wire   [31 : 0]  inst_o       ,

    input    wire   [31 : 0]  inst_addr_i  , 
    output    wire   [31 : 0]  inst_addr_o  ,  

    input    wire   [2  : 0]  hold_flag_i  ,

    input    wire   [7  : 0]  int_flag_i   ,    // 外设中断输入信号 
    output   wire   [7  : 0]  int_flag_o   
);

wire  hold_en = (hold_flag_i > 3'b010)     ; // 这里的和前面一样的控制信息 hold_IF 

wire [31 : 0]  inst       ; 
wire [31 : 0]  inst_addr  ; 
wire [7  : 0]  int_flag   ;  
 
gen_pipe_dff#(
    .DW       ( 32 )
)inst_ff(
    .clk      ( clk      ),
    .rst_n    ( rst_n    ),
    .hold_en  ( hold_en  ),
    .def_val  ( 32'h00000001  ),   // 其实我不懂默认的为什么要设置这个指令内容 1 我就设置成0 
    .din      ( inst_i       ),
    .qout     ( inst     )
);
assign  inst_o = inst ; 


gen_pipe_dff#(
    .DW       ( 32 )
)inst_addr_ff(
    .clk      ( clk      ),
    .rst_n    ( rst_n    ),
    .hold_en  ( hold_en  ),
    .def_val  ( 32'h0  ),       // 这里是 指令地址0 
    .din      ( inst_addr_i      ),
    .qout     ( inst_addr     )
);
assign  inst_addr_o = inst_addr  ;  

gen_pipe_dff#(
    .DW       ( 8 )
)int_flag_ff(
    .clk      ( clk      ),
    .rst_n    ( rst_n    ),
    .hold_en  ( hold_en  ),
    .def_val  ( 8'h0  ),
    .din      ( int_flag_i      ),  // 外设中断输入信号
    .qout     ( int_flag    )
);
assign  int_flag_o = int_flag ; 

endmodule  

id.v

// 译码阶段
module id(
    input                      rst_n          ,
    //
    input         [31 : 0]     inst_i         ,    // 指令内容
    input         [31 : 0]     inst_addr_i    ,
    // from reg 我在这里其实会等reg把指令传递回来
    input         [31 : 0]     reg1_rdata_i   ,
    input         [31 : 0]     reg2_rdata_i   ,
    // from csr reg
    input         [31 : 0]     csr_rdata_i    ,
    // from ex 跳转标志

    // input                      ex_jump_flag_i ,               // 跳转标志
    //这一个是根本用不到的数据 
    // 

    // to reg
    output   reg  [4 : 0]     reg1_raddr_o   ,   // 读通用寄存器1地址
    output   reg  [4 : 0]     reg2_raddr_o   ,
    // to csr reg
    output   reg  [31 : 0]     csr_raddr_o    ,
    // to ex
    output   reg  [31 : 0]     op1_o          ,
    output   reg  [31 : 0]     op2_o          ,
    output   reg  [31 : 0]     op1_jump_o     ,
    output   reg  [31 : 0]     op2_jump_o     ,
    output   reg  [31 : 0]     inst_o         ,
    output   reg  [31 : 0]     inst_addr_o    ,    // 指令地址
    output   reg  [31 : 0]     reg1_rdata_o   ,        // 通用寄存器1数据
    output   reg  [31 : 0]     reg2_rdata_o   ,        // 通用寄存器2数据
    output   reg               reg_we_o       ,        // 写通用寄存器标志
    output   reg  [4 : 0]      reg_waddr_o    ,        // 写通用寄存器地址
    output   reg               csr_we_o       ,        // 写CSR寄存器标志
    output   reg  [31 : 0]     csr_rdata_o    ,         // CSR寄存器数据
    output   reg  [31 : 0]     csr_waddr_o              // 写CSR寄存器地址
  ) ;


  // 还是先写整体的主题内容
  // 对于指令字段的分析
  // [31:25] [24:20] [19:15] [14:12] [11:7] [6:0]
  wire    [6 : 0]      opcode       ;
  wire    [4 : 0]      rd           ;
  wire    [2 : 0]      funct3       ;
  wire    [4 : 0]      rs1          ;
  wire    [4 : 0]      rs2          ;
  wire    [6 : 0]      funct7       ;

  assign    opcode  =   inst_i[6  : 0]  ;
  assign    rd      =   inst_i[11 : 7]  ;
  assign    funct3  =   inst_i[14 : 12] ;
  assign    rs1     =   inst_i[19 : 15] ;
  assign    rs2     =   inst_i[24 : 20] ;
  assign    funct7  =   inst_i[31 : 25] ;




  always@(*)
  begin
    inst_o          = inst_i        ;
    inst_addr_o     = inst_addr_i   ;
    reg1_rdata_o    = reg1_rdata_i  ;
    reg2_rdata_o    = reg2_rdata_i  ;
    csr_rdata_o     = csr_rdata_i   ;
    csr_raddr_o     = 0             ;
    csr_waddr_o     = 0             ;
    csr_we_o        = 0             ;
    op1_o           = 0             ;
    op2_o           = 0             ;
    op1_jump_o      = 0             ;
    op2_jump_o      = 0             ;

    case(opcode)
      7'b001_0011 :
      begin    // this is I type
        case(funct3)
          3'b000 ,             // addi  addi a0, a1, 0x5  //a0 = a1 + 0x5
          3'b010 ,             // slti a0, a1, 0x05  //a1 < 0x05 ? a0 = 1 : a0 = 0
          3'b011 ,             // SLTIU
          3'b100 ,             // XORI
          3'b110 ,             // ORI
          3'b111 ,             // ANDI
          3'b001 ,             // SLLI
          3'b101  :            // SRI
          begin
            reg_we_o      =  1              ;
            reg_waddr_o   =  rd             ;   // 这里的做法是写地址给出
            reg1_raddr_o  =  rs1            ;
            reg2_raddr_o  =  0              ;
            op1_o         =  reg1_rdata_i   ;
            op2_o         =  {
   {
   20{
   inst_i[31]}}, inst_i[31:20]}  ;
          end
          default :
          begin
            reg_we_o      =  0    ;
            reg_waddr_o   =  0    ;
            reg1_raddr_o  =  0    ;
            reg2_raddr_o  =  0    ;
          end
        endcase
      end

      7'b011_0011 :      // R型
      begin
        if( (funct7 == 7'b000_0000) || (funct7 == 7'b010_0000))
        begin
          case(funct3) // 这一部分是标准的指令集内容
            3'b000 ,           //  SUB
            3'b001 ,           //  SLL
            3'b010 ,           //  SLT
            3'b011 ,           //  SLTU
            3'b100 ,           //  XOR
            3'b101 ,           //  SR
            3'b110 ,           //  OR
            3'b111  :          //  AND
            begin
              reg_we_o      =   1               ;
              reg_waddr_o   =   rd              ;
              reg1_raddr_o  =   rs1             ;
              reg2_raddr_o  =   rs2             ;
              op1_o         =   reg1_rdata_i    ;
              op2_o         =   reg2_rdata_i    ;
            end
            default :
            begin
              reg_we_o    =   0               ;
              reg_waddr_o =   0               ;
              reg1_raddr_o =  0               ;
              reg2_raddr_o =  0               ;
            end
          endcase
        end
        else if( funct7 == 7'b000_0001)    // M
        begin
          case(funct3)
            3'b000 ,      // MUL
            3'b001 ,      // MULH
            3'b010 ,      // MULHSU
            3'b011  :     // MULHU
            begin
              reg_we_o      =   1               ;
              reg_waddr_o   =   rd              ;
              reg1_raddr_o  =   rs1             ;
              reg2_raddr_o  =   rs2             ;
              op1_o         =   reg1_rdata_i    ;
              op2_o         =   reg2_rdata_i    ;
            end
            3'b100 ,      // DIV
            3'b101 ,      // DIVU
            3'b110 ,      // REM
            3'b111    :   // REMU
            begin
              reg_we_o        =   0   ;   // 因为除法的计算时间比较长,所以会立即禁止写回
              reg_waddr_o     =   rd  ;
              reg1_raddr_o    =   rs1 ;
              reg2_raddr_o    =   rs2 ;
              op1_o           =   reg1_rdata_i  ;
              op2_o           =   reg2_rdata_i  ;
              op1_jump_o      =   inst_addr_i   ;       // 记录 当前指令的地址
              op2_jump_o      =   32'h4         ;
            end
            default:
            begin
              reg_we_o      =   0   ;
              reg_waddr_o   =   0   ;
              reg1_raddr_o  =   0   ;
              reg2_raddr_o  =   0   ;
            end
          endcase
        end
        else
        begin
          reg_we_o        =   0    ;
          reg_waddr_o     =   0    ;
          reg1_raddr_o    =   0    ;
          reg2_raddr_o    =   0    ;
        end
      end

      7'b000_0011 :
      begin     // 其实这里是对上面的I型指令的一部分扩展
        case(funct3)
          3'b000    ,    // lb x10,  0(x1)
          //将x1的值加上0,将这个值作为地址, 取出这个地址所对应的内存中的值, 将这个值赋值给x10(取出的是8位数值)
          3'b001    ,    // lh x10,  0(x1)  //从内存中取出16位数值
          3'b010    ,    // lw x10, 0(x1)  //从内存中取出32位数值
          3'b100    ,    //  lbu x10, 0(x1) //从内存中取出8位无符号数值
          3'b101    : // lhu x10, 0(x1) //从内存中取出16位无符号数值
          begin
            reg_we_o       =   1     ;
            reg_waddr_o    =   rd    ;
            reg1_raddr_o   =   rs1   ;
            reg2_raddr_o   =   0     ;
            op1_o          =   reg1_rdata_i  ;
            op2_o          =   {
   {
   20{
   inst_i[31]}},inst_i[31:20]} ;
          end
          default :
          begin
            reg1_raddr_o   =   0     ;
            reg2_raddr_o   =   0     ;
            reg_we_o       =   0     ;
            reg_waddr_o    =   0     ;
          end
        endcase
      end

      7'b01_00011 :      // S  类型
      begin
        case(funct3)         // S type
          3'b000        ,         // sb  x10, 0(x1)
          //x1的值加上0,将这个值作为地址, 将x10的值存储到上述地址所对应的内存中去 (只会将x10的值的低8位写入)
          3'b001        ,         // sh  x10, 0(x1)  //只会将x10的值的低16位写入
          3'b010        ://    sw  x10, 0(x1)  //只会将x10的值的低32位写入
          begin  
            reg_we_o      =     0    ;  // 并不需要写入寄存器 是直接存入内存的
            reg_waddr_o   =     0    ;
            reg1_raddr_o  =     rs1  ;
            reg2_raddr_o  =     rs2  ;
            op1_o         =     reg1_rdata_i  ;
            op2_o         =     {
   {
   20{
   inst_i[31]}}, inst_i[31:25], inst_i[11:7]}  ;
          end
          default :
          begin
            reg_we_o      =     0    ;
            reg_waddr_o   =     0    ;
            reg1_raddr_o  =     0    ;
            reg2_raddr_o  =     0    ;
          end
        endcase
      end

      7'b1100011  :         //  B 型指令
      begin
        case(funct3)
          3'b000    ,            //beq a1,a2,Label   //if(a1==a2){goto Label;}
          3'b001    ,            //bne a1,a2,Label   //if(a1!=a2){goto Label;}
          3'b100    ,            //blt a1,a2,Label   //if(a1< a2){goto Label;}
          3'b101    ,            //BGE: Branch if Greater or Equal (大于等于时跳转,有符号比较)
          3'b110    ,            //BLTU: Branch if Less Than Unsigned (小于时跳转,无符号比较)
          3'b111    :
          begin     // BGEU: Branch if Greater or Equal Unsigned (大于等于时跳转,无符号比较)
            reg_we_o       =   0       ;
            reg_waddr_o    =   0       ;
            reg1_raddr_o   =   rs1     ;
            reg2_raddr_o   =   rs2     ;
            op1_o          =   reg1_rdata_i   ;
            op2_o          =   reg2_rdata_i   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值