当前位置: 首页 > news >正文

【【深入浅出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:0input       [31 : 0]      jtag_reg_data_i ,       // jtag妯″潡鍐欏瘎瀛樺櫒鏁版嵁 31 : 0input                     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_idif_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_exid_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)beginpc_o  <= 32'h0 ;endelse if(jump_flag_i == 1)beginpc_o  <= jump_addr_i  ;endelse if(hold_flag_i >= 3'b001 )beginpc_o  <= pc_o ; // 这就是暂停保持的endelsebeginpc_o <= pc_o + 4'h4 ;endend
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 reginput         [31 : 0]     csr_rdata_i    ,// from ex 跳转标志// input                      ex_jump_flag_i ,               // 跳转标志//这一个是根本用不到的数据 // // to regoutput   reg  [4 : 0]     reg1_raddr_o   ,   // 读通用寄存器1地址output   reg  [4 : 0]     reg2_raddr_o   ,// to csr regoutput   reg  [31 : 0]     csr_raddr_o    ,// to exoutput   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@(*)begininst_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 typecase(funct3)3'b000 ,             // addi  addi a0, a1, 0x5  //a0 = a1 + 0x53'b010 ,             // slti a0, a1, 0x05  //a1 < 0x05 ? a0 = 1 : a0 = 03'b011 ,             // SLTIU3'b100 ,             // XORI3'b110 ,             // ORI3'b111 ,             // ANDI3'b001 ,             // SLLI3'b101  :            // SRIbeginreg_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]}  ;enddefault :beginreg_we_o      =  0    ;reg_waddr_o   =  0    ;reg1_raddr_o  =  0    ;reg2_raddr_o  =  0    ;endendcaseend7'b011_0011 :      // R型beginif( (funct7 == 7'b000_0000) || (funct7 == 7'b010_0000))begincase(funct3) // 这一部分是标准的指令集内容3'b000 ,           //  SUB3'b001 ,           //  SLL3'b010 ,           //  SLT3'b011 ,           //  SLTU3'b100 ,           //  XOR3'b101 ,           //  SR3'b110 ,           //  OR3'b111  :          //  ANDbeginreg_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    ;enddefault :beginreg_we_o    =   0               ;reg_waddr_o =   0               ;reg1_raddr_o =  0               ;reg2_raddr_o =  0               ;endendcaseendelse if( funct7 == 7'b000_0001)    // Mbegincase(funct3)3'b000 ,      // MUL3'b001 ,      // MULH3'b010 ,      // MULHSU3'b011  :     // MULHUbeginreg_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    ;end3'b100 ,      // DIV3'b101 ,      // DIVU3'b110 ,      // REM3'b111    :   // REMUbeginreg_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         ;enddefault:beginreg_we_o      =   0   ;reg_waddr_o   =   0   ;reg1_raddr_o  =   0   ;reg2_raddr_o  =   0   ;endendcaseendelsebeginreg_we_o        =   0    ;reg_waddr_o     =   0    ;reg1_raddr_o    =   0    ;reg2_raddr_o    =   0    ;endend7'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位无符号数值beginreg_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]} ;enddefault :beginreg1_raddr_o   =   0     ;reg2_raddr_o   =   0     ;reg_we_o       =   0     ;reg_waddr_o    =   0     ;endendcaseend7'b01_00011 :      // S  类型begincase(funct3)         // S type3'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]}  ;enddefault :beginreg_we_o      =     0    ;reg_waddr_o   =     0    ;reg1_raddr_o  =     0    ;reg2_raddr_o  =     0    ;endendcaseend7'b1100011  :         //  B 型指令begincase(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   ;op1_jump_o     =   inst_addr_i    ;op2_jump_o     =   {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};enddefault :beginreg_we_o     =   0    ;reg_waddr_o  =   0    ;reg1_raddr_o =   0    ;reg2_raddr_o =   0    ;endendcaseend7'b110_1111 :   // JAL  J型指令    pc = pc + imm 并将下一条指令的地址 给rdbeginreg_we_o        =   1             ;reg_waddr_o     =   rd            ;reg1_raddr_o    =   0             ;reg2_raddr_o    =   0             ;op1_o           =   inst_addr_i   ;op2_o           =   32'h4         ;op1_jump_o      =   inst_addr_i   ;op2_jump_o      =   {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};end7'b1100_111 :    // JALR  功能:PC = (rs1 + imm) & ~1,并将下一条指令地址存入 rd。beginreg_we_o        =   1             ;reg_waddr_o     =   rd            ;reg1_raddr_o    =   rs1           ;reg2_raddr_o    =   0             ;op1_o           =   inst_addr_i   ;op2_o           =   32'h4         ;op1_jump_o      =   reg1_rdata_i  ;op2_jump_o      =   {{20{inst_i[31]}}, inst_i[31:20]};end7'b011_0111 :   // LUT lui  将 imm[31:12] 左移 12 位后写入寄存器 rdbeginreg_we_o         =   1             ;reg_waddr_o      =   rd            ;reg1_raddr_o     =   0             ;reg2_raddr_o     =   0             ;op1_o            =   {inst_i[31:12], 12'b0}  ;op2_o            =   0             ;end7'b001_0111 :    // 功能:PC + (imm[31:12] << 12) 写入寄存器 rdbeginreg_we_o         =   1              ;reg_waddr_o      =   rd             ;reg1_raddr_o     =   0              ;reg2_raddr_o     =   0              ;op1_o            =   inst_addr_i    ;op2_o            =   {inst_i[31:12], 12'b0}   ;end7'b0000_001 :   // 单纯的占用流水线的时钟周期beginreg_we_o         =   0              ;reg_waddr_o      =   0              ;reg1_raddr_o     =   0              ;reg2_raddr_o     =   0              ;end7'b000_1111 :    //  功能:在执行不同类型的内存操作时插入屏障,确保指令执行顺序beginreg_we_o           =   0              ;reg_waddr_o        =   0              ;reg1_raddr_o       =   0              ;reg2_raddr_o       =   0              ;op1_jump_o         =   inst_addr_i    ;op2_jump_o         =   32'h4          ;end//下面是最后一部分CSR的编写7'b111_0011 :  //  CSR 指令属于 RISC-V 的标准基础指令集的扩展部分// 是的一共六个 特权指令集(Privileged ISA) 的核心部分。beginreg_we_o        = 0    ;reg_waddr_o     = 0    ;reg1_raddr_o    = 0    ;reg2_raddr_o    = 0    ;csr_raddr_o     = {20'h0, inst_i[31:20]};csr_waddr_o     = {20'h0, inst_i[31:20]};case (funct3)3'b001   ,3'b010   ,3'b011   :beginreg1_raddr_o   =   rs1   ;reg2_raddr_o   =   0     ;reg_we_o       =   1     ;reg_waddr_o    =   rd    ;csr_we_o       =   1     ;end3'b101    ,3'b110    ,3'b111    :beginreg1_raddr_o   =   0      ;reg2_raddr_o   =   0      ;reg_we_o       =   1      ;reg_waddr_o    =   rd     ;csr_we_o       =   1      ;enddefault:beginreg_we_o       =   0  ;reg_waddr_o    =   0  ;reg1_raddr_o   =   0  ;reg2_raddr_o   =   0  ;csr_we_o       =   0  ;endendcaseenddefault:beginreg_we_o      =     0   ;reg_waddr_o   =     0   ;reg1_raddr_o  =     0   ;reg2_raddr_o  =     0   ;endendcaseendendmodule

clint.v

// 核心中断管理、仲裁
module  clint(input                     clk           ,input                     rst_n         ,// 其实很简单的区分input   [7 : 0]           int_flag_i    ,  // 这个信号是 来自于core的//  这一部分是中断的指令内容input   [31 : 0]          inst_i        ,   // 这里确定的是指令的内容// clint 模块需要知道当前执行的指令,以便检查是否是一个需要处理的指令(例如,ECALL 或 EBREAK)。// 如果是同步中断(如系统调用),需要根据指令类型决定如何处理中断。input   [31 : 0]          inst_addr_i   ,// form exinput                     jump_flag_i   ,  //// 中断处理需要知道当前是否有跳转指令正在执行。如果有跳转指令发生,中断处理时要注意将跳转地址保存或调整。input   [31 : 0]          jump_addr_i   ,input                     div_started_i ,  // 除法指令// 如果正在进行除法操作 可能要推迟同步中断的处理//input   [2 : 0]           hold_flag_i   ,  // 流水线暂停标志// 标注一下这里的 hold_flag_i 并没有用到// 下面是正常的交互  csr_reg//  input   [31 : 0]          data_i        ,  这是一个没用的值input   [31 : 0]          csr_mtvec     ,// 中断向量表地址input   [31 : 0]          csr_mepc      ,// 中断返回地址input   [31 : 0]          csr_mstatus   ,// 全局中断状态寄存器input                     global_int_en_i ,   // 全局中断使能output                    hold_flag_o   ,     // 全局流水线暂停// to  csr_regoutput  reg               we_o          ,output  reg   [31 : 0]    waddr_o       ,output  reg   [31 : 0]    raddr_o       ,output  reg   [31 : 0]    data_o        ,// to exoutput  reg   [31 : 0]    int_addr_o    ,output  reg               int_assert_o);// ------------------------------------------------------------- ////           next is define  and parameter                       //// ------------------------------------------------------------- //// 定义中断的状态机localparam S_INT_IDLE            = 4'b0001;localparam S_INT_SYNC_ASSERT     = 4'b0010;localparam S_INT_ASYNC_ASSERT    = 4'b0100;localparam S_INT_MRET            = 4'b1000;// 写CSR寄存器状态定义localparam S_CSR_IDLE            = 5'b00001;localparam S_CSR_MSTATUS         = 5'b00010;localparam S_CSR_MEPC            = 5'b00100;localparam S_CSR_MSTATUS_MRET    = 5'b01000;localparam S_CSR_MCAUSE          = 5'b10000;reg[3  : 0]   int_state   ;reg[4  : 0]   csr_state   ;reg[31 : 0]   inst_addr   ;reg[31 : 0]   cause       ;assign hold_flag_o  =  ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE))? 1 : 0 ;// 中断仲裁阶段always@(*)beginif(rst_n == 0)beginint_state   <=  S_INT_IDLE  ;endelsebeginif(inst_i == 32'h0000_0073 || inst_i == 32'h0010_0073)beginif(div_started_i == 1)beginint_state  <=  S_INT_IDLE  ;endelsebeginint_state  <=  S_INT_SYNC_ASSERT ;endendelse if( int_flag_i != 0  && global_int_en_i == 1)beginint_state  <=  S_INT_ASYNC_ASSERT  ;endelse if(inst_i == 32'h3020_0073)beginint_state  <=  S_INT_MRET ;  // 这个表示需要从异常状态恢复到正常程序状态endelsebeginint_state <= S_INT_IDLE ;endendend// 写CSR寄存器状态切换always@( posedge clk )beginif(rst_n == 0)begincsr_state   <=  S_CSR_IDLE  ;   // 状态机cause       <=  0           ;inst_addr   <=  0           ;endelsebegincase( csr_state )S_CSR_IDLE :begin// 同步中断if(int_state == S_INT_SYNC_ASSERT )    // 这部分的意思是如果系统捕获到了同步中断begincsr_state   <=   S_CSR_MEPC         ;// 在中断处理函数里会将中断返回地址 - 4if (jump_flag_i ==  1 )begininst_addr <=   jump_addr_i - 4'h4 ;endelsebegininst_addr <=   inst_addr_i  ;endcase (inst_i)32'h0000_0073 :   // ECALLbegincause   <=   32'd11  ;end32'h010_0073  :   // EBREAKbegincause   <=   32'd3   ;enddefault:begincause   <=   32'd10  ;endendcaseend // 异步中断else if (int_state == S_INT_ASYNC_ASSERT)begin// 定时器中断cause <= 32'h80000004;csr_state <= S_CSR_MEPC;if (jump_flag_i == 1)begininst_addr <= jump_addr_i;// 异步中断可以中断除法指令的执行,中断处理完再重新执行除法指令endelse if (div_started_i == 1)begininst_addr <= inst_addr_i - 4'h4;endelsebegininst_addr <= inst_addr_i;end// 中断返回endelse if (int_state == S_INT_MRET)begincsr_state <= S_CSR_MSTATUS_MRET;endendS_CSR_MEPC:// 在这个状态下,系统会将当前的中断返回地址保存到 MEPC,以便中断处理完后可以正确返回。begincsr_state <= S_CSR_MSTATUS;endS_CSR_MSTATUS:// 这个状态用于处理 MSTATUS 寄存器,通常涉及到恢复系统的中断使能和相关状态。begincsr_state <= S_CSR_MCAUSE;endS_CSR_MCAUSE:// MCAUSE 寄存器用于存储中断的原因。在这个状态下,系统会把中断的原因写入 MCAUSE 寄存器。begincsr_state <= S_CSR_IDLE;endS_CSR_MSTATUS_MRET:// 这是中断返回的特殊状态。执行完中断处理后,处理器需要返回到中断发生前的程序。// 这是通过恢复 MSTATUS 寄存器和中断前的状态来实现的。begincsr_state <= S_CSR_IDLE;enddefault:begincsr_state <= S_CSR_IDLE;endendcaseendend// 发出信号前 先写几个寄存器always@(posedge clk )beginif(rst_n == 0)beginwe_o      <=  0   ;waddr_o   <=  0   ;data_o    <=  0   ;endelsebegin  // 这一部分是按照上面的情况进行给予的case(csr_state )S_CSR_MEPC :begin// 在这个状态下,系统会将当前的中断返回地址保存到 MEPC,以便中断处理完后可以正确返回。we_o      <=  1            ;waddr_o   <=  {20'h0 , 12'h341} ;data_o    <=  inst_addr    ;end// 写中断产生的原因S_CSR_MCAUSE:beginwe_o      <=  1      ;waddr_o   <=  {20'h0, 12'h342 };data_o    <=  cause  ;end// 关闭全局中断S_CSR_MSTATUS:beginwe_o      <=  1     ;waddr_o   <= {20'h0, 12'h300};data_o    <= {csr_mstatus[31:4], 1'b0, csr_mstatus[2:0]};end// 中断返回S_CSR_MSTATUS_MRET :beginwe_o      <=  0     ;waddr_o <= {20'h0, 12'h300};data_o <= {csr_mstatus[31:4], csr_mstatus[7], csr_mstatus[2:0]};enddefault:beginwe_o      <=    0   ;waddr_o   <=    0   ;data_o    <=    0   ;endendcaseendend// 发送中断信号给ex模块always@(posedge  clk )beginif(rst_n == 0)beginint_assert_o   <=  0   ;int_addr_o     <=  0   ;endelsebegincase (csr_state)// 发出中断进入信号.写完mcause寄存器才能发S_CSR_MCAUSE:beginint_assert_o   <= 1          ;int_addr_o     <= csr_mtvec  ;end// 发出中断返回信号S_CSR_MSTATUS_MRET:beginint_assert_o   <= 1         ;int_addr_o     <= csr_mepc  ;enddefault:beginint_assert_o   <= 0   ;int_addr_o     <= 0   ;endendcaseendendendmodule

csr_reg.v

module   csr_reg(  // 寄存器input                       clk               ,input                       rst_n             ,// from  exinput                       we_i              , // ex模块写寄存器标志位input   [31 : 0]            raddr_i           ,input   [31 : 0]            waddr_i           ,input   [31 : 0]            data_i            ,// from clintinput                       clint_we_i        ,input   [31 : 0]            clint_raddr_i     ,input   [31 : 0]            clint_waddr_i     ,input   [31 : 0]            clint_data_i      ,output                      global_int_en_o   ,// to  clintoutput  reg  [31 : 0]       clint_data_o      ,output       [31 : 0]       clint_csr_mtvec   ,output       [31 : 0]       clint_csr_mepc    ,output       [31 : 0]       clint_csr_mstatus ,// to exoutput  reg  [31 : 0]       data_o) ;// --------------------------------------------- ////          next is parameter and define         //// --------------------------------------------- //reg     [63 : 0]  cycle     ;reg     [31 : 0]  mtvec     ;reg     [31 : 0]  mcause    ;reg     [31 : 0]  mepc      ;reg     [31 : 0]  mie       ;reg     [31 : 0]  mstatus   ;reg     [31 : 0]  mscratch  ;assign global_int_en_o   = (mstatus[3] == 1'b1)? 1: 0  ;assign clint_csr_mtvec   = mtvec                       ;assign clint_csr_mepc    = mepc                        ;assign clint_csr_mstatus = mstatus                     ;// next is main codealways@(posedge clk )beginif(rst_n == 0 )begincycle  <=  0         ;endelsebegincycle  <=  cycle + 1 ;endend// write  reg  写寄存器always@(posedge  clk )beginif(rst_n == 0)beginmtvec         <=  0  ;mcause        <=  0  ;mepc          <=  0  ;mie           <=  0  ;mstatus       <=  0  ;mscratch      <=  0  ;endelsebeginif(we_i == 1)begin // 先响应ex写模块case( waddr_i[11 : 0])12'h305 :beginmtvec  <=  data_i  ;   //  处理器的中断向量地址寄存器。end12'h342:beginmcause <=  data_i  ;   //  记录中断发生的原因。end12'h341:beginmepc   <=  data_i  ;   //  记录中断发生时的程序计数器(PC)值,即出错时程序的执行地址end12'h304:beginmie    <=  data_i  ;   //   机器模式下的中断使能寄存器end12'h300:beginmstatus <= data_i  ;   //   机器状态寄存器,包含有关当前处理器状态的信息end12'h340:beginmscratch <= data_i  ;  //    用于保存机器模式下的临时值enddefault:beginendendcaseendelse if( clint_we_i == 1)begincase( clint_waddr_i[11:0])12'h305 :beginmtvec  <=  clint_data_i  ;   //  处理器的中断向量地址寄存器。end12'h342:beginmcause <=  clint_data_i  ;   //  记录中断发生的原因。end12'h341:beginmepc   <=  clint_data_i  ;   //  记录中断发生时的程序计数器(PC)值,即出错时程序的执行地址end12'h304:beginmie    <=  clint_data_i  ;   //   机器模式下的中断使能寄存器end12'h300:beginmstatus <= clint_data_i  ;   //   机器状态寄存器,包含有关当前处理器状态的信息end12'h340:beginmscratch <= clint_data_i  ;  //    用于保存机器模式下的临时值enddefault:beginendendcaseendendend// 读寄存器always@(*)beginif((waddr_i[11:0] == raddr_i[11:0]) &&(we_i == 1) )begindata_o  <=  data_i   ;endelsebegincase(raddr_i[11 : 0])12'hc00 :begindata_o    <= cycle[31:0]   ;end12'hc80 :begindata_o    <= cycle[63:32]  ;end12'h305 :begindata_o    <= mtvec         ;end12'h342 :begindata_o    <= mcause        ;end12'h341 :begindata_o    <= mepc          ;end12'h304 :begindata_o    <= mie           ;end12'h300 :begindata_o    <= mstatus       ;end12'h340 :begindata_o    <= mscratch      ;enddefault:begindata_o <= 0 ;endendcaseendendalways@(*)beginif((clint_waddr_i[11:0] == clint_raddr_i[11:0]) &&(clint_we_i == 1) )beginclint_data_o  <=  clint_data_i   ;endelsebegincase(clint_raddr_i[11 : 0])12'hc00 :beginclint_data_o    <= cycle[31:0]   ;end12'hc80 :beginclint_data_o    <= cycle[63:32]  ;end12'h305 :beginclint_data_o    <= mtvec         ;end12'h342 :beginclint_data_o    <= mcause        ;end12'h341 :beginclint_data_o    <= mepc          ;end12'h304 :beginclint_data_o    <= mie           ;end12'h300 :beginclint_data_o    <= mstatus       ;end12'h340 :beginclint_data_o    <= mscratch      ;enddefault:beginclint_data_o <= 0 ;endendcaseendendendmodule

ctrl.v

// 这是控制模块的设计
module  ctrl(// from  ex 来自于ex 的处理// input                          rst_n               ,// 经过分析 这里也没有用到 rst_ninput                          jump_flag_i         ,input           [31 : 0]       jump_addr_i         ,    // 传递给PC 跳转的input                          hold_flag_ex_i      ,    // 内部的比如说触发需要暂停这样的// from rib 总线input                          hold_flag_rib_i     ,// from  jtaginput                          jtag_halt_flag_i    ,// clintinput                          hold_flag_clint_i   ,// 输出 阶段output   reg     [2  : 0]      hold_flag_o         ,output   reg                   jump_flag_o         ,// to pcoutput   reg     [31 : 0]      jump_addr_o) ;// 非常简单的组合逻辑阵列always@(*)beginjump_addr_o   =   jump_addr_i  ;jump_flag_o   =   jump_flag_i  ;// 默认不暂停hold_flag_o   =   0            ;// 按照优先级程度处理不同模块if(jump_flag_i == 1 ||  hold_flag_ex_i == 1  || hold_flag_clint_i === 1)begin// 暂停整条流水线hold_flag_o  =  3'b011 ;endelse if(hold_flag_rib_i == 1)beginhold_flag_o  = 3'b001 ;endelse if(jtag_halt_flag_i == 1)beginhold_flag_o  = 3'b011 ;endelsebeginhold_flag_o = 0 ;endend
endmodule

div.v

// 这里作者说使用试商法 实现整除
module  div(input                          rst_n         ,input                          clk           ,// from exinput              [31 : 0]    dividend_i    ,  // 被除数input              [31 : 0]    divisor_i     ,  // 除数input                          start_i       ,  // 开始信号input              [2  : 0]    op_i          ,  // 声明具体执行的是什么指令input              [4  : 0]    reg_waddr_i   ,  // 寄存器地址// to exoutput   reg       [31 : 0]    result_o      ,  // 除法结果output   reg                   ready_o       ,output   reg                   busy_o        ,output   reg       [4  : 0]    reg_waddr_o      // 存放的寄存器地址);// 状态定义localparam    STATE_IDLE    =    4'b0001  ;localparam    STATE_START   =    4'b0010  ;localparam    STATE_CALC    =    4'b0100  ;localparam    STATE_END     =    4'b1000  ;// ----------------------------------------------------- ////    parameter   and  define                           ////  ------------------------------------------------   //reg  [2  : 0]    op_r         ;reg  [31 : 0]    dividend_r   ;reg  [31 : 0]    divisor_r    ;reg  [3  : 0]    state        ;wire op_div    = (op_r == 3'b100 );   // 100  有符号整数除法wire op_divu   = (op_r == 3'b101 );   // 101  无符号整数除法wire op_rem    = (op_r == 3'b110 );   // 110  有符号整数取余wire op_remu   = (op_r == 3'b111 );   // 111  无符号整数取余reg  [31 : 0]    count         ;reg  [31 : 0]    div_result    ;  // 暂存的商值reg  [31 : 0]    div_remain    ;  // 暂存的余数值reg  [31 : 0]    minuend       ;  // 表示当前的被减数reg              invert_result ;wire  [31 : 0]    dividend_invert  =   (-dividend_r ) ;wire  [31 : 0]    divisor_invert   =   (-divisor_r)   ;wire  minuend_ge_divisor  =   minuend >= divisor_r    ;  // 比较被减数 和 除数wire  [31 : 0]    div_result_tmp   =   minuend_ge_divisor ?({div_result[30 : 0] ,1'b1}) : ({div_result[30 : 0] , 1'b0}) ;wire  [31 : 0]    minuend_sub_res  =   minuend  - divisor_r  ;wire  [31 : 0]    minuend_tmp      =   minuend_ge_divisor  ? minuend_sub_res[30 : 0] : minuend[30 : 0] ;//   -----------------------------------------------    ////             next is  main  code                      ////   -------------------------------------------------  //// 状态机的更新always@(posedge clk  )beginif(rst_n == 0 )beginstate       <=   STATE_IDLE  ;ready_o     <=   0           ;result_o <= 0;div_result <= 0;div_remain <= 0;op_r <= 3'h0;reg_waddr_o <= 0;dividend_r <= 0;divisor_r <=0;minuend <= 0;invert_result <= 1'b0;busy_o <= 0;count <= 0;endelsebegincase(state)STATE_IDLE :beginif(start_i == 1)begin// 表示开始运算op_r            <=     op_i         ;dividend_r      <=     dividend_i   ;divisor_r       <=     divisor_i    ;reg_waddr_o     <=     reg_waddr_i  ;   // 寄存器地址 方便回写state           <=     STATE_START  ;busy_o          <=     1            ;endelsebeginop_r            <=     0            ;dividend_r      <=     0            ;divisor_r       <=     0            ;reg_waddr_o     <=     0            ;   // 寄存器地址 方便回写state           <=     0            ;busy_o          <=     0            ;endendSTATE_START :beginif(start_i == 1)begin // 开始运算//先假设除数为0if(divisor_r == 0 )beginif(op_div | op_divu )begin// 取商的操作 那么输出 32'hFFFFFFFF 表示 错误商值,在 除数为 0 时由硬件返回。result_o  <= 32'hffff_ffff ;endelsebegin  // 那就是取余数result_o  <=  dividend_r   ; // 取余数的话 余下来的正好是被除数end// 上面两个都执行的在除数为0的情况下ready_o     <=   1             ;state       <=   STATE_IDLE    ;busy_o      <=   0             ;endelsebegin// 这部分是除数不为0busy_o      <=   1             ;state       <=   STATE_CALC    ;count       <=   32'h4000_0000 ;div_result  <=   0             ;div_remain  <=   0             ;// 先进行有符号的运算if(op_div | op_rem)  // 有符号运算begin// 被除数求补码if(dividend_r[31] == 1)begindividend_r   <=  dividend_invert ;minuend      <=  dividend_invert[31] ;  // 初始化为被除数的符号位endelsebeginminuend    <=   dividend_r[31] ; // 其实就是0endif(divisor_r[31] == 1)begindivisor_r  <=  divisor_invert ;endelsebeginminuend    <=  dividend_r[31] ;end// 判断计算的结果是否需要取补码if((op_div &&(dividend_r[31] ^ divisor_r[31] == 1))|| (op_rem && (dividend_r[31]  == 1)))begininvert_result   <=  1 ;endelsebegininvert_result   <=  0  ;endendendendelsebeginstate       <=   STATE_IDLE   ;result_o    <=   0            ;ready_o     <=   0            ;busy_o      <=   0            ;endend// 这里是整体的计算部分STATE_CALC :beginif(start_i == 1)begindividend_r  <=   {dividend_r[30 : 0] , 1'b0}  ;div_result  <=   div_result_tmp               ;count       <=   {1'b0 , count[31 : 1] }      ;if(|count)beginminuend   <=   {minuend_tmp[30 : 0] , dividend_r[30]} ;endelsebeginstate     <=   STATE_END  ;if(minuend_ge_divisor)begindiv_remain   <=  minuend_sub_res   ;endelsebegindiv_remain   <=  minuend           ;endendendelsebeginstate          <=   STATE_IDLE  ;result_o       <=   0           ;ready_o        <=   0           ;busy_o         <=   0           ;endendSTATE_END  :beginif(start_i  == 1)beginready_o       <=    1               ;state         <=    STATE_IDLE      ;busy_o        <=    0               ;if(op_div  |  op_divu )beginif(invert_result == 1)beginresult_o  <=   (-div_result) ;endelsebeginresult_o  <=   div_result    ;endendelsebeginif(invert_result == 1)beginresult_o  <=  (-div_remain ) ;endelsebeginresult_o  <=  div_remain    ;endendendelsebeginstate      <=  STATE_IDLE  ;result_o   <=  0           ;ready_o    <=  0           ;busy_o     <=  0           ;endendendcaseendend
endmodule

ex.v

module ex(input                rst_n   ,// from idinput        [31:0] inst_i,            // 指令内容  31input        [31:0] inst_addr_i,   // 指令地址  31input         reg_we_i,                    // 是否写通用寄存器input        [4:0] reg_waddr_i,    // 写通用寄存器地址  4:0input        [31:0] reg1_rdata_i,       // 通用寄存器1输入数据 31input        [31:0] reg2_rdata_i,       // 通用寄存器2输入数据31input         csr_we_i,                    // 是否写CSR寄存器input        [31:0] csr_waddr_i,    // 写CSR寄存器地址 31input        [31:0] csr_rdata_i,        // CSR寄存器输入数据31input         int_assert_i,                // 中断发生标志     -- 来自于 clintinput        [31:0] int_addr_i,    // 中断跳转地址31   -- 来自于 clintinput        [31:0] op1_i,          // 31input        [31:0] op2_i,input        [31:0] op1_jump_i,input        [31:0] op2_jump_i,// from meminput wire[31:0] mem_rdata_i,        // 内存输入数据// from divinput wire div_ready_i,                 // 除法运算完成标志input wire[31:0] div_result_i,       // 除法运算结果input wire div_busy_i,                  // 除法运算忙标志input wire[4:0] div_reg_waddr_i,// 除法运算结束后要写的寄存器地址 4:0// to memoutput reg[31:0] mem_wdata_o,        // 写内存数据 31output reg[31:0] mem_raddr_o,    // 读内存地址output reg[31:0] mem_waddr_o,    // 写内存地址 31output wire mem_we_o,                   // 是否要写内存output wire mem_req_o,                  // 请求访问内存标志// to regsoutput wire[31:0] reg_wdata_o,       // 写寄存器数据 31:0output wire reg_we_o,                   // 是否要写通用寄存器output wire[4:0] reg_waddr_o,   // 写通用寄存器地址 4:0// to csr regoutput reg[31:0] csr_wdata_o,        // 写CSR寄存器数据output wire csr_we_o,                   // 是否要写CSR寄存器output wire[31:0] csr_waddr_o,   // 写CSR寄存器地址 31:0// to divoutput wire div_start_o,                // 开始除法运算标志output reg[31:0] div_dividend_o,     // 被除数output reg[31:0] div_divisor_o,      // 除数output reg[2:0] div_op_o,               // 具体是哪一条除法指令output reg[4:0] div_reg_waddr_o,// 除法运算结束后要写的寄存器地址4:0// to ctrloutput wire hold_flag_o,                // 是否暂停标志output wire jump_flag_o,                // 是否跳转标志output wire[31:0] jump_addr_o   // 跳转目的地址 31 : 0);wire[1:0] mem_raddr_index;                          //wire[1:0] mem_waddr_index;                          //wire[63:0] mul_temp;                      // 63:0wire[63:0] mul_temp_invert;               //wire[31:0] sr_shift;                               //wire[31:0] sri_shift;                              //wire[31:0] sr_shift_mask;                          //wire[31:0] sri_shift_mask;                         //wire[31:0] op1_add_op2_res;                        //wire[31:0] op1_jump_add_op2_jump_res;              //wire[31:0] reg1_data_invert;                       // 我合在一起写了wire[31:0] reg2_data_invert;                       //wire op1_ge_op2_signed;             			  //wire op1_ge_op2_unsigned;    					  //wire op1_eq_op2;                                  //reg[31:0] mul_op1;                             //1reg[31:0] mul_op2;                             //wire[6:0] opcode;                                 //wire[2:0] funct3;                                 //wire[6:0] funct7;                                 //wire[4:0] rd;                                     //wire[4:0] uimm;                                   //reg[31:0] reg_wdata;                          // 1reg reg_we;                                      // 1reg[4:0] reg_waddr;                      // 4: 0reg[31:0] div_wdata;                          //1reg div_we;                                      //1reg[4:0] div_waddr;                      // 4:0reg div_hold_flag;                               // 1reg div_jump_flag;                               // 1reg[31:0] div_jump_addr;                 //31 : 0reg hold_flag;                                   //reg jump_flag;                                   //reg[31:0] jump_addr;                     // 1reg mem_we;                                      //reg mem_req;                                    // 1reg div_start;                                  // 1assign opcode = inst_i[6:0];assign funct3 = inst_i[14:12];assign funct7 = inst_i[31:25];assign rd = inst_i[11:7];assign uimm = inst_i[19:15];assign sr_shift = reg1_rdata_i >> reg2_rdata_i[4:0];              //assign sri_shift = reg1_rdata_i >> inst_i[24:20];                //assign sr_shift_mask = 32'hffffffff >> reg2_rdata_i[4:0];       //assign sri_shift_mask = 32'hffffffff >> inst_i[24:20];          //assign op1_add_op2_res = op1_i + op2_i;                       //assign op1_jump_add_op2_jump_res = op1_jump_i + op2_jump_i;   //assign reg1_data_invert = ~reg1_rdata_i + 1;    //assign reg2_data_invert = ~reg2_rdata_i + 1;    //// 有符号数比较assign op1_ge_op2_signed = $signed(op1_i) >= $signed(op2_i);     //// 无符号数比较assign op1_ge_op2_unsigned = op1_i >= op2_i;      //assign op1_eq_op2 = (op1_i == op2_i);            //assign mul_temp = mul_op1 * mul_op2;             //assign mul_temp_invert = ~mul_temp + 1;         //assign mem_raddr_index = (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 2'b11;      //                      //assign mem_waddr_index = (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}) & 2'b11;  //           //assign div_start_o = (int_assert_i == 1)? 0: div_start;  //assign reg_wdata_o = reg_wdata | div_wdata; //// 响应中断时不写通用寄存器assign reg_we_o = (int_assert_i == 1)? 0: (reg_we || div_we);assign reg_waddr_o = reg_waddr | div_waddr;// 响应中断时不写内存assign mem_we_o = (int_assert_i == 1)? 0: mem_we;// 响应中断时不向总线请求访问内存assign mem_req_o = (int_assert_i == 1)? 0: mem_req;assign hold_flag_o = hold_flag || div_hold_flag;assign jump_flag_o = jump_flag || div_jump_flag || ((int_assert_i == 1)? 1: 0);assign jump_addr_o = (int_assert_i == 1)? int_addr_i: (jump_addr | div_jump_addr);// 响应中断时不写CSR寄存器assign csr_we_o = (int_assert_i == 1)? 0: csr_we_i;assign csr_waddr_o = csr_waddr_i;// 处理乘法指令always @ (*)beginif ((opcode == 7'b0110011) && (funct7 == 7'b0000001))begincase (funct3)3'b000, 3'b011:begin  // 3'b000  -  3'b011  无符号乘法 一个保留了低32位 一个保留了高32位mul_op1 = reg1_rdata_i;mul_op2 = reg2_rdata_i;end3'b010:begin   // 3'b010 有符号与 无符号混合乘法mul_op1 = (reg1_rdata_i[31] == 1'b1)? (reg1_data_invert): reg1_rdata_i;mul_op2 = reg2_rdata_i;end3'b001:begin  //3'b001  有符号乘法mul_op1 = (reg1_rdata_i[31] == 1'b1)? (reg1_data_invert): reg1_rdata_i;mul_op2 = (reg2_rdata_i[31] == 1'b1)? (reg2_data_invert): reg2_rdata_i;enddefault:beginmul_op1 = reg1_rdata_i;mul_op2 = reg2_rdata_i;endendcaseendelsebeginmul_op1 = reg1_rdata_i;mul_op2 = reg2_rdata_i;endend// 处理除法指令always @ (*)begindiv_dividend_o = reg1_rdata_i;div_divisor_o = reg2_rdata_i;div_op_o = funct3;div_reg_waddr_o = reg_waddr_i;if ((opcode == 7'b0110011) && (funct7 == 7'b0000001))begin // 7'b0110011div_we = 0;div_wdata = 32'h0;div_waddr = 32'h0;case (funct3)3'b100,3'b101, 3'b110, 3'b101:begin  // 100 101 110 111div_start = 1;div_jump_flag = 1;div_hold_flag = 1;div_jump_addr = op1_jump_add_op2_jump_res;enddefault:begindiv_start = 0;div_jump_flag = 0;div_hold_flag = 0;div_jump_addr = 32'h0;endendcaseendelsebegindiv_jump_flag = 0;div_jump_addr = 32'h0;if (div_busy_i == 1)begindiv_start = 1;div_we = 0;div_wdata = 32'h0;div_waddr = 32'h0;div_hold_flag = 1;endelsebegindiv_start = 0;div_hold_flag = 0;if (div_ready_i == 1)begindiv_wdata = div_result_i;div_waddr = div_reg_waddr_i;div_we = 1;endelsebegindiv_we = 0;div_wdata = 32'h0;div_waddr = 32'h0;endendendend// `define INST_ADDI   3'b000// `define INST_SLTI   3'b010// `define INST_SLTIU  3'b011// `define INST_XORI   3'b100// `define INST_ORI    3'b110// `define INST_ANDI   3'b111// `define INST_SLLI   3'b001// `define INST_SRI    3'b101// 执行always @ (*)beginreg_we = reg_we_i;reg_waddr = reg_waddr_i;mem_req = 0;           // 0csr_wdata_o = 32'h0;case (opcode)7'b0010011:begin   // 7'b0010011case (funct3)3'b000:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_add_op2_res;end3'b010:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = {32{(~op1_ge_op2_signed)}} & 32'h1;end3'b011:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = {32{(~op1_ge_op2_unsigned)}} & 32'h1;end3'b100:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_i ^ op2_i;end3'b110:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_i | op2_i;end3'b111:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_i & op2_i;end3'b001:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = reg1_rdata_i << inst_i[24:20];end3'b101:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;if (inst_i[30] == 1'b1)beginreg_wdata = (sri_shift & sri_shift_mask) | ({32{reg1_rdata_i[31]}} & (~sri_shift_mask));endelsebeginreg_wdata = reg1_rdata_i >> inst_i[24:20];endenddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseend// 			// R type inst// `define INST_ADD_SUB 3'b000// `define INST_SLL    3'b001// `define INST_SLT    3'b010// `define INST_SLTU   3'b011// `define INST_XOR    3'b100// `define INST_SR     3'b101// `define INST_OR     3'b110// `define INST_AND    3'b1117'b0110011:begin   // 7'b0110011if ((funct7 == 7'b0000000) || (funct7 == 7'b0100000))begincase (funct3)3'b000:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;if (inst_i[30] == 1'b0)beginreg_wdata = op1_add_op2_res;endelsebeginreg_wdata = op1_i - op2_i;endend3'b001:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_i << op2_i[4:0];end3'b010:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = {32{(~op1_ge_op2_signed)}} & 32'h1;end3'b011:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = {32{(~op1_ge_op2_unsigned)}} & 32'h1;end3'b100:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_i ^ op2_i;end3'b101:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;if (inst_i[30] == 1'b1)beginreg_wdata = (sr_shift & sr_shift_mask) | ({32{reg1_rdata_i[31]}} & (~sr_shift_mask));endelsebeginreg_wdata = reg1_rdata_i >> reg2_rdata_i[4:0];endend3'b110:begin // 110jump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_i | op2_i;end3'b111:begin  //111jump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = op1_i & op2_i;enddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseendelse if (funct7 == 7'b0000001)begin// M type inst//`define INST_MUL    3'b000//`define INST_MULH   3'b001//`define INST_MULHSU 3'b010//`define INST_MULHU  3'b011//`define INST_DIV    3'b100//`define INST_DIVU   3'b101//`define INST_REM    3'b110//`define INST_REMU   3'b111case (funct3)3'b000:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = mul_temp[31:0];end3'b011:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = mul_temp[63:32];end3'b001:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;case ({reg1_rdata_i[31], reg2_rdata_i[31]})2'b00:beginreg_wdata = mul_temp[63:32];end2'b11:beginreg_wdata = mul_temp[63:32];end2'b10:beginreg_wdata = mul_temp_invert[63:32];enddefault:beginreg_wdata = mul_temp_invert[63:32];endendcaseend3'b010:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;if (reg1_rdata_i[31] == 1'b1)beginreg_wdata = mul_temp_invert[63:32];endelsebeginreg_wdata = mul_temp[63:32];endenddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseendelsebeginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endend7'b0000011:begincase (funct3)3'b000:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;mem_req = 1;       // 1mem_raddr_o = op1_add_op2_res;case (mem_raddr_index)2'b00:beginreg_wdata = {{24{mem_rdata_i[7]}}, mem_rdata_i[7:0]};end2'b01:beginreg_wdata = {{24{mem_rdata_i[15]}}, mem_rdata_i[15:8]};end2'b10:beginreg_wdata = {{24{mem_rdata_i[23]}}, mem_rdata_i[23:16]};enddefault:beginreg_wdata = {{24{mem_rdata_i[31]}}, mem_rdata_i[31:24]};endendcaseend3'b001:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;mem_req = 1;mem_raddr_o = op1_add_op2_res;if (mem_raddr_index == 2'b0)beginreg_wdata = {{16{mem_rdata_i[15]}}, mem_rdata_i[15:0]};endelsebeginreg_wdata = {{16{mem_rdata_i[31]}}, mem_rdata_i[31:16]};endend3'b010:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;mem_req = 1;mem_raddr_o = op1_add_op2_res;reg_wdata = mem_rdata_i;end3'b100:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;mem_req = 1;mem_raddr_o = op1_add_op2_res;case (mem_raddr_index)2'b00:beginreg_wdata = {24'h0, mem_rdata_i[7:0]};end2'b01:beginreg_wdata = {24'h0, mem_rdata_i[15:8]};end2'b10:beginreg_wdata = {24'h0, mem_rdata_i[23:16]};enddefault:beginreg_wdata = {24'h0, mem_rdata_i[31:24]};endendcaseend3'b101:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;mem_req = 1;mem_raddr_o = op1_add_op2_res;if (mem_raddr_index == 2'b0)beginreg_wdata = {16'h0, mem_rdata_i[15:0]};endelsebeginreg_wdata = {16'h0, mem_rdata_i[31:16]};endenddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseend7'b0100011:begin    // 7'b0100011case (funct3)3'b000:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;reg_wdata = 32'h0;mem_we = 1;mem_req = 1;mem_waddr_o = op1_add_op2_res;mem_raddr_o = op1_add_op2_res;case (mem_waddr_index)2'b00:beginmem_wdata_o = {mem_rdata_i[31:8], reg2_rdata_i[7:0]};end2'b01:beginmem_wdata_o = {mem_rdata_i[31:16], reg2_rdata_i[7:0], mem_rdata_i[7:0]};end2'b10:beginmem_wdata_o = {mem_rdata_i[31:24], reg2_rdata_i[7:0], mem_rdata_i[15:0]};enddefault:beginmem_wdata_o = {reg2_rdata_i[7:0], mem_rdata_i[23:0]};endendcaseend3'b001:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;reg_wdata = 32'h0;mem_we = 1;mem_req = 1;mem_waddr_o = op1_add_op2_res;mem_raddr_o = op1_add_op2_res;if (mem_waddr_index == 2'b00)beginmem_wdata_o = {mem_rdata_i[31:16], reg2_rdata_i[15:0]};endelsebeginmem_wdata_o = {reg2_rdata_i[15:0], mem_rdata_i[15:0]};endend3'b010:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;reg_wdata = 32'h0;mem_we = 1;mem_req = 1;mem_waddr_o = op1_add_op2_res;mem_raddr_o = op1_add_op2_res;mem_wdata_o = reg2_rdata_i;enddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseend//					`define INST_BEQ    3'b000//`define INST_BNE    3'b001//`define INST_BLT    3'b100//`define INST_BGE    3'b101//`define INST_BLTU   3'b110//`define INST_BGEU   3'b1117'b1100011:begin   // 7'b1100011case (funct3)3'b000:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;jump_flag = op1_eq_op2 & 1;jump_addr = {32{op1_eq_op2}} & op1_jump_add_op2_jump_res;end3'b001:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;jump_flag = (~op1_eq_op2) & 1;jump_addr = {32{(~op1_eq_op2)}} & op1_jump_add_op2_jump_res;end3'b100:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;jump_flag = (~op1_ge_op2_signed) & 1;jump_addr = {32{(~op1_ge_op2_signed)}} & op1_jump_add_op2_jump_res;end3'b101:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;jump_flag = (op1_ge_op2_signed) & 1;jump_addr = {32{(op1_ge_op2_signed)}} & op1_jump_add_op2_jump_res;end3'b110:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;jump_flag = (~op1_ge_op2_unsigned) & 1;jump_addr = {32{(~op1_ge_op2_unsigned)}} & op1_jump_add_op2_jump_res;end3'b111:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;jump_flag = (op1_ge_op2_unsigned) & 1;jump_addr = {32{(op1_ge_op2_unsigned)}} & op1_jump_add_op2_jump_res;enddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseend//  `define INST_JAL    7'b1101111//  `define INST_JALR   7'b1100111////  `define INST_LUI    7'b0110111//  `define INST_AUIPC  7'b0010111//  `define INST_NOP    32'h00000001//  `define INST_NOP_OP 7'b0000001//  `define INST_MRET   32'h30200073//  `define INST_RET    32'h00008067////  `define INST_FENCE  7'b0001111//  `define INST_ECALL  32'h73//  `define INST_EBREAK 32'h001000737'b1101111, 7'b1100111:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;jump_flag = 1;jump_addr = op1_jump_add_op2_jump_res;reg_wdata = op1_add_op2_res;end7'b0110111, 7'b0010111:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;jump_addr = 32'h0;jump_flag = 0;reg_wdata = op1_add_op2_res;end7'b0000001:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;end7'b0001111:beginhold_flag = 0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;jump_flag = 1;jump_addr = op1_jump_add_op2_jump_res;end//   			// CSR inst//   `define INST_CSR    7'b1110011//   `define INST_CSRRW  3'b001//   `define INST_CSRRS  3'b010//   `define INST_CSRRC  3'b011//   `define INST_CSRRWI 3'b101//   `define INST_CSRRSI 3'b110//   `define INST_CSRRCI 3'b1117'b1110011:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;case (funct3)3'b001:begincsr_wdata_o = reg1_rdata_i;reg_wdata = csr_rdata_i;end3'b010:begincsr_wdata_o = reg1_rdata_i | csr_rdata_i;reg_wdata = csr_rdata_i;end3'b011:begincsr_wdata_o = csr_rdata_i & (~reg1_rdata_i);reg_wdata = csr_rdata_i;end3'b101:begincsr_wdata_o = {27'h0, uimm};reg_wdata = csr_rdata_i;end3'b110:begincsr_wdata_o = {27'h0, uimm} | csr_rdata_i;reg_wdata = csr_rdata_i;end3'b111:begincsr_wdata_o = (~{27'h0, uimm}) & csr_rdata_i;reg_wdata = csr_rdata_i;enddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseenddefault:beginjump_flag = 0;hold_flag = 0;jump_addr = 32'h0;mem_wdata_o = 32'h0;mem_raddr_o = 32'h0;mem_waddr_o = 32'h0;mem_we = 0;reg_wdata = 32'h0;endendcaseendendmodule

gen_diff.v

module gen_pipe_dff#(parameter DW = 32)(input    wire               clk        ,input    wire               rst_n      ,input    wire               hold_en    ,input    wire  [DW-1 : 0]   def_val    ,input    wire  [DW-1 : 0]   din        ,output   wire  [DW-1 : 0]   qout);reg [DW - 1 : 0]  qout_r  ;always@(posedge clk )beginif(rst_n == 0 | hold_en == 1)beginqout_r <= def_val ;endelsebeginqout_r <= din ;endendassign  qout = qout_r ;
endmodule

id_ex.v

module  id_ex(input                   rst_n               ,input                   clk                 ,//来自于id_ex的完全输入input   [31 : 0]        inst_i              ,input   [31 : 0]        inst_addr_i         ,input                   reg_we_i            ,input   [4  : 0]        reg_waddr_i         ,input   [31 : 0]        reg1_rdata_i        ,input   [31 : 0]        reg2_rdata_i        ,input                   csr_we_i            ,input   [31 : 0]        csr_waddr_i         ,input   [31 : 0]        csr_rdata_i         ,input   [31 : 0]        op1_i               ,input   [31 : 0]        op2_i               ,input   [31 : 0]        op1_jump_i          ,input   [31 : 0]        op2_jump_i          ,// 暂停设计input   [2  : 0]        hold_flag_i         ,   // 流水线暂停标志output   [31 : 0]        inst_o              ,output   [31 : 0]        inst_addr_o         ,output                   reg_we_o            ,output   [4  : 0]        reg_waddr_o         ,output   [31 : 0]        reg1_rdata_o        ,output   [31 : 0]        reg2_rdata_o        ,output                   csr_we_o            ,output   [31 : 0]        csr_waddr_o         ,output   [31 : 0]        csr_rdata_o         ,output   [31 : 0]        op1_o               ,output   [31 : 0]        op2_o               ,output   [31 : 0]        op1_jump_o          ,output   [31 : 0]        op2_jump_o);wire hold_en =   (hold_flag_i >= 3'b011)  ;// ---- 果然这样的组合要写13个// -------------------------------------wire [31 : 0] inst ;gen_pipe_dff#(.DW       ( 32 ))inst_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 32'h00000001        ),      // 它其实是32'h0000_0001 我就是写成0.din      ( inst_i      ),.qout     ( inst    ));assign  inst_o  =  inst  ;// ----------------------------------// -------------------------------------wire [31 : 0] inst_addr ;gen_pipe_dff#(.DW       ( 32 ))inst_addr_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( inst_addr_i      ),.qout     ( inst_addr    ));assign  inst_addr_o  =  inst_addr  ;// ----------------------------------// -------------------------------------wire  reg_we ;gen_pipe_dff#(.DW       ( 1 ))reg_we_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 1'h0        ),.din      ( reg_we_i      ),.qout     ( reg_we    ));assign  reg_we_o  =  reg_we  ;// ----------------------------------// -------------------------------------wire [4 : 0] reg_waddr ;gen_pipe_dff#(.DW       ( 5 ))reg_waddr_dff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 5'h0        ),.din      ( reg_waddr_i      ),.qout     ( reg_waddr    ));assign  reg_waddr_o  =  reg_waddr  ;// ----------------------------------// -------------------------------------wire [31 : 0] reg1_rdata ;gen_pipe_dff#(.DW       ( 32 ))reg1_rdata_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 32'h0        ),.din      ( reg1_rdata_i      ),.qout     ( reg1_rdata    ));assign  reg1_rdata_o  =  reg1_rdata  ;// ----------------------------------// -------------------------------------wire [31 : 0] reg2_rdata ;gen_pipe_dff#(.DW       ( 32 ))reg2_rdata_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( reg2_rdata_i      ),.qout     ( reg2_rdata    ));assign  reg2_rdata_o  =  reg2_rdata  ;// ----------------------------------// -------------------------------------wire csr_we ;gen_pipe_dff#(.DW       ( 1 ))csr_we_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 1'h0        ),.din      ( csr_we_i      ),.qout     ( csr_we    ));assign  csr_we_o  =  csr_we  ;// ----------------------------------// -------------------------------------wire [31 : 0] csr_waddr ;gen_pipe_dff#(.DW       ( 32 ))csr_waddr_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( csr_waddr_i      ),.qout     ( csr_waddr    ));assign  csr_waddr_o  =  csr_waddr  ;// ----------------------------------// -------------------------------------wire [31 : 0] csr_rdata ;gen_pipe_dff#(.DW       ( 32 ))csr_rdata_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( csr_rdata_i      ),.qout     ( csr_rdata    ));assign  csr_rdata_o  =  csr_rdata  ;// ----------------------------------// -------------------------------------wire [31 : 0] op1 ;gen_pipe_dff#(.DW       ( 32 ))op1_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( op1_i      ),.qout     ( op1    ));assign  op1_o  =  op1  ;// ----------------------------------// -------------------------------------wire [31 : 0] op2 ;gen_pipe_dff#(.DW       ( 32 ))op2_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( op2_i      ),.qout     ( op2    ));assign  op2_o  =  op2  ;// ----------------------------------// -------------------------------------wire [31 : 0] op1_jump;gen_pipe_dff#(.DW       ( 32 ))op1_jump_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( op1_jump_i      ),.qout     ( op1_jump   ));assign  op1_jump_o  =  op1_jump  ;// ----------------------------------// -------------------------------------wire [31 : 0] op2_jump ;gen_pipe_dff#(.DW       ( 32 ))op2_jump_ff(.clk      ( clk      ),.rst_n    ( rst_n    ),.hold_en  ( hold_en  ),.def_val  ( 0        ),.din      ( op2_jump_i      ),.qout     ( op2_jump    ));assign  op2_jump_o  =  op2_jump  ;// ----------------------------------
endmodule

regs.v

module  regs(input                       clk            ,input                       rst_n          ,// from ex  在后续处理完成之后 写回reginput                       we_i           ,   // 使能 | 地址 | 标志input         [4 : 0]       waddr_i        ,input         [31 : 0]      wdata_i        ,// from jtag 用于调试input                       jtag_we_i      ,input         [4 : 0]       jtag_addr_i    ,input         [31 : 0]      jtag_data_i    ,output reg    [31 : 0]      jtag_data_o    ,// from id1input         [4 : 0]       raddr1_i       ,output reg    [31 : 0]      rdata1_o       ,// from id2input         [4 : 0]       raddr2_i       ,output reg    [31 : 0]      rdata2_o);reg [31 : 0] regs[0 : 31]  ;// 写寄存器的发射信号always@(posedge clk )beginif(rst_n == 1)begin// 先进行exif((we_i == 1) && (waddr_i != 0))beginregs[waddr_i]      <=  wdata_i ;endelse if((jtag_we_i == 1) && ( jtag_addr_i != 0))beginregs[jtag_addr_i]  <=  jtag_data_i ;endendend// 读寄存器1always @ (*)beginif (raddr1_i == 0)beginrdata1_o   <=   0;// 如果读地址等于写地址,并且正在写操作,则直接返回写数据endelse if (raddr1_i == waddr_i && we_i == 1)beginrdata1_o   <=   wdata_i;endelsebeginrdata1_o   <=   regs[raddr1_i];endend// 读寄存器2always @ (*)beginif (raddr2_i == 0)beginrdata2_o    <=    0;// 如果读地址等于写地址,并且正在写操作,则直接返回写数据endelse if (raddr2_i == waddr_i && we_i == 1)beginrdata2_o    <=    wdata_i;endelsebeginrdata2_o    <=    regs[raddr2_i];endend// jtag 读寄存器always@(*)beginif(jtag_addr_i == 0)beginjtag_data_o  <=  0  ;endelsebeginjtag_data_o  <=  regs[jtag_addr_i]  ;endendendmodule

rib.v

//这一部分是RIB总线模块
module rib(input                               clk         ,input                               rst_n       ,//  主四   从六// master 0input          [31 : 0]             m0_addr_i   ,input          [31 : 0]             m0_data_i   ,output  reg    [31 : 0]             m0_data_o   ,input                               m0_req_i    ,input                               m0_we_i     ,// master 1input          [31 : 0]             m1_addr_i   ,input          [31 : 0]             m1_data_i   ,output  reg    [31 : 0]             m1_data_o   ,input                               m1_req_i    ,input                               m1_we_i     ,// master 2input          [31 : 0]             m2_addr_i   ,input          [31 : 0]             m2_data_i   ,output  reg    [31 : 0]             m2_data_o   ,input                               m2_req_i    ,input                               m2_we_i     ,// master 3input          [31 : 0]             m3_addr_i   ,input          [31 : 0]             m3_data_i   ,output  reg    [31 : 0]             m3_data_o   ,input                               m3_req_i    ,input                               m3_we_i     ,// slave 0output  reg    [31 : 0]             s0_addr_o   ,output  reg    [31 : 0]             s0_data_o   ,input          [31 : 0]             s0_data_i   ,output  reg                         s0_we_o     ,// slave 1output  reg    [31 : 0]             s1_addr_o   ,output  reg    [31 : 0]             s1_data_o   ,input          [31 : 0]             s1_data_i   ,output  reg                         s1_we_o     ,// slave 2output  reg    [31 : 0]             s2_addr_o   ,output  reg    [31 : 0]             s2_data_o   ,input          [31 : 0]             s2_data_i   ,output  reg                         s2_we_o     ,// slave 3output  reg    [31 : 0]             s3_addr_o   ,output  reg    [31 : 0]             s3_data_o   ,input          [31 : 0]             s3_data_i   ,output  reg                         s3_we_o     ,// slave 4output  reg    [31 : 0]             s4_addr_o   ,output  reg    [31 : 0]             s4_data_o   ,input          [31 : 0]             s4_data_i   ,output  reg                         s4_we_o     ,// slave 5output  reg    [31 : 0]             s5_addr_o   ,output  reg    [31 : 0]             s5_data_o   ,input          [31 : 0]             s5_data_i   ,output  reg                         s5_we_o     ,output  reg                         hold_flag_o);// 访问地址的最高4位确定要访问的parameter   [3 : 0]  slave_0  =  4'b0000   ;parameter   [3 : 0]  slave_1  =  4'b0001   ;parameter   [3 : 0]  slave_2  =  4'b0010   ;parameter   [3 : 0]  slave_3  =  4'b0011   ;parameter   [3 : 0]  slave_4  =  4'b0100   ;parameter   [3 : 0]  slave_5  =  4'b0101   ;parameter   [1 : 0]  grant0   =  2'h0      ;parameter   [1 : 0]  grant1   =  2'h1      ;parameter   [1 : 0]  grant2   =  2'h2      ;parameter   [1 : 0]  grant3   =  2'h3      ;wire    [3 : 0]  req    ;reg     [1 : 0]  grant  ;// 主设备请求信号assign  req = {m3_req_i , m2_req_i  , m1_req_i , m0_req_i } ;// 接下来配置的是仲裁优先级// 优先级顺序按照3-0-2 - 1always@(*)beginif(req[3] == 1)begingrant        =   grant3   ;  // 第三个hold_flag_o  =   1        ;endelse if(req[0] == 1)begingrant        =   grant0   ;  // 第三个hold_flag_o  =   1        ;endelse if(req[2] == 1)begingrant        =   grant2   ;  // 第三个hold_flag_o  =   1        ;endelse begingrant        =   grant1   ;  // 第三个hold_flag_o  =   0        ;endend// 根据仲裁结果选择 访问从机always@(*)beginm0_data_o     =      0      ;m1_data_o     =      0      ;m2_data_o     =      0      ;m3_data_o     =      0      ;// 从机s0_addr_o     =      0      ;s0_data_o     =      0      ;s0_we_o       =      0      ;s1_addr_o     =      0      ;s1_data_o     =      0      ;s1_we_o       =      0      ;s2_addr_o     =      0      ;s2_data_o     =      0      ;s2_we_o       =      0      ;s3_addr_o     =      0      ;s3_data_o     =      0      ;s3_we_o       =      0      ;s4_addr_o     =      0      ;s4_data_o     =      0      ;s4_we_o       =      0      ;s5_addr_o     =      0      ;s5_data_o     =      0      ;s5_we_o       =      0      ;case(grant)grant0 :begincase(m0_addr_i[31:28])slave_0 :begins0_we_o      =     m0_we_i  ;s0_addr_o    =     {{4'h0} , {m0_addr_i[27 : 0]}} ;s0_data_o    =     m0_data_i     ;m0_data_o    =     s0_data_i     ;endslave_1 :begins1_we_o      =     m0_we_i  ;s1_addr_o    =     {{4'h0} , {m0_addr_i[27 : 0]}} ;s1_data_o    =     m0_data_i     ;m0_data_o    =     s1_data_i     ;endslave_2 :begins2_we_o      =     m0_we_i  ;s2_addr_o    =     {{4'h0} , {m0_addr_i[27 : 0]}} ;s2_data_o    =     m0_data_i     ;m0_data_o    =     s2_data_i     ;endslave_3 :begins3_we_o      =     m0_we_i  ;s3_addr_o    =     {{4'h0} , {m0_addr_i[27 : 0]}} ;s3_data_o    =     m0_data_i     ;m0_data_o    =     s3_data_i     ;endslave_4 :begins4_we_o      =     m0_we_i  ;s4_addr_o    =     {{4'h0} , {m0_addr_i[27 : 0]}} ;s4_data_o    =     m0_data_i     ;m0_data_o    =     s4_data_i     ;endslave_5 :begins5_we_o      =     m0_we_i  ;s5_addr_o    =     {{4'h0} , {m0_addr_i[27 : 0]}} ;s5_data_o    =     m0_data_i     ;m0_data_o    =     s5_data_i     ;enddefault :beginendendcaseendgrant1 :begincase(m1_addr_i[31:28])slave_0 :begins0_we_o      =     m1_we_i  ;s0_addr_o    =     {{4'h0} , {m1_addr_i[27 : 0]}} ;s0_data_o    =     m1_data_i     ;m1_data_o    =     s0_data_i     ;endslave_1 :begins1_we_o      =     m1_we_i  ;s1_addr_o    =     {{4'h0} , {m1_addr_i[27 : 0]}} ;s1_data_o    =     m1_data_i     ;m1_data_o    =     s1_data_i     ;endslave_2 :begins2_we_o      =     m1_we_i  ;s2_addr_o    =     {{4'h0} , {m1_addr_i[27 : 0]}} ;s2_data_o    =     m1_data_i     ;m1_data_o    =     s2_data_i     ;endslave_3 :begins3_we_o      =     m1_we_i  ;s3_addr_o    =     {{4'h0} , {m1_addr_i[27 : 0]}} ;s3_data_o    =     m1_data_i     ;m1_data_o    =     s3_data_i     ;endslave_4 :begins4_we_o      =     m1_we_i  ;s4_addr_o    =     {{4'h0} , {m1_addr_i[27 : 0]}} ;s4_data_o    =     m1_data_i     ;m1_data_o    =     s4_data_i     ;endslave_5 :begins5_we_o      =     m1_we_i  ;s5_addr_o    =     {{4'h0} , {m1_addr_i[27 : 0]}} ;s5_data_o    =     m1_data_i     ;m1_data_o    =     s5_data_i     ;enddefault :beginendendcaseendgrant2 :begincase(m2_addr_i[31:28])slave_0 :begins0_we_o      =     m2_we_i  ;s0_addr_o    =     {{4'h0} , {m2_addr_i[27 : 0]}} ;s0_data_o    =     m2_data_i     ;m2_data_o    =     s0_data_i     ;endslave_1 :begins1_we_o      =     m2_we_i  ;s1_addr_o    =     {{4'h0} , {m2_addr_i[27 : 0]}} ;s1_data_o    =     m2_data_i     ;m2_data_o    =     s1_data_i     ;endslave_2 :begins2_we_o      =     m2_we_i  ;s2_addr_o    =     {{4'h0} , {m2_addr_i[27 : 0]}} ;s2_data_o    =     m2_data_i     ;m2_data_o    =     s2_data_i     ;endslave_3 :begins3_we_o      =     m2_we_i  ;s3_addr_o    =     {{4'h0} , {m2_addr_i[27 : 0]}} ;s3_data_o    =     m2_data_i     ;m2_data_o    =     s3_data_i     ;endslave_4 :begins4_we_o      =     m2_we_i  ;s4_addr_o    =     {{4'h0} , {m2_addr_i[27 : 0]}} ;s4_data_o    =     m2_data_i     ;m2_data_o    =     s4_data_i     ;endslave_5 :begins5_we_o      =     m2_we_i  ;s5_addr_o    =     {{4'h0} , {m2_addr_i[27 : 0]}} ;s5_data_o    =     m2_data_i     ;m2_data_o    =     s5_data_i     ;enddefault :beginendendcaseendgrant3 :begincase(m3_addr_i[31:28])slave_0 :begins0_we_o      =     m3_we_i  ;s0_addr_o    =     {{4'h0} , {m3_addr_i[27 : 0]}} ;s0_data_o    =     m3_data_i     ;m3_data_o    =     s0_data_i     ;endslave_1 :begins1_we_o      =     m3_we_i  ;s1_addr_o    =     {{4'h0} , {m3_addr_i[27 : 0]}} ;s1_data_o    =     m3_data_i     ;m3_data_o    =     s1_data_i     ;endslave_2 :begins2_we_o      =     m3_we_i  ;s2_addr_o    =     {{4'h0} , {m3_addr_i[27 : 0]}} ;s2_data_o    =     m3_data_i     ;m3_data_o    =     s2_data_i     ;endslave_3 :begins3_we_o      =     m3_we_i  ;s3_addr_o    =     {{4'h0} , {m3_addr_i[27 : 0]}} ;s3_data_o    =     m3_data_i     ;m3_data_o    =     s3_data_i     ;endslave_4 :begins4_we_o      =     m3_we_i  ;s4_addr_o    =     {{4'h0} , {m3_addr_i[27 : 0]}} ;s4_data_o    =     m3_data_i     ;m3_data_o    =     s4_data_i     ;endslave_5 :begins5_we_o      =     m3_we_i  ;s5_addr_o    =     {{4'h0} , {m3_addr_i[27 : 0]}} ;s5_data_o    =     m3_data_i     ;m3_data_o    =     s5_data_i     ;enddefault :beginendendcaseenddefault :beginendendcaseendendmodule

readme.md

本设计创建于2024年11月7日 预计完成时间2025年1月1日

支持RV32IM指令集 所以指令集的扩展是来自于RV32IM

一开始书写的是pc_reg 用于地址的把控跳转

if_id更像是一个中介模块 用于传递ROM的信息给下一级id的
gen_pipe_dff 来自于 gen_diff.v

2024年11月14日 continue

  1. CSR是特权寄存器 其中的CSR是特权指令集中的一部分
  2. 在这一个操作中虽然我暂时不知道这个的内容,但是我知道地址 我是阻塞赋值,所以我在前面把rs1给到reg1_raddr_o 过一会就会把reg1_rdada_i的值拿回来
  3. | opcode (7) | rd (5) | funct3 (3) | rs1 (5) | rs2 (5) | funct7 (7) |
    4.指令 功能描述
    CSRRW 将寄存器 rs1 的值写入 CSR,同时将 CSR 原值写入目标寄存器 rd。
    CSRRS 读取 CSR 原值并将其写入 rd,同时将 CSR 的指定位(由 rs1 指定)置 1。
    CSRRC 读取 CSR 原值并将其写入 rd,同时将 CSR 的指定位清 0。
    CSRRWI 与 CSRRW 类似,但立即数(imm)代替 rs1 作为写入 CSR 的值。
    CSRRSI 与 CSRRS 类似,但立即数(imm)代替 rs1 作为位掩码。
    CSRRCI 与 CSRRC 类似,但立即数(imm)代替 rs1 作为位掩码。

2024年11月20日 continue 开始写的是

2024年11月28日 continue

好久没看了 先去对整体的各个模块复习一下 -我觉得 这周能写的挺多的 28日周四

在pc_reg.v 中的
else if(hold_flag_i >= 3’b001 )
begin
pc_o <= pc_o ; // 这就是暂停保持的

这一段的代码 是为了后续流水线设置的方便
有人会问为什么设置了3bit 暂停而不是设置为1bit 因为后续的暂停标志位需要被if_id 和 id_ex使用
后续防线设置的阈值比001高 这样后面停PC就会被停下来 一级控制着一级 这就是三级流水线的定义

if_id 是流水线的暂存

reg是通用寄存器 reg模块里面的 两个寄存器意思指 一条指令里有可能会同时读取两个寄存器的值

regs.v 中的代码

else if (raddr2_i == waddr_i && we_i == 1)
beginrdata2_o    <=    wdata_i;
end

原因在于可能会有 译码阶段可能会需要用到上一条指令的结果
add x1 , x2 , x3
add x4 , x1 , x5

id.v是单纯的译码阶段的工作
— 11.28目前工作是 id_ex.v
这个模块的作用跟我想的一样 是作为过渡作用的 和 if_id 是用来传递存储到ex的信息的
// 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寄存器地址
就是这个


clint 的作用是 核心本地中断模块,对输入的中断请求信号进行总裁,产生最终的中断信号

2024年 11月29日

在编写 clint.v 模块
外设产生的中断信号与处理器的CSR寄存器紧密结合,共同构成了中断管理和中断响应机制。通过 CSR 寄存器的操作,系统能够记录中断的原因、保存当前的执行状态,并根据需要使能或屏蔽中断。这一过程确保了中断能够按预期进行处理,且在处理完中断后,处理器能够从正确的位置恢复并继续执行。

在你的系统架构中,clint 模块就是用来处理这些中断请求,并与 CSR 寄存器交互的核心组件,而 CSR 寄存器则承担了中断的状态管理和控制任务。

所以 clint是专门处理中断控制与管理的模块,负责与CSR寄存器相关联

为什么这个设计放在了第二阶段 ?
因为 中断是一个外部事件,通常是异步的,即它的发生时刻并不一定与指令的执行同步。在处理器流水线中,中断需要在适当的时机被捕获和响应,而选择在 ID 阶段进行中断的处理有助于确保中断能够及时响应,同时避免干扰指令的正常执行

问答? 还是有点疑惑的地方 就是说clint处理两种不同的中断嘛 一种是指令本身提供的中断 还有一种是外设提供的嘛?指令的中断从id解析出来之后反正都会传递给csr_reg 然后再给到clint 而 还有一种是外设的中断 这种需要clint写完传递给 csr_reg嘛 ???
–>
因此,clint 在处理中断时,确实需要通过 csr_reg 读取和更新中断相关的寄存器,如 mtvec(中断向量)、mepc(中断返回地址)和 mcause(中断原因)。而外设中断(来自 int_flag_i)也是通过 clint 来处理和管理,最终影响 csr_reg 中的寄存器,指导处理器如何跳转到中断处理程序。

所以,整体上你的理解是对的,clint 处理的是两类中断:指令中断和外设中断,并且它依赖于 csr_reg 来管理中断状态的保存和恢复。

理解之后 我决定先编写 csr_reg.v

问题 : ? 所以说ex是一个唯一的处理阶段的模块,处理了中断的信息,中断需要操作都经由ex模块来完成,clint是一个中断仲裁分析模块,会把外部的外设 指令的信息接收处理了 还给csr_reg 寄存器,最后由ex模块接收到详细处理嘛

–>
ex 模块是唯一的处理阶段模块,负责执行指令并处理与中断、异常相关的操作。
clint 是外部中断的控制器,它接收外设中断信号并将其信息传递给 csr_reg,然后 ex 模块在执行时根据这些信息进行中断处理。
csr_reg 存储与中断、异常相关的控制状态信息,而 ex 模块会根据这些信息执行实际的中断处理逻辑。

问题 : 为什么在写csr寄存器的时候会优先响应ex写模块 ?
–>
中断和异常处理可能会影响执行:当处理器需要处理中断或异常时,它会修改一些控制寄存器。这个修改必须在当前指令执行完后进行。也就是说,EX阶段的修改优先级更高,因为它关系到当前指令是否能顺利执行。比如,如果发生中断时,必须知道从哪里跳转到异常处理函数(mepc),但这是在指令执行完毕之后才处理的。

问题 : 所以这里是有变换的先后要求的嘛 先是保证除法的正常进行 然后是同步的指令 然后是core的外部中断吗 ?
–>
首先,需要确保除法指令等较长周期操作的完成,因此在除法未完成时,不会处理中断。
其次,优先处理中同步中断(如 ECALL、EBREAK),这些通常与程序的控制流相关,可能是系统调用或异常。
然后,处理外部的异步中断(来自硬件或外部设备),这些通常在同步中断后处理。
最后,处理 MRET 指令,恢复到机器模式继续执行。

问题 : 所以跳转中断处理是一个设定的特殊的地址 特殊的指令 包括特殊的 信息,PC是会不断自增的 jump_addr_i 的值在ex阶段会被确定成需要跳转的中断处理地址 ,但是 PC是会不断自增+4 的 ,所以回退一个位置,这样在处理的时候jump的地址就会是需要跳转的地址了 ?
—>
—>
这里的东西 我先按下不表 等我看到后面分析的时候自然而然懂了
我的理解是这样的
GPT 也觉得我的没问题
jump_addr_i - 4 是为了确保跳转到中断处理程序时,从发生中断的正确位置继续执行。
跳转的目标地址 jump_addr_i 是由中断向量表决定的,通常是中断处理程序的入口。
在 EX 阶段,处理器决定了跳转地址,而跳转到中断处理程序时需要回退 4 字节,因为 PC 是自动自增的。


2024年11月30日 -> 2024年12月1日 对前模块进行小总结

稍微带入一点整体的思想观念
注意 在id模块 – J型指令中 有这么一段代码
7’b1100_111 : // JALR 功能:PC = (rs1 + imm) & ~1,并将下一条指令地址存入 rd。
begin
reg_we_o = 1 ;
reg_waddr_o = rd ;
reg1_raddr_o = rs1 ;
reg2_raddr_o = 0 ;
op1_o = inst_addr_i ;
op2_o = 32’h4 ;
op1_jump_o = reg1_rdata_i ;
op2_jump_o = {{20{inst_i[31]}}, inst_i[31:20]};
end
这里所说的 op1_o 和 op2_o 是操作数
用这两个数值 来计算出 rd的值 inst_addr_i + 4 是下一条指令的地址
op1_jump_o 与 op2_jump_o操作 的得到 下一条指令的内容

  ---注明 读寄存器 不需要判断信号 直接读就可以了 问题 : 为什么已经传递了op1 op1_jump_o 等信息 还要把 寄存器的数据 reg1_rdata_o给ex模块?--> 回答: 将寄存器的数据 reg1_rdata_o 和 reg2_rdata_o 也传递给 EX 模块,是为了提供灵活性,允许在 EX 阶段根据指令的具体需求直接使用原始的寄存器数据。这种设计既考虑了性能优化,又兼顾了流水线设计的实际需求。如果流水线遇到特殊情况(例如复杂指令),EX 阶段可以直接使用寄存器的原始数据,而无需回退到 ID 阶段重新解码。

OK OK 我对中断充满了很多的疑问 我准备等 ex.v 完全结束之后开始了解这中断变换的含义

2024年12月1日 开始写执行模块

2024年 12月2日 开始编写执行模块

2024年 12月4日 备受折磨的12月 开始继续 ex模块的书写

2024年12月9日 继续进行ex.v模块的编写

问题? 没听懂字节对齐的含义 因为reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]} 这不是一个32位的数嘛 这是内存的地址嘛 ? 是不是因为内存的数据都是32位访问的 所以地址是4字节4字节变换的,所以传入的非4的倍数 就是定位到内存的哪一个具体的八位嘛 ?

回答 : 是的,你的理解正在接近正确!

参数的含义
jump_flag 跳转信号
hold_flag 跳转信号
jump_addr 跳转信号
mem_wdata_o 内存
mem_raddr_o
mem_waddr_o
mem_we
reg_wdata 寄存器数据信号

2024年12月11日 继续ex.v的编写

对于模块的第755行 其中 写成 jump_addr = {32{op1_eq_op2}} & op1_jump_add_op2_jump_res; 是为了一个保护作用
当不触发时,跳转地址设置到了保护的0
0 可以作为一个特殊寄存器的存在专门用来存储复位的信息情况

观察后面写的几个程序 才发现前面id分解的时候 全部拆开写的重要性

— 2024年12.11 21:43 结束到 CSR寄存器
希望明天上午把ex里面的 CSR寄存器搞完 和前面关系搞清楚
最后再检查一遍 下班

2024年12月12日 继续ex.v的CSR编写

问题 : 我现在有一个问题 就是 除法指令也都是写入reg寄存器的嘛 因为这里的复位的时候给reg_wdata 和 div_wdata都给0 所以本质上这两个数据再一条指令处理的时候不会赋值 ?
回答 : 关键: 在一个周期内,这两个信号 只能有一个有效数据源,不会出现两个同时非零的情况


现在开始讲述一下之前没懂的几个问题

解析

在clint 的第83行 if(inst_i == 32’h0000_0073 || inst_i == 32’h0010_0073)
这两个指令是直接从ROM中读出来的 系统指令
ECALL 和 EBACK

2024年12月14日 经过那么长时间的学习 终于把这个问题给搞清楚

我的理解 :
所以 我来说一下 我的理解 ,现在说同步中断的概念,首先假设输入的上一条是跳转指令,首先在系统内部会有关于clint 包括csr_reg寄存的读写的信息的,这是系统的概念,这一部分的执行,完全依靠于ex模块的读取和写入,和其他的具体具体跳转没有任何关系,接下来假设上一条的是跳转指令,因为是三级流水线的概念,所以clint的输入来自于id,其实是 ex阶段的下一个指令,所以当输入ecall指令时候,会立即读取csr_reg 寄存器中的信息,这些信息是由一开始就是我上面说的那段话传递进去的,接下来的会在这个阶段上把地址mevpc通过ex阶段完全发送给pc ,这时候并不会暂停流水线,会根据这个指令完成设计,接下来是当指令完成之后会重新回到ret保存的地址,因为Pc会自动+4 ,对于原来的指令Inst+4 就把当前的这个中断指令跳过了,对于上一条是jump的指令,那么这里-4也很合理了

GPT : 你的理解是很清晰的!让我总结并补充一下你说的内容,确保概念清晰

吃饭去了 接下来速速的完成其他模块的编写

2024年12月14日 这次编写的是 同为ex阶段的ctrl模块

ctrl 在了解清楚另外几个模块之后

现在编写div模块 就是 ex后面的除法单元

这边介绍一下试熵法的原理和使用规范


试熵法的基本步骤:**

  1. 初始化:**
    被除数(Dividend)和除数(Divisor)被加载到寄存器中。
    商(Quotient)和余数(Remainder)寄存器清零
  2. 试商(Trial Division):**
    从被除数中提取一个对应除数长度的高位部分,称为“被减数”(Minuend)。
    假设当前位的商为1,并尝试执行 减法运算:
    ( \text{Minuend} - \text{Divisor} \
  3. 判断结果:**
    如果减法结果为非负,则 试商成功,当前位的商值为1。
    如果减法结果为负,则 试商失败,恢复之前的被减数,当前位的商值为0
  4. 商寄存器更新:**
    将当前商位移入商寄存器,余数寄存器存储减法的结果(如果减法成功)
  5. 重复步骤 2 - 4:**
    对被除数的下一个最高位重复上述过程,直到处理完成
  6. 最终结果:**
    商寄存器中保存最终商值。
    余数寄存器中保存剩余的余数。

示例:
假设我们要计算 ( 1011_2 \div 10_2 )(即 11 除以 2)。

步骤:

  1. 初始被除数:1011,除数:10
  2. 提取最高位,得到 10,尝试减去 10,成功,商位为 1
  3. 移位提取下一位 1,组合成 01,无法减去 10,商位为 0
  4. 提取最后一位 1,组合成 11,减去 10 成功,商位为 1

最终结果:

  • 商:101_2(即 5
  • 余数:01_2(即 1

试商的除法 就是现实版的长除法的使用
自己拿笔推一下就出来了

2024年12月15日 上面的设计基本完成了

剩下top顶层 还有 rib总线的书写
现在是17:14先去吃饭
回来完成 rib总线的部分处理
完成之后 全部内容 检查一遍开始撰写top

2024年12月16日 下面该到了 tinyriscv的顶层模块的设计了

现在是北京时间2024年12月16日 完成了整个的主模块 risc-v的撰写
还剩下粗略15天 用来完成其他部分的书写

先去完成 外设的部分的设计

2024年12月16日

下面先进行 6个外设的设计
ROM
RAM
timer
uart_tx
gpio
spi

啊啊啊啊回归了

2024年12月22日 经过了长时间的蛰伏该到了

不会12月底来不及完成吧
先抓紧了

问题 : ok 我不懂的就是这个图上为什么说 ROM的大小是256MB,给他分配了 0x0000_0000到0x1000_0000的呢 ?
物理 ROM 实际大小可能远小于 256MB,比如你的设计中实际只有 16KB (4096 × 4B) 的 ROM。
剩余未用的空间是为了方便扩展或地址解码简化而划分出来的。

问题 : 那我有一个问题 就是说如何 准确完成CPU的处理,再解析C语言的时候就规定了你的 举例0x1000_0000到0x2000_0000是GPIO这样子嘛 ?
这个问题我想起来了,在C语言的define中 确实有这样的定义 ,
C 语言中,通过指针直接访问这些映射地址。例如 GPIO 寄存器的定义如下:

c
复制代码
#define GPIO_BASE 0x40000000 // GPIO 基地址
#define GPIO_DIR (volatile unsigned int)(GPIO_BASE + 0x00) // 方向寄存器
#define GPIO_OUT (volatile unsigned int)(GPIO_BASE + 0x04) // 输出寄存器
#define GPIO_IN (volatile unsigned int)(GPIO_BASE + 0x08) // 输入寄存器
示例操作:

c
复制代码
void gpio_init() {
GPIO_DIR = 0xFF; // 将所有 GPIO 设置为输出
}

void gpio_set(uint32_t value) {
GPIO_OUT = value; // 设置 GPIO 输出值
}

uint32_t gpio_read() {
return GPIO_IN; // 读取 GPIO 输入值
}
解析:

寄存器地址计算: 通过基地址 + 偏移量定义具体寄存器。
volatile 关键字: 确保每次访问直接读写硬件地址,而不是缓存值。


疑惑解除 开始继续工作

timer模块的作用
基于输入时钟信号进行计数,当计数值达到预设值时触发一个 中断信号,实现定时器功能。

飞快 现在在 使用 uart 端口

uart 有点长 所以先弄 gpio 吧 弄 GPIO的时候 感觉 死去的记忆在攻击我了

现在写完了 gpio 再写 uart

2024年12月23日 继续完成uart外设的编写

问题 : 是不是这个意思 下降沿呢 是和外面交流接收的 ,再在这里设计上升沿 是为了给下面uart传入寄存器做准备的 ?
是的,你的理解非常正确!

完成uart模块

2024年 12月23日 ----- spi.v 继续做另一个外设的设计

2024年 12月25日 ----- 继续spi

问题 : 那么其实说到底,同步进行输入输出的 并不是同一批数据喽 ?
回答 : 没错!

问题 : 那么我有一个问题 ,就是这里没有握手 或者数据对齐的功能 而且这个spi是不断的传输的,那么万一传输错误了 错就错了 是这个意思嘛 ?
回答 : 是的,你理解得完全正确!

CPOL 和 CPHA 控制具体行为
模式 CPOL CPHA 时钟空闲状态 采样边沿 输出边沿
模式 0 0 0 低电平 上升沿 (clock=1) 下降沿 (clock=0)
模式 1 0 1 低电平 下降沿 (clock=0) 上升沿 (clock=1)
模式 2 1 0 高电平 下降沿 (clock=0) 上升沿 (clock=1)
模式 3 1 1 高电平 上升沿 (clock=1) 下降沿 (clock=0)
示例分析:CPOL = 0, CPHA = 0(模式 0)
**时钟空闲状态:**低电平。
**数据输出:**下降沿 (clock=0) 更新 MOSI。
**数据采样:**上升沿 (clock=1) 从 MISO 读取数据

2024年12月25日 21:31 目前完成的进度是外设全部书写完毕

明天开始对uart模块进行创作
我把整个jtag删去了 因为我手头没有对JTAG的调试工具
把这个完成应该就差不多了
over 加油

2024年12月26日 开始编写其中使用的 UART_DEBUG 下载单元

状态机的第一步是往 UART的ctrl 地址 写入 3也就 11 表示
启用了TX使能 和 RX 使能

问题 : 那么对于下载而言的话 ,这个写入UART 的我看就是一个输出信号 是专门用来配置连接到FPGA上的UART串口模块吗 ?
回答 : 这段代码中的 UART 配置和数据传输信号 是用来控制连接到 FPGA 上的 UART 串口模块 的。

问题 : 这个地址status_reg是什么作用的 ,为什么写完首位就要清除接收溢出标志,这个状态寄存器有什么作用 ?
回答 : 第一步:
将地址 mem_addr_o 设置为 UART_STATUS_REG,准备访问状态寄存器。

第二步:
写入数据 32’h0,清除所有错误标志,包括溢出标志。

第三步:
写使能 mem_we_o 设置为 1,确保写入数据有效。

第四步:
状态机进入 S_WAIT_BYTE,开始等待 UART 模块接收新的字节数据。

位位置 标志名称 描述
0 TX_EMPTY_FLAG 发送 FIFO 空标志,表示发送缓冲区为空,可以写入新数据。
1 RX_FULL_FLAG 接收 FIFO 满标志,表示接收缓冲区已满,需要读取数据以避免溢出。
2 RX_OVER_FLAG 接收溢出标志,表示在读取数据之前 UART 收到更多数据,导致数据丢失。
3 PARITY_ERROR_FLAG 奇偶校验错误标志,接收数据时检测到校验错误。
4 FRAME_ERROR_FLAG 帧错误标志,接收数据的起始位或停止位异常。
5 BREAK_DETECT_FLAG 中断检测标志,检测到线路上出现中断信号。
其他位 保留位 未来扩展或保留位,默认忽略。

-> 问题 : ok 我明白了我们这个uart其实是跟外部的连接到FPGA端口的这个连接器的uart模块,我们读取的也就是这里的uart寄存器的信息,一旦上位机发起写入信号,那么其实这个的uart的寄存器的某些位就会发生变换,所以其实我们读取的是这个变化信息 ?
回答 ;
没错,你理解得很准确!

2024年12月26日 差不多可以说是结束了 现在把顶层写好找个tb验证一下

2024年12月27日 我还是怂了 我现在要把这个的JTAG端口加上去了 不然真的没法调试了

我没看 但是把jtag_dm.v这个模块先抄上去
这里面用到了 full_handshake_rx.v
– full_handshake_rx.v
– 现在加上 fuull_handshake_tx.v
– 加上了 jtag_top.v
–.–.–.–.—.----
再做一个合集把 剩下的几个module 写进去

2024年12月27日

准备把代码进行替换验证了
第一次
if_id 原代码 修改了
这个官方的 tb里 我把 最后的rst换成了rst_n
id 原代码也修改了
tinyrisc.v修改
tinyriscvsoc.v 修改

第二次
修改了id_ex

第三次
修改 tinyriscv.v

2024年12月28日 基本完成功能

其他的几个外设 我懒得去验证了 到时候想用直接拿过来
对于RTL部分核心的代码是完全无误的

2024.11.7 —> 2024.12.28

相关文章:

【【深入浅出TinyRisc-v】】

深入浅出TinyRisc-v 本代码参考于 https://gitee.com/liangkangnan/tinyriscv 自己理解之后又重新写了一遍 tinyriscv.v // 涓嬮潰鏄鏁翠釜top妯″潡鐨勪功鍐? module tinyriscv(input clk ,input rst_n …...

常见的限流算法

常见的限流算法 限流的定义固定窗口算法滑动窗口算法漏桶算法&#xff08;推荐&#xff09;令牌桶算法(推荐)限流粒度本地限流&#xff08;单机限流&#xff09;分布式限流&#xff08;多机限流&#xff09;分布式限流的实现 限流的定义 限流&#xff0c;也称流量控制。是指系统…...

【Leetcode 每日一题】3159. 查询数组中元素的出现位置

问题背景 给你一个整数数组 n u m s nums nums&#xff0c;一个整数数组 q u e r i e s queries queries 和一个整数 x x x。 对于每个查询 q u e r i e s [ i ] queries[i] queries[i]&#xff0c;你需要找到 n u m s nums nums 中第 q u e r i e s [ i ] queries[i] q…...

xadmin后台首页增加一个导入数据按钮

xadmin后台首页增加一个导入数据按钮 效果 流程 1、在添加小组件中添加一个html页面 2、写入html代码 3、在urls.py添加导入数据路由 4、在views.py中添加响应函数html代码 <!DOCTYPE html> <html lang...

行为树详解(5)——事件驱动

【分析】 如果行为树的节点很多&#xff0c;那么会存在要经过很多节点才会走到动作节点的情况。显然&#xff0c;性能上不如状态机。 每帧都需要重新遍历一系列节点才会走到动作节点&#xff0c;而实际上很多条件节点在数帧内不会有变化&#xff0c;这是造成性能问题的重要原…...

3.若依前端项目拉取、部署、访问

因为默认RuoYi-Vue是使用的Vue2,所以需要另外去下载vue3来部署。 拉取代码 git clone https://gitee.com/ys-gitee/RuoYi-Vue3.git 安装node才能执行npm相关的命令 执行命令npm install 如果npm install比较慢的话&#xff0c;需要添加上国内镜像 npm install --registrhttp…...

Debian操作系统相对于Ubuntu有什么优势吗?

更高的稳定性&#xff1a;Debian 以其出色的稳定性闻名&#xff0c;得益于严格的软件包测试和发布流程。其稳定版经过长时间测试与验证&#xff0c;确保了系统的高度稳定&#xff0c;更适合对稳定性要求极高的长期运行服务器环境。而 Ubuntu 虽有稳定版本&#xff0c;但更新周期…...

【漏洞复现】CVE-2015-3337 Arbitrary File Reading

漏洞信息 NVD - CVE-2015-3337 Directory traversal vulnerability in Elasticsearch before 1.4.5 and 1.5.x before 1.5.2, when a site plugin is enabled, allows remote attackers to read arbitrary files via unspecified vectors. 在安装了具有“site”功能的插件以…...

win10、win11-鼠标右键还原、暂停更新

系统优化 win 10jihuo win 11jihuo鼠标右键还原暂停更新 update 2024.12.28win 10 jihuo winx&#xff0c;打开powershell管理员&#xff0c;输入以下命令,选择1并等待 irm https://get.activated.win | iex参考&#xff1a;https://www.bilibili.com/video/BV1TN411M72J/?sp…...

FFmpeg来从HTTP拉取流并实时推流到RTMP服务器

当使用FFmpeg来从HTTP拉取流并实时推流到RTMP服务器时&#xff0c;你可以使用以下命令&#xff1a; ffmpeg -i http://输入流地址 -c:v copy -c:a copy -f flv rtmp://RTMP服务器地址/应用名称/流名称 这是一个基本的命令示例&#xff0c;其中&#xff1a; - -i http://输入流地…...

Quo Vadis, Anomaly Detection? LLMs and VLMs in the Spotlight 论文阅读

文章信息&#xff1a; 原文链接&#xff1a;https://arxiv.org/abs/2412.18298 Abstract 视频异常检测&#xff08;VAD&#xff09;通过整合大语言模型&#xff08;LLMs&#xff09;和视觉语言模型&#xff08;VLMs&#xff09;取得了显著进展&#xff0c;解决了动态开放世界…...

Rust : tokio中select!

关于tokio的select宏&#xff0c;有不少的用途。包括超时和竞态选择等。 关于select宏需要关注&#xff0c;相关的异步条件&#xff0c;会同时执行&#xff0c;只是当有一个最早完成时&#xff0c;会执行“抛弃”和“对应”策略。 说明&#xff1a;对本文以下素材的来源表示感…...

【hackmyvm】hacked靶机wp

tags: HMVrootkitDiamorphine Type: wp 1. 基本信息^toc 文章目录 1. 基本信息^toc2. 信息收集2.1. 端口扫描2.2. 目录扫描2.3. 获取参数 3. 提权 靶机链接 https://hackmyvm.eu/machines/machine.php?vmHacked 作者 sml 难度 ⭐️⭐️⭐️⭐️️ 2. 信息收集 2.1. 端口扫描…...

MaixBit k210学习记录

开发背景&#xff1a;Window系统主机&#xff0c;在主机上安装了虚拟机&#xff08;VirtualBoxUbuntu23.04&#xff09; 目标实现&#xff1a;在虚拟机&#xff08;Ubuntu&#xff09;中&#xff0c;实现对Maix bit&#xff08;k210&#xff09;开发板的开发 虚拟机的安装参考…...

Wordperss漏洞 DeDeCMS漏洞

Wordperss漏洞 环境搭建 #执⾏命令 cd /vulhub/wordpress/pwnscriptum docker-compose up -d #靶场地址 http://8.155.7.173:8080/wp-admin/ 注册账号 登录 漏洞一&#xff1a;后台修改模板拿WebShell 步骤一&#xff1a;思路是修改其WP的模板写入⼀句话木马后门并访问其文件…...

如何构建有效的AI Agents:从复杂到简约——深度解读Claude实践总结《Building effective agents》(上)

在人工智能技术日新月异的今天&#xff0c;大语言模型(LLM)已经成为技术创新的热点。 然而&#xff0c;在追逐技术前沿的热潮中&#xff0c;我们是否忽视了工程设计的本质&#xff1f; 作为全球人工智能领域的领军企业之一&#xff0c;Anthropic以其在AI安全和伦理方面的深入…...

git status 耗时

某个git库每次status一下就是半小时起步&#xff0c;gc后还是没有效果&#xff0c;后来排查记录发现某笔记录提交几百G的冗余文件&#xff0c;虽然revert了&#xff0c;但是还是存在库中&#xff0c;遂如下清理&#xff1a; # 查找大文件 git verify-pack -v .git/objects/pac…...

C++进阶重点知识(一)|智能指针|右值|lambda|STL|正则表达式

目录 1智能指针1.shared_ptr1.1 shared_ptr的基本用法使用shared_ptr要注意的问题运用 2.unique_ptr独占的智能指针示例&#xff1a;管理动态内存 3.weak_ptr弱引用的智能指针weak_ptr的基本用法lock 的作用&#xff1a;weak_ptr返回this指针weak_ptr解决循环引用问题weak_ptr使…...

OSCP打靶大冒险之Solidstate:多端口获取信息,shell逃逸,计划任务提权

声明&#xff01; 学习资源来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…...

八股(One Day one)

最近老是看到一些面试的视频&#xff0c;对于视频内部面试所提到的八股文&#xff0c;感觉是知道是什么&#xff0c;但是要说的话&#xff0c;却又不知道该怎么说&#xff08;要不咋称之为八股文呢&#xff09;&#xff0c;所以就想到写一篇八股文总结的博客&#xff0c;以便进…...

将材质球中的纹理属性对应的贴图保存至本地

通过Texture2D的EncodeToPNG方法将纹理转为图片形式 material.GetTexture方法通过属性名获取纹理贴图 material.SetTexture方法通过属性名设置纹理贴图 属性名可在shader代码中查看 using UnityEngine; using System.IO;public class TextureSaver : MonoBehaviour {public…...

Nginx 的配置文件

核心概念&#xff1a; 指令 (Directives): 配置文件的基本构建块。每条指令以分号 ; 结束。指令可以设置参数&#xff08;如 worker_processes auto;&#xff09;。 上下文 (Contexts): 指令被组织在特定的块&#xff08;用花括号 {} 包围&#xff09;中&#xff0c;称为上下文…...

基于PostGIS的GeoTools执行原生SQL查询制图实践-以贵州省行政区划及地级市驻地为例

目录 前言 一、空间相关表简介 1、地市行政区划表 2、地市驻地信息表 3、空间查询检索 二、GeoTools制图实现 1、数据类型绑定 2、WKT转Geometry 3、原生SQL转SimpleFeatureCollection 4、集成调用 5、成果预览 三、总结 前言 在当今这个信息爆炸的时代&#xff0c…...

Nginx详解(三):ngx_http_rewrite_module模块核心指令详解

概要&#xff1a; 在 Nginx 的众多功能模块中&#xff0c;ngx_http_rewrite_module是实现请求动态处理的核心组件&#xff0c;它通过一系列指令实现 URI 重写、条件判断、响应返回等功能。本文将以 CentOS 7.9 环境为例&#xff08;主机名www.a.com&#xff0c;IP 172.25.0.10…...

.NET Core 中预防跨网站请求伪造 (XSRFCSRF) 攻击

.NET Core 中预防跨网站请求伪造 (XSRF/CSRF) 攻击 在如今的网络环境中&#xff0c;安全问题一直是开发者们不可忽视的重要方面。跨网站请求伪造&#xff08;Cross-Site Request Forgery&#xff0c;简称 CSRF&#xff09;就是一种常见且具有威胁性的网络攻击方式。攻击者通过…...

原始数据去哪找?分享15个免费官方网站

目录 一、找数据的免费官方网站 &#xff08;一&#xff09;国家级数据宝库&#xff1a;权威且全面 1.中国国家统计局 2.香港政府数据中心 3.OECD数据库 &#xff08;二&#xff09;企业情报中心&#xff1a;洞察商业本质 4.巨潮资讯 5.EDGAR数据库 6.天眼查/企查查&a…...

极智项目 | 基于PyQT实现的YOLOv12行人目标检测软件设计

基于YOLOv12的专业级行人目标检测软件应用 开发者: 极智视界 软件下载&#xff1a;链接 &#x1f31f; 项目特色 专业检测: 基于最新YOLOv12模型&#xff0c;专门针对行人检测优化现代界面: 采用PyQt5构建的美观、直观的图形用户界面高性能: 支持GPU加速&#xff0c;检测速…...

Matlab数值计算

MATLAB数值计算 数值计算函数句柄匿名函数线性与非线性方程组求解1. \&#xff08;左除运算&#xff09;2. fzero3. fsolve4. roots 函数极值的求解1. fminbnd2. fmincon3. fminsearch与fminunc 数值积分1. quad / quadl2. quadgk3. integral4. trapz5. dblquad, quad2d, integ…...

【八股消消乐】索引失效与优化方法总结

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《八股消消乐》旨在记录个人所背的八股文&#xff0c;包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点&#xff…...

C++ 内存泄漏检测器设计

文章目录 1. C中的动态内存分配2. 什么是内存泄漏3. 内存泄漏的代码案例4. 内存泄漏检查器的设计模块1&#xff1a;位置信息捕获&#xff1a;模块2&#xff1a;内存分配跟踪&#xff1a;模块3&#xff1a;内存释放跟踪&#xff1a;模块4&#xff1a;泄漏记录存储&#xff1a;模…...