1、NOP指令
2、JAL指令(无条件跳转)
核心点:将当前PC指针加4存入reg[rd],跳转到PC+imm继续执行

execute阶段:
1 2 3 4 5 6 7 8
| `INST_JAL:begin wr_reg_en = 1'b1 ; wr_reg_addr = rd ; wr_reg_data = instr_addr + 32'h4 ; jump_en = 1'b1 ; jump_addr = instr_addr + op2 ; jump_hold = 1'b0 ; end
|
译码阶段:
1 2 3 4 5 6
| `INST_JAL:begin rd_rs1_addr = 5'h0 ; rd_rs2_addr = 5'h0 ; op1_out = 32'h0 ; op2_out = imm ; end
|
3、JALR间接跳转指令
1 2 3 4 5 6
| `INST_JALR:begin rd_rs1_addr = rs1 ; rd_rs2_addr = 5'h0 ; op1_out = rd_rs1_data ; op2_out = imm ; end
|
执行阶段的跳转:
1 2 3 4 5 6 7 8
| `INST_JAL:begin wr_reg_en = 1'b1 ; wr_reg_addr = rd ; wr_reg_data = instr_addr + 32'h4 ; jump_en = 1'b1 ; jump_addr = instr_addr + op2 ; jump_hold = 1'b0 ; end
|
4、LUI指令
译码阶段:
1 2 3 4 5
| `INST_LUI:begin rd_rs1_addr = 5'h0 ; rd_rs2_addr = 5'h0 ; op1_out = 32'h0 ; op2_out = imm ;
|
执行阶段:
1 2 3 4 5 6 7
| `INST_LUI:begin wr_reg_en = 1'b1 ; wr_reg_addr = rd ; wr_reg_data = op2 ; jump_en = 1'b0 ; jump_addr = 'h0 ; jump_hold = 1'b0 ;
|
5、LUIPC
这里简单提一嘴,就是LUI跟LUIPC的立即数计算方式如下:
1 2 3 4 5 6
| always_comb begin case(opcode) `INST_LUI,`INST_LUIPC: imm = {instr_in[31:12],12'h0}; endcase end
|
译码阶段:
1 2 3 4 5 6
| `INST_LUIPC:begin rd_rs1_addr = 5'h0 ; rd_rs2_addr = 5'h0 ; op1_out = instr_addr_in ; op2_out = imm ; end
|
执行阶段:
1 2 3 4 5 6 7 8
| `INST_LUIPC:begin wr_reg_en = 1'b1 ; wr_reg_addr = rd ; wr_reg_data = op1 + op2 ; jump_en = 1'b0 ; jump_addr = 'h0 ; jump_hold = 1'b0 ; end
|
6、B型指令
B型指令的立即数计算方式:
1 2 3 4 5 6
| always_comb begin case(opcode) `INST_TYPE_B: imm = {{20{instr_in[31]}},instr_in[7],instr_in[30:25],instr_in[11:8],1'b0}; endcase end
|
B型指令的指令定义方式:
B型指令译码阶段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| `INST_TYPE_B:begin case(func3) `INST_BEQ,`INST_BNE,`INST_BLT,`INST_BGE,`INST_BLTU,`INST_BGEU:begin rd_rs1_addr = rs1 ; rd_rs2_addr = rs2 ; op1_out = rd_rs1_data ; op2_out = rd_rs2_data ; end default:begin rd_rs1_addr = 'h0 ; rd_rs2_addr = 'h0 ; op1_out = 'h0 ; op2_out = 'h0 ; end endcase end
|
执行阶段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| assign imm = {{20{instr[31]}},instr[7],instr[30:25],instr[11:8],1'b0}; assign equal = (op1 == op2) ? 1'b1 : 1'b0; assign less_signed = ($signed(op1) < $signed(op2)) ? 1'b1 : 1'b0; assign less_unsigned = (op1 < op2) ? 1'b1 : 1'b0; assign jump_imm = instr_addr + imm ;
`INST_TYPE_B: begin case(func3) `INST_BEQ: begin wr_reg_en = 1'b0 ; wr_reg_addr = 5'h0 ; wr_reg_data = 'h0 ; jump_en = equal ; jump_addr = equal ? jump_imm : 'h0 ; jump_hold = 1'b0 ; end `INST_BNE: begin wr_reg_en = 1'b0 ; wr_reg_addr = 5'h0 ; wr_reg_data = 'h0 ; jump_en = ~equal ; jump_addr = ~equal ? jump_imm : 'h0 ; jump_hold = 1'b0 ; end `INST_BLT: begin wr_reg_en = 1'b0 ; wr_reg_addr = 5'h0 ; wr_reg_data = 'h0 ; jump_en = less_signed ; jump_addr = less_signed ? jump_imm : 'h0 ; jump_hold = 1'b0 ; end `INST_BGE: begin wr_reg_en = 1'b0 ; wr_reg_addr = 5'h0 ; wr_reg_data = 'h0 ; jump_en = ~less_signed ; jump_addr = ~less_signed ? jump_imm : 'h0 ; jump_hold = 1'b0 ; end `INST_BLTU: begin wr_reg_en = 1'b0 ; wr_reg_addr = 5'h0 ; wr_reg_data = 'h0 ; jump_en = less_unsigned ; jump_addr = less_unsigned ? jump_imm : 'h0 ; jump_hold = 1'b0 ; end `INST_BGEU: begin wr_reg_en = 1'b0 ; wr_reg_addr = 5'h0 ; wr_reg_data = 'h0 ; jump_en = ~less_unsigned ; jump_addr = ~less_unsigned ? jump_imm : 'h0 ; jump_hold = 1'b0 ; end default:begin wr_reg_en = 1'b0 ; wr_reg_addr = 5'h0 ; wr_reg_data = 'h0 ; jump_en = 1'b0 ; jump_addr = 'h0 ; jump_hold = 1'b0 ; end endcase end
|