RISC-V指令系统

一.介绍

指令系统:计算机语言中的单词成为指令,而这个词汇表就是指令系统。

指令集架构(ISA)

        x86:传统pc市场的主流,善于处理大数据。

        ARM:移动端设备(手机)市场,处理快数据为主。

        RISC-V:当需要同时兼顾数据传输速度和传输量时,RISC-V更有优势。

更重要的是RISC-V是开源的。

二.计算机硬件的操作

主要包括:算术运算、逻辑运算、数据传输、移位操作、条件分支、无条件跳转。

数据存储模式:大端存储,小端存储。

大端:高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

小端:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

设计原则:简单源于规整、优秀的设计需要适当的折中、更少则更快(寄存器数量太多可能会增加时钟周期)。


三.计算机中的指令表示

RISC-V常见指令表示:R型,I型,S型,B型,J型指令

R型:一般用于寄存器-寄存器操作。

I型:一般用于立即数访问和load操作。

S型:用于访存store操作。

B型:用于条件跳转操作。

J型:用于无条件操作。


R型:一般用于寄存器-寄存器操作。

funct7(7bit)rs2(5bit)rs1(5bit)funct3(3bit)rd(5bit)opcode(7bit)

funct7:操作码字段。

funct3:操作码字段。

rs2:第二个源操作数寄存器。

rs1:第一个源操作数寄存器。

rd:目的操作数寄存器,存放操作结果。

opcode:(操作码)指令的基本操作。

下面以add x9,x20,x21为例介绍。

00000001010110100000010010110011

01001:9        10100:20        10101:21

通过funct7,funct3,opcode来识别是一个R型加法指令

将x20寄存器中的值加上x21寄存器中的值相加的结果存放到x9寄存器中。


I型:一般用于短立即数和访存操作

immediate(12bit)rs1(5bit)funct3(3bit)rd(5bit)opcode(7bit)

注意:计算机中是以补码形式存储immediate;12位立即数。立即数范围-2^11到((2^11)-1)(-2048到2047)

下面以lb x9,64(x22)介绍

lb x9,64(x22)

000001000000

10110

000

01001

0000011

 000001000000 :64        10110:22        01001:9

解释:将rs1地址偏移立即数位空间中的值存储到rd所指的寄存器空间中。


S型:用于访存store操作

immediate[11:5](7bit)rs2(5bit)rs1(5bit)funct3(3bit)immediate[4:0](5bit)opcode(7bit)

个人理解这里的立即数为何这样存储:为了规整,将原本的rd用来存储立即数的低5位。

下面以sb x5,40(x6)介绍

sb x5,40(x6)

0000001

00101

00110

000

01000

0100011

000000101000:40        00101:5        00110:6

解释:将rs2寄存器中的值存储到rs1寄存器偏移立即数位地址中去。


B型:有条件分支

immediate[12,[10:5]](7bit)rs2(5bit)rs1(5bit)funct3(3bit)immediate[[4:1],11](5bit)opcode(7bit)

注意:13位立即数,末尾始终为0;

B型立即数格式(末尾时钟为零)
imm[12]imm[11]imm[10:5]imm[4:1]0

下面以beq x5,x6,100为例

beq x5,x6,100

0000011

00110

00101

000

00100

1100011

代码中整理出的立即数
0000001100100

       注意在使用b型指令时,代码末尾别忘了补个0(或者获取的立即数别忘了左移一位)。解释:如果rs1和rs2寄存器中的值相等,则pc跳转到pc+immediate位置去,这是要重建流水线的。


J型:无条件跳转

immediate[20,[10:1],11,[19:12]]

(20bit)

rd

(5bit)

opcode

(7bit

J型立即数(20位)

immediate[20] immediate[19:12] immediate[11] immediate[10:1] 0

下面以jal x1,100为例

jal x1,100

00000110010000000000

00001

1101111

代码中立即数
000000000000001100100

        写代码时,末尾补0别忘了

解释:将pc+4存储到rd寄存器中,同时pc跳转到pc+立即数位置去。


U型:格式和B型类似,20位大立即数操作

immediate[31:12]rdopcode

vfd

与J型区别在于立即数放的位置

下面以lui x1,0xf0000为例

lui x1,0xf0000

11110000000000000000

00001

0110111

解释:rd寄存器存储立即数  x1=0xf0000;


常见操作及其指令

1、算术运算指令

包括addi,slti,sltiu,add,sub,slt,sltu。

slt比较指令 指令后边加i 一般表示是指令中有立即数,而u表示有无符号。

immediate[11:0]rs1000rd0010011addi(I型)
immediate[11:0]rs1010rd0010011slti(I型)
immediate[11:0]rs1011rd0010011sltiu(I型)
0000000rs2rs1000rd0110011add(R型)
0100000rs2rs1000rd0110011sub(R型)
0000000rs2rs1010rd0110011slt(R型)
0000000rs2rs1011rd0110011sltu(R型)

2、移位指令

包括slli,srli,srai,sll,srl,sra。

注意立即数移位指令中立即数(shamt)的范围:(这里立即数是5位的立即数)具体如下表:

0000000shamtrs1001rd0010011slli(I型)
0000000shamtrs1101rd0010011srli(I型)
0100000shamtrs1101rd0010011srai(I型)
0000000rs2rs1001rd0110011sll(R型)
0000000rs2rs1101rd0110011srl(R型)
0100000rs2rs1101rd0110011sral(R型)

注意逻辑右移和算术右移是由区别的。

逻辑右移:数据向右移立即数位,空位填0。

算术右移:数据向右移立即数位,空位填最高位(符号位)。

为了区别这两个机器码的第30位用来作为判断。具体仔细观察上表。

3、逻辑操作指令

包括xori ,ori,andi,xor,or,and。

imm[11:0]rs1100rd0010011xori(I型)
imm[11:0]rs1110rd0010011ori(I型)
imm[11:0]rs1111rd0010011andi(I型)
0000000rs2rs1100rd0110011xor(R型)
0000000rs2rs1110rd0110011or(R型)
0000000rs2rs1111rd0110011and(R型)

小总结:算术运算,逻辑运算,移位运算这些基本运算指令一般都为R型或者I型指令

4、访问存储类指令

包括lb,lh,lw,lbu,lhu,sb,sh,sw。

lb,lh ,lw,lbu,lhu:从存储器(data_mem)中取出一个数值,存入寄存器(regfile)中去。

sb,sh,sw:将寄存器(regfile)中的数值存入存储器(data_mem)中去。

imm[11:0]rs1000rd0000011lb(I型)
imm[11:0]rs1001rd0000011lh(I型)
imm[11:0]rs1010rd0000011lw(I型)
imm[11:0]rs1100rd0000011lbu(I型)
imm[11:0]rs1101rd0000011lhu(I型)
imm[11:5]rs2rs1000imm[4:0]0100011sb(S型)
imm[11:5]rs2rs1001imm[4:0]0100011sh(S型)
imm[11:5]rs2rs1010imm[4:0]0100011sw(S型)

5、控制转移指令

主要是一些跳转指令:beg,bne,blt,bge,bltu,bgeu,jalr,jal。

imm[12]imm[10:5]rs2rs1000imm[4:1]imm[11]1100011beq(B型)
imm[12]imm[10:5]rs2rs1001imm[4:1]imm[11]1100011bne(B型)
imm[12]imm[10:5]rs2rs1100imm[4:1]imm[11]1100011blt(B型)
imm[12]imm[10:5]rs2rs1101imm[4:1]imm[11]1100011bge(B型)
imm[12]imm[10:5]rs2rs1110imm[4:1]imm[11]1100011bltu(B型)
imm[12]imm[10:5]rs2rs1111imm[4:1]imm[11]1100011bgeu(B型)
imm[11:0]rs1000rd1100011jalr(I型)
imm[20]imm[10:1]imm[11]imm[19:12]rd1100011jal(J型)

注意上述立即数存储方式,在上面的B型指令讲解中有提到。

总结

资源里有我使用FPGA写的一个基于RISC-V的单周期CPU。目前不具备流水线,后续准备写一个5级流水的单周期处理器,同样会发布到博客上。希望大家评论给出意见。

  • 19
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,针对您的问题,我提供如下的单周期CPU设计Verilog的J型指令示例,希望能对您有所帮助: ``` module single_cycle_cpu ( input clk, input reset, input [31:0] instruction, output reg [31:0] out_reg1, output reg [31:0] out_reg2 ); reg [31:0] pc; reg [31:0] instruction_reg; reg [31:0] jump_address; always @(posedge clk) begin if (reset) begin pc <= 32'h00000000; instruction_reg <= 32'h00000000; end else begin pc <= pc + 4; instruction_reg <= instruction; end end always @(*) begin case (instruction_reg[31:26]) 6'b000010: // J-type instruction jump_address = {pc[31:28], instruction_reg[25:0], 2'b00}; default: jump_address = 32'h00000000; endcase end always @(*) begin case (instruction_reg[31:0]) // Other instruction cases here... 32'h08000000: // J instruction pc = jump_address; endcase end endmodule ``` 在这里,我们实现了一个单周期CPU,支持J型指令。具体来说,我们使用了一个32位的PC寄存器,每个时钟周期增加4,代表下一条指令的地址。同时,我们使用一个instruction_reg寄存器,将当前执行的指令存储下来,以便后续操作。在每个时钟周期内,我们根据指令的类型,计算出J型指令的跳转地址,并存储在jump_address寄存器中。在执行J型指令时,我们直接将PC寄存器的值设置成jump_address,实现跳转操作。 需要注意的是,这只是一个简单的示例代码,实际的CPU设计中还需要考虑很多其他因素,例如指令的解码、数据的存储和访问等等。如果您需要更详细和完整的CPU设计,建议参考相关的教材和文献。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值