华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx

上传人:b****8 文档编号:10029110 上传时间:2023-02-08 格式:DOCX 页数:27 大小:246.10KB
下载 相关 举报
华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx_第1页
第1页 / 共27页
华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx_第2页
第2页 / 共27页
华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx_第3页
第3页 / 共27页
华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx_第4页
第4页 / 共27页
华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx

《华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx》由会员分享,可在线阅读,更多相关《华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx(27页珍藏版)》请在冰豆网上搜索。

华科HUST微机原理类MIPS单周期微处理器设计实验报告.docx

华科HUST微机原理类MIPS单周期微处理器设计实验报告

微机原理实验报告

 

学号

姓名华中科技大学

专业通信1301

指导教师罗杰

院(系、所)电信学院

 

类MIPS单周期微处理器设计

一.实验目的

1.了解微处理器的基本结构。

2.掌握哈佛结构的计算机工作原理。

3.学会设计简单的微处理器。

4.了解软件控制硬件工作的基本原理。

二.实验任务

利用HDL语言,基于XilinxFPGAnexys4实验平台,设计一个能够执行以下MIPS指令集的单周期类MIPS处理器,要求完成所有支持指令的功能仿真,验证指令执行的正确性,要求编写汇编程序将本人学号的ASCII码存入RAM的连续内存区域。

(1)支持基本的算术逻辑运算如add,sub,and,or,slt,andi指令

(2)支持基本的内存操作如lw,sw指令

(3)支持基本的程序控制如beq,j指令

三.各模块实现原理

1.指令存储器设计

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

设置一个程序计数器指针PC指向指令存储器,当时钟上升沿到来时,取出PC所指的指令,当时钟的下降沿到来时,修改PC的值,使其指向下一条要执行的指令。

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

在本实验中调用ISE提供的IP核进行设计,设定的指令存储器大小为128字。

指令存储器模块在顶层模块中被调用。

输入为指令指针(PC)与时钟信号(clkin),输出为32位的机器指令,并将输出的机器指令送到后续的寄存器组模块、控制器模块、立即数符号扩展模块进行相应的处理。

2.数据存储器设计

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

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

当时钟上升沿到来时,如果写信号(we)为真,根据addr所表示的地址找到对应的存储单元,并将输入的数据(datain)写到对应的存储单元中;如果写信号为假,则根据addr所表示的地址,将对应存储单元的数据送到输出端(dataout)。

在本实验中调用ISE提供的IP核进行设计,设定的数据存储器大小为64字。

数据存储器模块在顶层模块中被调用。

输入的时钟信号来自于顶层模块的clkin,addr信号来自于ALU单元的输出端(对基地址与偏移量执行加操作),datain来自于寄存器组的第二个数据输出端(Rtdata),而控制信号we则来自于控制器对指令的译码。

输出数据dataout通过一个选择器(MUX3)决定是否写入到相应的寄存器。

3.寄存器组设计

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

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

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

另外,当RegWriteEn信号有效时,数据应该写入RegWriteAddr寄存器,并且每次复位时所有寄存器都清零。

寄存器组模块在顶层模块中被调用。

clk信号来自于顶层模块的clkin,reset信号来自于顶层模块的reset,RegWriteData来自于ALU单元的运算结果输出端或者是数据存储器的输出端(通过一个选择器MUX3进行选择),RegWriteAddr、RsAddr、RtAddr来自于指令的对应位,RegWriteEn来自于控制器对指令的译码。

输出信号Rsdata与Rtdata则分别来自于Rsaddr与Rtaddr对应的寄存器。

代码如下:

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、input2和aluCtr,输出端口为zero和aluRes。

ALU模块在顶层模块被调用。

input1来自于寄存器组模块输出信号Rsdata,input2来自于寄存器组模块输出信号Rtdata或者是立即数符号扩展模块的输出信号(通过一个选择器MUX2进行选择),aluCtr来自于aluctr模块的输出端。

aluRes与zero为ALU单元的运算结果,其中zero主要用于beq指令。

代码如下:

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种操作的编码。

MIPS指令中具有6位操作码,如果为R型指令,进一步采用6位功能码来表示R型指令的具体操作。

由于设计的微处理器支持的运算类指令全部为R型指令,因此可以通过对R型指令的6位功能码编码产生ALU的4为控制信号。

但是lw、sw以及beq、j型指令没有功能码,因此需要区分指令的类型。

由于只有三类指令需要ALU单元,因此可以采用两位二进制码对指令的ALU操作类型进行编码。

指令的ALU操作类型编码由指令译码器产生。

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

指令

2位操作码

指令功能

6位功能码

ALU的运算

ALU的控制信号

LW

00

取字

XXXXXX

0010

SW

00

存字

XXXXXX

0010

BEQ

01

相等跳转

XXXXXX

0110

R型指令

10

100000

0010

R型指令

10

100010

0110

R型指令

10

100100

0000

R型指令

10

100101

0001

R型指令

10

小于设置

101010

小于设置

0111

ADDI

11

加立即数

XXXXXX

0010

因此该模块的主要功能就是根据译码控制单元产生的2位操作码以及6位功能码产生4位ALU控制信号,因此输入信号为aluop(2位)、funct(6位),输出信号为aluctr(4位)。

ALU控制模块在顶层模块被调用。

aluop来自于控制器对指令的6位opcode的译码,而funct来自于指令的后6位。

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字段,即操作码。

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

指令

opcode

R型:

add,sub,and,or,slt

000000

I型:

lw

100011

I型:

sw

101011

I型:

beq

000100

J型:

J

000010

I型:

addi

001000

该模块在顶层模块中被调用,输入的opcode来自于指令的前6位,而输出信号aluSrc、MemToReg、RegWrite、MemRead、MemWrite、branch、aluop和jmp则是对6位opcode的译码。

译码结果在此不做说明。

代码如下:

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.立即数符号扩展模块设计

对于I型指令,将指令的低十六位作为立即数符号扩展模块的输入inst[15:

0],如果十六位立即数的最高位(即符号位)为1,则在inst[15:

15]前面补16个1,如果为0,则在前面补16个0。

然后将符号扩展之后的data[31:

0]通过一个选择器(即MUX2)输送到ALU单元的第二个源操作数输入端(即input2)。

代码如下:

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程序设计

本程序的目的是将自己学号的ASCII码存储到数据存储器中。

每个字存储一个ASCII码。

汇编程序代码如下:

main:

addi$2,$0,85#U

sw$2,0($3)

addi$2,$0,50#2

sw$2,4($3)

addi$2,$0,48#0

sw$2,8($3)

addi$2,$0,49#1

sw$2,12($3)

addi$2,$0,51#3

sw$2,16($3)

addi$2,$0,49#1

sw$2,20($3)

addi$2,$0,51#3

sw$2,24($3)

addi$2,$0,54#6

sw$2,28($3)

addi$2,$0,53#5

sw$2,32($3)

addi$2,$0,49#1

sw$2,36($3)

jmain

对应的机器码为:

MEMORY_INITIALIZATION_RADIX=16;

MEMORY_INITIALIZATION_VECTOR=

20020055,

ac620000,

20020032,

ac620004,

20020030,

ac620008,

20020031,

ac62000c,

20020033,

ac620010,

20020031,

ac620014,

20020033,

ac620018,

20020036,

ac62001c,

20020035,

ac620020,

20020031,

ac620024,

08100000,

特别值得注意的有两点:

一是寄存器组中的$1号寄存器被系统占用,在编写汇编代码时不可使用,否则Qtspim会报错;二是机器码的最后一条指令是跳转到程序入口main处,应将机器码改为08100000。

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

四.模块仿真

1.寄存器组仿真:

代码如下:

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

//InitializeInpu

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

当前位置:首页 > 解决方案 > 商业计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1