基于verilog数字秒表的设计实现.docx
《基于verilog数字秒表的设计实现.docx》由会员分享,可在线阅读,更多相关《基于verilog数字秒表的设计实现.docx(16页珍藏版)》请在冰豆网上搜索。
基于verilog数字秒表的设计实现
班级:
通信13-2班
姓名:
闫振宇
学号:
1306030222
成绩:
电子与信息工程学院
信息与通信工程系
基于verilog数字秒表的设计实现
1.概述
硬件描述语言HDL(HardwareDescriptionLangyage)是一种用形式化方法来描述数字电路和系统的语言。
数字电路系统的设计这里用这种语言可以从上层倒下层逐层描述自设计思想用一系列分层的模块来表示极其复杂的数字系统,然后用EDA工具逐层验证,把其中需要为具体物理电路的模块组合由自动综合工具转换到门级电路网表。
VerilogHDL是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。
被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统之间。
数字系统能够按层次描述,并可在相同描述中显式地进行时序建模。
使用VERILOG进行系统设计时采用的是从顶至下的设计,自顶向下的设计是从系统机开始巴西同划分为若干个基本单元,然后再把每个单元划分为下一层的基本单元,这样下去直到可以直接用EDA元件库中的基本元件来实现为止。
2.设计目的及要求
a.有源晶振频率:
50MHZ;
b.测试计时范围:
00’00”00~59’59”99,显示的最长时间为59分59秒;
c.数字秒表的计时精度是10ms;
d.显示工作方式:
六位BCD七段数码管显示读数,两个按钮开关(一个按钮使秒表复位,另一个按钮控制秒表的启动/暂停)。
3.设计原理
秒表的逻辑结构较简单,它主要由四进制计数器、十六进制计数器、分频器、数据选择器、和显示译码器等组成。
在整个秒表中最关键的是如何获得一个精确的100HZ计时脉冲,除此之外,整个秒表还需有一个启动信号和一个清零信号,以便秒表能随意停止、启动以及清零复位。
秒表有共有6个输出显示,其中6个显示输出数据,分别为百分之一秒、十分之一秒、秒、十秒、分、十分,所以共有6个计数器与之相对应;6个计数器的输出全都为BCD码输出,这样便与同显示译码器连接。
利用一块芯片完成除时钟源,按键和显示器之外的所有数字电路功能。
所有数字逻辑功能都在CPLD器件上用Verilog语言实现。
这样设计具有体积小,设计周期短,调试方便,故障率地和修改升级容易等特点。
本设计采用依次采用以下设计方法:
1)按键输入缓存,键盘消抖设计;
2)分频产生0.01秒信号,产生100HZ的时钟信号设计;
3)数码管动态扫描显示设计;
4)3-8译码器显示(译码)设计;
5)流水线式计数方法设计。
4.设计原理框图
秒表计时器设计原理框图,如图4-1所示。
图4-1秒表计时器设计原理框图
根据设计原理框图4-1,以及设计的要求及目的,可以将VerilogHDL语言设计的秒表计时程序分为四大模块:
1)按键输入缓存,按键消抖模块;
2)分频产生100HZ的时钟信号模块;
3)数码管动态扫描显示驱动模块;
4)计时处理部模块。
5.软件设计
5.1按键输入缓存,按键消抖模块
常在按键较少时可用硬件方法消除抖动,一般采用RS触发器作为常用的消抖电路,如果按键较多时,常用软件消除抖动。
在EDA的设计应用中,软件消抖的方法即可使用 RS 触发器进行消抖,也可通过检测按键按下的时间进行消抖。
5.1.1按键输入缓存,按键消抖程序:
always@(posedgecount[16])
begin
key_inner<=key;
end
always@(posedgekey_inner[0])
begin
key_flag=~key_flag;
end
5.1.2键盘消抖工作原理:
设置输入信号key[1:
0],设置一个模值为 4 的控制计数器key_inner,判断计数寄存器count的第16位的上升沿,检测到key_inner为高电平。
由于计数寄存器的位数为18位。
则说明在0.01s内可以检测到4次高电平。
在人工按键key=‘1’时,key_inner为‘1’,如连续 4 次检测到高电平则key_inner一直为‘1’。
4 次以上检测到高电平key_inner依旧为‘1’,也一直输出高电平。
这就确保了当按键信号持续高电平0.01s 以上按键信号才有效。
抖动期间的高电平持续时间不足以输出高电平。
如没有连续 4 次以上检测到高电平,则 key_inner为‘0’。
再判断 key_inner的上升沿(按键按下为下降沿,弹起为上升沿),每当key_inner[0]出现一次上升沿(按键按下并弹起),key_flag将取反一次(设置key_flag的初值为‘0’)。
5.2分频产生100HZ的时钟信号模块
5.2.1分频产生100HZ的时钟信号程序:
always@(posedgeclk)
begin
if(count==249999)
begin
clk_100hz<=~clk_100hz;
count<=0;
end
else
count<=count+1;
end
分频原理图,如图5-1所示。
图5-1分频原理图
5.2.2分频原理:
由于开发板的输入频率为50MHZ的时钟信号,说明1s产生
个时钟信号。
每个时钟信号持续的时间为
s,由于秒表计时器的最小单位为0.01s,所以要将50MHZ的时钟信号进行
分频,得到100HZ的时钟信号,即0.01s。
5.3数码管动态扫描显示驱动模块
5.3.1数码管动态扫描显示驱动程序:
always@(posedgecount[15])
begin
count3b=count3b+1;
case(count3b)
3'd5:
dis_dat=hour[3:
0];
3'd4:
dis_dat=hour[7:
4];
3'd3:
dis_dat=hour[11:
8];
3'd2:
dis_dat=hour[15:
12];
3'd1:
dis_dat=hour[19:
16];
3'd0:
dis_dat=hour[23:
20];
default:
dis_dat=4'bxxxx;
endcase
sel=count3b;
end
always@(dis_dat)
begin
case(dis_dat)
0:
seg=8'b1100_0000;//显示“0”
1:
seg=8'b1111_1001;//显示“1”
2:
seg=8'b1010_0100;//显示“2”
3:
seg=8'b1011_0000;//显示“3”
4:
seg=8'b1001_1001;//显示“4”
5:
seg=8'b1001_0010;//显示“5”
6:
seg=8'b1000_0010;//显示“6”
7:
seg=8'b1111_1000;//显示“7”
8:
seg=8'b1000_0000;//显示“8”
9:
seg=8'b1001_0000;//显示“9”
default:
seg=8'bxxxxxxxx;
endcase
end
5.3.2数码管动态扫描显示原理:
数码管动态扫描显示表,如表5-1所示。
表5-1数码管动态扫描显示表
六位数码管
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
hour
23:
20
19:
16
15:
12
11:
8
7:
4
3:
0
count3b
5
4
3
2
1
0
dis_dat
0-9
0-9
0-9
0-9
0-9
0-9
由于数码管显示一共有6位,计数寄存器共有18位,则判断计数寄存器的第15位的上升沿即可。
则在每0.01s内判断数码管显示判断8次。
每判断一次,确定一次一只七位数码管的显示数字。
由于在0.01s内六只数码管会发生数值上的变化,共有6只数码管,所以只需要判断8次就能确定秒表计时器0.01s秒内的变化。
将hour显示的值赋给显示数据寄存器dis_dat,再判断dis_dat的值,来确定每只数码管显示的数值。
5.4计时处理部模块
5.4.1计时处理程序:
always@(posedgeclk_100hz)
begin
if(~key_inner[1]&&key_flag==1)
begin
hour=24'h0;
end
elseif(!
key_flag)
begin
hour[3:
0]=hour[3:
0]+1;
if(hour[3:
0]==4'ha)
begin
hour[3:
0]=4'h0;
hour[7:
4]=hour[7:
4]+1;
if(hour[7:
4]==4'ha)
begin
hour[7:
4]=4'h0;
hour[11:
8]=hour[11:
8]+1;
if(hour[11:
8]==4'ha)
begin
hour[11:
8]=4'h0;
hour[15:
12]=hour[15:
12]+1;
if(hour[15:
12]==4'h6)
begin
hour[15:
12]=4'h0;
hour[19:
16]=hour[19:
16]+1;
if(hour[19:
16]==4'ha)
begin
hour[19:
16]=4'h0;
hour[23:
20]=hour[23:
20]+1;
end
if(hour[23:
20]==4'h6)
hour[23:
20]=4'h0;
end
end
end
end
end
end
5.4.2计时处理原理:
计时器处理流程框图,如图5-2所示。
图5-2计时器处理流程框图
判断复位键用key_flag为启动/暂停的切换标志,判断key_flag是否为‘1’,为‘1’说明计数暂停,为‘0’说明计数开始;key_inner[1]是输入信号端,按键未按下时,key_inner[1]为‘1’,按下后为‘0’,~key_inner[1]判断为‘1’,则说明,在程序暂停的情况下,控制按键可使秒表计时器清零。
百秒位,十秒位,秒位是十进制计数,十秒位,分位,十分位是6进制计数。
6.实验设计原理图
实验设计原理图,如图6-1所示。
图6-1实验设计原理图
实验设计有三个输入位,key[1:
0]为手动输入端,key[0]为启动/暂停控制键,key[1]是复位控制键。
clk是时钟输入端。
输出分为sel[2:
0]为数码管的位选,实验中共有6只数码管,则可以选择8位的位选。
seg[7:
0]是数码管的段选,将每一位的数字进行显示。
7.心得体会
在将近两周的学习时间内,大致了解了利用VerilogHDL硬件描述语言来编写简单的程序代码。
并对所编写的程序结合开发板得以实现,对所编写的程序进行仿真得到了理论值,结合开发板得到了实际结果。
在学习的过程中,要了解一种新语言,要了解这种语言的语法结构,书写格式,特殊语句实现的操作等。
在老师的指导下,在比较紧的时间内学习了FPGA利用Verilog语言编写程序的流程以及QuartusⅡ软件的使用方法及操作。
学到了很多的知识,也看到了软件的强大的功能。
在整个的学习过程中,有过疑问,在编写中出现了很多的错误,但经过想老师请教,与同学讨论,都得以解决。
本实验使用Verilog语言编写秒表计时器的程序,实验中将程序分为四个模块,按键输入缓存,按键消抖模块,分频产生100HZ的时钟信号模块,数码管动态扫描显示驱动模块,计时处理部模块。
按照模块的划分对程序进行编写,经四个模块连通起来实现秒表计时的功能。
希望有机会做到更多有趣的实验,丰富自己,让自己学到更多的知识。
参考文献
[1]陈耀省.Verilog秒表设计.2012:
15
17.
[2]大彬哥.基于VerilogHDL的数字计时器的设计.2013:
11.
附件:
moduleled_on
(
input[1:
0]key,//输入信号
inputclk,//输入频率为50MHZ的时钟
outputreg[2:
0]sel,//数码管位选
outputreg[7:
0]seg,//数码管段选
outputen//3-8译码器使能
);
reg[2:
0]count3b;
reg[3:
0]dis_dat;//定义显示数据寄存器
reg[18:
0]count;//定义计数寄存器
reg[23:
0]hour;//定义现在时刻寄存器
regclk_100hz;//50MHZ的时钟信号500000分频,得到100HZ的时钟信号
regkey_flag;//启动/暂停的切换标志
reg[1:
0]key_inner;
assignen=0;
//
(1)按键输入缓存,按键消抖设置
always@(posedgecount[16])//在0.01s内,扫描2的2次方,可以检测到4次高电平
begin
key_inner<=key;
end
always@(posedgekey_inner[0])
begin
key_flag=~key_flag;
end
//
(2)0.01秒信号产生部分,产生100HZ的时钟信号
always@(posedgeclk)
begin
if(count==249999)
begin
clk_100hz<=~clk_100hz;
count<=0;
end
else
count<=count+1;
end
//(3)数码管动态扫描显示部分
always@(posedgecount[15])//时序逻辑,由于有6个数码管,则在一秒内扫描2的6次方
begin
count3b=count3b+1;
case(count3b)
3'd5:
dis_dat=hour[3:
0];
3'd4:
dis_dat=hour[7:
4];
3'd3:
dis_dat=hour[11:
8];
3'd2:
dis_dat=hour[15:
12];
3'd1:
dis_dat=hour[19:
16];
3'd0:
dis_dat=hour[23:
20];
default:
dis_dat=4'bxxxx;
endcase
sel=count3b;
end
always@(dis_dat)
begin
case(dis_dat)
0:
seg=8'b1100_0000;//显示“0”
1:
seg=8'b1111_1001;//显示“1”
2:
seg=8'b1010_0100;//显示“2”
3:
seg=8'b1011_0000;//显示“3”
4:
seg=8'b1001_1001;//显示“4”
5:
seg=8'b1001_0010;//显示“5”
6:
seg=8'b1000_0010;//显示“6”
7:
seg=8'b1111_1000;//显示“7”
8:
seg=8'b1000_0000;//显示“8”
9:
seg=8'b1001_0000;//显示“9”
default:
seg=8'bxxxxxxxx;
endcase
end
//(4)计时处理部分
always@(posedgeclk_100hz)//计时处理
begin
if(~key_inner[1]&&key_flag==1)//判断是否复位键,
begin
hour=24'h0;
end
elseif(!
key_flag)
begin
hour[3:
0]=hour[3:
0]+1;
if(hour[3:
0]==4'ha)
begin
hour[3:
0]=4'h0;
hour[7:
4]=hour[7:
4]+1;
if(hour[7:
4]==4'ha)
begin
hour[7:
4]=4'h0;
hour[11:
8]=hour[11:
8]+1;
if(hour[11:
8]==4'ha)
begin
hour[11:
8]=4'h0;
hour[15:
12]=hour[15:
12]+1;
if(hour[15:
12]==4'h6)
begin
hour[15:
12]=4'h0;
hour[19:
16]=hour[19:
16]+1;
if(hour[19:
16]==4'ha)
begin
hour[19:
16]=4'h0;
hour[23:
20]=hour[23:
20]+1;
end
if(hour[23:
20]==4'h6)
hour[23:
20]=4'h0;
end
end
end
end
end
end
endmodule