系统硬件综合设计.docx
- 文档编号:25120010
- 上传时间:2023-06-05
- 格式:DOCX
- 页数:17
- 大小:225.91KB
系统硬件综合设计.docx
《系统硬件综合设计.docx》由会员分享,可在线阅读,更多相关《系统硬件综合设计.docx(17页珍藏版)》请在冰豆网上搜索。
系统硬件综合设计
计算机与信息学院
《系统硬件综合设计》
课程设计报告
学生姓名:
李
学号:
1234567890
专业班级:
计算机
2017年07月01日
一、实验原理及设计
本次试验我主要根据上图进行理解和编程,起先参考了5个基础实验,期间又翻阅了自己动手写cpu,并且在网上查了很多资料,下面我将对该图做出我的理解和设计:
1.pcf部分
always@(posedgeClk)
begin
PCPlus4F_Reg=PCPlus4F;
if(BranchM&ZeroM)PCF=PCBranchM;
elsePCF=PCPlus4F;
InstructionF_Reg=InstructionF;
if(InstructionF[31:
26]==6'b000010)
begin
PCF={6'h0,InstructionF[25:
0]};
PCF=PCF<<2;
end
End
assignPCPlus4F=PCF+4;
assignImemRdAddrF=PCF;
每个时钟上升沿到来,根据上一个时钟的PCSrcM判断是否为分支指令,若是,则选择PCBranchM作为这个时钟的指令地址,否则选PCF+4作为这个指令的指令地址,另外对于J类指令,我设计了一个特定的OpCode==“000010”,即为跳转指令,因为每个指令以字节格式存储,占用,4个字节,故将后26位立即数进行位扩展后将其左移两位,效果等同于乘4,再将其赋值给PCF,这样下一跳的指令地址即为所要跳转的地址。
对于这个部分,我起先是准备将其设计成一个模块的,之后由于模块接口连接时出现了无法解决的错误:
输出PCF要作为InstructionMemory的输入,又要作为自身模块下一跳的输入,导致三者关联一起变化,程序报错,后来我又想到将PCF的输出改成两个,PCFout及PCFnext,PCFout作为InstructionMemory的输入,PCFnext作为自身模块下一跳的输入,但是程序仍无法正常运行,最后我想到了在top模块中对PCF进行处理并得以实现。
2.InstructionMemory模块
initial
begin
$readmemh("instruction",InstMem,8'h0);
end
always@(ImemRdAddr)
begin
Instruction<=InstMem[ImemRdAddr>>2];
end
这个模块很简单,主要是通过instructin文档来存储指令,以PCF作为地址取出指令输出至Control,SignExtend,Register三个模块。
3.Ctr模块
always@(OpCode)
begin
case(OpCode)
//R-I
//addiu
6'b001001:
begin
RegDstD=1;
ALUSrcD=1;
MemtoRegD=0;
RegWriteD=1;
MemWriteD=0;
BranchD=0;
ALUOp=2'b10;
end
//addi
......
endcase
end
always@(ALUOporFunct)
begin
casex({OpCode,ALUOp,Funct})
14'b10001100xxxxxx:
ALUControlD=5'b00010;//LW:
add
14'b00010001xxxxxx:
ALUControlD=5'b00110;//SW:
substractbeq
......
endcase
end
endmodule
Control模块主要对来自InstructionMemory模块的指令进行分解,得到OpCode(指令高六位),Funct(指令低六位),在通过分析OpCode得到RegDstD,ALUSrcD,MemtoRegD,RegWriteD,BranchD,ALUOp这六个信号量,用于后面的运算,再使用OpCode,ALUOp,Funct三者的组合对指令的运算方法进行分析,得到相应的ALUControlD输出至ALU模块。
4.Register模块
initial
begin
$readmemh("register",regFile,32'h0);
end
//writeonfallingclockedge
always@(posedgeClk)
begin
if(RegWrite==1'b1)
regFile[RegWrAddr]<=RegWrData;
end
assignRegARdData=(RegARdAddr>=0)?
regFile[RegARdAddr]:
0;
assignRegBRdData=(RegBRdAddr>=0)?
regFile[RegBRdAddr]:
0;
通过信号量RegWrite来判断读写操作,RegWrite=1即为写操作,0为读操作,读写皆操作于建立的register文档中,另在top模块中有
assignRegARdAddr=InstructionD[25:
21];
assignRegBRdAddr=InstructionD[20:
16];
对寄存器地址赋值,register读出的两个数可供ALU选择使用。
5.ALU模块
assignZero=(ALURes==0)?
1:
0;//ALURes0跳转
always@(SrcAorSrcBorALUCtr)
begin
OverFlow=0;
TmpForSrcB=0;
HI=0;
LO=0;
A=0;
B=0;
case(ALUCtr)
5'b10011:
begin
TmpForSrcB=SrcB;
TmpForSrcB[31]=(TmpForSrcB[31]+1)%2;
ALURes=SrcA+TmpForSrcB;
if((SrcA[31]!
=TmpForSrcB[31])||(SrcA[31]==TmpForSrcB[31]&&ALURes[31]==SrcA[31]))
begin
OverFlow=1'b0;
end
else
if(SrcA[31]==TmpForSrcB[31]&&ALURes[31]!
=SrcA[31])
begin
OverFlow=1'b1;
end
......
default:
ALURes=32'h0;
endcase
end
ALU模块进行的是运算操作,本模块通过来自Control模块的ALUCtr判断所要执行的运算,在通过Register模块读出的值或者从Instruction中得到的立即数进行运算,结果ALURes根据信号量MemToReg来判断是否写入DataMemory,这一块写在top中,另外ALU还对Zero信号量进行了赋值,Zero信号量用于对分支指令的判断。
6.DataMemory模块
initial
begin
$readmemh("Data",DataMem,10'h0);
end
always@(posedgeClk)
begin
if(DmemWrite==1'b1)
DataMem[DmemAddr>>2]<=DmemWrData;
end
assignDmemRdData=(DmemWrite==1'b0)?
DataMem[DmemAddr>>2]:
0;
endmodule
本模块通过从Ctr模块得来的信号量DmemWrite选择进行读写操作,读写皆操作于所建立的Data文档,另外DmemAddr左移两位跟上述PCF左移两位异曲同工。
7.top模块
这个模块相比前面的6个模块要复杂得多,也是我在实验时出现问题最多,所花时间最长的模块。
Top模块主要用于各个模块之间的数据连接,以及一些模块外的操作。
PCF的设计我是放在这个模块的,另外像二选一数据选择器我也是放在这里的,本来是写了一个小模块来做这个工作,但是本次试验用到太多次二选一数据选择器了,为了防止数据传输紊乱,我决定在top中解决这个小操作。
由于本模块代码太长,这里就不一一阐述,仅以Ctr的例化和接口连接为例简要说明:
CtrCtr(
.OpCode(OpCode),
.Funct(Funct),
.RegWriteD(RegWriteForCtrD),
.MemtoRegD(MemtoRegD),
.MemWriteD(MemWriteD),
.BranchD(BranchD),
.ALUControlD(ALUControlD),
.ALUSrcD(ALUSrcD),
.RegDstD(RegDstD)
);
assignOpCode=InstructionD[31:
26];
assignFunct=InstructionD[5:
0];
assignRegWrDataD=(MemtoRegW)?
ReadDataW:
ALUOutW;
always@(posedgeClk)
begin
MemtoRegD_Reg=MemtoRegD;
MemWriteD_Reg=MemWriteD;
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条指令,实验时原以为指令格式为固定的,查阅很多资料都没得到想要的OpCode与指令操作一一对应的关系,问了指导实验的学长才知道,OpCode是自己设计的,后又参考《自己动手写cpu》的指令设计技巧,才总结设计出指令。
3种指令:
R类型:
具体操作由OpCode,Funct来控制,rs,rt为源寄存器,rd为目的寄存器,sa为移位位数。
I类型:
具体操作由OpCode控制,低16位是立即数,经过位扩展作为另一个源操作数参与用算。
J类型:
具体操作由OpCode控制,一般是跳转指令,低26位经过位扩展作为目标地址。
34条指令:
32’b1010110000100100000000000000010
ALURes=SrcA-SrcB;
Store指令,判断00001号寄存器的值是否等于00100号寄存器的值,若相等,则当前指令地址加00000000000000010,否则执行下一条指令;
32’b00000000001000100001100000100000
TmpForSrcB=SrcB;
TmpForSrcB[31]=(TmpForSrcB[31]+1)%2;
ALURes=SrcA+TmpForSrcB;
if((SrcA[31]!
=TmpForSrcB[31])||(SrcA[31]==TmpForSrcB[31]&&ALURes[31]==SrcA[31]))
begin
OverFlow=1'b0;
end
else
if(SrcA[31]==TmpForSrcB[31]&&ALURes[31]!
=SrcA[31])
begin
OverFlow=1'b1;
end
Add指令,有符号加法指令,实现将00001号寄存器和00002号寄存器的值进行有符号加法,结果放到00003号寄存器中;
32’b00010100001000100000000000000010
ALURes=~(SrcA-SrcB);
Bne指令,实现将00001号寄存器和00002号寄存器的值进行比较,若不相等,则当前指令地址加00000000000000010,否则执行下一条指令;
32’b00010000001000100000000000000010
ALURes=SrcA-SrcB;
Beq指令,实现将00001号寄存器和00002号寄存器的值进行比较,若相等,则当前指令地址加00000000000000010,否则执行下一条指令;
32’b00000100001000000000000000000010
ALURes=(SrcA>=0)?
0:
1;
Bgez指令,实现00001号寄存器的值与0比较,若大于等于0,则当前指令地址加00000000000000010,否则执行下一条指令;
32’b00011100001000000000000000000010
ALURes=(SrcA>0)?
0:
1;
Bgtz指令,实现00001号寄存器的值与0比较,若大于0,则当前指令地址加00000000000000010,否则执行下一条指令;
32’b00011000001000000000000000000010
ALURes=(SrcA<=0)?
0:
1;
Blez指令,实现00001号寄存器的值与0比较,若小于等于0,则当前指令地址加00000000000000010,否则执行下一条指令;
32’b01000100001000000000000000000010
ALURes=(SrcA<0)?
0:
1;
Bltz指令,实现00001号寄存器的值与0比较,若小于0,则当前指令地址加00000000000000010,否则执行下一条指令;
32’b10001100001000100001100000100001
ALURes=SrcA+SrcB;
Addu指令,无符号加法指令,实现将00001号寄存器和00002号寄存器的值进行无符号加法,结果放到00003号寄存器中;
32’b10001100001000100001100000100011
ALURes=SrcA-SrcB;
subu指令,无符号减法指令,实现将00001号寄存器和00002号寄存器的值进行无符号减法,结果放到00003号寄存器中;
32’b00000000001000100001100000100100
ALURes=SrcA&SrcB;
And指令,与操作,实现将00001号寄存器和00002号寄存器的值进行与操作,结果放到00003号寄存器中;
32’b00000000001000100001100000100101
ALURes=SrcA|SrcB;
OR指令,或操作,实现将00001号寄存器和00002号寄存器的值进行或运算,结果放到00003号寄存器中;
32’b00000000001000100001100000101010
ALURes=SrcA 1: 0; slt指令,有符号比较操作,实现将00001号寄存器和00002号寄存器的值进行有符号比较,若SrcA 32’b00000000001000100001100000101010 ALURes=SrcA 1: 0; sltu指令,无符号比较操作,实现将00001号寄存器和00002号寄存器的值进行无符号比较,若SrcA 32’b00000000001000100001100000011010 ALURes=SrcA/SrcB; LO=SrcA/SrcB; HI=SrcA%SrcB; div指令,有符号除法指令,实现将00001号寄存器和00002号寄存器的值进行有符号除法,结果放到00003号寄存器中; 32’b00000000001000100001100000011000 A=SrcA[31: 31]? {32'hffffffff,SrcA}: {32'h00000000,SrcA}; B=SrcB[31: 31]? {32'hffffffff,SrcB}: {32'h00000000,SrcB}; Temp=A*B; ALURes=Temp[31: 0]; HI=Temp[63: 32]; LO=Temp[31: 0]; mul指令,有符号乘法指令,实现将00001号寄存器和00002号寄存器的值进行有符号乘法,结果放到00003号寄存器中; 32’b00000000001000100001100000000100 ALURes=(SrcB< sllv指令,逻辑可变左移指令,实现将00001号寄存器的值左移00002号寄存器的值位,结果放到00003号寄存器中; 32’b00000000001000100001100000000100 ALURes=(SrcB>>SrcA); srlv指令,逻辑可变右移指令,实现将00001号寄存器的值右移00002号寄存器的值位,结果放到00003号寄存器中; 32’b00000000001000100001100000100110 ALURes=(SrcB>>SrcA); xor指令,异或指令,实现将00001号寄存器的值和00002号寄存器进行异或,结果放到00003号寄存器中; 32’b00000000001000100001100000100110 ALURes=(SrcA^SrcB); xor指令,异或指令,实现将00001号寄存器的值和00002号寄存器进行异或,结果放到00003号寄存器中; 32’b00100100001000100001100000000000 ALURes=SrcA+SrcB; addiu指令,无符号立即数加法指令,实现将00001号寄存器的值和立即数进行无符号加法,结果放到00003号寄存器中; 32’b00110000001000100001100000000000 ALURes=SrcA+SrcB; addi指令,有符号立即数加法指令,实现将00001号寄存器的值和立即数进行有符号加法,结果放到00003号寄存器中; 32’b00110100001000100001100000000000 ALURes=SrcA|SrcB; ori指令,立即数或指令,实现将00001号寄存器的值和立即数进行或运算,结果放到00002号寄存器中; 32’b00110100001000100001100000000000 ALURes=SrcA 1: 0; slti指令,有符号立即数比较操作,实现将00001号寄存器的值和立即数进行有符号比较,若SrcA 32’b00111000001000100001100000000000 ALURes=(SrcA^SrcB); xori指令,立即数异或指令,实现将00001号寄存器的值和立即数进行异或运算,结果放到00002号寄存器中; 32’b00101100001000100001100000000000 ALURes=SrcA 1: 0; slti指令,无符号立即数比较操作,实现将00001号寄存器的值和立即数进行无符号比较,若SrcA 32’b00000000001000100001100001000000 ALURes=(SrcB< sll指令,逻辑左移指令,实现将00001号寄存器的值左移sa位,结果存入00002号寄存器; 32’b00000000001000100001100001000010 ALURes=(SrcB>>SrcA); srl指令,逻辑右移指令,实现将00001号寄存器的值右移sa位,结果存入00002号寄存器; 32’b00000000001000100001100001000111 j=SrcB[31: 31]; TmpForSrcB=SrcB; TmpForSrcA=SrcA; /* for(i=0;i begin ALURes={j,31'h0}|(ALURes>>1); srav指令,算术可变右移指令,实现将00001号寄存器的值算术右移sa位,结果存入00002号寄存器; 32’b00000000001000100001100001000011 j=SrcB[31: 31]; TmpForSrcB=SrcB; TmpForSrcA=SrcA; TmpForSrcB=TmpForSrcB>>SrcA; if(j) begin ALURes={~(TmpForSrcB[31: 31]),TmpForSrcB[30: 0]}; end else begin ALURes=TmpForSrcB; end sra指令,算术右移指令,实现将00002号寄存器的值算术右移00001号寄存器的值位,结果存入00003号寄存器; 32’b00000000001000100001100000100010 ALURes=SrcA-SrcB; sub指令,有符号减法指令,实现将00001号寄存器和00002号寄存器的值进行有符号减法,结果放到00003号寄存器中; 32’b00100000001000100001100000000000 ALURes=SrcA+SrcB; addi指令,立即数加法指令,实现将00001号寄存器和00立即数进行有符号加法,结果放到0000
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 系统 硬件 综合 设计