系统硬件综合设计.docx

上传人:b****6 文档编号:12743817 上传时间:2023-06-07 格式:DOCX 页数:15 大小:222.75KB
下载 相关 举报
系统硬件综合设计.docx_第1页
第1页 / 共15页
系统硬件综合设计.docx_第2页
第2页 / 共15页
系统硬件综合设计.docx_第3页
第3页 / 共15页
系统硬件综合设计.docx_第4页
第4页 / 共15页
系统硬件综合设计.docx_第5页
第5页 / 共15页
系统硬件综合设计.docx_第6页
第6页 / 共15页
系统硬件综合设计.docx_第7页
第7页 / 共15页
系统硬件综合设计.docx_第8页
第8页 / 共15页
系统硬件综合设计.docx_第9页
第9页 / 共15页
系统硬件综合设计.docx_第10页
第10页 / 共15页
系统硬件综合设计.docx_第11页
第11页 / 共15页
系统硬件综合设计.docx_第12页
第12页 / 共15页
系统硬件综合设计.docx_第13页
第13页 / 共15页
系统硬件综合设计.docx_第14页
第14页 / 共15页
系统硬件综合设计.docx_第15页
第15页 / 共15页
亲,该文档总共15页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

系统硬件综合设计.docx

《系统硬件综合设计.docx》由会员分享,可在线阅读,更多相关《系统硬件综合设计.docx(15页珍藏版)》请在冰点文库上搜索。

系统硬件综合设计.docx

系统硬件综合设计

计算机与信息学院

系统硬件综合设计》

课程设计报告

学生姓名:

学号:

1234567890

专业班级:

计算机

2017年07月01日

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模块

initialbegin

$readmemh("instruction",InstMem,8'h0);

end

always@(ImemRdAddr)begin

Instruction<=InstMem[ImemRdAddr>>2];

end

这个模块很简单,主要是通过instructin文档来存储指令,以PCF作为地址取出指令输出至Control,SignExtend,Register三个模块。

3.Ctr模块

always@(OpCode)begincase(OpCode)//R-I//addiu6'b001001:

begin

RegDstD=1;

ALUSrcD=1;

MemtoRegD=0;

RegWriteD=1;

MemWriteD=0;

BranchD=0;

ALUOp=2'b10;end//addi

endcase

end

always@(ALUOporFunct)

begincasex({OpCode,ALUOp,Funct})

14'b10001100xxxxxx:

ALUControlD=5'b00010;//LW:

add

14'b00010001xxxxxx:

ALUControlD=5'b00110;//SW:

substractbeq

endcaseendendmodule

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文档,另外DmemAdd左r移两位跟上述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模块的输入。

二、指令设计

本次试验实现了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'b00000000001000100001100000100000TmpForSrcB=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'b00010000001000100000000000000010

ALURes=SrcA-SrcB;

Beq指令,实现将00001号寄存器和00002号寄存器的值进行比较,若相等,则当前指令地址加00000000000000010,否则执行下一条指令;

Addu指令,无符号加法指令,实现将00001号寄存器和00002号寄存器的值进行无符号加法,结果放到00003号寄存器中;32'b10001100001000100001100000100011ALURes=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

1:

0;

00002号寄存器的值进行无符号比较,

sltu指令,无符号比较操作,实现将00001号寄存器和若SrcA

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=(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'b00110100001000100001100000000000ALURes=SrcA

1:

0;

slti指令,有符号立即数比较操作,实现将00001号寄存器的值和立即数进行有符号比较,若SrcA

ALURes=(SrcA^SrcB);

xori指令,立即数异或指令,实现将00001号寄存器的值和立即数进行异或运算,结果放到00002号寄存器中;32'b00101100001000100001100000000000

ALURes=SrcA

1:

0;

slti指令,无符号立即数比较操作,实现将00001号寄存器的值和立即数进行无符号比较,若SrcA

sll指令,逻辑左移指令,实现将00001号寄存器的值左移sa位,结果存入00002号寄存器;

j=SrcB[31:

31];

TmpForSrcB=SrcB;

TmpForSrcA=SrcA;

/*

for(i=0;i

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立即数进行有符号加法,结果放到00003号寄存器中;

32'b00000000001000100001100000011000

ALURes=SrcA/SrcB;

mulu指令,无符号乘法指令,实现将00001号寄存器和00002号寄存器的值进行无符号乘法,结果放到00003号寄存器中;

32'b00000000001000100001100000011000

ALURes=SrcA/SrcB;

divu指令,无符号除法指令,实现将00001号寄存器和00002号寄存器的值进行无符号除法,

结果放到00003号寄存器中;32'b00001000000000000000000000000003

PCF={6'h0,InstructionF[25:

0]};

PCF=PCF<<2;

Jump指令,跳转指令,实现跳转到立即数的指令地址,执行程序。

三、实验结果截图及分析

如图所示进行了三条指令,我仅以此三条指令的结果进行分析:

1.32'h00221820

OpCode=000000,Funct=100000,为有符号加法运算,从00001号寄存器取出第一个操作数00000002,第二个寄存器取出第二个数00000003,相加得到ALUResE=00000005;2.32'h08000003

OpCode=000010,为跳转指令,立即数为00000003,故跳转到第三条指令执行,PCF=0000000c;

3.32'hac240001

OpCode=101011,为分支指令,立即数为0001,故PCF=PCF+4;

四、实验感想

本次试验,我经历了历时13天的cpu设计,从刚开始的一无所知,只是拿到了五个基础实验和《自己动手写cpu》,到最后做出来,过程之艰辛无法言说,记忆深刻的地方是在写模块连接时,我按照书上的连接方法写模块连接,总是会报错,卡了将近一天时间,后来问老师,老师给我们讲了模块连接的部分,才解决了这个问题。

写cpu的过程中用到了很多知识,计算机组成原理的有符号乘法,算术移位,计算机体系结构的五级流水等等,通过本次实验不仅学会了怎样做cpu,还将学过的课程复习了一遍,觉得受益良多。

最后以一句《自己动

手写cpu》上的话来结尾

一个人的旅行

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2