年级/专业: 19计算机科学与技术
开始时间:2021 年9月9日
结束时间:2021 年11月4日
本次实验在quatus II 9.0平台上设计了16
位单周期CPU及其对应的指令系统,包括运算类指令、传送类指令、储存类指令、控制类指令。详细指令有Clear
指令、MovN指令、MovR指令、ADD指令、ADDN指令、SUB指令、JMP指令、STORE指令、LOAD指令、CMP指令、BEQ指令等.对应操作码分别为0000、0001、0010、0011、0100、0101、0110、0111、1000、1001、1010。在此基础上,我们进一步设计了7段数码显示管的驱动逻辑电路,对结果进行输出显示.最后,自己设计了一段程序并编译测试能够顺利运行。
从功能的角度来看,本次设计的CPU可以分为共分为:逻辑模块、存储模块、运算模块和时钟周期模块。逻辑模块通过逻辑电路对操作码或数码管驱动进行译码,存储模块可以存储编译好的指令或暂存运算结果,运算模块负责对数据或地址进行算数操作。时钟信号协调全局模块统一有序地执行。所有的这些模块相互配合,协调完成CPU的核心功能。
本次的硬件基础课程设计让我们对计算机的硬件认识从简单的理论认识上升到具体的,可操作的实践。从本质来看,CPU是一个有着复杂控制信号的有限状态自动机(Finite
State Machine)。各时刻存储器的存储值组成了一个个状态, 在时钟周期的控制下进行状态转换。
它无法理解任何软件,只负责01运算与存取操作。而对数据和指令的编译与解释操作都由其上层的操作系统完成。
In this experiment, 16-bit single-cycle CPU and its corresponding instruction system were designed on Quatus II 9.0 platform, including operation instruction, transmission instruction, storage instruction and control instruction. Detailed instructions include Clear, MovN, MovR, ADD, ADDN, SUB, JMP, STORE, LOAD, CMP, BEQ and so on. The corresponding operation codes are 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, 1000, 1001, and 1010. On this basis, we further design 7 digital display tube drive logic circuit, the results of output display. Finally, I designed a program and compiled the test to run smoothly. From the functional point of view, our CPU can be divided into: logic module, storage module, operation module and clock cycle module. The logic module decodes the OpCode or digital tube driver through the logic circuit. The storage module can store compiled instructions or temporary operation results. The operation module is responsible for arithmetic operations on data or addresses. Clock signal coordination global module uniformly and orderly execution. All of these modules work together to coordinate the core functions of the CPU. The hardware foundation course design makes our understanding of computer hardware from simple theoretical understanding to concrete, operable practice. In essence, the CPU is a Finite State Machine with complex control signals. The values of the memory at each time form a state, which is converted under the control of the clock cycle. It can’t understand any software and only handles 01 operations. The data and instructions are compiled and interpreted by the upper operating system.
Keywords: CPU design, Quartus II, Finite State Machine
1、掌握硬布线单周期CPU工作原理、实现方法及组成部件原理和设计方法。
2、认识和掌握指令的执行过程,掌握指令设计的流程。
3、熟练使用Quartus II进行设计与仿真,培养学生的分析和设计CPU的能力。
完成16位单周期CPU数据通路和线路图的设计,实现功能指令:Clear 指令、MovN指令、MovR指令、ADD指令、ADDN指令、SUB指令、JMP指令、STORE指令、LOAD指令、CMP指令、BEQ指令。
目标电路设计如下图所示:
图1 16位单周期CPU逻辑电路图
本实验所需的硬件设备:PC计算机和FPGA板–Cyclone III系列实验开发板。
本实验所需的软件器材有:Windows操作系统、Quartus II 9.0集成开发软件。
了解CPU的指令执行流程可以进一步加深我们对复杂状态机的理解,有助于我们设计自己的指令集和信号量。CPU指令的处理过程如下:
图2 CPU执行周期
设计的指令共有11条,分别是Clear 指令、MovN指令、MovR指令、ADD指令、ADDN指令、SUB指令、JMP指令、STORE指令、LOAD指令、CMP指令、BEQ指令。这11条指令的指令格式如下:
Op码 4位 3位Reserved 3位Reserved 3位目标寄存器 3位Reserved
功能:将目标寄存器清零。
Op码 4位 3位Reserved 3位目标寄存器 6位 立即数
功能:将6位立即数扩展为16位,存到目标寄存器。
Op码 4位 3位Reserved 3位 源寄存器 3位目标寄存器 3位
功能:将源寄存器内容转移到目标寄存器。
Op码 4位 3位a寄存器 3位b寄存器 3位c寄存器 3位Reserved
功能:将寄存器a与寄存器b中值相加后存到寄存器c。
Op码 4位 3位Reserved 3位 累加寄存器 6位立即数
功能:将经扩展到16位的6位立即数与寄存器中内容相加后存入该寄存器。
Op码 4位 3位a寄存器 3位b寄存器 3位c寄存器 3位Reserved
功能:将寄存器a与寄存器b中内容相加后存到寄存器c。
Op码 4位 12位目标跳转地址
功能:将12位地址扩展到16位后作为下一条PC指令。
Op码 4位 3位 BASE寄存器 3位 源寄存器 6位offset
功能:将源寄存器中的内容存到内存指定地址处。
Op码 4位 3位 BASE寄存器 3位 目的寄存器 6位offset
功能:算好偏移地址后去该地址处取出数据并存到指定目标寄存器。
Op码 4位 3位a寄存器 3位b寄存器 3位temp寄存器
功能:比较两个数的大小,主要通过结果最高位和符号位的值判断。
Op码 4位 3位 base寄存器 3位Reserved 6位offset
功能:实现有条件的地址跳转,可以用来进行循环操作。
在该实验中我们设计了11个控制信号,分别为RegDst、ALUSrcB、ALUOp、RegWrite、Mem2Reg、MemWrite、PCSource、Clear、Branch、ST、Reg2Reg 它们的作用如下表所示。
表 1 控制信号说明
每条指令的执行都涉及到相关的器件单元,而要保证每条指令的正确执行,就需要精准控制相关的信号量。例如比较复杂的LOAD指令,涉及到寄存器,ram,数据选择器,alu单元,符号扩展单元。首先其指令格式如下:
Op码 4位 3位 BASE寄存器 3位 目的寄存器 6位offset
数据流向应为从指令码的11到9位确定base寄存器地址,然后从中取出内容(一个地址)传输到outdata1端口,然后送到ALU,同时offset经符号扩展后通过数据选择器也到达ALU,经过加法运算后得到新地址,作为ram读地址输入端输入内容,从ram中读取的数据经过一个数据选择器后到达寄存器写数据端口;同时指令码的8到6位经过两个数据选择器到达寄存器写地址端口。最后完成内容写入寄存器指定地址操作。
11到9位为寄存器地址,其中存储一个地址,要让此数据到达寄存器地址输入端口,不涉及控制信号;8到6为目的寄存器地址,要让此数据到达寄存器地址输入端口,涉及到寄存器堆多路读选择器(图 12),其中包括ST、RegDst两个控制信号,并且这两个信号量需要全部置0;扩展后的偏移量若要到达ALU单元与BASE相加,则涉及到ALU操作数B选择器(图 14),其中包括控制信号ALUsource,并且需要置0;要让ALU单元(图 9)进行加法操作,则涉及到控制信号 ALUOP并且需要置1;若要让从ram中读取数据并传输到寄存器写端口,则涉及到ram存储器(图 6)和寄存器堆多路写选择器(图 11)到控制信号MemWrite,需置0,RegtoReg、MemToReg,clear(从高到低),分别置0、1、0;若要写入寄存器堆(图 4),则涉及到控制信号RegWrite,并且需要置1。其余没有涉及到的控制信号pc和Brance置0。
综上得出的LOAD指令的控制信号量如下表所示:
其余指令的控制信号量也由如上分析得出。
指令与控制信号对应关系如下表所示。
表2 Op码对应的控制信号
设4位Op码从高到低分别表示为A4A3A2A1,则根据指令的指令码,可以获得控制信号的组合逻辑及逻辑电路:
再将这些控制信号组成单个元件,再将单个原件封装成控制器,如下所示。
图3 封装控制器
寄存器堆作为数据保存的器件,当读取寄存器中的数据时,设计有一个时钟信号端口(上升沿触发读数据)、两个读地址端口,两个数据输出端口;当写入寄存器数据时,设计有写信号使能端端口、写地址端口以及写数据端口。总共端口共有8个。如图所示。
图4 寄存器堆
由于位数限制,设计的寄存器给定寄存器位数3位,即最多可寻址8个寄存器,所以只有8个16位D寄存器的综合模块。寄存器堆详细设计图如下图所示。
图5 寄存器堆的实现
图中还有一个74138译码器,G1端为WE写信号,当要向寄存器存数时,应使写信号有效,同时给出3位需要写的地址,将要写入的数据存至译码生成对应的寄存器中。
同时图中还有2个8位数据选择器,主要是用于当读取寄存器数据时,由输入的3位寄存器地址,得到对应寄存器中的数据并输出。
数据存储器RAM实现将数据写入和读出功能。输入端包括需存储的数据(data[15…0])、读写使能端(wren 1为写,0为读)、读写地(address[4…0])、时钟信号(clock);输出端(q[15…0])用于输出从内存中取出16位数据。如下图所示。
图6 RAM存储器
其中写操作需要以下条件:数据、地址、wren=1。随着时钟信号来临,数据写入存储器。读操作需要条件:地址、wren=0。随着时钟信号来临,数据被读出。
指令存储器ROM能够实现将指令代码从指令存储器中取出。输入端包括地址和时钟信号;输出端只有一个,用来输出16位指令代码。如下图所示。
图7 ROM存储器
其中addr由PC计数器给出。输出内容为已写在rom中的指令代码cd[15…0]。
4.2.3 计数器
程序计数器是用于当每个时钟的上升沿到来后,将原来PC指令地址加 1,然后从指令存储器(rom)中取出对应地址的指令数据,作为本轮运算的指令。PC计数器模块由5部分组成:加1的ALU单元、16位扩展器、以及PC跳转数据选择器。如下图所示。
图8 PC跳转部分
其中各模块对应功能如下:
表3 add_PC模块说明
ALU单元有3个输入端,分别是数据输入端(dataa[15…0]、datab[15…0])和控制信号端(add_sub),和2个输出端(ataa[15…0]和datab[15…0]经运算的结果)。如下图所示。
图9 ALU单元
1.当执行MovN指令时,将指令的后6位数据扩展为16位后存到目标寄存器。
2.当执行AddN指令时,将指令的后6位数据扩展为16位后与到目标寄存器中内容相加再存到目标寄存器。
3.当执行Jmp指令时,将指令的后12位数据扩展为16位做为下一条PC指令
4.当执行Store指令时,将指令的11-9位数据和5-0位数据分别扩展为16后相加作为目标寄存器,作为存储地址。
5.当执行Load指令时,将指令的11-9位数据和5-0位数据分别扩展为16后相加作为源寄存器地址并取数。
6.当执行Beq指令时,将指令的后6位数据扩展为16位后作为下一条PC的偏移地址
综上,共涉及到两类位扩展单元,即6-16扩展和12-16扩展。如下图所示。
图11 12-16扩展单元
数据选择器主要用于根据控制信号,来选择对应的数据端输入,在本次设计中用到5处数据选择器。
1.写入寄存器地址的数据选择器:根据MemSel[2…0]信号判断写入寄存器的数据是来自于ALU或是存储器或是经扩展16位立即数或是0:MemSel信号和对应的数据来源如下:
采用8选3数据选择器,具体设计如下图所示。
图11 寄存器堆多路写选择器
2.写入寄存器的地址数据选择器:根据RegDst信号确定写入寄存器的地址是来自于指令数据的[5-3]位或[8-6]或(base)+offset(result[2…0])。如下图所示。
图12 寄存器堆多路读选择器
3.PC数据选择器:根据PCSel控制信号,判断PC计数器的下一条地址是来自于PC+1还是来自于的12位扩展16位目标地址或者BEQ跳转的地址。采用3选1数据选择器,具体设计如下图所示。
图13 下址跳转多路选择
4.ALU操作数B选择器:根据ALUSrcB控制信号确定ALU单元的输入B端的数据来源,主要用于LW指令中,判断存储器地址是由寄存器的1端和2端相加得到还是由寄存器的1端和指令后6位扩展成16位相加得到。如下图所示。
图14 ALU操作数B选择器
5.BEQ跳转地址数据选择器:根据ALU判断两数是否相等(相等为0,不相等为1)为信号,判断数据是PC+1还是PC与6位偏移地址扩展到16位后相加所得到的地址。如下图所示。
图15 BEQ跳转地址数据选择器
分析:对于CPU的计算结果,我们可以通过led7段数码管进行更加直观的输出,从而增加结果的可读性。分析可知,我们设计的CPU结果输出为16位二进制,而给定数码管为4位。
方案一,若考虑为十进制输出结果,则数码管最大表示9999,最小为0,总共可以显示10000个数字,而结果最大为二的十六次方,远大于数码管显示上限。在此种条件下,若搭建逻辑电路,则有两种方案:
第一种:对于0-9999的结果分别和四个数码管(28位),建立真值表对应关系,即得到我们的数码管驱动电路。显然,此种思路过于繁琐,工程量巨大。
第二种:将得到的二进制转换成四个四位的二进制数(表示一个十进制数),再将四个数分别显示在数码管上。此时,工作量大大减小,然而,二进制转8421BCD需要较大的计算量(如下所示),无法满足再时钟周期较快时的实时显示,所以以上两种方案均不具有可行性。
给定一个二进制数,要转BCD码。一个常用算法就是不断将该数除以10,以此依次分解出个位、十位、百位……上的数字,这些数字的4位二进制数就是对应的BCD。但是这样的算法需要不断做除法操作十分的麻烦。我们可以使用加三左移法来完成。
这个算法基于以下的事实:
一个数乘以2,相当于其二进制左移1位 两个BCD码相加,如果结果大于9,需要加上6作为修正
四位二进制大于15才进位,而8421BCD码是大于9就进位,若四位二进制大于9时进位,这样得到的就是15的BCD码,因此将大于9的四位二进制数加6就能得到其BCD码。对于大于四位的二进制数,通过左移,逢9加6进位,即可转换任意位的二进制数,比如说,对于5位二进制数,由高4位二进制数左移一位得到,那么将前4位得到的BCD码也左移一位,并重新判断低四位是否大于9,若大于9,则加6进位,即可得5位二进制数对应的BCD码。
加3移位法相比与加6移位法在算法上的结果是等效的,但占用的资源更小,相比于加6移位法先移位,再判断低4位是否大于9,加3移位法是先判断低四位是否大于4,再进行移位。
图13 二进制转BCD码逻辑电路实现
可行方案分析:四个数码管,16位输出结果,我们可以自然而然地想到每个数码管对应四位输出,即十六进制输出(0-F),在此种考虑下,我们可以通过建立四位二进制与数码管的对应输出的真值表来搭建逻辑电路。然而,难点在于7段数码管显示时,无法对B和8,D和0进行有效区分。幸运的是,给定的开发板提供了小数点位,因此我们可以利用该位对字母和数字进行区分。分析可得7段数码管和四位二进制的对应真值表如下:
根据以上真值表可以得到逻辑电路图如下
图15 数码管驱动电路
由得到的驱动电路接入计算所得结果,即可在开发板上显示输出结果。
五、测试结果及分析
为了测试我们设计的CPU的扩展性,我们设计了两套测试方案,并提前给定译码,分别对CPU进行测试.
第一套方案:
说明: 第一套方案可以执行基本的运算与存取操作,可以初步证明该CPU具有基本的运算能力。
MovN ax,5 0000 000 000 000 101
MovN bx,3 0000 000 001 000 011
Add ax,bx,cx 0010 000 001 010 000
MovR cx,dx 0001 000 010 011 000
AddN dx,2 0011 011 000 000 010
Clear cx 0110 000 000 010 000
Sub dx,cx,temp 0100 011 010 101 000
Store temp 1001 000 101 000 010
Load temp 1000 000 111 000 010
Jmp start 0111 000 000 000 001
第二套方案:
说明: 第二套方案可以实现如循环,判断这样的更加高级的逻辑结构。
编号 内存地址 伪代码 内存存放的值
A 000001 MovN temp,50 0000 000 101 110 010
B 000010 MovN cx,1 0000 000 010 000 001
C 000011 Clear Ax 0110 000 000 000 000
D 000100 Add ax,cx,ax 0010 000 010 000 000
E 000101 AddN cx,1 0011 000 010 000 001
F 000110 BEQ D 1010 010 101 000 100
模块初始值
初始值为指令编译后的01串,两套方案都以mif的格式存在rom寄存器中。
本次实验实现了基本16位单周期CPU的基本功能,但和现代处理器的复杂架构相距甚远。但是在本质上,所有的CPU都可以看成是一个复杂的有限状态自动机。经过操作系统的封装,程序员是无法看到底层的运行情况,但是在特殊情况时,如某些程序需要debug时,了解底层的寄存器情况是非常有必要的。程序的每一次单步执行都会对寄存器的状态造成改变。而引入系统调用时情况则会更加地复杂,因此合理的使用工具如GDB等工具能够让我们更快的找到bug。
当我们的硬件模拟在开发板上成功运行时,不禁让人陷入思考。我们开发用的软件非国产,硬件亦是由进口的FPGA组装的芯片制造。这大概就是中国至今陷入无芯可用的困境的原因吧。尽管知道实际芯片开发过程中,面临的困境远非我们设计CPU时所遇到的可以相提并论的。但是这确实是一个有待解决的问题,当核心技术无法突破,就会导致很多电子设备的成本居高不下,这是需要我们思考和解决的问题。
参考文献 [1] 钱江波. 短学期指导. 宁波大学实验手册,2016/09/10 [2]