北工大学实验学院(论文)
3.3 指令集设计
指令系统直接与计算机系统的性能和硬件结构的复杂程度等密切相关,它是设计一台计算机的起始点和基本依据。本次设计的指令集总共包含12条,能够执行加法、减法、逻辑或、逻辑与及乘法和除法。主要有三种类型,即R型、I型和J型。可以进行四种操作,下面对所用到的三种指令形式逐一说明。
3.2.1 寄存器型(R型)
指令中最常见的类型就是R型,本指令集中属于该类型的有add、sub、and和or指令。R型指令是指操作数全部为寄存器变量,其寻址方式为寄存器寻址。每条指令由一个操作码,两个源操作数寄存器,和一个目的寄存器组成,如add r3 r1 r2。如图3-2给出了典型的R型指令,如ADD R1,R2,R3。所有指令都有3位操作码(Opcode),操作码是用来确定哪一种类型的指令将被执行。
15 13 12 10 9 7 6 4 3 0
Opcode Rd Rs 图3-2 R型指令格式
在本指令系统中,R类型的指令及其OPCODE如下:
指令 Add Sub And Or 下表为所有R型指令的指令格式及其含义。 指令格式 Add r1 r2 r3 sub r1 r2 r3 And r1 r2 r3 Or r1 r2 r3 操作 r1 = r2 + r3 r1 = r1 - r3 r1 = r2 & r3 r1 = r2 | r3 Opcode 00001 00010 00011 00100 Rt non 11
北工大学实验学院(论文)
3.2.2 立即数型(I型)
I型指令结构如图3-4所示。其与R型指令区别在于指令中只包含一个源寄存器变量,另一个元操作数由立即数表示。
15 13 12 10 9 7 6 0
Opcode Rd 图3-3 I型指令格式
如addi r3 r1 #7,该指令表示r1中的值与立即数7相加,储存于寄存器r3中。本设计的指令集中,属于该类型的指令还有subi,lw,sw和beq指令。下表为指令格式,操作码及操作。 指令格式 Addi r1 r2 imm Subi r1 r2 imm Lw r1 r2 offset Sw r1 r2 offset Beq r1 r2 offset Opcode 00011 00100 10000 10001 11000 操作 r1 = r2 + imm r1 = r2 - imm [r2 + offset] -> r1 r1 -> [r2 + offset] If r1 == r2 -> PC +2+ offset 在以上指令中,Addi和Subi比较容易理解。Lw,Sw和Beq需要解释一下。Lw表示加载指令,即从内存中加载一个数据至寄存器。从上表中可以看到,本条指令先用两个源操作数求和,然后将结果作为内存地址,称为变基址寻址,得到地址后,就可以读取相应的数据,最后将结果储存于目的寄存器中。同理,sw是储存指令,与Lw类似。Beq指令为跳转指令,当r1和r2中数字相等的时候,则跳转到PC + 2 + offset处。由于opcode占5位,r1占3位,r2占3位,因此offset只有5位,可以储存的值最大只有32。同时由于16位指令地址低二位不需要储存,因此实际寻址范围为2^7 = 128,即只能实现跳转到当前PC+2的-64~+64处。
Rs Imm 3.2.3 立即移位型(J型)
由于beq指令跳转范围有限,为了实现长跳转,必须给指令集添加新的指令。在本文设计的指令集中,由Jump指令完成。该指令由一个5位操作码opcode和一个10位的立即数组成,立即数表示需要跳转的绝对地址。下表是Jump指令的指令格式及opcode
12
北工大学实验学院(论文)
15 13 12 8 7 0 Opcode Non 图3-4 J型指令格式
指令格式 Jump #imm Opcode 00011 操作 -> imm Imm 3.4 本章小结 本章主要介绍了CPU的方案论证,整体结构设计以及指令集设计。确定了本文的设计的CPU为8位单周期精简指令集CPU。再确定了方案的基础上,绘制了CPU的结构图,完成了CPU结构设计。最后详细确定了CPU的指令集。为后续实现CPU打下基础。
13
北工大学实验学院(论文)
4 基于Quartus II的8位RISC实现
4.1 取指阶段
取值阶段主要包括四个器件,一个寄存器PipePC,用于储存程序计数器PC的值;一个计算PC+1的专用加法电路adder2;一个多路选择器,用于选择程序计数器的更新值得来源,如图中的XLXI_117所示;最后一个器件是instmem,用于存放程序指令。IF阶段结构如图3-6所示。每个周期的正跳变到来的时候,程序计数器的储存值进行更新,由npc引脚输入新的地址信号,并从pc引脚送出。Instmem接收到新的程序地址信号。从而将相应地址处的指令通过q引脚端送出,为后续阶段提供新的指令。这个过程被称为取指令操作。程序计数器代码如下所示:
module PipePC( input [7:0] npc, input clk, input clear, output reg [7:0] pc );
always @(negedge clear,posedge clk)
begin end
if(clear == 0)
pc <= 0; pc <= npc; else
end module
always @(negedge clear,posedge clk)
触发块中包含两个触发信号,clear表示复位信号,当该信号下跳变时,执行always,并且由于if(clear == 0)成立,因此pc被赋值为0,用于CPU上电复位。当CPU运行正常后,每一个时钟上跳变,触发一次always功能块。此时将npc引脚输入信号幅值给寄存器pc,将更新寄存器pc的值。当取值操作完成后,PC同时送入到adder2模块中,该模块中执行assign sum = a + 8'd1;操作,即将PC值加1,为下一周期更新pc值做准备,运算结果送入到多路选择器Mux2中。Mux2是一个双路选择器,其数据来源一个是adder2的运算结果,表示程序顺序
14
北工大学实验学院(论文)
运行的时候的PC+1值,一个是由控制器件CU送出,表示程序需要跳转的时候的PC跳转目的值。当下一个周期到来时,新的NPC值被写入到程序计数器中。
图3-6 IF取指令段的结构
4.2 译码阶段
CPU译码阶段主要负责对指令进行译码,确定指令中的源操作数,目的寄存器和具体运算类型。同时从相应的寄存器号下取得寄存器值。译码的主要部件是控制部件,即Control Unit,该部件如下图所示:
以下为CU中与译码相关的代码。 wire [3:0] op = Inst[15:13];
wire i_add = ~op[2]&~op[1]&~op[0];
wire i_sub = ~op[2]&~op[1]& op[0]; wire i_and = ~op[2]& op[1]&~op[0]; wire i_or = ~op[2]& op[1]& op[0];
15