FPGA期末论文.docx
《FPGA期末论文.docx》由会员分享,可在线阅读,更多相关《FPGA期末论文.docx(16页珍藏版)》请在冰豆网上搜索。
FPGA期末论文
研究生学位课程试卷
院(系、所)专业
考试科目FPGA系统设计与实践第一学期
研究生姓名学号
考试成绩
导师评语:
导师签字
年月日
基于FPGA的CPU的设计
学号:
姓名:
专业:
一、课题要求
1.设计CPU的各个模块,并进行各个模块的综合仿真;
2.掌握VerilogHDL语言编程和程序调试的基本技能;
3.熟悉QuartusII、Modelsim软件的使用;
4.提高运用VerilogHDL语言解决实际问题的能力;
二、CPU总体设计
2.1结构图
RISC_CPU是一个复杂的数字逻辑电路,但是它的基本部件的逻辑并不复杂。
它分成八个基本部件:
1)时钟发生器
2)指令寄存器
3)累加器
4)RISC_CPU算术逻辑运算单元
5)数据控制器
6)状态控制器
7)程序计数器
8)地址多路器
而本课题进一步的将其简化,极大的减少了其工作量及其功能,简化后的CPU共分为六个模块,分别为:
1)数据存储器DRAM;
2)程序存储器IRAM;
3)控制器CONTROL;
4)程序计数器PC;
5)寄存器REG;
6)算术逻辑单元ALU;
本设计的CPU结构图如图2.1所示
图2.1CPU结构图
2.2工作流程
首先,在read=1的前提下从pc程序控制器那里获得指令地址,通过Pc_addr口传递给指令寄存器,否则ir_data为高阻态。
接着通过ir_data口将指令传递给控制器,控制器对9位的指令进行相当于解码的工作,不同的指令对应不同的口传递,这是本设计的不足之处,因为当时为了考虑设计简单点,控制器的各个端口和寄存器和数字存储器的端口对应相连,实现相应的指令。
比如:
当Pc_addr当前地址的内容为000000111,将这条指令交给控制器,控制器对这条指令进行解码分解,(从左往右数)前3位000交给Alu_sel口并传给算术逻辑运算单元控制8种运算,中间的0001分别给Data1_addr[1:
0],Data2_addr[1:
0]口并于寄存器相连,表示要选取的两个操作数在寄存器里面的地址,最后两位11传给Ram_addr并于寄存器相连,Ram_addr用于存储算术逻辑运算单元的输出结果的地址,及选择A,B,C,D四个寄存器的D寄存器。
在执行其他指令时也是同样的思路。
2.3各模块简介
1)数据存储器
图2.2数据存储器图
本DRAM大小为4*16,端口Data为数据端口;四位;Dr_addr为地址线,四位,与控制器相连;Store_dr_addr为地址线,和控制器相连,当执行store语句时,将目标地址传给DRAM;load,store分别控制DRAM加载和存储,1位
2)程序存储器
图2.3指令存储器图
本程序存储器大小为4×16,PC_addr为地址线,四位,与程序计数器相连,程序计数器每次执行完将地址加1传给Iram,read为控制端口,当read=1时,此时将指令传给控制器;ir_data为9位,和控制器相连,代表指令。
3)控制器
图2.3控制器图
Ir_data和程序存储器相连,代表9位指令;Alu_sel为Alu的控制端口及8中不同的操作;Dr_addr和数据存储器相连,R_addr为地址线,2位,当load时,将Dram里面的数据放到四个寄存器中;Data1_addr,Data2_addr用于从A,B,C,D四个寄存器中选择两个操作数;Ram_addr用于存储Alu的输出结果,及选择A,B,C,D四个寄存器的一个;Store_dr_addr,Store_r_addr为地址线,将寄存器里的数据存到指定的Dram里,Jmp用于跳转。
4)程序计数器
图2.4程序计数器图
程序计数器是对程序进行计数,每次加1;pc_addr与程序存储器相连,rst用于复位,ir_addr与控制器相连。
5)寄存器
图2.5寄存器图
寄存器大小为4×4,及A,B,C,D,每个寄存器为四位,data为数据线,Alu_out为alu的输出,Data1_addr,Data2_addr为用户进行加,减,与,或,非操作时的两个操作数,其余的在控制器里均已解释.。
6)算术运算逻辑单元
图2.6算术逻辑运算单元图
alu共有3个输入口,一个输出口,输入口data1,data2代表两个输入,alu_sel;为alu控制端口,及控制加、减、与、或,四种运算,alu_out为输出口。
三、模块设计
本人在设计过程中主要负责控制器模块(contr模块)和指令存储器模块(iram模块)的程序设计和功能仿真。
3.1指令存储器模块设计
指令存储器模块(iram模块)是用来存放指令,本设计中的iram大小是16*9bit,存放了八条指令,依次分别是下载指令(L)、下载指令(L)、加法指令(+)、减法指令(—)、与运算指令(&)、或运算指令(|)、存储指令(S)、跳转指令(J),每条指令共有9位,下面对每条指令进行分析。
下载指令(L):
功能是把数据存储器中的数据提取出来,并存放在寄存器中,分别作为算术逻辑运算单元的操作数和被操作数。
下载指令的前三位是“000”和“001”,即执行两次下载指令,从数据存储器中提取两个数据存放在寄存器中;第五位到第二位代表的是数据存储器的地址,提取该地址对应的数据;最后两位是寄存器的地址,即把数据从数据存储器中提取出来后,将要存放在寄存器中的位置。
加法指令(+):
功能是把寄存器中的数据传输到逻辑运算单元中,进行加法计算,并把计算的结果重新存放在寄存器中。
加法指令的前三位是“010”;第五位到第四位和第三位到第二位是寄存器的两个地址,分别对应操作数和被操作数;最后两位也是寄存器的地址,是逻辑运算单元的运算结果存放的位置。
减法指令(—):
功能类似加法指令。
与运算指令(&):
功能类似同加法指令。
或运算指令(|):
功能类似同加法指令。
存储指令(S):
功能是把存放在寄存器中的数据存储到数据存储器中。
存储指令的前三位是“110”;第五位到第二位代表的是数据存储器的地址,即数据将要存储的位置;最后两位是寄存器的地址,即把对应地址上的数据存储到数据寄存器中。
3.2控制器模块设计
控制器模块(contr模块)实质是对指令存储器中的指令进行翻译,解释执行的每一条指令,把解释的结果传输到各个CPU中各个模块中,控制其执行相应的操作。
四、程序调试和功能仿真
在QuartusII9.0软件中进行程序的编写和调试,编译成功后,把生成的“.V”文件添加到ModelsimSE6.5软件中进行功能仿真,得到仿真结果。
4.1指令存储器模块
4.1.1指令存储器模块程序编译成功
图4.1指令存储器模块程序编译成功图
4.1.2指令存储器模块的功能仿真
图4.2指令存储器模块仿真图
4.2控制器模块
4.2.1控制器模块程序编译成功
图4.3控制器模块程序编译成功图
4.2.1控制器模块程序的功能仿真
图4.4控制器模块仿真图
四、总结
通过CPU系统的设计锻炼了我们的独立思考能力、动手实践能力和团队合作能力,对VerilogHDL语言编程和程序调试的基本技能进一步熟悉,并提高了运用VerilogHDL语言解决实际问题的能力,加深了对FPGA系统设计的理解,建立起“Top—Down”系统设计的思路,另外,对QuartusII、Modelsim软件的使用也更加熟悉。
在和小组成员共同努力下,完成了CPU各个模块的编写,并仿真成功。
但是,本设计还存在问题,各个模块的综合仿真没有能实现,个别模块的仿真还有一点小问题。
总的来说,这次课程设计让我获益匪浅。
五、程序
5.1指令存储器模块程序
moduleiram(ir_data,pc_addr,read);
output[8:
0]ir_data;
input[3:
0]pc_addr;
inputread;
reg[8:
0]memory[15:
0];
wire[8:
0]ir_data;
assignir_data=(read)?
memory[pc_addr]:
9'bzzzzzzzzz;
endmodule
测试程序:
`timescale1ns/1ns
moduleiram_test;
reg[3:
0]pc_addr;
regread;
wire[8:
0]ir_data;
reg[8:
0]memory[15:
0];
parameterDELY=100;
iramAD1(.ir_data(ir_data),.pc_addr(pc_addr),.read(read));
initial
begin
AD1.memory[4'b0000]=9'b000000100;
AD1.memory[4'b0001]=9'b001110001;
AD1.memory[4'b0010]=9'b010000110;
AD1.memory[4'b0011]=9'b011000111;
AD1.memory[4'b0100]=9'b100000110;
AD1.memory[4'b0101]=9'b101000111;
AD1.memory[4'b0110]=9'b110111101;
AD1.memory[4'b0111]=9'b111001000;
read=1;pc_addr=4'b0001;
#DELYread=1;pc_addr=4'b0111;
#DELYread=1;pc_addr=4'b0110;
#DELYread=0;pc_addr=4'b0111;
#DELYread=1;pc_addr=4'b0010;
end
endmodule
5.2控制器模块程序
modulecontr(ir_data,clock,alu_sel,load,store,dr_addr,r_addr,data1_addr,
data2_addr,ram_addr,R,jmp,store_dr_addr,store_r_addr,cf,zf,ir_addr);
input[8:
0]ir_data;
inputcf,zf,clock;
output[2:
0]alu_sel;
outputload,store,R,jmp;
output[3:
0]dr_addr;
output[1:
0]data1_addr;
output[1:
0]data2_addr;
output[1:
0]r_addr;
output[1:
0]ram_addr;
output[3:
0]store_dr_addr;
output[1:
0]store_r_addr;
output[3:
0]ir_addr;
wire[8:
0]ir_data;
wirecf,zf,clock;
reg[2:
0]alu_sel;
reg[3:
0]dr_addr;
reg[1:
0]r_addr;
reg[1:
0]data1_addr;
reg[1:
0]data2_addr;
reg[1:
0]ram_addr;
reg[3:
0]store_dr_addr;
reg[1:
0]store_r_addr;
reg[3:
0]ir_addr;
regload,store,R,jmp;
always@(posedgeclock)
begin
case(ir_data[8:
6])
3'b000:
begin
load=1;store=0;R=0;jmp=0;
dr_addr<=ir_data[5:
2];
r_addr<=ir_data[1:
0];
end
3'b001:
begin
load=1;store=0;R=0;jmp=0;
dr_addr<=ir_data[5:
2];
r_addr<=ir_data[1:
0];
end
3'b010:
begin
load=0;store=0;R=1;jmp=0;
alu_sel<=3'b010;
data1_addr<=ir_data[5:
4];
data2_addr<=ir_data[3:
2];
ram_addr<=ir_data[1:
0];
end
3'b011:
begin
load=0;store=0;R=1;jmp=0;
alu_sel<=011;
data1_addr<=ir_data[5:
4];
data2_addr<=ir_data[3:
2];
ram_addr<=ir_data[1:
0];
end
3'b100:
begin
load=0;store=0;R=1;jmp=0;
alu_sel<=3'b100;
data1_addr<=ir_data[5:
4];
data2_addr<=ir_data[3:
2];
ram_addr<=ir_data[1:
0];
end
3'b101:
begin
load=0;store=0;R=1;jmp=0;
alu_sel<=3'b101;
data1_addr<=ir_data[5:
4];
data2_addr<=ir_data[3:
2];
ram_addr<=ir_data[1:
0];
end
3'b110:
begin
load=0;store=1;R=0;jmp=0;
store_dr_addr<=ir_data[5:
2];
store_r_addr<=ir_data[1:
0];
end
3'b111:
begin
load=0;store=0;R=0;
if(cf||zf)
ir_addr<=ir_data[5:
2];
jmp=1;
end
endcase
end
endmodule
测试程序:
`timescale1ns/1ns
modulecontr_test;
reg[8:
0]ir_data;
regcf;
regzf;
regclock;
wire[2:
0]alu_sel;
wire[3:
0]dr_addr;
wire[1:
0]r_addr;
wire[1:
0]data1_addr;
wire[1:
0]data2_addr;
wire[1:
0]ram_addr;
wire[3:
0]store_dr_addr;
wire[1:
0]store_r_addr;
wire[3:
0]ir_addr;
wireload,store,R,jmp;
parameterDELY=100;
contrAD1(.ir_data(ir_data),.clock(clock),.alu_sel(alu_sel),.load(load),.store(store),
.dr_addr(dr_addr),.r_addr(r_addr),.data1_addr(data1_addr),
.data2_addr(data2_addr),.ram_addr(ram_addr),.R(R),.jmp(jmp),
.store_dr_addr(store_dr_addr),.store_r_addr(store_r_addr),
.cf(cf),.zf(zf),.ir_addr(ir_addr));
initial
begin
clock=0;
#DELYcf=0;zf=0;ir_data=9'b000000100;
#DELYcf=0;zf=0;ir_data=9'b010000110;
#DELYcf=0;zf=0;ir_data=9'b100000110;
#DELYcf=0;zf=0;ir_data=9'b110111101;
#DELYcf=1;zf=0;ir_data=9'b111001000;
#DELYcf=0;zf=0;ir_data=9'b100000110;
end
always#1clock<=~clock;
Endmodule
致谢
参考文献
[1]verilog数字系统设计教程夏宇闻编著北京航空航天大学出版社.