华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx

上传人:b****1 文档编号:13829316 上传时间:2023-06-17 格式:DOCX 页数:29 大小:677.38KB
下载 相关 举报
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第1页
第1页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第2页
第2页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第3页
第3页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第4页
第4页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第5页
第5页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第6页
第6页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第7页
第7页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第8页
第8页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第9页
第9页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第10页
第10页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第11页
第11页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第12页
第12页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第13页
第13页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第14页
第14页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第15页
第15页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第16页
第16页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第17页
第17页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第18页
第18页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第19页
第19页 / 共29页
华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx_第20页
第20页 / 共29页
亲,该文档总共29页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx

《华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx》由会员分享,可在线阅读,更多相关《华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx(29页珍藏版)》请在冰点文库上搜索。

华中科技大学HUST类MIPS单周期微处理器设计实验报告.docx

华中科技大学HUST类MIPS单周期微处理器设计实验报告

类MIPS单周期微处理器设计

实验报告

 

专业:

班级:

学号:

姓名:

 

 

一、微处理器各模块设计

各模块的框图结构如上图所示。

由图可知,该处理器包含指令存储器、数据存储器、寄存器组、ALU单元、符号数扩张、控制器、ALU控制译码以及多路复用器等。

图中还忽略了一个单元:

时钟信号产生器,而且以上各个部件必须在时钟信号的控制下协调工作。

1.指令存储器的设计

指令寄存器为ROM类型的存储器,为单一输出指令的存储器。

因此其对外的接口为clk、存储器地址输入信号(指令指针)以及数据输出信号(指令)。

(1)在IPwizard中配置ROM,分配128个字的存储空间,字长为32位宽。

(2)选择输入具有地址寄存功能,只有当时钟上升沿有效时,才进行数据的输出。

(3)配置ROM内存空间的初始化COE文件。

最后单击Generate按钮生成IROM模块。

2.数据存储器的设计

数据存储器为RAM类型的存储器,并且需要独立的读写控制信号。

因此其对外的接口输入信号为clk、we、datain、addr;输出信号为dataout。

数据存储器基本建立过程同ROM的建立。

3.寄存器组设计

寄存器组是指令操作的主要对象,MIPS中一共有32个32位寄存器。

在指令的操作过程中需要区分Rs、Rt、Rd的地址和数据,并且Rd的数据只有在寄存器写信号有效时才能写入,因此该模块的输入为clk、RegWriteAddr、RegWriteData、RegWriteEn、RsAddr、RtAddr、reset;输出信号为RsData、RtData。

由于$0一直输出0,因此当RsAddr、RtAddr为0时,RsData以及RtData必须输出0,否则输出相应地址寄存器的值。

另外,当RegWriteEn有效时,数据应该写入RegWriteAddr寄存器。

并且每次复位时所有寄存器都清零。

代码如下:

moduleregFile(

inputclk,

inputreset,

input[31:

0]regWriteData,

input[4:

0]regWriteAddr,

inputregWriteEn,

output[31:

0]RsData,

output[31:

0]RtData,

input[4:

0]RsAddr,

input[4:

0]RtAddr

);

reg[31:

0]regs[0:

31];

assignRsData=(RsAddr==5'b0)?

32'b0:

regs[RsAddr];

assignRtData=(RtAddr==5'b0)?

32'b0:

regs[RtAddr];

integeri;

always@(posedgeclk)

begin

if(!

reset)

begin

if(regWriteEn==1)

begin

regs[regWriteAddr]=regWriteData;

end

end

else

begin

for(i=0;i<31;i=i+1)

regs[i]=0;

regs[31]=32'hffffffff;

end

end

endmodule

4.ALU设计

在这个简单的MIPS指令集中,微处理器支持add、sub、and、or、slt运算指令,需要利用ALU单元实现运算,同时数据存储指令sw、lw也需要ALU单元计算存储器地址,条件跳转指令beq需要ALU来比较两个寄存器是否相等。

所有这些指令包含的操作为加、减、与、或小于设置5种不同的操作。

该模块根据输入控制信号对输入数据进行相应的操作,并获得输出结果以及零标示,由于MIPS处理器ALU单元利用4根输入控制线的译码决定执行何种操作,因此该模块的接口为:

输入:

input1(32bit),input2(32bit),aluCtr(4bit)

输出:

zero(1bit),alluRes(32bit)

代码如下:

moduleALU(

input[31:

0]input1,

input[31:

0]input2,

input[3:

0]aluCtr,

output[31:

0]aluRes,

outputzero

);

regzero;

reg[31:

0]aluRes;

always@(input1orinput2oraluCtr)

begin

case(aluCtr)

4'b0110:

begin

aluRes=input1-input2;

if(aluRes==0)

zero=1;

else

zero=0;

end

4'b0010:

aluRes=input1+input2;

4'b0000:

aluRes=input1&input2;

4'b0001:

aluRes=input1|input2;

4'b1100:

aluRes=~(input1|input2);

4'b0111:

begin

if(input1

aluRes=1;

end

default:

aluRes=0;

endcase

end

endmodule

5.ALU控制设计

ALU单元对应以上5种操作的编码如表所示:

输入信号

操作类型

0000

0001

0010

0110

0111

小于设置

通过2位操作类型码以及6位指令功能码就可以产生ALU单元的4位控制信号。

它们之间的对应关系如表所示:

因此该模块的主要功能就是根据译码控制单元产生2位操作码以及6位功能码产生4位ALU控制信号,接口为:

输入:

aluop(2bit),funt(6bit)

输出:

aluctr(4bit)

代码为:

modulealuctr(

input[1:

0]ALUOp,

input[5:

0]funct,

output[3:

0]ALUCtr

);

reg[3:

0]ALUCtr;

always@(ALUOporfunct)

casex({ALUOp,funct})

8'b00xxxxxx:

ALUCtr=4'b0010;

8'b01xxxxxx:

ALUCtr=4'b0110;

8'b11xxxxxx:

ALUCtr=4'b0000;

8'b10xx0000:

ALUCtr=4'b0010;

8'b10xx0010:

ALUCtr=4'b0110;

8'b10xx0100:

ALUCtr=4'b0000;

8'b10xx0101:

ALUCtr=4'b0001;

8'b10xx1010:

ALUCtr=4'b0111;

endcase

endmodule

6.控制器设计

控制器输入为指令的opCode字段,即操作码。

操作码经过主控制单元的译码,给ALUCtr、Data、Memory、Registers、Muxs等部件输出正的控制信号。

微处理器在执行不同指令时,控制信号相对应的状态表如下:

因此该模块的接口为:

输入:

opcode(6bit)

输出:

alusrc,memtoreg,regwrite,memread,memwrite,branch,,aluop[1:

0],jmp

代码为:

modulectr(

input[5:

0]opCode,

outputregDst,

outputaluSrc,

outputmemToReg,

outputregWrite,

outputmemRead,

outputmemWrite,

outputbranch,

output[1:

0]aluop,

outputjmp

);

regregDst;

regaluSrc;

regmemToReg;

regregWrite;

regmemRead;

regmemWrite;

regbranch;

reg[1:

0]aluop;

regjmp;

always@(opCode)

begin

case(opCode)

6'b000010:

//jmp

begin

regDst=0;

aluSrc=0;

memToReg=0;

regWrite=0;

memRead=0;

memWrite=0;

branch=0;

aluop=2'b00;

jmp=1;

end

6'b000000:

//R

begin

regDst=1;

aluSrc=0;

memToReg=0;

regWrite=1;

memRead=0;

memWrite=0;

branch=0;

aluop=2'b10;

jmp=0;

end

6'b100011:

//lw

begin

regDst=0;

aluSrc=1;

memToReg=1;

regWrite=1;

memRead=1;

memWrite=0;

branch=0;

aluop=2'b00;

jmp=0;

end

6'b101011:

//sw

begin

regDst=0;

aluSrc=1;

memToReg=0;

regWrite=0;

memRead=0;

memWrite=1;

branch=0;

aluop=2'b00;

jmp=0;

end

6'b000100:

//beq

begin

regDst=0;

aluSrc=0;

memToReg=0;

regWrite=0;

memRead=0;

memWrite=0;

branch=1;

aluop=2'b01;

jmp=0;

end

6'b001100:

//andi

begin

regDst=0;

aluSrc=1;

memToReg=0;

regWrite=1;

memRead=0;

memWrite=0;

branch=0;

aluop=2'b11;

jmp=0;

end

default:

begin

regDst=0;

aluSrc=0;

memToReg=0;

regWrite=0;

memRead=0;

memWrite=0;

branch=0;

aluop=2'b00;

jmp=0;

end

endcase

end

endmodule

7.符号数扩展

将16位有符号扩展为32位有符号数。

带符号扩展只需要在前面补足符号即可。

代码为:

modulesignext(

input[15:

0]inst,

output[31:

0]data

);

assigndata=inst[15:

15]?

{16'hffff,inst}:

{16'h0000,inst};

endmodule

8.顶层模块

顶层模块需要将前面多个模块实例化,通过导线以及多路复用器将各个部件连接起来,并且在时钟的控制下修改PC的值,PC是一个32位的寄存器,每个时钟沿自动增加4。

多路复用器MUX直接通过三目运算符实现:

AssignOUT=SEL?

INPUT1:

INPUT2;

其中,OUT、SEL、INPUT1、INPUT2都是预先定义的信号。

代码如下:

moduletop(

inputclkin,

inputreset

);

reg[31:

0]pc,add4;

wirechoose4;

wire[31:

0]expand2,mux2,mux3,mux4,mux5,address,jmpaddr,inst;

wire[4:

0]mux1;

//wireforcontroller

wirereg_dst,jmp,branch,memread,memwrite,memtoreg;

wire[1:

0]aluop;

wirealu_src,regwrite;

//wireforaluunit

wirezero;

wire[31:

0]aluRes;

//wireforaluctr

wire[3:

0]aluCtr;

//wireformemory

wire[31:

0]memreaddata;

//wireforregister

wire[31:

0]RsData,RtData;

//wireforext

wire[31:

0]expand;

always@(negedgeclkin)

begin

if(!

reset)begin

pc=mux5;

add4=pc+4;

end

elsebegin

pc=32'b0;

add4=32'h4;

end

end

ctrmainctr(

.opCode(inst[31:

26]),

.regDst(reg_dst),

.aluSrc(alu_scr),

.memToReg(memtoreg),

.regWrite(regwrite),

.memRead(memread),

.memWrite(memwrite),

.branch(branch),

.aluop(aluop),

.jmp(jmp));

ALUalu(.input1(RsData),

.input2(mux2),

.aluCtr(aluCtr),

.zero(zero),

.aluRes(aluRes));

aluctraluctr1(.ALUOp(aluop),

.funct(inst[5:

0]),

.ALUCtr(aluCtr));

dramdmem(

.a(aluRes[7:

2]),

.d(RtData),

.clk(!

clkin),

.we(memwrite),

.spo(memreaddata)

);

irom_numberimem(

.a(pc[8:

2]),

.clk(clkin),

.spo(inst)

);

regFileregfile(

.RsAddr(inst[25:

21]),

.RtAddr(inst[20:

16]),

.clk(!

clkin),

.reset(reset),

.regWriteAddr(mux1),

.regWriteData(mux3),

.regWriteEn(regwrite),

.RsData(RsData),

.RtData(RtData)

);

signextsignext(.inst(inst[15:

0]),.data(expand));

assignmux1=reg_dst?

inst[15:

11]:

inst[20:

16];

assignmux2=alu_scr?

expand:

RtData;

assignmux3=memtoreg?

memreaddata:

aluRes;

assignmux4=choose4?

address:

add4;

assignmux5=jmp?

jmpaddr:

mux4;

assignchoose4=branch&zero;

assignexpand2=expand<<2;

assignjmpaddr={add4[31:

28],inst[25:

0],2'b00};

assignaddress=pc+expand2;

endmodule

 

二、Rom汇编程序设计

下面以将本人学号U201513343的ASCII码存入RAM的连续内存区域编写为汇编程序为例:

编辑MIPS汇编源代码:

采用ultraedit编辑汇编源程序代码,并保存为number.asm文件。

代码如下:

main:

andi$2,$31,85#U

sw$2,0($3)

andi$2,$31,50#2

sw$2,4($3)

andi$2,$31,48#0

sw$2,8($3)

andi$2,$31,49#1

sw$2,12($3)

andi$2,$31,53#5

sw$2,16($3)

andi$2,$31,49#1

sw$2,20($3)

andi$2,$31,51#3

sw$2,24($3)

andi$2,$31,51#3

sw$2,28($3)

andi$2,$31,52#4

sw$2,32($3)

andi$2,$31,51#3

sw$2,36($3)

jmain

获取机器代码,并保存为coe文件:

利用QtSpim装载number.asm,并测试功能是否正常。

装载之后的用户代码段在QtSpim中的结构如附图所示:

提取的用户代码对应的机器码,并把jmain指令对应的机器码0x08100009修改为0x08000000。

将上述机器指令保存在ultraedit中新的文件中,添加coe文件头描述语句,完成后的完整coe文件内容如下:

MEMORY_INITIALIZATION_RADIX=16;

MEMORY_INITIALIZATION_VECTOR=

33e20055,

ac620000,

33e20032,

ac620004,

33e20030,

ac620008,

33e20031,

ac62000c,

33e20035,

ac620010,

33e20031,

ac620014,

33e20033,

ac620018,

33e20033,

ac62001c,

33e20034,

ac620020,

33e20033,

ac620024,

08000000,

将该文件保存为coe文件,即number.coe。

至此,coe文件制作完成。

最后,把coe文件导入irom中,如下图所示:

 

三、模块仿真

1.寄存器组仿真:

建立仿真代码,在自动生成的激励代码基础上加入功能仿真需要的代码:

reset测试、写入测试、输出测试等、完整代码如下:

moduleregsim;

//Inputs

regclk;

regreset;

reg[31:

0]regWriteData;

reg[4:

0]regWriteAddr;

regregWriteEn;

reg[4:

0]RsAddr;

reg[4:

0]RtAddr;

//Outputs

wire[31:

0]RsData;

wire[31:

0]RtData;

//InstantiatetheUnitUnderTest(UUT)

regFileuut(

.clk(clk),

.reset(reset),

.regWriteData(regWriteData),

.regWriteAddr(regWriteAddr),

.regWriteEn(regWriteEn),

.RsData(RsData),

.RtData(RtData),

.RsAddr(RsAddr),

.RtAddr(RtAddr)

);

integeri;

initialbegin

//InitializeInputs

clk=0;

reset=0;

regWriteData=0;

regWriteAddr=0;

regWriteEn=0;

RsAddr=0;

RtAddr=0;

//Wait100nsforglobalresettofinish

#100;

//Addstimulushere

regWriteData=32'h55aaaa55;

regWriteEn=1;

reset=1;

#100;

reset=0;

end

parameterPERIOD=20;

alwaysbegin

clk=1'b0;

#(PERIOD/2)clk=1'b1;

#(PERIOD/2);

end

alwaysbegin

for(i=31;i>=1;i=i-1)begin

regWriteAddr=i;

RsAddr=i;

#PERIOD;

end

end

endmodule

仿真结果如下:

下图可以观察到Reset为高电平状态。

Reset高电平状态下输出数据为0,表示Reset有效地工作了。

Reset信号无效后,正常输入和输出数据。

第一次for循环的地址范围输出数据在时钟低电平时输出0,高电平输出0x55aaaa55,如下图所示,表明数据正确地在时钟上升沿写入的。

之后一直输出的数据与写入的数据相同,表明数据都正确地保存在寄存器组中。

2.控制器仿真:

控制器仿真需要包含所有case的输入,仿真激励文件修改代码后,如下:

modulectrsim;

//Inputs

reg[5:

0]opCode;

//Outputs

wireregDst;

wirealuSrc;

wirememToReg;

wireregWrite;

wirememRead;

wirememWrite;

wirebranch;

wire[1:

0]aluop;

wirejmp;

//InstantiatetheUnitUnderTest(UUT)

ctruut(

.opCode(opCode),

.regDst(regDst),

.aluSrc(aluSrc),

.memToReg(memToReg),

.regWrite(regWrite),

.memRead(memRead),

.memWrite(memWrite),

.branch(branch),

.aluop(aluop),

.jmp(jmp)

);

initialbegin

//InitializeInputs

opCode=0;

//Wait100nsforglobalresettofinish

#100;

opCode=6'b000010;//jump

#100;

opCode=6'b000000;//R

#100;

opCode=6'b100011;//lw

#100;

opCode

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

当前位置:首页 > 自然科学 > 物理

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

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