深入浅出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