RISC-V处理器 (二.处理器的基本构成)

  1. 1. 电路建模
    1. 1.1. 一. 指令行为分析
      1. 1.1.1. 获得指令
      2. 1.1.2. 分析指令
      3. 1.1.3. 取得数据
        1. 1.1.3.1. 寄存器获取
        2. 1.1.3.2. 立即数扩展
      4. 1.1.4. 数据处理
      5. 1.1.5. 数据储存
    2. 1.2. 二. 逻辑框图
    3. 1.3. 三. 模块划分
      1. 1.3.1. 数据通路
      2. 1.3.2. 程序计数器
      3. 1.3.3. 指令储存器
      4. 1.3.4. 译码模块
      5. 1.3.5. 寄存器组
      6. 1.3.6. 算朮逻辑单元(ALU)
      7. 1.3.7. 随机存储器(RAM)

本文为通过Verliog HDL编写简易RISC-V CPU的试验笔记,如有错误敬请指正。


电路建模

复杂电路通常使用自顶向下的设计方法,先决定电路所需的功能,划分出实现功能的各个子模块,确保顶层设计无逻辑错误后,再进行各子模块的设计。

处理器的结构总是与指令集相关,对于RISC-V指令集,处理器需要按指令集的要求对数据进行处理操作。

一. 指令行为分析

对于任意一条RISC-V指令,它在处理器中的执行步骤皆可概括如下。

获得指令

从外部或储存器获得当前需要执行的指令,如:ADD rd rs1 rs2;

分析指令

获得指令后,使可以按指令的内容进行执行,但电路中指令以二进制方式储存,电路得到的只是32位的0、1,不能直接用于执行。为使电路"理解"指令的内容,需要对指令进行"翻译"以得到电路控制讯号。

对此,处理器须加入一个译码模块,作用按指令内容为生成电路各模块的控制讯号。

如对ADD_Rd_Rs1_Rs2ADD\_Rd\_Rs1\_Rs2进行分析,得知ALU执行加法操作,数据来源A的地址为Rs1,数据来源B的地址为Rs2;运算结果保存至Rd。此时应设定电路为寄存器取数据的加法模式。

实例:00F707B316=0000000(funct7)01111(rs2)01110(rs1)000(funct3)01111(rd)0110011(opcode)200F707B3_{16} = 0000000_{(funct7)}01111_{(rs2)}01110_{(rs1)}000_{(funct3)}01111 _{(rd)}0110011_{(opcode)2}进行译码,从Opcode=01100112Opcode = 0110011_2得知为R-Type类型,从Funct3=000Funct 3 = 000得到电路执行加法操作,数据来源A的地址为Rs1=011102Rs1 = 01110_2,数据来源B的地址为Rs2=011112Rs2 = 01111_2,运算结果保存至Rd=011112Rd = 01111 _2

附注:在实际的电路译码中,不分析Rs1,Rs2,Rd的信息,而是根据Opcode及指令中的其他信息位设置数据通路与算朮单元。

取得数据

寄存器获取

出于节省指令长度,方便数据调用等考量,指令中并不直接包含需操作的32位数据。而是记录了储存数据的5位地址数据。处理器通过5位地址对储存单元进行访问,间接得到所需的运算数据。在这一步中,处理器中需要25=322^5=32个32位寄存器组以储存临时数据。

如:ADD_Rd_Rs1_Rs2ADD\_Rd\_Rs1\_Rs2,结果储存至Rd,数据来源A的地址为Rs1,数据来源B的地址为Rs2;从Rs1,Rs2中获得寄存的32位数据。

附注:在处理器中,少量的临时数据被储存于寄存器而非内存,其特点为访问速度快,需要时可直接进行存放以获得数据,若储存于内存则至少需要占用一个指令周期以获得数据。

立即数扩展

对于立即数形式指令,其运算数据被部份地储存于指令当中,一般为12位(I-Type)或20位(J-Type)。不符合32位操作数的标准,需要对数据进行扩展以得到完整的32位操作数。在RISC-V中,大部分立即数皆按有符号数进行扩展处理。

如:ADDI_Rd_Rs1_99ADDI\_Rd\_Rs1\_99,结果储存至Rd,数据来源A的地址为Rs1,数据来源B为指令中储存的99,9910=0110_0011299_{10} = 0110\_0011_2,但输入为32位,扩展为9910=0(220)0_0110_0011299_{10} = 0…(22位0)…0\_ 0110\_0011_2

附注:符号扩展,由于立即数通过补码保存,正数的补码表示为其自身的二进制值,负数的补码表示为自身的二进制值取反加一,如$7_{10} = 0111_2;-7_{10} = 1001_2$,为7的4位二进制表示,若以8位表示则有$7_{10} = 00000111_2;-7_{10} = 11111001_2$,把4位二进制扩展为8位,只需判断数据的符号位(最高位),随后随扩展每一位值与最高值相同即可。

数据处理

参考指令集中定义的几种数据处理方式,分别有算朮加法、按位与、按位或、左右移。对数据的处理一般通过算朮逻辑单元(ALU)进行处理。

数据储存

假若处理结果不被保存或不改变状态机,则数据运算显得毫无意义。对大部分指令而言,数据的处理结果需要重新写回至寄存器组中等待后续指令的调用。又或是通过Store指令储存至"大型"储存器,如内存当中。

二. 逻辑框图

下为RISC-V处理器的基础构成框图,其组成与上述提到的指令执行步骤相差不大。

三. 模块划分

数据通路

数据通路是处理器的重要构成部份,主要负责模块间的数据传递。主要的部件为受译码模块控制的数据选择器。译码器通过选择器控制各模块的输入数据,例如选择ALU运算数据从寄存器或是立即数单元进行输入。

数据通路的设计需与指令相配合,对于RISC-V指令集的指令执行流程,可以得到一种数据通路设计如上。

程序计数器

在处理器中,指令一般被顺序存放于存储器,存储器的特点时访问数据时需提供地址,随后存储器通过地址取得被储存的数据。因此,程序计数器的核心为记录当前执行的指令计数,随后通过此计数值于存储器中读出相应的32位指令码。

在RISC-V中,若不考虑跳转与分支等情况,则PC在每条指令执行完毕后自增4。对应的电路为一组32位触发器及一个32位加法器。

指令储存器

存放指令的存储区域,可以是专用的指令储存器,亦可以是内存中特定的一块区域。

译码模块

翻译指令编码为控制讯号的电路,一般需与数据通路及其他模块协同设计。作为例子,译码器需为算朮逻辑单元提供操作码,以确保算朮逻辑单元的行为正确。亦需为数据通路中的各数据选择器提供操作讯号,确保各模块的输入数据正确。

寄存器组

处理器临时存放程序数据的寄存器,寄存器组的加入使程序数据能被迅速取用而无需专门访问内存空间,减少电路的延时。

算朮逻辑单元(ALU)

算朮逻辑单元的行为与使用的指令集有重要关系。对于RV32I指令集,指令集中包含了加减法、与、或、或非、移位、比较等操作指令。对应地需为ALU设计加法器及逻辑单元,从而实现指令集规定的操作行为。

随机存储器(RAM)

随机存储单元用于大规模地保存程序中的数据,对于大型程序,32个寄存器并不足以存放所有程序数据,但增加寄存器将导致地址位宽的进一步上升,使指令体系变得臃肿。因此必须使用规模更大,代价更低的器件以储存大量的运行数据。其中随机存储单元由于成本相对较低,数据可随机存放等特点而被广泛用于数据存储中。

附注:随机存储器中随机二字不是指获取的数据随机,而是指电路可以非顺序的方式读取储存器中的数据。如磁带、CD、硬碟等存储介质需从数据起始点开始一个个数据读取,而不能直接读取某一位置的数据。而随机存储器则可直接读出存储器中指定的数据,因此称为随机存储器。