数字逻辑与处理器基础实验
32位MIPS CPU设计
综述:
我们的最后验收结果时钟频率是84.9MHz。
本实验报告主要分为实验设计说明与实验收获总结两个部分。 附件中有CPU工程文档与模块代码。
第一部分 实验设计
一、 ALU设计
1、设计思路
实现基本的算术、逻辑、关系、位与移位运算,尽量优化以达到最小的面积延时积。 结构图如下:
主要设计思想:
A. 加法运算实现可以采用逐次进位、超前进位等结构,减法可以通过加法实现(参见见面理论课讲义或者前面实验);同时输出Z(结果为零)、V(结果溢出)、N(结果为
负)等标志位,注意有符号数和无符号数标志产生的不同。
B. 比较运算根据减法运算的结果(Z/V/N)产生,自行分析比较操作与算术运算之间的关系。
C. 移位运算可以考虑将移位操作拆分为16 位移位、8 位移位、4 位移位、2 位移位、1位移位等几个子运算的组合,然后级联形成最后的运算结果。 D. 逻辑运算可以根据要求直接产生。
功能表
接口说明 名称 类型 描述 A[31:0] B[31:0] ALUFun[5:0] Sign S[31:0]
输入 输入 输入 输入 输出 操作数1 操作数2 功能码 符号:有符号1,无符号0 结果输出 2、主要模块
a) 32bit加法器
采用8个4bit超前进位加法器极连的方式,构成32bit加法器。对于逸出位v的处理如下:由有符号数的性质可知,对最高位32和次高位31位取抑或,输出信号则为是否逸出。对32位运算结果取反后,再对相邻两位反复取与,最终得到结果是否为零的输出z.如果是有符号数,则符号位=n。
由于这一方法部分程度上减弱了高位计算对低位计算的依赖程度,因此可以实现延时的降低。同时,由于其超前进位网络的大量逻辑运算,较大程度上提升了电路的面积,造成最终的面积延时积特性恶化。 关键代码见附录1
b) 32bit减法器
对加法器按位取反,再加一。 关键代码见附录1
c) 32bit 右移 32bit 左移 32bit 算术右移
将移位操作拆分为16 位移位、8 位移位、4 位移位、2 位移位、1位移位等几个子运算的组合,然后级联得到最后的运算结果。 关键代码见附录1
d) 32bit 逻辑比较单元
采用行为级语句直实现逻辑比较功能。 关键代码见附录1
e) ALU顶层控制模块
用多路选择器实现对输出结果的控制,采用行为级语句实现设计。
附加说明:对于无符号运算的结果,由于z,v,n已经将符号的作用考虑进去,因此,对于需要实现的六个指令,仅有A<B需要特殊处理,而其他指令对于无符号数和有符号数的结果一致。因此,针对A<B指令,添加针对无符号数的专用比较电路,并使用与超前进位加法器类似的方式进行并行加速操作。 关键代码见附录1
二、单周期MIPS处理器设计
流程框图:
1、 中间参数说明 1) ILLOP=0x80000004,为发生中断时,中断处理程序的PC地址,处于内核态。 2) XADR=0x80000008,为发生异常时,异常处理程序的PC地址,处于内核态。 3) Xp=26,为ILLOP与XADR中中断/异常处理程序调用,用来存储返回地址,即发生
异常/中断的PC值。
4) Ra=31,为返回值存储器,应用于jr,jalr指令,跳转到寄存器中所存的PC地址。 5) Instruction截取部分:
a) 寄存器:Rs=Ins[25:21];Rt=Ins[20:16];Rd=Ins[15:11]; b) Shamt=Ins[10:6]应用于sll,srl,sra三条指令
c) Imm/Offset=Ins[15:0]应用于lw,sw,lui,addi,addiu,andi,slti,sltiu,
beq,bne,blez,bgtz,bgez这些I型指令
d) JT,应用于j型指令j与jal,JT=Ins[25:0]<<2(框图中未左移有误),保存跳转地
址,由于地址为32位,JT仅28位,由本题地址特殊性高位接4’b0000,表示在外部。
6) ConBA为条件分支跳转地址,ConBA=PC+4+Offset<<2。
2、 控制信号说明 1) PCSrc,3位,6种有效取值。
PCSrc PC更新值 000(缺省) 001 PC+4 分支见2 010 JT 011 DatabusA 100 ILLOP 101 XADR 详细说明:
000时为默认PC更新为PC+4,应用于不需要跳转的各条指令。
001时进入条件分支,满足条件PC=ConBA,不满足时PC=PC+4,应用于各种branch指令。
010时PC更新为无条件跳转地址,PC=JT,应用于j,jal指令。 011时PC更新为寄存器跳转,PC=$Ra,应用于jr,jalr指令。 100,101分别为中断与异常时的跳转地址。
2) ALUout[0],1位信号(是否跳转判断)
Zero 0(缺省) 1 ConBA 条件分支PC更新 PC+4 0时不满足分支条件(branch下ALU输出为0),1时满足分支条件。
3) RegDst信号,控制寄存器堆写入地址
RegDst AddrC 00 Rd 01 Rt 10 Ra 11 Xp 详细说明:
00时写入Rd,应用于所有R型指令,唯一例外jr指令,R型指令不需要写入,令
写入$0即可。其中jalr与10中一种情况冲突,处理见10中说明。
01时写入Rt,应用于部分需要写入的I型指令(配合RegWr=1)有lw,lui,addi,addiu,andi,slti,sltiu,以及部分不需要写入的I型指令(配合RegWr=0)有sw,beq,bne,blez,bgtz,bgez。 10时写入ra,应用于跳转链接指令jal
11时写入Xp,应用于异常/中断时,写入异常/中断处的最终执行完的下条指令
4) RegWr,1位信号,寄存器堆写入使能信号,1时可写,缺省0不写入
R型指令(jr时配合rd写入到$0不影响),需写入的I型指令lw,lui,addi,addiu,andi,slti,sltiu,需写入的j型指令jal(jalr使用R型指令方法写入)。
5) ALUSrc1,1位信号,ALU第一操作数选择控制信号。
ALUSrc1 ALU第一操作数 0 DataBus A 1 shamt 详细说明:
0时第一操作数来自寄存器应用于所有非偏移操作
1时第一操作数来自R型中shamt部分,应用于偏移操作sll,srl,sra
6) ALUSrc2,1位信号,ALU第二操作数选择控制信号。
ALUSrc2 ALU第二操作数 0 DataBus B 1 Imm/Offset操作结果 详细说明:
0时第二操作数来自寄存器,应用于所有R型指令与J型指令(无效操作) 1时第一操作数来自I型中Imm部分的某种计算结果,应用于I型指令,另有EXTop与LUop两个某种计算的控制信号配合操作。
7) EXTop,扩展方式选择信号
EXTop 扩展方式 0(缺省) 无符号扩展 1 有符号扩展 详细说明:
0时对Imm/Offset无符号扩展,应用于unsigned的I型指令,addiu,sltiu 1时对Imm/Offset有符号扩展,应用于非unsigned的I型指令
8) LUop,Imm计算方式选择控制信号
EXTop 输出结果 0(缺省) 用之前扩展结果 1 取立即数高位 详细说明:
0时将Imm扩展结果作为ALUSrc2选择输入中的一路。
1时取立即数高16位与16位0拼接作为ALUSrc2选择输入中的一路,应用于lui指令。
9) ALUFun,6位控制信号,控制ALU计算功能
类型 算式 位运算 功能 ADD SUB AND OR XOR NOR “A” 移位运算 SLL SRL SRA 关系运算 EQ NEQ LT LEZ GEZ GTZ ALUFun 000000 000001 011000 011110 010110 010001 011010 100000 100001 100011 110011 110001 1101101 111101 111001 111111 描述 S=A+B S=A-B S=A&B S=A|B S=A^B S=~( A^B) S=A S=B<>A[4:0] S=B<=0) S=1 else S=0 If(A>0) S=1 else S=0 10) Sign,ALU运算是否有符号运算控制说明
Sign 计算方式 0(缺省) 无符号计算 1 有符号计算 详细说明:
0时ALU进行无符号计算,应用于unsigned计算addu,subu,addiu,sltiu 1时ALU进行有符号计算,应用于正常有符号运算除了上述4种指令之外的计算指令。
11) MemRd,读取内存控制信号
MemRd 结果 0(缺省) 不读取,ReadData输出全0 1 读取内存,ReadData输出为该地址内容 1时应用于需要读取内存的指令lw
12) MemWr,写入内存控制信号
MemWr 结果 0(缺省) 不写入,ReadData输出全0 1 写入内存,将输入内容写入输入地址 1时应用于需要写入内存的指令sw
13) MemToReg,2位控制信号,3个有效输入
MemToReg 输出 00 ALUOut 01 ReadData 10 PC+4 详细说明:
00时为应用于R型指令以及不需要读取内存且需要写入内存的I型指令 01时应用于将内存中读取内容写入寄存器的指令lw
10时应用于需要将PC值写入到寄存器的指令jal,jalr,以及中断或异常时将PC写入Xp的操作。
3、 编译程序的设计 为了方便地将汇编语言转换成机器语言,进而写入rom模块中变成一条条指令,送至处理器处理,我们利用C++语言编写了一个小程序,用于实现上述的功能。
程序设计的思路就是实现一种解释的功能,能够逐句地按照MIPS指令的格式规则将汇编语言解释成机器语言。所以,读入指令后,提取出指令里的关键字,按照(见附件,指令集.xlsx)指令集中的规则,对应翻译即可。
程序的核心函数是translation函数,输入是指令字符串,输出是机器码结构体(结构体中是指令的op,rs,rt,rd,shamt,funct,imm,target值)。该函数首先逐字符地检测指令,将指令名称读出,进而以$为标志,读出对应寄存器名称,对数字进行拼数处理,也存储下来。接下来根据读出的指令,确定对应的机器码值,分别赋给上述结构体中即可。
另外,程序利用文件处理的方法,输入指令可以复制到input.txt中,输出到output.txt中,方便存储和之后的利用。
为了将转换好的机器语言复制到rom模块中,需要对每一串二进制数进行格式处理,这里有一个小程序用于格式处理。处理成如下的格式
0: data <= 32'b00111100000000011000000000000000;//lui $at,0x8000
程序代码见附件(Assembler.cpp,Try.cpp)。
4、 计算最大公约数汇编程序的设计 计算最大公约数,这里采用辗转相减法。即给定两个数s1和s2,用较大的数减去较小的数得到的结果赋值给之前较大的那个数,重复做这件事,直到s1和s2中至少出现了一个0为止,这样,此时s1和s2的和就是要求的最大公约数。
例如,s1=8,s2=12,第一次相减得到s2=4,s1=8,第二次相减得到s1=4,s2=4,第三次相减得到s1=0,s2=4,发现s1=0,停止做,最大公约数就是s1+s2=4。
利用这种方法也可以计算两个数中有一个数为0的情况。这里不举例,经过验证是正确的。
为了使处理器工作正常,在执行计算最大公约数程序之前,应该完成必要的前期处理。具体包括,设置定时器的初始值和相关参数(TH,TL,TCON),设置中断程序的入口和计算最大公约数的入口等。这样,完成了前期准备就可以计算最大公约数,并且在计算完最大公约数之后继续跳转会计算最大公约数的第一条语句,重复执行,而前期准备的指令不再执
行。这样,等待定时器计数达到要求,中断信号到来,进入中断程序。
中断程序里完成对最大公约数的数码管显示。这里,显示用软件实现,即将显示的代码提前设计好,写入rom模块中。将计算的结果和0~15之间的数字依次对比,如果相等,则给数码管赋予相应的值,使其显示。对于两位数,依次显示数码管的十位和个位,并利用系统时钟的高频性实现数码管的显示。
执行完中断程序之后,继续跳转到之前进入中断时语句的下一条语句,继续计算最大公约数,等待下一次中断的来临。这样,只要reset信号一直是高电平,就可以根据switch的变化实时地显示出对应的结果,实现自刷新的功能。
具体代码见附件(rom.v)
3、多周期MIPS处理器设计
流程框图(流程图较大,故分模块画) IFPCtemp_IFPCSrcALUOut_EX[0]PCWrite+400ConBA_EX1{PC[31:28,JT_EX,00]}RegjumpILLOPXADRBranch12345PCwaitingPCDFFPCInstructionMemorgIn_IFInstructionMemorgJT_IF[15:0]Imm16_IF[10:6]Shamt_IF[15:11]Rd_IF[20:16]Rt_IF[25:21]Rs_IFPCSrc_IFRegDst_IFRegWr_IFALUSrc1_IFALUSrc2_IFEXTop_IFLUop_IFSign_IFMemRd_IFMemWr_IFALUFun_IFMemToReg_IF[25:0]IF/IDPCtemp_IFIn_IDJT_IDImm16_IDShamt_IDRd_IDRt_IDRs_IDPCSrc_IDRegDst_IDRegWr_IDALUSrc1_IDALUSrc2_IDEXTop_IDLUop_IDSign_IDMemRd_IDMemWr_IDALUFun_IDMemToReg_IDDataBusA_EXDataBusCDataBusC_MEM012ForwardCRegjumpIDstall
IDXpRaRt_IDRd_IDRt_IDRegDst_IDRs_IDALUSrc1_ID3210AddrBAddrAShamt_IDDataBusA_IDAddrC_IDRegWr_WBWrC10num1_IDRead Data ARegister FileDataBusCWrite Data CWrCRead Data BDataBusB_ID01num2_ID{Imm16_ID,16'b0}Imm16_ID1EXT32Imm32_IDImm_IDALUSrc2_ID0Pctemp_IDImm32_IDRd_IDRt_IDRs_IDPCSrc_IDAddC_IDJT_IDRegWr_IDSign_IDMemRd_IDMemWr_IDALUFun_IDMemToReg_IDnum1_IDnum2_IDDataBusA_IDDataBusB_IDALUSrc1_IDALUSrc2_IDID/EXPctemp_EXImm32_EXRd_EXRt_EXRs_EXPCSrc_EXAddC_EXJT_EXRegWr_EXSign_EXMemRd_EXMemWr_EXALUFun_EXMemToReg_EXnum1_EXnum2_EXDataBusA_EXDataBusB_EXALUSrc1_EXALUSrc2_EXEXTop_IDLUop_IDEXstall
EXForwardAALUFun_EXnum1_EXDataBusCDataBusC_MEMDataBusB_EXDataBusCDataBusC_MEM012PCtemp_EXForwardDPCSrc_EXAddrC_EXRegWr_EXPCtemp_MEMPCSrc_MEMAddrC_MEMRegWr_MEMstore012ALUnum1Sign_EXALUnum2_EXDataBusCDataBusC_MEMALUOut_EXMemRd_EXMemWr_EXMemToReg_EXALUOut_EX012ALUnum2EX/MEMMemRd_MEMMemWr_MEMMemToReg_MEMALUOut_MEMDataBusA_MEMDataBusB_MEMDataBusA_EXForwardBstorePCtemp_EXImm32_EXShift Left 2bitsOffset_EX+ConBA_EXMEMstall
MEMALUOut_MEMAddrDataReadMemorgDataDataBusB_MEMWriteDataReadData_MEMAddrC_MEMRegWr_MEMMemToReg_MEMALUOut_MEMReadData_MEMAddrC_WBPCtemp_MEMPCtemp_WBWBALUOut_WBReadData_WBPctemp_WB012MemToReg_WBDataBusCMEM/WBRegWr_WBMemToReg_WBALUOut_WBReadData_WBMemRd_MEMMemWr_MEMPCSrcALUOut_MEMReadData_MEMPctemp_MEM0PCWrite12DataBusC_MEMIDstallEXstallMemToReg_MEMRed ColourRiskMEMstallForwardAForwardBForwardCForwardD 1、 系统综述 流水线分5个阶段完成IF,ID,EX,MEM,WB。
Branch与跳转在EX阶段判断并且执行,并且有必要时清空ID与IF 中断与异常在IF阶段判断 流程说明:
0. reset->0x80000000(控制信号使维持该地址,该地址中存储跳转到0的jalr指令) 1. reset=1之后在clk上升沿
(1) 定时器操作,写入TH,TL,TCON
(2) 读取操作数并且计算最大公约数写入结果寄存器 (3) 遇到中断操作:
A. TCON&=0xfffffff9停止计数 B. 利用七段数码管显示结果
C. TCON|=0x00000002重新开始计数
D. jalr Xp
2、 中间参数说明 1) ILLOP=0x80000004,为发生中断时,中断处理程序的PC地址,处于内核态。 2) XADR=0x80000008,为发生异常时,异常处理程序的PC地址,处于内核态。 3) Xp=26,为ILLOP与XADR中中断/异常处理程序调用,用来存储返回地址,即发生异
常/中断的PC值。
4) Ra=31,为返回值存储器,应用于jr,jalr指令,跳转到寄存器中所存的PC地址。 5) Instruction截取部分:
a) 寄存器:Rs=Ins[25:21];Rt=Ins[20:16];Rd=Ins[15:11]; b) Shamt=Ins[10:6]应用于sll,srl,sra三条指令
c) Imm16=Ins[15:0]应用于lw,sw,lui,addi,addiu,andi,slti,sltiu,beq,
bne,blez,bgtz,bgez这些I型指令
d) JT,应用于j型指令j与jal,JT=Ins[25:0]<<2,保存跳转地址,由于地址为32位,
JT仅28位,由本题地址特殊性高位接4’b0000,表示在外部。
6) ConBA为条件分支跳转地址,ConBA=PC+4+Offset<<2。
3、 控制信号说明(后缀表示该信号所处的阶段) 1) PCSrc,3位,6种有效取值。
PCSrc PC更新值 000(缺省) 001 PCtemp_IF 分支见2 010 JT_EX 011 Regjump 100 ILLOP 101 XADR 详细说明:
PCSrc生成于冒险控制单元
000时为默认PC更新为PCtemp_IF,即处于IF阶段的PC+4,应用于不需要跳转的各条指令。
001时进入条件分支,满足条件PC=ConBA_EX(在EX阶段计算为
PCtemp_EX<<2+Offset,如果跳转则清除IF,ID),不满足时PC=PCtemp_IF(考虑EX判断branch,ID,IF已经进入下两条指令,所以不跳转是应该进入IF的下一条指令),应用于各种branch指令。
010时PC更新为无条件跳转地址,PC=JT_EX(于EX阶段判断,清除IF,ID阶段指令),应用于j,jal指令。
011时PC更新为寄存器跳转,PC=Regjump(寄存器跳转值,详见冒险控制单元介绍),应用于jr,jalr指令。(于EX阶段判断) 100,101分别为中断与异常时的跳转地址。
2) ALUout_EX[0],1位信号(是否跳转判断)
Zero 0(缺省) 1 ConBA 条件分支PC更新 PCtemp_IF ALUout生成于EX阶段(不传递)
0时不满足分支条件(branch下ALU输出为0),1时满足分支条件。
3) RegDst信号,控制寄存器堆写入地址
RegDst AddrC 00 Rd 01 Rt 10 Ra 11 Xp 详细说明:
RegDst生成于控制信号产生模块,不传递
RegDst用来生成写入寄存器的地址AddrC,于ID阶段生成传递到WB阶段写入。 00时写入Rd,应用于所有R型指令,唯一例外jr指令,R型指令不需要写入,但是jr指令Rd段为5’b00000,即令写入为$0。
01时写入Rt,应用于部分需要写入的I型指令(配合RegWr=1)有lw,lui,addi,addiu,andi,slti,sltiu,以及部分不需要写入的I型指令(配合RegWr=0)有sw,
beq,bne,blez,bgtz,bgez。 10时写入ra,应用于跳转链接指令jal
11时写入Xp,应用于异常/中断时,写入异常/中断处的最终执行完的下条指令
4) RegWr,1位信号,寄存器堆写入使能信号,1时可写,缺省0不写入
RegWr生成于IF的控制信号生成模块,传递到WB阶段
R型指令(jr时配合rd写入到$0不影响),需写入的I型指令lw,lui,addi,addiu,andi,slti,sltiu,需写入的j型指令jal(jalr使用R型指令方法写入)。
5) ALUSrc1,1位信号,ALU第一操作数选择控制信号。(需在经过冒险控制多路选择器)
ALUSrc1 ALU第一操作数 0 DataBusA 1 shamt 详细说明:
ALUSrc1生成与IF的控制信号生成模块传递至EX阶段 0时第一操作数来自寄存器应用于所有非偏移操作
1时第一操作数来自R型中shamt部分,应用于偏移操作sll,srl,sra
6) ALUSrc2,1位信号,ALU第二操作数选择控制信号。(需在经过冒险控制多路选择器)
ALUSrc2 ALU第二操作数 0 DataBusB 1 Imm/Offset操作结果 详细说明:
ALUSrc2生成与IF的控制信号生成模块传递至EX阶段
0时第二操作数来自寄存器,应用于所有R型指令与J型指令(无效操作) 1时第二操作数来自I型中Imm部分的某种计算结果,应用于I型指令,另有EXTop与LUop两个某种计算的控制信号配合操作。
7) EXTop,扩展方式选择信号
EXTop 扩展方式 0(缺省) 无符号扩展 1 有符号扩展 详细说明:
EXTop生成于IF的控制信号生成模块传递至ID阶段
0时对Imm/Offset无符号扩展,应用于unsigned的I型指令,addiu,sltiu 1时对Imm/Offset有符号扩展,应用于非unsigned的I型指令
8) LUop,Imm计算方式选择控制信号
EXTop 输出结果 0(缺省) 用之前扩展结果 1 取立即数高位 详细说明:
LUop生成于IF的控制信号生成模块传递至ID阶段 0时将Imm扩展结果作为ALUSrc2选择输入中的一路。
1时取立即数高16位与16位0拼接作为ALUSrc2选择输入中的一路,应用于lui指令。
9) ALUFun,6位控制信号,控制ALU计算功能
类型 算式 位运算 功能 ADD SUB AND OR XOR NOR “A” 移位运算 SLL SRL SRA 关系运算 EQ NEQ LT LEZ GEZ GTZ ALUFun 000000 000001 011000 011110 010110 010001 011010 100000 100001 100011 110011 110001 1101101 111101 111001 111111 描述 S=A+B S=A-B S=A&B S=A|B S=A^B S=~( A^B) S=A S=B<>A[4:0] S=B<=0) S=1 else S=0 If(A>0) S=1 else S=0 ALUFun生成于IF的控制信号生成模块传递至EX阶段
10) Sign,ALU运算是否有符号运算控制说明
Sign 计算方式 0(缺省) 无符号计算 1 有符号计算 详细说明:
Sign生成于IF的控制信号生成模块传递至EX阶段
0时ALU进行无符号计算,应用于unsigned计算addu,subu,addiu,sltiu 1时ALU进行有符号计算,应用于正常有符号运算除了上述4种指令之外的计算指令。
11) MemRd,读取内存控制信号
MemRd 结果 0(缺省) 不读取,ReadData输出全0 1 读取内存,ReadData输出为该地址内容 MemRd生成于IF的控制信号生成模块传递至MEM阶段 1时应用于需要读取内存的指令lw
12) MemWr,写入内存控制信号
MemWr 结果 0(缺省) 不写入 1 写入内存,将输入内容写入输入地址 MemWr生成于IF的控制信号生成模块传递至MEM阶段 1时应用于需要写入内存的指令sw
13) MemToReg,2位控制信号,3个有效输入
MemToReg 输出 00 ALUOut 01 ReadData 10 PCtemp_所处阶段 详细说明:
MemToReg生成于IF的控制信号生成模块传递至WB阶段
00时为应用于R型指令以及不需要读取内存且需要写入内存的I型指令 01时应用于将内存中读取内容写入寄存器的指令lw
10时应用于需要将PC值写入到寄存器的指令jal,jalr,以及中断或异常时将PC
写入Xp的操作。
4、 冒险控制单元说明 ? 转发
主要判断MEM与WB阶段写入地址AddrC_MEM与AddrC_WB与EX阶段使用寄存器地址是否相同(且是否使用),决定是否转发。 (1) ALU第一操作数的转发,控制信号ForwardA
控制代码如下:
if(RegWr_MEM && (AddrC_MEM!=0) && (AddrC_MEM==Rs_EX) && (~ALUSrc1_EX)) ForwardA<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rs_EX && (~ALUSrc1_EX)) ForwardA<=2'b01; else ForwardA<=2'b00; 其中先要判断MEM与WB阶段写入的是否是$0寄存器(由于$0寄存器恒零不允许转发),然后判断先后判断MEM与WB阶段写入地址是否与Rs_EX相同并且ALUSrc1_EX是否为0(表示num1选择就是Rs中读取的内容),由于MEM的指令后运行,所以可能产生对于WB写入的覆盖,所以优先判断MEM阶段,均不符合情况ForwardA为00。
ForwardA ALUnum1 00 num1 01 DataBusC_WB 10 DataBusC_MEM (2) ALU第二操作数的转发,控制信号ForwardB
控制代码如下:
if(RegWr_MEM && (AddrC_MEM!=0) && (AddrC_MEM==Rt_EX) && (~ALUSrc2_EX)) ForwardB<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rt_EX && (~ALUSrc2_EX)) ForwardB<=2'b01; else ForwardB<=2'b00; 判断方式与ForwardA完全相同
ForwardB ALUnum2 00 num2 01 DataBusC_WB 10 DataBusC_MEM (3) 寄存器跳转地址的转发,控制信号ForwardC
控制代码如下:
if(RegWr_MEM && (AddrC_MEM!=0) && (AddrC_MEM==Rs_EX) && (~ALUSrc1_EX) && PCSrc_EX==3'b011) ForwardC<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rs_EX && (~ALUSrc1_EX) && PCSrc_EX==3'b011)//MEM?? ForwardC<=2'b01; else ForwardC<=2'b00; 寄存器跳转在EX阶段完成,目标是用寄存器中存储的地址更新PC,但是考虑到对于该寄存器可能在MEM与WB阶段进行写入寄存器,首先需要判断在EX阶段是否是寄存器跳转,主要利用PCSrc_EX==3'b011表明为寄存器跳转,然后判断是否需要转发。
ForwardC Regjump 00 num1 01 DataBusC_WB 10 DataBusC_MEM (4) sw中写入内存数据的转发,控制信号ForwardD
控制代码如下:
if(RegWr_MEM && (AddrC_MEM!=0) && (AddrC_MEM==Rt_EX) && (ALUSrc2_EX) && MemWr_EX==1'b1) ForwardD<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rt_EX && (ALUSrc2_EX) && MemWr_EX==1'b1) ForwardD<=2'b01; else ForwardD<=2'b00; 由于在单周期设计中MEM写入内容直接是DataBusB也就是某一寄存中存储内容,所以在流水线中就会产生数据冒险,所以需要对其进行转发,首先判断EX阶段是否为sw,只需判断MemWr和ALUSrc2是否为1与0即可,转发方式依然相同,形成存储内容store传递到MEM阶段写入
ForwardD store 00 DataBusB_EX 01 DataBusC_WB 10 DataBusC_MEM ? 分支/跳转的控制与PCSrc的生成
按优先度高到低说明 (1) 中断与异常
在IF阶段进行判断PCSrc_IF是否为中断或异常,清空ID阶段指令,更新PCSrc为100与101进行中断异常。
(2) 在EX阶段判断是否为lw指令,如果是进一步判断是否ID阶段指令所用到的
寄存器为lw写入的寄存器,若是阻塞一周期,若不是程序继续正常运行,此时PCSrc一直维持000
(3) 在EX阶段判断是否为branch指令,如果是更新PCSrc为001,且进一步判
断是否会发生跳转,如果跳转了则清空IF与ID阶段指令,如果没有跳转继续正常运行。
(4) 在EX阶段判断是否为j/jal指令,如果是更新PCSrc为010,且清空ID/IF阶
段指令。
(5) 在EX阶段判断是否为jr/jalr指令,如果是更新PCSrc为011,且清空ID/IF
阶段指令。
(6) 其他情况不存在分支冒险,正常流水线运行即可。
代码如下
always@(*) begin //Data sender if(RegWr_MEM && (AddrC_MEM!=0) && (AddrC_MEM==Rs_EX) && (~ALUSrc1_EX)) ForwardA<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rs_EX && (~ALUSrc1_EX))//MEM?? ForwardA<=2'b01; else ForwardA<=2'b00; if(RegWr_MEM && AddrC_MEM!=0 && AddrC_MEM==Rt_EX && (~ALUSrc2_EX)) ForwardB<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rt_EX && (~ALUSrc2_EX)) ForwardB<=2'b01; else ForwardB<=2'b00; if(RegWr_MEM && (AddrC_MEM!=0) && (AddrC_MEM==Rs_EX) && (~ALUSrc1_EX) && PCSrc_EX==3'b011) //for jr&jalr ForwardC<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rs_EX && (~ALUSrc1_EX) && PCSrc_EX==3'b011)//MEM?? ForwardC<=2'b01; else ForwardC<=2'b00; if(RegWr_MEM && (AddrC_MEM!=0) && (AddrC_MEM==Rt_EX) && (ALUSrc2_EX) && MemWr_EX==1'b1) //for sw ForwardD<=2'b10; else if(RegWr_WB && AddrC_WB!=0 && AddrC_WB==Rt_EX && (ALUSrc2_EX) && MemWr_EX==1'b1) ForwardD<=2'b01; else ForwardD<=2'b00; // control if(PCSrc_IF==3'b100) //ILLOP begin PCSrc<=3'b100; PCWrite<=1'b1; IDstall<=1'b0; EXstall<=1'b1; MEMstall<=1'b1; enable<=1'b1; end else if(PCSrc_IF==3'b101) //XADR begin PCSrc<=3'b101; PCWrite<=1'b1; IDstall<=1'b0; EXstall<=1'b1; MEMstall<=1'b1; enable<=1'b1; end else begin if(MemRd_EX) //if lw in EX begin if(((AddrC_EX==Rs_ID) (~ALUSrc2_ID || MemWr_ID))) begin PCSrc<=3'b000; PCWrite<=1'b0; IDstall<=1'b0; EXstall<=1'b1; MEMstall<=1'b0; enable<=1'b0; end end else if(PCSrc_EX==3'b001) begin //if branch in EX PCSrc<=3'b001; && (~ALUSrc1_ID)) || ((AddrC_EX==Rt_ID) && if(ALUOut_EX[0]) begin PCWrite<=1'b1; IDstall<=1'b1; EXstall<=1'b1; MEMstall<=1'b0; enable<=1'b1; end else begin PCWrite<=1'b1; IDstall<=1'b0; EXstall<=1'b0; MEMstall<=1'b0; enable<=1'b1; end end else if(PCSrc_EX==3'b010) begin PCSrc<=3'b010; PCWrite<=1'b1; IDstall<=1'b1; EXstall<=1'b1; MEMstall<=1'b0; enable<=1'b1; //if jr/jalr in EX end else if(PCSrc_EX==3'b011) begin PCSrc<=3'b011; PCWrite<=1'b1; IDstall<=1'b1; EXstall<=1'b1; //if j/jal in EX MEMstall<=1'b0; enable<=1'b1; end else begin PCSrc<=3'b000; PCWrite<=1'b1; IDstall<=1'b0; EXstall<=1'b0; MEMstall<=1'b0; enable<=1'b1; end end end
第二部分 反思与总结
针对我的调试过程,在ALU部分,补充以下几个方面:
一、仿真验证
分模块验证
f) 32bit加法器 有符号sign=1 357+253=610
258-263=-5 n=1
678-678=0 z=1
2147483640+3451=~ v=1,n=1
无符号sign=0 258+263=521
4294967293+3451=~ v=1
g) 32bit减法器,处理有符号数,要求sign=1 42-345=-303 n=1,
-213-2147483647=~ v=1,
h) 位移函数 Sll 左移3位
Srl 右移31位
Sra
算术右移23位
算术右移6位
整体ALU功能验证 注意事项:
(1) ALUalways设置为在A or B or Function 改变时变化更新,与时钟无关。
测试结果:
指令 add sub and or xor nor rs sll srl sra slt beq op码 Func码 ALUFun 功能注释 测试 Ok Ok Ok Ok Ok Ok Ok Ok Ok Ok Ok Ok 000000 100000 000000 PC=PC+4,rd=rs+rt 000000 100010 000001 PC=PC+4,rd=rs-rt 000000 100100 011000 PC=PC+4,rd=rs&rt 000000 100101 011110 PC=PC+4,rd=rs|rt 000000 100110 010110 PC=PC+4,rd=rs^rt 000000 100111 010001 PC=PC+4,rd=(rs^rt)' 011010 PC=PC+4,rt=rs 000000 000000 100000 PC=PC+4,rd=rt<
000001 PC=PC+4, 二、综合结果
Device Utilization Summary (estimated values) Logic Utilization Number of Slice LUTs Number of fully used LUT-FF pairs Number of bonded IOBs
========================================================================= Timing Report
NOTE: THESE TIMING NUMBERS ARE ONLY A SYNTHESIS ESTIMATE.
FOR ACCURATE TIMING INFORMATION PLEASE REFER TO THE TRACE REPORT GENERATED AFTER PLACE-and-ROUTE.
Clock Information: ------------------
No clock signals found in this design
Asynchronous Control Signals Information: ----------------------------------------
No asynchronous control signals found in this design
Timing Summary: --------------- Speed Grade: -3
Minimum period: No path found
Minimum input arrival time before clock: No path found
[-]Used Available Utilization 446 0 103 9112 446 232 4% 0% 44% Maximum output required time after clock: No path found Maximum combinational path delay: 24.979ns
Timing Details: ---------------
All values displayed in nanoseconds (ns)
=========================================================================
三、 性能优化与对比分析
以上设计采用的是ALU顶层采用行为级设计,底层如加法器减法器均采用门级设计,下面我们不妨尝试全部语句均用行为级设计,利用软件自动生成门级结构,与我们自己设计的门级运算结构对比。
ALU代码修改见附录1
Device Utilization Summary (estimated values) Logic Utilization Number of Slice LUTs Number of fully used LUT-FF pairs Number of bonded IOBs
========================================================================= Timing Report
NOTE: THESE TIMING NUMBERS ARE ONLY A SYNTHESIS ESTIMATE.
FOR ACCURATE TIMING INFORMATION PLEASE REFER TO THE TRACE REPORT GENERATED AFTER PLACE-and-ROUTE.
[-]Used Available Utilization 470 0 102 9112 470 232 5% 0% 43%
Clock Information: ------------------
No clock signals found in this design
Asynchronous Control Signals Information: ----------------------------------------
No asynchronous control signals found in this design
Timing Summary: --------------- Speed Grade: -3
Minimum period: No path found
Minimum input arrival time before clock: No path found Maximum output required time after clock: No path found Maximum combinational path delay: 12.989ns
Timing Details: ---------------
All values displayed in nanoseconds (ns) 分析:
经过以上对比,采用我们的门级设计,将节约1%的LUTs,但采用软件自动设计的
门及结构,虽然对于器件的消耗略大,但将缩短进一半的Maximum combinational
path delay。所以从减少时间延时,提高时钟频率的角度可以选择采用纯行为级语句设计,利用现有软件实现门级设计,比手工设计更为优化。这一结果可能是因为相关软件对基本门及结构的设计水平高于我们现有的手工设计水平,采用了更为复杂的优化方法所致。
但鉴于实验的实际锻炼意义考虑,我们仍然采用自己设计的门级结构来搭建ALU,供后续CPU结构使用。
四、实验中存在的问题
i) 无符号数的减法如何处理?
无符号数的减法A-B,如果A
j) 对于设计中关键路性的分析:
将加法器、比较器、移位器、逻辑运算器的独立延时特性进行比较可以发现,移位器与逻辑运算器的延时远小于加法器与比较器的延时,因此,集中对加法器与比较器进行分析。由于比较器的结果需要待加法器输出结果稳定之后才能得到,因此,关键路径出现在比较器中。对于无符号数的比较,单独设计的比较电路的延时同样小于加法器的一般延时,因此,电路的关键路径锁定为有符号数的比较操作所经的各个部分:加法运算,比较逻辑电路。
由于比较器主要的判断方式是对z,v,n三个值进行逻辑判断,而且其逻辑门级不超过两级,相对而言对整体延时影响较小。对z,v,n三个值的稳定状态进行观察,可以发现,z值的稳定速度最慢,造成的延时最长。其主要原因为,在经过加法器运算后,需要对结果进行三级门处理,因而引入了比较大的延时。由于有符号数的补码设计末位加1,因而,难以直接在加法器的输入端对两数相减进行相等判断,为电路性能的改进造成了较大的问题。
五、实验心得体会
在ALU设计部分,关于加法器设计,我采用的主要优化策略为采用了超前进位
加法器,没有使用1位全加器进行级联。一位全加器要是级联的话延时会很大,4位超前进位加法器可以减少延时,再进行8个加法器级联的话设计较为方便。若用32位的超前进位加法器则逻辑复杂,且延时效果下降。
通过整个ALU的构建过程,我更将清晰地明白了ALU的内部电路原理,明白了如何根据指令使ALU完成不同的功能。加深了对于有符号数和无符号数的加减、比较运算规则的理解。
根据数字集成电路设计中的理论,提高电路的工作速度的方法主要有以下几种: 1、减小负载电容CL. 2、增大晶体管尺寸W/L. 3、增大供电电压VDD. 4、化简逻辑.
5、在输出后面级联反相器。
这其中最为有效的方法是增大晶体管尺寸W/L, 由于工艺以及给定,W/L,VDD都不能变化,简化逻辑和级联反相器对于电路来说是仅有的优化方法。由于本次CPU设计时间较紧迫,我并没有能够对ALU进行太多优化,将在以后的过程中优化。
在这次CPU完成后,我们终于设计出了一个具有一定功能的CPU,并且使它通过了测试。做整个大作业的过程,我们收获了很多,对CPU有了较为深刻的理解。我们设计的CPU从最基本的单周期单指令的CPU,到后来加入流水,多周期等可以提高性能的电路,很大程度上加深了我对流水线的理解。在后期复杂的调试过程中,不但锻炼了我熟练使用仿真软件的能力,也磨练了我克服困难的的意志与面对复杂问题的耐性。
通过团队协作,唐敏豪孙晓峰同学和我,精确计划时间和分工,按时完成了计划任务,并取得了84.5MHz较为良好的成绩,在这个团队合作过程中,我即学会了沟通,也从别人学到了很多自己没有能够领悟透彻的知识点。
感谢助教和老师的指导与帮助。