数字系统课程设计报告书基于FPGA的数字钟设计

数字钟
硬件描述语言Verilog
HDL
FPGA
1.
设计目的
1.掌握利用EDA开发工具QUARTUSII进行可编程逻辑器件设计的方法;
2.掌握用FPGA进行计数器设计的方法;
3.熟练掌握可编程逻辑器件的原理图输入层次化设计方法;
4.掌握利用QUARTUSII进行软件仿真及对可编程逻辑器件进行硬件下载的方法;
5.进一步巩固所学的理论知识,提高运用所学知识分析和解决实际问题的能力。
2.设计内容及要求
1.设计一个具有“时”、“分”、“秒”显示的计时器,(23时59分59秒);
2.“秒电路”、“分电路”均为00—59的六十进制计数、译码、显示电路;
3.“时电路”为00—23的二十四进制计数、译码、显示电路;
4.该实验是基于FPGA的设计,采用Verilog
HDL进行系统功能描述,采用自顶向下的设计方法,用QUARTUSⅡ软件进行仿真测试。
3.系统整体方案及设计原理
如下图(3.1)所示,该系统框图由6个模块组成,分别为:秒、分、时计数器模块,分频器模块(fp20m),计数器显示模块,1602显示驱动模块(
lcd_1602_drive)。
工作原理是:基准脉冲输入信号同时加到秒、分、时的脉冲输入端,采用并行计数的方式,秒的进位接到分的使能端上,分的进位接到时的使能端上,完成秒、分、时的循环计数。要求输入信号有1kHz/1Hz时钟信号、低电平有效的调秒信号set_state、低电平有效的调分信号min_state、低电平有效的调时信号hour_state。
图3.1
4.各模块电路设计与实现
4.1
分频模块设计与实现
4.1.1分频模块图
图(4.1)分频模块图
4.1.2分频模块程序
//输入频率:20MHz
//输出频率:1Hz,1000Hz
module
fp20m(clk,clk1,clk4,clk1000,clk6m);
input
clk;
output
clk1,clk4,clk1000,clk6m;
reg
clk1,clk4,clk1000,clk6m;
reg
[25:0]
cnt,cnt1,cnt2,cnt3;
[emailprotected](posedge
clk)
//1Hz分频
begin
if(cnt>=
9999999
)
//从0到9999999总共10000000次
begin
cnt=0;
clk1=~clk1;//每10000000次翻转,周期为20000000次,也就是1S
end
else
cnt=cnt+1;
end
[emailprotected](posedge
clk)
//1000Hz分频
begin
if(cnt1>=9999)
begin
cnt1=0;
clk1000=~clk1000;
end
else
cnt1=cnt1+1;
end
[emailprotected](posedge
clk)
//1Hz分频
begin
if(cnt2>=
1
)
//从0到9999999总共10000000次
begin
cnt2=0;
clk6m=~clk6m;//每10000000次翻转,周期为20000000次,也就是1S
end
else
cnt2=cnt2+1;
end
[emailprotected](posedge
clk)
//1Hz分频
begin
if(cnt3
>=
2499999
)
//从0到9999999总共10000000次
begin
cnt3=0;
clk4=~clk4;//每10000000次翻转,周期为20000000次,也就是1S
end
else
cnt3=cnt3+1;
end
endmodule
4.2
计数器模块设计与实现
4.2.1计数模块图
图(4.2)计数器模块图
4.2.2秒计数器程序
module
sec_count
(clk,sec_ten_c,//
分钟的十位的进位信号
sec_one_set,//小时的个位设置数
sec_ten_set,//小时的十位设置数
set_state,//设置状态,0的时候计数,1的时候置数
sec_one,//小时的个位
sec_ten);//小时的十位
input
clk;
input
set_state;
input
[3:0]sec_one_set;
input
[3:0]sec_ten_set;
output
[3:0]sec_one;
output
[3:0]sec_ten;
output
[3:0]sec_ten_c;
reg
[3:0]sec_one;
reg
[3:0]sec_ten;
reg
[3:0]sec_ten_c;
reg
temp;
reg
temp2;
reg
sec_one_c;
initial
begin
sec_one
=
0
;
sec_ten
=
0
;
end
always
@(
posedge
clk)
begin
temp2
=
8
h59)
begin
sec_one
=
8
h58)
begin
sec_ten_c
=
9)
begin
sec_one
=
8
h59)
begin
min_one
=
8
h58)
begin
min_ten_c
=
9)
begin
min_one
=
8
h23)
begin
hour_one
=
9)
begin
hour_one
<=
0;
hour_ten
<=
hour_ten
+
1;
end
else
hour_one
<=
hour_one
+
1
;
end
end
temp
<=
min_ten_c;
end
endmodule
4.3
1602显示驱动模块设计与实现
4.3.1
1602显示驱动模块图
图(4.3)
4.3.2
1602显示驱动模块程序
module
lcd_1602_drive(clk,//500Hz时钟
set_state,second_one_set,second_ten_set,minute_one_set,minute_ten_set,hour_one_set,hour_ten_set,second_one,second_ten,minute_one,minute_ten,hour_one,hour_ten,rs,rw,en,data);
input
clk;
input
set_state;
input
[3:0]
second_one_set,second_ten_set;
input
[3:0]
minute_one_set,minute_ten_set;
input
[3:0]
hour_one_set,hour_ten_set;
input
[3:0]
second_one,second_ten;
input
[3:0]
minute_one,minute_ten;
input
[3:0]
hour_one,hour_ten;
output
rs,rw,en;
reg
rs,rw,en;
output
[7:0]
data;
reg
[7:0]
data;
reg
[7:0]
seg1,seg2,next;
reg
[31:0]
data_clock;
reg
[39:0]
data_chars;
reg
[27:0]
counter,counter1,counter2;
reg
[0:7]
m[10:0];
wire[31:0]
data_clock1;
wire[31:0]
set_clock;
parameter
chars=“CLOCK“;
parameter
state0=
8
d0,camd0=
8
d1,state1=
8
d2,camd1=
8
d3,state2=
8
d4,camd2=
8
d5,state3=
8
d6,camd3=
8
d7,state4=
8
d8,camd4=
8
d9,state5=
8
d10,data0=
8
d11,state6=
8
d12,camd5=
8
d13,state7=
8
d14,data1=
8
d15,state8=
8
d16;
initial
begin
m[0]
=8
b0011_0000;//字符“0”代码
m[1]
=8
b0011_0001;//字符“1”代码
m[2]
=8
b0011_0010;//字符“2”代码
m[3]
=8
b0011_0011;//字符“3”代码
m[4]
=8
b0011_0100;//字符“4”代码
m[5]
=8
b0011_0101;//字符“5”代码
m[6]
=8
b0011_0110;//字符“6”代码
m[7]
=8
b0011_0111;//字符“7”代码
m[8]
=8
b0011_1000;//字符“8”代码
m[9]
=8
b0011_1001;//字符“9”代码
m[10]=8
b0011_1010;//字符“:”代码
end
Assign
data_clock1={hour_ten,hour_one,4
d10,minute_ten,minute_one,4
d10,second_ten,second_one};
//8
assign
set_clock={hour_ten_set,hour_one_set,4
d10,minute_ten_set,minute_one_set,4
d10,second_ten_set,second_one_set};
//8
[emailprotected](posedge
clk)
begin
if(set_state==0)
begin
case(next)
//
初始化
//******************************************************************
state0:
begin
rs<=0;
rw<=0;
data<=8
h38;
en<=1;
next<=camd0;
//8位总线,显示2行
5*7
seg1<=8
b1000_0101;
//第一行首地址
seg2<=8
b1100_0011;
//第二行首地址
end
camd0:
begin
en<=0;
rw<=1;
next<=state1;
end
state1:
begin
rs<=0;
rw<=0;
data<=8
h0c;
en<=1;
next<=camd1;
end
//显示器打开,无光标,光标不闪烁
camd1:
begin
en<=0;
rw<=1;
next<=state2;
end
state2:
begin
rs<=0;
rw<=0;
data<=8
h06;
en<=1;
next<=camd2;
end
//写入新数据光标右移,写入新数据后显示屏不移动
camd2:
begin
en<=0;
rw<=1;
next<=state3;
end
state3:
begin
rs<=0;
rw<=0;
data<=8
h01;
en<=1;
next<=camd3;
end
//清屏
camd3:
begin
en<=0;
rw<=1;
next<=state4;
end
//*******************************************************************
//
第一行,显示CLOCK
//******************************************************************state4:
begin
rs<=0;
rw<=0;
data<=seg1;
en<=1;
next<=camd4;
//if(seg1==8
b1000_0101)
seg1=8
b1000_0111;
//可在此处,设置让CLOCLK动态显示
//else
seg1<=seg1-1
b1;
end
camd4:
begin
en<=0;
rw<=1;
next<=state5;
data_chars<=chars;
end
state5:
begin
rs<=1;
rw<=0;
data<=data_chars[39:32];
en<=1;
next<=data0;
end
data0:
begin
if(counter1==5)
begin
next<=state6;counter1=0;end
else
begin
en<=0;rw<=1;counter1=counter1+1;
data_chars<=(data_chars<<8);next<=state5;end
end
//*******************************************************************
//
第二行显示,时间
//*******************************************************************
state6:
begin
rs<=0;
rw<=0;
data<=seg2;
en<=1;
next<=camd5;
//if(seg1==8
b1000_0101)
seg1=8
b1000_0111;
//可在此处,设置让CLOCLK动态显示
//else
seg1<=seg1-1
b1;
end
camd5:
begin
en<=0;
rw<=1;
next<=state7;
data_clock<=data_clock1;
end
state7:
begin
rs<=1;
rw<=0;
data<=m[data_clock[31:28]];
en<=1;
next<=data1;
end
data1:
begin
if(counter2==8)
begin
next<=state8;counter2=0;end
else
begin
en<=0;rw<=1;counter2=counter2+1;
data_clock<=(data_clock<<4);next<=state7;end
end
//*******************************************************************
//
延迟处理
//******************************************************************
state8:
begin
if(counter==100)
begin
counter=0;
next<=state3;end
else
counter=counter+1;
end
//*******************************************************************
endcase
end
if(set_state
==
1)
begin
case(next)
//
初始化
//******************************************************************
state0:
begin
rs<=0;
rw<=0;
data<=8
h38;
en<=1;
next<=camd0;
//8位总线,显示2行
5*7
seg1<=8
b1000_0101;
//第一行首地址
seg2<=8
b1100_0011;
//第二行首地址
end
camd0:
begin
en<=0;
rw<=1;
next<=state1;
end
state1:
begin
rs<=0;
rw<=0;
data<=8
h0c;
en<=1;
next<=camd1;
end
//显示器打开,无光标,光标不闪烁
camd1:
begin
en<=0;
rw<=1;
next<=state2;
end
state2:
begin
rs<=0;
rw<=0;
data<=8
h06;
en<=1;
next<=camd2;
end
//写入新数据光标右移,写入新数据后显示屏不移动
camd2:
begin
en<=0;
rw<=1;
next<=state3;
end
state3:
begin
rs<=0;
rw<=0;
data<=8
h01;
en<=1;
next<=camd3;
end
//清屏
camd3:
begin
en<=0;
rw<=1;
next<=state4;
end
//*******************************************************************
//
第一行,显示CLOCK
//*******************************************************************state4:
begin
rs<=0;
rw<=0;
data<=seg1;
en<=1;
next<=camd4;
//if(seg1==8
b1000_0101)
seg1=8
b1000_0111;
//可在此处,设置让CLOCLK动态显示
//else
seg1<=seg1-1
b1;
end
camd4:
begin
en<=0;
rw<=1;
next<=state5;
data_chars<=chars;
end
state5:
begin
rs<=1;
rw<=0;
data<=data_chars[39:32];
en<=1;
next<=data0;
end
data0:
begin
if(counter1==5)
begin
next<=state6;counter1=0;end
else
begin
en<=0;rw<=1;counter1=counter1+1;
data_chars<=(data_chars<<8);next<=state5;end
end
//****************************************************************
//
第二行显示,时间
//*******************************************************************
state6:
begin
rs<=0;
rw<=0;
data<=seg2;
en<=1;
next<=camd5;
//if(seg1==8
b1000_0101)
seg1=8
b1000_0111;
//可在此处,设置让CLOCLK动态显示
//else
seg1<=seg1-1
b1;
end
camd5:
begin
en<=0;
rw<=1;
next<=state7;
data_clock<=set_clock;
end
state7:
begin
rs<=1;
rw<=0;
data<=m[data_clock[31:28]];
en<=1;
next<=data1;
end
data1:
begin
if(counter2==8)
begin
next<=state8;counter2=0;end
else
begin
en<=0;rw<=1;counter2=counter2+1;
data_clock<=(data_clock<<4);next<=state7;end
end
//*******************************************************************
//
延迟处理
//*******************************************************************
state8:
begin
if(counter==100)
begin
counter=0;
next<=state3;end
else
counter=counter+1;
end
//*******************************************************************
endcase
end
end
Endmodule
5.
系统仿真及硬件下载
5.1系统仿真
5.1.1系统仿真步骤
(1)建立project项目,在软件主窗口单击File菜单后,单击New选项,选择Verilog
HDL
File选项。
(2)单击OK进入空白的文本编辑区,进行文本编辑。
(3)V文件名必须与模块名相同,将dff1.v文件设置为顶层文件,Project—Set
as
Top-level
Entity。
(4)单击编译器快捷方式按钮,完成编译后,弹
出菜单报告错误和警告数目,并生成编译报告。
(5)利用v文件生成原理图模块。在v文件编辑界面中,
File—Creat/Update—Creat
Symbol
Files
for
Curent
File.
(6)打开project
项目,新建波形仿真文件;在建立的波形文件左侧一栏中,点击鼠标右键,在弹出菜单中选择
Insert
Node
or
Bus。
(7)在出现的图中,选择Node
Finder,将打开Node
Finder
对话框,本试验对输入输出的管脚信号进行仿真,所以在Filter
中选择
Pins:all,点击List
按钮。
(8)在图左栏中选择需要进行仿真的端口通过中间的按钮加入到右栏中,点击OK,端口加入到波形文件中。
(8)选择一段波形,通过左边的设置工具条,给出需要的值,设置完成激励波形,保存。
(9)设置为功能仿真:Assignment—Timing
Analysis
Settings--
Simulator
Settings—Simulation
mode
选择Functional,生成网络表Processing—Generate
Functional
Simulation
Netlist;
点击快捷按钮,开始仿真,完成后得到波形。
5.1.2总原理图
图(5.1)
5.1.3仿真图
图(5.2)
5.2硬件下载
5.2.1引脚分配
(1)根据硬件接口设计,对芯片管脚进行绑定。选择Assignments菜单下Pins选项;
(2)双击对应管脚后Location空白框,出现下拉菜单中选择要绑定的管脚,
图(5.3)
5.2.2下载步骤
(1)对目标版适配下载,(此处认为实验板已安装妥当)单击按钮。
选择Hardware
Setup
,之后在图中选择添加硬件ByteBlasteMV
or
ByteBlaster
II,如图(5.4)所示。
图(5.4)
添加下载硬件
(2)可以根据需要添加多种硬件于硬件列表中,双击可选列表中需要的一种,使其出现在当前选择硬件栏中(本实验板采用ByteBlaster
II
下载硬件),如图(5.5)所示;
图(5.5)
选择当前下载硬件
(3)选择下载模式,本实验板可采用两种配置方式,AS模式对配置芯片下载,可以掉电保持,而JTGA模式对FPGA下载,掉电后FPGA信息丢失,每次上电都需要重新配置。
(4)选择下载文件和器件,JTAG
模式使用后缀为sof
的文件,AS模式使用后缀为pof的文件,选择需要进行的操作,分别如图(5.6),图(5.7)所示;使用AS模式时,还要设置Assignments
菜单下Device,选择图中Device
&
Pin
Options,选择使用的配置芯片,编译。
图(5.6)
JTAG下载模式
图(5.7)
AS下载模式
(5)点击Start按键,开始下载。
6.设计总结
本设计利用硬件描述语言Verilog
HDL和FPGA芯片相结合进行数字钟的研究,从中可以看到EDA技术的发展在一定程度上实现了硬件设计软件化。相信随着电子技术的发展,数字钟的功能会更加多样化,满足人们的各种需要。
通过本次数字钟的设计,我了解了用Verilog
HDL语言编程设计电路的一般方法。同时锻炼了自己的分析理解能力和动手能力,并且加深了对数电相关知识的理解。实验时需要十分细心,特别是用Verilog
HDL语言编辑程序,一不小心就容易出错。由于刚开始什么都不了解,EDA开发工具QUARTUSII软件也不会用,花费时间较多,老师讲解后,我们团队又在网上找相关资料,最后终于完成了数字钟设计。
这次EDA设计锻炼了我很多方面的能力,为将来的继续学习和工作都积累了宝贵的经验,令我受益匪浅。非常感谢学校能增加这种实习课程来培养我们的动手能力、分析能力,这些都是在理论课上不曾学到的。更要感谢刘艳昌老师的辅导,我们才可以顺利完成实习课程。
参考文献
[1]阎石.数字电子技术基础(第五版)[M].北京:高等教育出版社,2006.
[2]王金明.数字系统设计与Verilog
HDL(第4版)[M].北京:电子工业出版社,2011.
[3]冼进.Verilog
HDL数字控制系统设计实例[M].北京:中国水利水电出版社,2007.
[4]翁木云.FPGA设计与应用[M].西安:西安电子科技大学出版社,2002.
第
20
页
