32位MIPS单周期CPU设计

参考实验书目:《数字设计和计算机体系结构》机械工业出版社,7章

实验平台:vivado

语言:system verilog

一、实验信息

     略...咱的专业课实验报告

二、实验内容

(一)设计原理及实验方案

总体设计思路:

将微体系结构分为两个部分:数据路径和控制。数据路径对数据字进行操作。控制单元从数据路径接收当前指令,并控制数据路径如何执行指令。前者包含存储器,寄存器,ALU和复用器等结构,本次实验设计32位的处理器,因此应采用32位数据路径。后者根据指令需求产生各种使能信号来控制寄存器写,存储器写,复用器数据选择等功能。

设计+实验流程:

1.基础部分(只涉及到教材所提及的指令)

  • 确定MIPS处理器的状态元件,再基于当前状态在状态元件之间增加组合逻辑计算新的状态。在本次实验中,共涉及到4个状态元件:                                                                                 
  • 1)程序计数器:输入计算的新的PC,输出为当前PC,每个PC指向对应的指令。           
  • 2)寄存器文件:以instr的rs,rt字段(如果有的话)为地址,读数据;写入数据。               
  • 3)指令存储器:输入PC取指令instr。                                                                                 
  • 4)数据存储器:以ALU的计算结果为地值取数据或者存数据,lw或者sw,取数据会加载到寄存器,存数据时数据来源于rt字段从寄存器中读取的数据。
  • 处理器的动作取决于取出的具体指令。
  • 从具体指令出发,构造数据路径连接,逐步引入电路元件,当遇到需要共用数据通路时(如寄存器写入时数据来源,ALU计算时的srcB来源等),增加复用器和选择信号。
  • 完成一条指令的数据通路后,逐步泛化,在已完成的数据通路上增加连接,引入复用器和其他元件,完成其他指令的数据路径扩展,当lw,sw,R类型,beq,addi,j指令的数据通路都完成后,所有数据路径板块设计完毕。
  • 接着整理电路中引入的使能信号(包括寄存器文件,数据存储器的写信号,各个复用器的选择信号,ALU模块执行运算的选择信号),开始完善控制板块。
  • 因为指令的不同导致处理器的动作不同,故指令为控制单元的输入信号。本实验中指令的高6位Opcode以及低6位Funct决定指令的功能类型,因此决定各信号的值。在控制单元的设计中,将其分为主译码器和ALU译码器,Opcode作为主译码器的输入信号,计算大部分控制信号,如memtoreg, memwrite, branch, alusrc, regdst, regwrite, jump等,同时产生一个信号aluop(位数取决于指令数,在基础部分时该信号为2位,扩展andi,ori,bne指令后,该信号扩展成3位),该信号与Funct信号一起输入ALU译码器,决定alucontrol的值,控制alu模块的运算类型。
  • 根据以上分析做出主译码器和ALU译码器的真值表。

主译码器真值表:

32位MIPS单周期CPU设计_第1张图片

ALU译码器真值表:

32位MIPS单周期CPU设计_第2张图片

  • 结合上述流程中做出的最终原理图和完成的两个译码器的真值表,编写system verilog代码,并加入仿真测试文件testbench.sv以及指令文件memfile.txt做仿真测试,观察仿真结果。

基础部分处理器原理图:

32位MIPS单周期CPU设计_第3张图片

2.扩展部分(增加andi,ori,bne指令)

  • 在基础部分设计的的CPU基础上,从指令出发,根据增加的指令,扩展数据通路,增加需要的元件和信号。
  • 扩展指令功能分析:bne: 条件跳转指令,与beq跳转条件相反,若指令instr的rs字段在寄存器中读取的数据和rt字段读取的数据不相等(Zero为两信号是否相等的标志,zero==1表示读取数据相等,0表示不等),则PC’=(PC)+4+(4*符号扩展后的立即数(即偏移量)。andi:将rs字段对应数据与经过零扩展的立即数做逻辑与运算,得到的值储存到rt指向的寄存器里。ori(或运算),xori(异或运算)的功能类似。
  • 扩展指令的具体实现:
    1. bne部分,考虑增加一个复用器,复用器选择信号zeroselect,当zeroselect值为1时选择输入zero,表示prcsrc=branch&zero,进行beq条件判断;当zeroselect值为0时,选择输入(~zero),表示prcsrc=branch&~zero,进行bne条件判断。zero值为1表示指令取出的两个数据值相等,zero值为0则表示不相等。
    2. andi部分,需要增加一个复用器,复用器选择信号immselect来选择signimm或者zeroimm,值为1表示选择符号扩展立即数进入接下来alusrc的选择,值为0表示选择零扩展立即数进入接下来alusrc的选择。考虑到此复用器关系到进入ALU运算的srcB的来源(rt字段取数or符号扩展立即数or零扩展立即数),所以alusrc==1(选择立即数作为srcb)的指令,需要明确给出immselect的值,如lw,sw,addi等,immselect=1;而andi,ori指令对应的immselect==0。
    3. ori部分,因为已经在扩展andi指令时完成了数据路径的扩展,所以只需在addi的基础上,将对应真值表中aluop定为100,使srca和srcb在ALU模块里的运算变成按位或。
  • 整理新增控制信号,扩展主译码器和ALU译码器真值表。因为扩展指令后需要的aluop数超过4(加,减,与,或,R类),所以aluop变量更改为三位向量。扩展后的两真值表如下图所示。

主译码器真值表:

指令

opcode

regwrite

regdst

alusrc

branch

memwrite

memtoreg

aluop

jump

zeroselect

immselect

R类型

000000

1

1

0

0

0

0

010

0

x

x

lw

100011

1

0

1

0

0

1

000

0

x

1

sw

101011

0

x

1

0

1

x

000

0

x

1

beq

00100

0

x

0

1

0

x

001

0

1

x

addi

001000

1

0

1

0

0

0

000

0

x

1

j

000010

0

x

x

x

0

x

xxx

1

x

x

bne

000101

0

x

0

1

0

x

001

0

0

X

andi

001100

1

0

1

0

0

0

011

0

x

0

ori

001101

1

0

1

0

0

0

100

0

x

0

 

ALU译码器真值表:

aluop

funct

alucontrol

000

X

010(加)

001

X

110(减)

010

100000

010(加)

010

100010

110(减)

010

100100

000(与)

010

100101

001(或)

010

101010

111(小于置位)

011

x

000(与)

100

x

001(或)

  • 根据扩展后的原理图和真值表,修改system Verilog代码,指令文件等,重新进行仿真测试,观察仿真结果。

        扩展指令后的原理图:

32位MIPS单周期CPU设计_第4张图片

     3.增加I/O接口准备上板部分

         将dmem扩展成DataMemoryDecoder,该模块包括数据存储器(dmem)、I/O接口,7段数码管三个子模块,其原理图如下。

32位MIPS单周期CPU设计_第5张图片

    • 从主译码器中output出的Write值与数据地址的第八位共同决定目前的writedata写入数据存储器还是I/O接口部分,当Write值为1时,若addr[7]==1,则pWrite=1;若addr[7]==0,则WE=1,可以将writedata存入数据存储器。因为七段数码管需要显示十六进制数,每组数码管的显示值由四位二进制数决定,实验开发板上开关为16位,决定输入的两个两位十六进制数,另外增加一个12位的变量led,决定加法运算得出的结果——一个三位十六进制,数码管上等号的实现不需要动态变化,直接在代码中为数码管赋相应值即可。因为要将开关输入的两个十六进制数相加并且输出结果到七段数码管的操作,所以增加将mips处理后output的writedata写入I/O接口的路径。当pWrite==1时,若addr[3:2]为01,则将经过alu加法计算得到的writedata值写入I/O中的led变量,根据led的真值(三组0/1串)给对应的数码管赋值。
    • 数据地址的第八位addr[7]映射到I/O接口的pRead端口,表示当addr[7]==1时,如下图所示,根据具体内存位置00,10,11,来决定pReadData的内容是状态端口(Switchcheck和ledcheck,是否准备好输入数据和输出数据)或者Switch端口低位值或者Switch端口高位值,数据读入到pReadData后,经addr[7]作为使能信号的复用器传输到mips处理器的readdata处,然后进行lw操作存值到寄存器,进行条件判断或者加法运算。
    • 此外,I/O接口部分有从top文件映射过来的Switch,ButtonL(决定status[0]的值,led输出是否已准备就绪),ButtonR(决定status[1]的值,switch值读入是否已准备就绪),reset(ButtonC,清零信号)。
    • I/O接口部分的led端口值为用拼接符赋值的32位变量,从高位到低位每四位一组,决定一组数码管的显示值。该端口映射到7段数码管的digit端口。
    • 7段数码管的分时显示:用时钟分频得到的三位向量和case语句选择0~7编号的各个数码管和该数码管显示的十六进制数,因为遍历8个数码管的周期很小,所以在人眼看来是同时显示了各个数码管的值,即显示出两个两位十六进制数相加得到一个三位十六进制数的结果的等式
    • 更改top文件端口和调用模块(将对dmem 的调用改为对DatamemoryDecoder的调 用),  加入引脚约束文件,将指令文件加入design source和simulation source,前者用于生成bitstream文件上板验证,后者用于vivado内的仿真。
    • 对于仿真文件,首先logic定义top文件中的端口值,然后实例化top文件,然后对top文件中input端口对应的变量做初始化(initial)。时钟设置为100MHZ。做清零操作并输出:ButtonC先设置为1,一段时间后设置为0,ButtonL设置为1一段时间后又设置为0。输入Switch的值4’h1234。将输入输出状态调整为准备就绪:ButtonL和ButtonR的值赋为1。仿真文件写好后,进行仿真操作,调整并观察波形,查看AN,和A2G的值是否与预期相符合。
    • 上板验证时,将生成的bit文件下载到实验开发板上,按顺序进行清零,输入数据,读入数据,输出数据操作。更改输入的数据多次验证,可得到不同的2位十六进制数相加的等式和正确结果。

(二)实验结果及分析

  1. 关键代码分析

(1)在基础verilog代码上根据需要扩展代码而发生改动的局部代码。

1)maindec

32位MIPS单周期CPU设计_第6张图片

因为增加了zeroselect,immselect以及aluop从2位扩展成3位,controls更改位12位向量。根据真值表在case语句中,增加了bne,andi,ori对应的controls值,同时对其他指令的controls值做了修改。

2)aludec

32位MIPS单周期CPU设计_第7张图片

因为aluop的变为3位,所以aludec的case语句中各条件值也做了变化,新增011和100令alucontrol赋值为与运算、或运算的信号值。

3)增加零扩展模块

32位MIPS单周期CPU设计_第8张图片

令扩展时,高位直接补零,将16位立即数扩展称32位,用于andi和ori运算。

4)datapath中增加选择扩展后进入alu运算的立即数类型的复用器。

32位MIPS单周期CPU设计_第9张图片

immselect选择immsrc,immsrc参与srcb的选择。

5)controller中增加选择beq或者bne的zerosrc的语句。

在controller中选择条件跳转的信号来源zerosrc,zero表示beq条件;opzero=~zero,表示bne条件。

(2)最终代码整体分析

1)top.sv

32位MIPS单周期CPU设计_第10张图片

增加了IO设备后的top文件端口发生了变化,输入和输出与实验开发板的开关,按钮,7段数码管联系起来。

增加DataMemoryDecoder模块,该模块包含数据存储器,I/O接口,7段数码管3个子模块。

2)mips

包含controller和datapath模块,controller模块包含主译码器,alu译码器模块,datapath包含原理图中的各个功能模块,controller中的译码器代码因为真值表的变化而产生一些变化,aluop变成3位向量,以及增加immselect信号,从controller输出,输入datapath,datapath中增加了零扩展模块和立即数选择模块。

3)imem

32位MIPS单周期CPU设计_第11张图片

指令存储器,根据pc读取memfile.dat中的指令,因为指令文件添加到了项目中,所以读取时采用相对路径。

4)DataMemoryDecoder

包含dmem,IO,mux7seg模块。

dmem模块根据we和rd信号进行存数、取数操作。

32位MIPS单周期CPU设计_第12张图片

IO模块,switchl用于接收从switch端口输入的信号,并在pRead==1时,内存地址正确时将开关输入的数据经过pReadData进入mips处理器;ledl用于在pWrite==1时,内存地址正确时,接收开关输入数据经mips处理的结果writedata。并且在ButtonL==1时,即输出就绪时,将ledl中暂存的结果输出到led端口,output到DataMemoryDecoder,与switch一起组成32位digit输入到7段数码管模块;status用于储存目前状态,当按下ButtonR时status[1]=1,表示准备读入开关数据,当按下ButtonL时status[0]=1,表示准备输出运算结果。

32位MIPS单周期CPU设计_第13张图片

 32位MIPS单周期CPU设计_第14张图片

7段数码管模块

利用时钟产生一个3位向量s用于选择数码管。

选择亮起的数码管后,同时用s选择对应该数码管应该显示的值digit2

根据digit2的值选择数码管的A2G值,注意到当digit2值为0000时使用if else语句做出判断,这是因为digit输入mux7seg时,应该显示等号的数码管对应的digit值为0000,所以对digit2=0000时应该显示“0”或者“=”做出了判断。

32位MIPS单周期CPU设计_第15张图片

32位MIPS单周期CPU设计_第16张图片

32位MIPS单周期CPU设计_第17张图片

 32位MIPS单周期CPU设计_第18张图片

仿真testbench

32位MIPS单周期CPU设计_第19张图片

2. 仿真结果         

   1)基础部分

根据教材给出的测试文件和指令集,对具有R类型、lw,sw、beq、addi、j指令的单周期CPU代码进行测试,得到仿真结果如下,说明该CPU各项功能正常。

32位MIPS单周期CPU设计_第20张图片

 2)扩展指令后

32位MIPS单周期CPU设计_第21张图片

扩展andi,ori,bne指令后,进行仿真验证3个指令的功能,由仿真结果可知,三个指令的功能正常。

3)增加IO设计后

32位MIPS单周期CPU设计_第22张图片

仿真时钟自定为100MHZ,每隔约1.3ms选择数码管的信号count一次。仿真开始时,设置了10ns的清零操作和输出操作此后输入信号与输出信号一直保持为1,switch信号设置为4’h1234,可通过AN和A2G信号的仿真波形看出,各个数码管依次显示1234=046。仿真成功。

3.实验开发板

  1. 上板清零     

 32位MIPS单周期CPU设计_第23张图片

      2.实现12+34=046

32位MIPS单周期CPU设计_第24张图片

  1. 其他十六进制数相加的验证

32位MIPS单周期CPU设计_第25张图片

  • 实验中的问题分析总结
  1. 添加memfile.dat时的问题

在仿真和最后实验上板的时候都出现了无法读入指令的情况,经过探索与实践,得到的解决办法是在design source和simulation source中都添加memfile.dat文件,前者用于生成.bit文件,后者用于vivado内的仿真。且用于生成bit文件的指令文件需要为.dat格式而非.txt格式。

     2.调试代码

根据仿真结果判断仿真是否正确时,可以加入内部变量的波形,如pc,instr等,根据pc地址和指令逐步分析,查漏补缺。

另外判断其他部分代码是否正确可以通过vivado中的open elaborated design查看电路图,比对设计时理想的电路图排除错误。

你可能感兴趣的:(计算机组成实验,fpga开发,硬件架构)