RISC-V项目(2)---RISC-V指令解析

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

ESC 关闭 | 导航 | Enter 打开
输入关键词开始搜索