cpuxiong.docx
《cpuxiong.docx》由会员分享,可在线阅读,更多相关《cpuxiong.docx(20页珍藏版)》请在冰豆网上搜索。
cpuxiong
CPU设计实验报告(受陈超同学指点)
1设计目的:
1)初步学习硬件逻辑电路建模,并用HDL语言描述硬件电路。
2)掌握应用quarter环境进行开发的流程,学会使用maxplus进行操作。
3)掌握基本verilog语言,可以编写基本的程序。
4)掌握cpu的组成原理,懂得运行过程,实现相应的编码。
2设计目标:
设计一简单的CPU模型,可以实现基本的运算,跳转,装入,读出等功能,通过微指令和机器指令的编写来实现相应的功能。
3模块设计规格及输入输出端变量说明:
1)简单cpu模型,通过微指令和机器指令的编写来实现传输、运算和读写
等基本功能。
2)模块原理框图
3)CPU指令格式:
1.单字节指令:
操作码OP4位
目的寄存器Rd2位
源寄存器Rs2位
操作码OP4位
相对转移偏移量,4位补码,含一位符号位
2.双字节指令
操作码OP4位
目的寄存器Rd2位
2位
立即数字段8位
举例:
LDI操作
3.CPU设计指令集
序号
指令助记符
实现的功能
操作码
指令举例
二进制机器码
1
LDIRd,data
立即数传输
Rd←data
0000
LDIR2,78H
00001000
01111000
2
LDRd,(Rs)
读内存
Rd←M(Rs)
0001
LDR2,(R1)
00011001
3
STR(Rd),Rs
写内存
M(Rd)←Rs
0010
STR(R2),R1
00101001
4
ADDRd,Rs
加运算
Rd←Rs+Rd
并设置Cy,Zero标志
0011
ADDR3,R0
00111100
5
ANDRd,Rs
与运算
Rd←Rs&Rd
并设置Zero标志
0100
ANDR1,R0
01000100
6
MOVRd,Rs
寄存器传输
Rd←Rs
0101
MOVR1,R2
01010110
7
JPtarget
相对转移
PC←PC+target
0110
JP-5
01101011
JP6
01100110
8
JCtarget
条件相对转移、有进位时相对转移
如果Cy==1’b1,
那么PC←PC+target,程序实现转移。
否则不修改PC,程序顺序执行。
0111
JC-5
01111011
-5的补码为1011
JC6
01110110
6的补码为0110
9
HLT
停机
1000
HLT
10000000
6)具体器件功能描述:
1.总线:
当XXX_B为1时,XXX部件输出到总线上,否则为高阻态。
LDYYY为1时,当T2上升沿到来时,将总线上的数据输入到YYY部件。
2.ALU运算器:
当ALU_B为1时,ALU输出,否则处于高阻态S2、S1、S0控制ALU进行何
种运算,本设计主要有加运算和与运算。
3.寄存器R3~R0:
以R0为例:
当R0_B为1时,R0输出,否则处于高阻态。
当LDR0为1时,
在时钟上升沿,接收数据。
由于主存中方的是RD和RS的值,所以通过程
序解码来选择相应的R寄存器。
4.寄存器PC:
当LDPC为1时,在时钟上升沿,接收数据。
当PCINC为1时,在时钟
上升沿,实现PC+1。
当PC_B为1时,输出数据。
否则高阻态。
5.寄存器IR:
当LDIR为1时,在时钟上升沿接收数据,送入微程序控制器,IR_B为1
时,送数据到数据总线。
6.AR地址寄存器、A、B暂存器:
当LDAR为1时,AR在时钟上升沿接收数据,送入主存;LDA为1时,A暂
存器从主线接收数据,B与A相同。
7.Cy进位标志寄存器:
当做加法指令时,进位保存在Cy中。
8.内存:
CE=1WE=0:
读内存
CE=0WE=1:
写内存。
7)输入输出变量详述:
1.T1,T2:
相反的节拍信号。
2.reset:
初始化信号,初始化主存和微存。
3.bus[7:
0]:
数据总线,用来输入和输出数据。
4.UA[4:
0]:
微指令的存放地址。
5.XXX_B[2:
0]:
三位信号,进行译码,选择具体器件,将值送总线。
6.LDYYY[2:
0]:
三位信号,进行译码后,选择具体器件,总线的值送器件。
7.PC_B,ALU_B,Rs_B,Rd_B,IR_B:
信号为1时相应器件的值送总线。
8.LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR:
信号为1时总线的值送器件。
9.PCINC:
信号为1时实现PC+1送PC操作。
10.IR,AR,PC,R0,R1,R2,R3,bus,A,B,ALU[7:
0]:
器件定义,为8位。
11.MEM_00到MEM_0F:
主存地址定义。
12.CE,WE:
实现主存的读写操作。
13.s2,s1,s0:
控制运算器进行相关的运算。
8)微指令格式:
微指令设计:
读写内存
2位
运算器
3位
向总线输出
4位
从总线输入
3位
下地址
先暂定5位
/CE/WE
S2S1S0
XXX_B
LDYYY
/CE=1/WE=x,不操作。
/CE=0/WE=0写内存;/CE=0/WE=1读内存
运算器指令:
运算类型
S2S1S0
功能
逻辑运算
000
ALU=A
001
ALU=A&B
010
ALU=A|B
011
ALU=~A
移位运算
100
ALU=A逻辑左移一位
算术运算
101
ALU=A+B
110
ALU=A+1
111
ALU=A-1
总线输出:
LDYYY
选择
0
0
0
0
NOP
0
0
0
1
LDA
0
0
1
0
LDB
0
0
1
1
LDRs
0
1
0
0
LDRd
0
1
0
1
LDIR
0
1
1
0
LDAR
0
1
1
1
LDPC
1
0
0
0
LDMDR
总线输入:
XXX_B
选择
0
0
0
NOP
0
0
1
ALU_B
0
1
0
Rs_B
0
1
1
PC_B
1
0
0
IR_B
1
0
1
MDR_B
1
1
0
Rd_B
微指令表:
地址
读写/CE/WE
运算
S2-S0
总线输入
LDxxx
总线输入
xxx_B
PCINC
下一跳
功能
00000
10
000
0000
000
0
00001
NOP
00001
10
000
0110
011
1
00010
PC-AR,PC+1
LDI
00010
01
000
0101
000
0
11111
MEM-IR
00011
10
000
0110
011
1
00100
PC-ARPC+1
00100
01
000
0100
000
0
00001
MEM-Rd
LD
00101
10
000
0110
010
0
00100
Rs-AR
STR
00110
10
000
0110
110
0
00111
Rd-AR
00111
00
000
!
!
1000
010
0
00001
Rs-MEM
ADD
01000
10
000
0001
110
0
01001
Rd-A
01001
10
000
0010
010
0
01010
Rs-B
01010
10
101
0100
001
0
00001
A+B-Rd
AND
01011
10
000
0001
010
0
01100
Rd-A
01100
10
000
0010
010
0
01101
Rs-B
01101
10
001
0100
001
0
00001
A&B-Rd
MOV
01110
10
000
0011
110
0
00001
Rd-Rs
HLT
01111
10
000
0000
000
0
01111
HLT
JP
10000
10
000
0001
011
0
10001
PC-A
10001
10
000
0010
100
0
10010
Code[3:
0]-B
10010
10
101
0111
001
0
00001
ALU-PC
JC
4.程序代码(需要注解):
module
cpu(reset,T1,T2,XXX_B,bus,LDYYY,PC_B,ALU_B,Rs_B,Rd_B,IR_B,LDRs,LDRd,UA,LDPC,LDA,LDB,LDIR,LDAR,PCINC,CE,WE,s2,s1,s0);
inputreset,T1,T2;//input变量定义
output[7:
0]bus;//output变量定义
output[4:
0]UA;
output[2:
0]XXX_B,LDYYY;
outputPC_B,ALU_B,Rs_B,Rd_B,IR_B,LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR,PCINC,CE,WE,s2,s1,s0;
reg[2:
0]XXX_B,LDYYY,s;//reg型变量定义
regPC_B,ALU_B,Rs_B,Rd_B,IR_B,CE,WE,s2,s1,s0;
regLDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR,PCINC;
reg[4:
0]UA;
reg[7:
0]IR,AR,PC,R0,R1,R2,R3,bus,A,B,ALU;
reg[7:
0]MEM_00,MEM_01,MEM_02,MEM_03,MEM_04,MEM_05,MEM_06,MEM_07,MEM_08,MEM_09,MEM_0A,MEM_0B,MEM_0C,MEM_0D,MEM_0E,MEM_0F;
regcy;
always@(posedgeT1)
begin
if(reset)//微指令赋初值
begin
{CE,WE}=2'b00;
UA=5'b00000;
XXX_B=3'b000;
LDYYY=3'b000;
{s2,s1,s0}=3'b000;
PCINC=1'b0;
end
case(UA)
5'b00000:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000000000000001;
//开始,下条地址00001
5'b00001:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000111010100100;
//PC_B,PCINC,LDAR信号为1,实现PC送AR,PC+1送PC,下条地址00100
5'b00010:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000111010100101;
//PC_B,PCINC,LDAR信号为1,实现PC送AR,PC+1送PC,下条地址00101
5'b00011:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000111011001000;
//Rs_B,LDAR信号为一,实现Rs送AR操作
5'b00100:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b10000110000010011;
//CE,LDIR信号为,读内存送总线,写入IR,下条地址10011
5'b00101:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b10000010000000001;
//CE,LDRD信号为1,读出内存写入Rd,完成LDI,返回00001
5'b00110:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000111100001001;
//STR操作,完成RD送AR
5'b00111:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000100100001100;
//RD_B,LDA信号为1,实现RD送A,下条地址01100
5'b01000:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b10000010000000001;
//CE,LDRD信号为1,实现主存送bus写入微存的操作,完成LD,返回00001
5'b01001:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b01000000011000001;
//RS送MEM,返回00001
5'b01010:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000100100010000;
//与运算,与加运算相同
5'b01011:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000010011000001;
5'b01100:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000101011001101;
//实现RS送B,下条地址01101
5'b01101:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00001010001000001;
//s2,s1,s0为001,进行加运算,ALU_B,LDPC为1,实现A+B送回RD,返回00001
5'b01110:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000100010010100;
//JP运算入口,实现PC送A,跳到10100
5'b01111:
begin
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC}=12'b000000000000;
if(cy==1'b1)//有进位,进行JP操作
UA=5'b01110;
else//没有进位,返回00001
UA=5'b00001;
end
5'b10000:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000101011010001;
5'b10001:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00010010001000001;
5'b10010:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000000000010010;
//停机操作
5'b10011:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}={12'b000000000000,IR[7],IR[6],IR[5],1'b1,IR[4]};
//P<1>改地址,修改下条地址为IR高四位,中间插入1
5'b10100:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00000101101010101;
//IR送B,跳到10101
5'b10101:
{CE,WE,s2,s1,s0,LDYYY,XXX_B,PCINC,UA}=17'b00001011001000001;
//相加送给PC,返回00001
endcase
end
always@(XXX_B)//XXX_B信号变化执行此模块
begin
case(XXX_B)//给相应的读取信号赋值
3'b000:
{ALU_B,PC_B,Rs_B,Rd_B,IR_B}=5'b00000;
3'b001:
{ALU_B,PC_B,Rs_B,Rd_B,IR_B}=5'b10000;
3'b010:
{ALU_B,PC_B,Rs_B,Rd_B,IR_B}=5'b01000;
3'b011:
{ALU_B,PC_B,Rs_B,Rd_B,IR_B}=5'b00100;
3'b100:
{ALU_B,PC_B,Rs_B,Rd_B,IR_B}=5'b00010;
3'b101:
{ALU_B,PC_B,Rs_B,Rd_B,IR_B}=5'b00001;
endcase
end
always@(LDYYY)//LDYYY信号变化执行此模块
begin
case(LDYYY)//给相应的装入信号赋值
3'b000:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b0000000;
3'b001:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b1000000;
3'b010:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b0100000;
3'b011:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b0010000;
3'b100:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b0001000;
3'b101:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b0000100;
3'b110:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b0000010;
3'b111:
{LDRs,LDRd,LDPC,LDA,LDB,LDIR,LDAR}=7'b0000001;
endcase
end
always@(posedgeT2)
begin
if(reset)//主存指令初始化
begin
MEM_00=8'b00000000;//LDIR0
MEM_01=8'b00000010;
MEM_02=8'b00000100;//LDIR1
MEM_03=8'b11000011;
MEM_04=8'b00011001;//LDR2<-M(R1)
MEM_05=8'b00101001;//STRM(R2)R1
MEM_06=8'b00110100;//ADDR0+R1->R1
MEM_07=8'b01000100;//ANDR0&R1->R1
MEM_08=8'b01010100;//MOVR0->R1
MEM_0A=8'b00001010;
MEM_0B=8'b01100001;//JP
MEM_0C=8'b01110001;//JCcy=1时,PC+target
MEM_0D=8'b10000000;//HLT
end
end
always@(posedgeT2)//实现总线送入相应的寄存器
begin
case({LDPC,PCINC})//都是装入PC,防止冲突,进行判断
2'b01:
PC=PC+1;
2'b10:
PC=bus;
endcase
case({LDRd,LDRs,LDIR,LDAR,LDA,LDB})//判断送入哪个寄存模块
6'b100000:
begin
case(IR[3:
2])//通过IR的三四位选择目的寄存器
2'b00:
R0=bus;
2'b01:
R1=bus;
2'b10:
R2=bus;
2'b11:
R3=bus;
endcase
end
6'b010000:
begin
case(IR[1:
0])//通过IR的低两位位选择源寄存器
2'b00:
R0=bus;
2'b01:
R1=bus;
2'b10:
R2=bus;
2'b11:
R3=bus;
endcase
end
6'b001000:
IR=bus;
6'b000100:
AR=bus;
6'b000010:
A=bus;
6'b000001:
B=bus;
endcase
end
always@(Rs_BorRd_BorIR_BorPC_BorALU_BorCEorWEorAR)
begin//实现相应的寄存器参数送总线
case({Rs_B,Rd_B,IR_B,PC_B,ALU_B})//判断哪个寄存模块输入总线
5'b10000:
begin
case(IR[1:
0])//通过IR的三四位选择目的寄存器
2'b00:
bus=R0;
2'b01:
bus=R1;
2'b10:
bus=R2;
2'b11:
bus=R3;
endcase
end
5'b01000:
begin//通过IR的低两位位选择源寄存器
case(IR[3:
2])
2'b00:
bus=R0;
2'b01:
bus=R1;
2'b10:
bus=R2;
2'b11:
bus=R3;
endcase
end
5'b00100:
bus={IR[3],IR[3],IR[3],IR[3],IR[3],IR[2],IR[1],IR[0]};
5'b00010:
bus=PC;
5'b00001:
bus=ALU;
endcase
if({CE,WE}==2'b10)////读内存,内存送总线
begin
case(AR[7:
0])
8'b00000000:
bus=MEM_00;
8'b00000001:
bus=MEM_01;
8'b00000010:
bus=MEM_02;
8'b00000011:
bus=MEM_03;
8'b00000100:
bus=MEM_04;
8'b00000101:
bus=MEM_05;
8'b00000110:
bus=MEM_06;
8'b00000111:
bus=MEM_07;
8'b00001000:
bus=MEM_08;