康磊,李鑫,李慧,郑豪威
(西安石油大学计算机学院,西安710000)
《计算机组成原理》是计算机相关专业的一门重要的专业基础课。该课程主要介绍计算机内部的工作原理,帮助学生深入理解计算机的工作流程[1]。对于这种实践性很强的课程,实验环节是学好课程的关键步骤,它有助于学生对抽象理论的理解,可以亲身体验平时只能依靠老师讲解、自己想象的情景[2-3]。控制器的设计是课程的核心,它需要控制整个硬件系统的各个模块,因此必须深刻了解指令系统中各条指令功能,以及每条指令的数据通路的建立过程,能够正确给出各部件时序控制信号,保证每一条指令的顺利执行。
本文基于RISC-V 指令集设计了单周期的教学模型机。学生可以对于CPU 内部的工作流程以及各个功能部件有更深刻的理解,并根据个人的理解设计模型机的控制器,设计完成后进行功能仿真,学生可以通过观察仿真结果图判断指令执行的正确性,加强自身对计算机系统的理解。
在进行模型机设计时,需根据模型机的指令集,设计模型机内部功能模块和完整的数据通路。本文使用Verilog 硬件描述语言实现对各个模块,然后进行整机的功能仿真和测试。
指令集(Instruction Set Architecture,ISA),是指可以被一台计算机执行的全部指令的集合,是计算机硬件和上层软件之间的接口。本文基于RISC-V 指令集进行设计,存储系统采用哈佛结构。
RISC-V 指令集[4-5]共有R-type、I-type、S-type、Btype、U-type、J-type 六种指令类型,具体指令格式如图1 所示。
图1 RISC-V指令格式
本文设计的模型机选取了表1 所示的10 条指令,这10 条指令分别属于算术逻辑运算类指令、访存类指令和跳转类指令,满足程序设计的基本要求。RISC-V 指令集中32 个通用寄存器名称为x0~x31。表1 中,x[rs1]表示源操作数寄存器1,x[rs2]表示源操作数寄存器2,x[rd]表示目的寄存器。
表1 选取的10 条指令
一个完整的指令周期可分为取指(IF)、译码(ID)、执行(EX)、访存(MEM)、写回(WB)五个阶段[6]。IF 是将一条指令从指令存储器中取出;取出指令后,计算机进入ID 阶段,指令译码器按照预定的指令格式对取出的指令进行拆分和解释;之后进入EX 阶段,完成指令所规定的具体操作,实现指令的功能;MEM 根据指令功能,从内存中读出或写入数据;WB 是将执行阶段的运行结果写回到寄存器中。
这五个阶段由多个模块协同工作实现。其中,控制器按照指令功能的要求,自动产生的各种控制信号以保证数据在各模块之间的正确流动,达到正确执行指令的目的,指令执行中形成的数据传输路径称为数据通路[7]。
不同类型的指令在相同的指令执行各阶段进行的操作也不相同,所以需要对每条指令的功能以及进行的操作进行分析,以LW 指令的执行为例,LW 所执行的操作是x[rd] = mem[rs1+imm],指令编码格式如图2所示。
图2
根据LW 要完成操作,分析其执行需要以下阶段:
(1)IF:Instruction[31:0]=Instruction[PC];PC=PC+4;
(2)ID:rs1 = instr[19:15];rd = instr[11:7];IMM12_I=instr[31:20];
(3)EX:A= X[rs1];B ={ 20’b0,instr[31:20]},C =A+B;
(4)MEM:addr=C[9:0],Dout=dmem[addr];
(5)WB:WD=Dout。
根据LW 指令执行过程,可以得到其他指令的执行步骤,完整数据通路如图3 所示。
图3 完整数据通路
图3 中,程序计数器(PC)、指令存储器(IM)、指令译码器(ID)、寄存器堆(RF)、算术逻辑单元(ALU)、数据存储器(DM)是完成指令功能的基本模块。由于不同指令执行时需要进行不同的操作,对相同模块复用时要求的数据源也不同,所以增加了多路选择器(MUX)为模块选择正确的数据源,并增加了控制器(Control Unit)控制各个模块的执行,实现了CPU 基本功能。
单周期CPU 中一条指令在一个时钟周期内执行完毕,控制模块一次输出所有的控制信号[8]。控制模块的输入引脚有指令操作码Op,指令功能码funct3 和运算结果状态标志位Zero,输出引脚为模型机的多个控制信号。
控制模块根据输入的操作码和功能码判断当前指令类型,根据指令类型和Zero 产生控制信号,完成指令功能。控制模块采用组合逻辑实现。通过Verilog 编码生成的模块如图4 所示。
图4 Control Unit
一条指令的执行需要内部的功能部件共同完成[9]。IF 阶段需要程序计数器模块和指令存储器模块,ID 功能由译码模块完成,EX 阶段由运算器进行所需操作,MEM 需要对数据存储器进行操作,WB 阶段需要将指令运行的结果写到寄存器组中。下面对于指令执行过程中的主要功能部件进行简单介绍。
(1)程序计数器(Program Counter,PC)
程序计数器给出下一条执行的指令地址,并能通过控制器给出的控制信号更新下一条指令的地址。输入引脚有时钟信号clk、复位信号rst、写使能信号PCWr 以及下一条指令的地址NPC。
在PCWr 信号有效时,PC 值进行更新,PC=NPC。NPC 值有以下几种情况:
①程序顺序执行,NPC=PC+4;
②程序进行条件分支转移(BRANCH),NPC = PC+Imm12_B*2;
③程序进行跳转并链接(JAL),NPC = PC +Imm20_J*2;
④程序进行跳转并寄存器链接(JALR),NPC ={25'b0,rs1[4:0]}+Imm12_I。
通过Verilog 编码生成的模块如图5 所示。
图5 PC模块
(2)译码部件(Instruction Decoder ID)
RISC-V 指令集共有6 种指令类型,如图5 所示。译码模块根据不同的指令类型对输入的指令进行拆分输出。输出引脚有操作码Opcode、功能码funct3、rs1寄存器地址、rs2 寄存器地址、rd 寄存器地址、12 位立即数、12 位的偏移地址、20 位的立即数、20 位的转移地址。具体的指令拆分方式如图6 所示。
图6 指令拆分方式
控制器通过Opcode 和funct3 产生不同的控制信号。在R-Type 中,rs1、rs2 是两个源地址,rd 是目的地址。在I-Type 中,Imm12_I 作为立即数或跳转地址偏移量进行运算。在U-Type 中,IMM20_U 作为立即数进行运算。在B-Type 中,Imm12_B 作为跳转地址偏移量进行运算。在S-Type 中,Imm12_S 作为立即数进行运算。在J-Type 中,Imm20_J 作为跳转地址进行运算。
(3)寄存器组(Register File,RF)
寄存器组包含了32 个通用寄存器,从x0 到x31,每个都是32 位宽,其中X0 寄存器总是返回零。
通过Verilog 编码生成的模块如图7 所示。
图7 RF模块
其中A1、A2 为读地址数据输入,A3 为写地址数据输入,WD 为写数据输入,clk 为系统时钟,RFWr 为寄存器组写控制信号,RD1、RD2 为通用寄存器组数据输出端口。
RF 在时钟的下降沿监测RFWr 是否有效,RFWr有效时,做写操作,将WD 的数据写入到A3 指定的寄存器中,否则不做写操作。读出寄存器中的数据不受时钟控制。
(4)运算器(Arithmetic Logic Unit,ALU)
ALU 实现对数据的算术逻辑运算。在模型机的指令集中运算类指令有add、ori、auipc、slli、srli 和slt,所以ALU 中加、或、左移、右移和比较五类运算,运算操作符需要三位。编码时采用组合逻辑实现ALU,通过Verilog 编码生成的模块如图8 所示。
图8 ALU模块
其中A、B 是运算的两个源操作数,ALUOp 是运算操作符,C 是运算结果,Zero 是判断运算结果状态的标志位,运算结果的低10 位作为数据存储器的地址addr[9:0]。
(5)指令存储器(Instruction Memory,IM)
指令存储器中存储32 位指令机器码,输入指令地址,输出指令机器码。指令存储器在编译的时候写入测试程序,模型机运行时只进行读操作。
(6)数据存储器(Data Memory,DM)
数据存储器中存储32 位数据,输入引脚有:时钟信号clk、写入的32 位数据din、写入的数据地址addr、写控制信号DMWr。输出引脚是读出的数据dout。在时钟上升沿监测DMWr 是否有效,DMWr 有效时做写操作,否则不进行写操作。读操作可在任意时刻进行。通过Verilog 编码生成的模块如图9 所示。
图9 DM模块
设计中使用样例程序对模型机进行功能仿真验证,仿真正确后将程序下载到FPGA 开发板进行功能测试。
为了测试模型机完整指令集的功能,设计了使用全部10 条指令的样例程序,如表2 所示。
表2 样例程序
样例程序的执行过程如下:
(1)程序初始化;
(2)将数据1、2、4 分别存到存储器中;
(3)通过jalr 指令进行跳转并链接到子程序中;
(4)从存储器中加载出刚存的数据并进行求和,结果存到存储器中;
(5)从存储器中取出数据;
(6)返回起始地址。
根据样例程序预测执行结果:程序执行时,loop1循环一共执行三次,loop1 循环结束后,执行jalr 指令跳至loop2 循环,loop2 循环共执行三次,跳出loop2 循环时,add x4,x4,x6 的执行结果x4 为07h,最后lw x7,0(x0)的执行结果x7 的执行结果为07h,最后执行jal 指令回到起始地址。
将样例程序写入到单周期CPU 的IM 中,编写testbench,给出需要的激励信号,使用Vivado 中的仿真工具XSIM 进行功能仿真。样例程序的仿真结果如图10所示。
图10 样例程序仿真结果
从图10 仿真结果(1)中可以看到,在PC 值为58h处,当前指令机器码IR 为00002383h,对应指令为lw x7,0(x0),从存储器中取出的数据dout 为07h,lw 的执行结果符合预期。
从仿真结果(2)中看到,在310ns 时PC 值为5ch,当前指令机器码IR 为32’hFA5FF0EF,对应指令为jal x1,start,下个周期时PC 值为0h,程序回到起始地址处,与预期结果一致。测试程序在模型机正确执行。
功能仿真结果正确后,将程序生成的比特流文件下载到Nexys 4 DDR,Artix-7 开发板上进行测试。在100MHz 的外部时钟输入下,结果与测试程序预期结果一致,模型机可以正确运行。
本文利用Verilog HDL 设计并实现了一个基于RISC-V 的单周期模型机的设计,实现了RISC-V 指令集中的常用指令,让学生能够深入理解计算机的基本组成、内部结构和工作原理,提高学生的自主学习能力和创新能力。