1、系统硬件综合设计计算机与信息学院系统硬件综合设计课程设计报告学生姓名: 李 学 号: 1234567890 专业班级: 计算机 2017 年 07 月 01日一、实验原理及设计本次试验我主要根据上图进行理解和编程,起先参考了5个基础实验,期间又翻阅了自己动手写cpu,并且在网上查了很多资料,下面我将对该图做出我的理解和设计:1.pcf部分always (posedge Clk) begin PCPlus4F_Reg = PCPlus4F; if (BranchM&ZeroM) PCF = PCBranchM; else PCF = PCPlus4F; InstructionF_Reg = In
2、structionF; if (InstructionF31:26 = 6b000010) begin PCF = 6h0,InstructionF25:0; PCF = PCF 2; endEndassign PCPlus4F = PCF + 4;assign ImemRdAddrF = PCF;每个时钟上升沿到来,根据上一个时钟的PCSrcM判断是否为分支指令,若是,则选择PCBranchM作为这个时钟的指令地址,否则选PCF+4作为这个指令的指令地址,另外对于J类指令,我设计了一个特定的OpCode=“000010”,即为跳转指令,因为每个指令以字节格式存储,占用,4个字节,故将后26位
3、立即数进行位扩展后将其左移两位,效果等同于乘4,再将其赋值给PCF,这样下一跳的指令地址即为所要跳转的地址。对于这个部分,我起先是准备将其设计成一个模块的,之后由于模块接口连接时出现了无法解决的错误:输出PCF要作为Instruction Memory的输入,又要作为自身模块下一跳的输入,导致三者关联一起变化,程序报错,后来我又想到将PCF的输出改成两个,PCFout及PCFnext,PCFout作为Instruction Memory的输入,PCFnext作为自身模块下一跳的输入,但是程序仍无法正常运行,最后我想到了在top模块中对PCF进行处理并得以实现。2. Instruction Me
4、mory模块 initial begin $readmemh(instruction, InstMem, 8h0); end always (ImemRdAddr) begin Instruction 2; end这个模块很简单,主要是通过instructin文档来存储指令,以PCF作为地址取出指令输出至Control,SignExtend,Register三个模块。3.Ctr模块 always (OpCode) begin case(OpCode) / R-I / addiu 6b001001: begin RegDstD = 1; ALUSrcD = 1; MemtoRegD = 0; R
5、egWriteD = 1; MemWriteD = 0; BranchD = 0; ALUOp = 2b10; end /addi.endcase end always (ALUOp or Funct) begin casex(OpCode ,ALUOp, Funct) 14b10001100xxxxxx: ALUControlD = 5b00010; / LW : add 14b00010001xxxxxx: ALUControlD = 5b00110; / SW : substract beq . endcase endendmoduleControl模块主要对来自Instruction
6、Memory模块的指令进行分解,得到OpCode(指令高六位),Funct(指令低六位),在通过分析OpCode得到RegDstD,ALUSrcD ,MemtoRegD,RegWriteD,BranchD ,ALUOp这六个信号量,用于后面的运算,再使用OpCode ,ALUOp, Funct三者的组合对指令的运算方法进行分析,得到相应的ALUControlD输出至ALU模块。4.Register模块initial begin $readmemh(register, regFile, 32h0); end / write on falling clock edge always (posedg
7、e Clk) begin if(RegWrite = 1b1) regFileRegWrAddr = 0)? regFileRegARdAddr:0; assign RegBRdData = (RegBRdAddr = 0)? regFileRegBRdAddr:0;通过信号量RegWrite来判断读写操作,RegWrite=1即为写操作,0为读操作,读写皆操作于建立的register文档中,另在top模块中有assign RegARdAddr = InstructionD25:21;assign RegBRdAddr = InstructionD20:16;对寄存器地址赋值,register
8、读出的两个数可供ALU选择使用。5.ALU模块assign Zero = (ALURes = 0)? 1:0;/ALURes 0 跳转always (SrcA or SrcB or ALUCtr)begin OverFlow = 0; TmpForSrcB = 0; HI = 0; LO = 0; A = 0; B = 0; case(ALUCtr) 5b10011: begin TmpForSrcB = SrcB; TmpForSrcB31 = (TmpForSrcB31+1)%2; ALURes = SrcA + TmpForSrcB; if (SrcA31 != TmpForSrcB31
9、) | (SrcA31 = TmpForSrcB31 & ALURes31 = SrcA31) begin OverFlow = 1b0; end else if (SrcA31 = TmpForSrcB31 & ALURes31 != SrcA31) begin OverFlow = 1b1; end .default: ALURes = 32h0; endcaseendALU模块进行的是运算操作,本模块通过来自Control模块的ALUCtr判断所要执行的运算,在通过Register模块读出的值或者从Instruction中得到的立即数进行运算,结果ALURes根据信号量MemToReg来
10、判断是否写入DataMemory,这一块写在top中,另外ALU还对Zero信号量进行了赋值,Zero信号量用于对分支指令的判断。6.Data Memory模块initialbegin $readmemh(Data, DataMem, 10h0);endalways (posedge Clk) begin if(DmemWrite = 1b1) DataMemDmemAddr2 2:0;endmodule本模块通过从Ctr模块得来的信号量DmemWrite选择进行读写操作,读写皆操作于所建立的Data文档,另外DmemAddr左移两位跟上述PCF左移两位异曲同工。7.top模块这个模块相比前面
11、的6个模块要复杂得多,也是我在实验时出现问题最多,所花时间最长的模块。Top模块主要用于各个模块之间的数据连接,以及一些模块外的操作。PCF的设计我是放在这个模块的,另外像二选一数据选择器我也是放在这里的,本来是写了一个小模块来做这个工作,但是本次试验用到太多次二选一数据选择器了,为了防止数据传输紊乱,我决定在top中解决这个小操作。由于本模块代码太长,这里就不一一阐述,仅以Ctr的例化和接口连接为例简要说明:Ctr Ctr( .OpCode(OpCode), .Funct(Funct), .RegWriteD(RegWriteForCtrD), .MemtoRegD(MemtoRegD),
12、.MemWriteD(MemWriteD), .BranchD(BranchD), .ALUControlD(ALUControlD), .ALUSrcD(ALUSrcD), .RegDstD(RegDstD);assign OpCode = InstructionD31 : 26;assign Funct = InstructionD5 : 0;assign RegWrDataD = (MemtoRegW)? ReadDataW : ALUOutW;always (posedge Clk) beginMemtoRegD_Reg = MemtoRegD;MemWriteD_Reg = MemW
13、riteD;BranchD_Reg = BranchD;ALUControlD_Reg = ALUControlD;ALUSrcD_Reg = ALUSrcD;RegDstD_Reg = RegDstD;end输入来源OpCode来自于取指阶段Instruction的高6位,Funct来自于取指阶段Instruction的低6位,RegWriteD通过信号量MemToRegW来选择ReadDataW 或 ALUOutW,输出信号量MemtoRegD,MemWriteD,BranchD,ALUControlD,ALUSrcD,RegDstD作为Reg模块的输入。2、指令设计本次试验实现了3种34
14、条指令,实验时原以为指令格式为固定的,查阅很多资料都没得到想要的OpCode与指令操作一一对应的关系,问了指导实验的学长才知道,OpCode是自己设计的,后又参考自己动手写cpu的指令设计技巧,才总结设计出指令。3种指令:R类型:具体操作由OpCode,Funct来控制,rs,rt为源寄存器,rd为目的寄存器,sa为移位位数。I类型:具体操作由OpCode控制,低16位是立即数,经过位扩展作为另一个源操作数参与用算。J类型:具体操作由OpCode控制,一般是跳转指令,低26位经过位扩展作为目标地址。34条指令:32b101011 00001 00100 000000000000010ALURe
15、s = SrcA - SrcB;Store指令,判断00001号寄存器的值是否等于00100号寄存器的值,若相等,则当前指令地址加00000000000000010,否则执行下一条指令;32b000000 00001 00010 00011 00000 100000TmpForSrcB = SrcB; TmpForSrcB31 = (TmpForSrcB31+1)%2; ALURes = SrcA + TmpForSrcB; if (SrcA31 != TmpForSrcB31) | (SrcA31 = TmpForSrcB31 & ALURes31 = SrcA31) begin OverF
16、low = 1b0; end else if (SrcA31 = TmpForSrcB31 & ALURes31 != SrcA31) begin OverFlow = 1b1; endAdd指令,有符号加法指令,实现将00001号寄存器和00002号寄存器的值进行有符号加法,结果放到00003号寄存器中;32b000101 00001 00010 0000000000000010ALURes = (SrcA - SrcB);Bne指令,实现将00001号寄存器和00002号寄存器的值进行比较,若不相等,则当前指令地址加00000000000000010,否则执行下一条指令;32b000100
17、 00001 00010 0000000000000010ALURes = SrcA - SrcB;Beq指令,实现将00001号寄存器和00002号寄存器的值进行比较,若相等,则当前指令地址加00000000000000010,否则执行下一条指令;32b000001 00001 00000 0000000000000010ALURes = (SrcA = 0)?0:1;Bgez指令,实现00001号寄存器的值与0比较,若大于等于0,则当前指令地址加00000000000000010,否则执行下一条指令;32b000111 00001 00000 0000000000000010ALURes
18、= (SrcA 0)?0:1;Bgtz指令,实现00001号寄存器的值与0比较,若大于0,则当前指令地址加00000000000000010,否则执行下一条指令;32b000110 00001 00000 0000000000000010ALURes = (SrcA = 0)?0:1;Blez指令,实现00001号寄存器的值与0比较,若小于等于0,则当前指令地址加00000000000000010,否则执行下一条指令;32b010001 00001 00000 0000000000000010ALURes = (SrcA 0)?0:1;Bltz指令,实现00001号寄存器的值与0比较,若小于0
19、,则当前指令地址加00000000000000010,否则执行下一条指令;32b100011 00001 00010 00011 00000 100001ALURes = SrcA + SrcB;Addu指令,无符号加法指令,实现将00001号寄存器和00002号寄存器的值进行无符号加法,结果放到00003号寄存器中;32b100011 00001 00010 00011 00000 100011ALURes = SrcA - SrcB;subu指令,无符号减法指令,实现将00001号寄存器和00002号寄存器的值进行无符号减法,结果放到00003号寄存器中;32b000000 00001 0
20、0010 00011 00000 100100ALURes = SrcA & SrcB;And指令,与操作,实现将00001号寄存器和00002号寄存器的值进行与操作,结果放到00003号寄存器中;32b000000 00001 00010 00011 00000 100101ALURes = SrcA | SrcB;OR指令,或操作,实现将00001号寄存器和00002号寄存器的值进行或运算,结果放到00003号寄存器中;32b000000 00001 00010 00011 00000 101010ALURes = SrcA SrcB ? 1:0;slt指令,有符号比较操作,实现将0000
21、1号寄存器和00002号寄存器的值进行有符号比较,若SrcA SrcB,则置1,否则置0;32b000000 00001 00010 00011 00000 101010ALURes = SrcA SrcB ? 1:0;sltu指令,无符号比较操作,实现将00001号寄存器和00002号寄存器的值进行无符号比较,若SrcA SrcB,则置1,否则置0;32b000000 00001 00010 00011 00000 011010 ALURes = SrcA / SrcB; LO = SrcA / SrcB; HI = SrcA % SrcB;div指令,有符号除法指令,实现将00001号寄存
22、器和00002号寄存器的值进行有符号除法,结果放到00003号寄存器中;32b000000 00001 00010 00011 00000 011000 A = SrcA31:31?32hffffffff, SrcA : 32h00000000, SrcA; B = SrcB31:31?32hffffffff, SrcB : 32h00000000, SrcB; Temp = A * B ; ALURes = Temp31:0; HI = Temp63:32; LO = Temp31:0;mul指令,有符号乘法指令,实现将00001号寄存器和00002号寄存器的值进行有符号乘法,结果放到000
23、03号寄存器中;32b000000 00001 00010 00011 00000 000100ALURes = (SrcB SrcA);srlv指令,逻辑可变右移指令,实现将00001号寄存器的值右移00002号寄存器的值位,结果放到00003号寄存器中;32b000000 00001 00010 00011 00000 100110ALURes = (SrcB SrcA);xor指令,异或指令,实现将00001号寄存器的值和00002号寄存器进行异或,结果放到00003号寄存器中;32b000000 00001 00010 00011 00000 100110ALURes = (SrcA
24、SrcB); xor指令,异或指令,实现将00001号寄存器的值和00002号寄存器进行异或,结果放到00003号寄存器中;32b001001 00001 00010 00011 00000 000000ALURes = SrcA + SrcB; addiu指令,无符号立即数加法指令,实现将00001号寄存器的值和立即数进行无符号加法,结果放到00003号寄存器中;32b001100 00001 00010 00011 00000 000000ALURes = SrcA + SrcB; addi指令,有符号立即数加法指令,实现将00001号寄存器的值和立即数进行有符号加法,结果放到00003号
25、寄存器中;32b001101 00001 00010 00011 00000 000000ALURes = SrcA | SrcB; ori指令,立即数或指令,实现将00001号寄存器的值和立即数进行或运算,结果放到00002号寄存器中;32b001101 00001 00010 00011 00000 000000ALURes = SrcA SrcB ? 1:0; slti指令,有符号立即数比较操作,实现将00001号寄存器的值和立即数进行有符号比较,若SrcA SrcB,则置1,否则置0;32b001110 00001 00010 00011 00000 000000ALURes = (S
26、rcA SrcB);xori指令,立即数异或指令,实现将00001号寄存器的值和立即数进行异或运算,结果放到00002号寄存器中;32b001011 00001 00010 00011 00000 000000ALURes = SrcA SrcB ? 1:0; slti指令,无符号立即数比较操作,实现将00001号寄存器的值和立即数进行无符号比较,若SrcA SrcB,则置1,否则置0;32b000000 00001 00010 00011 00001 000000 ALURes = (SrcB SrcA); srl指令,逻辑右移指令,实现将00001号寄存器的值右移sa位,结果存入00002
27、号寄存器;32b000000 00001 00010 00011 00001 000111j = SrcB31:31; TmpForSrcB = SrcB; TmpForSrcA = SrcA; /* for(i = 0; i 1); srav指令,算术可变右移指令,实现将00001号寄存器的值算术右移sa位,结果存入00002号寄存器; 32b000000 00001 00010 00011 00001 000011 j = SrcB31:31; TmpForSrcB = SrcB; TmpForSrcA = SrcA; TmpForSrcB = TmpForSrcBSrcA; if (j)
28、 begin ALURes = (TmpForSrcB31:31), TmpForSrcB30:0; end else begin ALURes = TmpForSrcB; end sra指令,算术右移指令,实现将00002号寄存器的值算术右移00001号寄存器的值位,结果存入00003号寄存器;32b000000 00001 00010 00011 00000 100010ALURes = SrcA - SrcB;sub指令,有符号减法指令,实现将00001号寄存器和00002号寄存器的值进行有符号减法,结果放到00003号寄存器中;32b001000 00001 00010 00011 00000 000000ALURes = SrcA + SrcB;addi指令,立即数加法指令,实现将00001号寄存器和00立即数进行有符号加法,结果放到00003号寄存器中;