FPGA数字钟之欧阳育创编.docx

上传人:b****8 文档编号:10854814 上传时间:2023-02-23 格式:DOCX 页数:24 大小:39.18KB
下载 相关 举报
FPGA数字钟之欧阳育创编.docx_第1页
第1页 / 共24页
FPGA数字钟之欧阳育创编.docx_第2页
第2页 / 共24页
FPGA数字钟之欧阳育创编.docx_第3页
第3页 / 共24页
FPGA数字钟之欧阳育创编.docx_第4页
第4页 / 共24页
FPGA数字钟之欧阳育创编.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

FPGA数字钟之欧阳育创编.docx

《FPGA数字钟之欧阳育创编.docx》由会员分享,可在线阅读,更多相关《FPGA数字钟之欧阳育创编.docx(24页珍藏版)》请在冰豆网上搜索。

FPGA数字钟之欧阳育创编.docx

FPGA数字钟之欧阳育创编

数字钟设计

时间:

2021.02.04

创作:

欧阳育

一、实验目的:

通过设计实例,深入理解自顶向下设计方法,系统设计规范、系统设计、模块设计和系统仿真与实现各阶段的设计内容,初步掌握规范的数字系统设计方法并实践。

二、实验要求:

1、系统概述:

设计一个用LED7段显示器显示的24小时制数字钟。

2、系统目标:

(1)用8个LED显示时间,如9点25分10秒显示为,09-25-10。

(2)设置2个按键,按键SET用于工作模式选择,按键UP用于设置数值。

(可选)

(3)按SET键循环设置工作模式为:

正常显示->时设置->分设置->秒设

置。

在设置工作模式时,被设置相应数字按1秒速率闪烁,其它数字不变。

(4)在设置工作模式时,按UP键一次,被设置相应数字增加1,加到最大值后再加返回0,如小时加到23后再加就返回0,分和秒加到59后再加返回0。

3、系统设计依据:

外部输入时钟为40MHZ,通过分频产生秒脉冲信号,用模60计数器对其计数产生分脉冲信号,对分脉冲用模60计数器对其计数产生时脉冲信号,再用模24计数器对时脉冲计数,即可实现一天24小时的时间信号,通过7段LED数码管显示出来则为基本数字钟,校时电路通过两个外部异步按键对“时”、“分”、“秒”显示数字进行校对调整。

4、系统实现要求:

要求用Mars-EP1C3-EDA实验平台。

芯片与封装选择:

本设计用EP1C3TFPGA实现,144脚封装,输入输出为LVTTL电平。

5、系统验证及测试要求:

用Mars-EP1C3-EDA实验平台搭建模拟测试平台测试,测试验证数字钟实现设计目标。

三、系统设计关键技术

1、按键消抖

图3-1

由图3-l可见,在按键闭合和断开时产生了多个边沿,而在实际中每按一次键,我们只需要一组稳定的上升或下降边沿,所以对于电路中的按键信号,如果我们不滤除抖动的话,还是简单的读取信号的边沿,会引起一次按键被误读多次,这样就会引起电路的误动作。

为了保证按一次键电路只有一次正确的响应,即在键闭合稳定时读取键的状态,就要求电路中必须采取滤除抖动的措施。

原理:

在设计中用时钟信号(key_clk)进行采样,对于按键输入信号,当两次采样信号相同时,这是判定已经稳定的按下或放开了按键,D触发器相应的被置成0态或1态。

如两次采样结果不相同,则触发器维持原输出信号不变,由于直接由触发器输出的信号时间宽度可能过长,所以在触发器后再接一级同步化电路,保证每次输出的信号只占有一个时钟周期的宽度。

应用这种方法去滤除抖动,关键是确定采样时钟的频率,保证两次采样的时间间隔能够大于按键的抖动时间,且小于正常按键时的按键稳定闭合时间。

2、采用BCD码的计数模式

时、分、秒的计数都采用BCD码计数,如果采用二进制计数,分的最大计数值为59,只需要6位就可以,因为时的计数值要通过两个数码管显示,所以计数值需要经过两级译码才能驱动数码管使其正常显示,必须先把计数值译码成高低四位的BCD码,然后再分别把高、低四位BCD码译码成数码管的显示编码。

如果直接采用BCD码计数,只需要一次译码就可以正常显示计数值,故采用BCD码计数更方便,简化电路。

3、数码管的动态显示

数码管的动态扫描,就是轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时在显示。

数码管的轮流扫描频率不能太小,否则数码管不能同时显示,一般扫描频率在500Hz到1Khz即可。

本设计中的数码管位选信号为低电平有效,数码管的段为低显,复位后把位选信号d_col赋值为8’b1111_1110,然后以1Khz的扫描频率使其循环左移,并送出相应位的字形码,即可实现数码管的动态显示。

四、系统详细设计方案:

1、系统设计分析:

数字钟是一个将“时”,“分”,“秒”显示于人的视觉器官的计时装置。

它的计时周期为24小时,显示满刻度为23时59分59秒,另外应有校时功能。

秒信号产生器是整个系统的时基信号,它直接决定计时系统的精度,通过将外部输入时钟为40MHZ分频实现。

将标准秒信号送入“秒计数器”,“秒计数器”采用60进制计数器,每累计60秒发生一个“分脉冲”信号,该信号将作为“分计数器”的时钟脉冲。

“分计数器”也采用60进制计数器,每累计60分钟,发出一个“时脉冲”信号,该信号将被送到“时计数器”。

“时计数器”采用24进制计时器,可实现对一天24小时的累计。

将“时”、“分”、“秒”计数器的输出值经七段显示译码器译码,通过八位LED七段显示器显示出来,显示格式为“时—分—秒”。

通过Set和Up按键对“时”、“分”、“秒”显示数字进行校对调整,Set键循环控制工作模式,即“正常显示”、“时设置”、“分设置”、“秒设置”的循环控制,在设置工作模式时,被设置相应数字按1秒速率闪烁,其它数字不变。

Up键实现调整状态时相应时间的快速加“1”以实现时间校准。

2、系统时钟和复位规划:

本设计采用一个全局时钟clk和复位reset。

3、顶层模块划分及模块功能说明

系统分为5个模块,Freq_div模块,Clock_cnt模块,Clock_ctl模块,Key_ctl模块和Display模块。

系统框图如图4-1所示,图4-2是顶层模块设计。

输入信号:

clk:

系统时钟;reset:

系统复位;

set:

工作模式选择按键;up:

调时按键;

输出信号:

d_col[7:

0]:

八位LED动态选择;

d_out[7:

0]:

LED显示数据;

图4-1系统框图

图4-2顶层模块设计

4、每个模块详细功能说明,信号定义及时序定义

(1)Freq_div模块:

将40MHz的系统时钟进行分频产生三种时钟使能信号:

scan_clk(1khz)、key_clk(100hz)、s_clk(1hz)。

输入信号:

clk:

系统时钟rst_n:

复位信号

输出信号:

scan_clk:

数码管扫描频率key_clk:

按键采样频率

s_clk:

1s时钟信号

(2)Key_ctl模块:

完成对按键的同步、去抖功能,输出稳定的按键信号set_en、up_en。

输入信号:

clk:

系统时钟rst_n:

复位信号

set:

模式设置按键up:

计数值加按键

输出信号:

Set_en:

模式设置使能信号up_en:

按键加使能信号

(3)Clock_ctl模块:

通过set_en信号对“正常显示”、“时设置”、“分设置”、“秒设置”模式的循环控制,并产生设置信号h_set(时)、m_set(分)、s_set(秒)供Clock_cnt使用。

输入信号:

Clk:

系统时钟;reset:

复位信号;

set_en:

工作模式选择信号;

输出信号:

H_set:

时设置使能信号;M_set:

分设置使能信号,

S_set:

秒设置使能信号;状态机信号:

Normal:

正常显示状态;Hour_set:

时设置状态;

Minute_set:

分设置状态;Second_set:

秒设置状态。

(4)Clock_cnt模块:

完成数字钟的正常显示和数字钟的时、分、秒的校时,在校时模式下,通过ctl信号控制LED的闪烁,也就是间隔1s输出时间数据。

输入信号:

Clk:

系统时钟reset:

复位信号;

up_en:

校时信号s_clk:

1秒脉冲信号;

h_set:

时设置使能信号;m_set:

分设置使能信号,

s_set:

秒设置使能信号;

输出信号:

h_data:

时输出信号;m_data:

分输出信号;

s_data:

秒输出信号;

(5)Display模块:

LED的动态显示,显示格式“时—分—秒”。

输入信号:

reset:

复位信号;clk:

系统时钟信号

scan_clk:

数码管扫描信号h_data:

时信号;

m_data:

分信号;s_data:

秒信号;

输出信号:

d_col:

数码管的位选择信号

d_out:

译码后驱动数码管信号

五、系统设计仿真及测试方案

A、采用Quartusii和Modelsim的功能仿真,采用Quartusii的时序仿真分析,验证设计的正确性。

B、在Mars-EP1C3-EDA实验平台上实现本设计,并测试其正确性。

具体方案如图4-3所示。

图4-3

C、实验板信号定义

本设计

信号名

实验板

信号名

FPGA引脚

备注

本设计

信号名

实验板

信号名

FPGA引脚

备注

d_out[0]

display7

p5

低显dp段

d_col[2]

Dis_A6

P10

低显示

d_out[1]

display6

p4

低显g段

d_col[3]

Dis_A5

P7

低显示

d_out[2]

display5

p3

低显f段

d_col[4]

Dis_A4

P6

低显示

d_out[3]

display4

p2

低显e段

d_col[5]

Dis_A3

P11

低显示

d_out[4]

display3

p1

低显d段

d_col[6]

Dis_A2

P26

低显示

d_out[5]

display2

p143

低显c段

d_col[7]

Dis_A1

P27

低显示

d_out[6]

display1

p141

低显b段

set

KEY1

p107

按下为低

d_out[7]

display0

p142

低显a段

up

KEY2

p106

按下为低

d_col[0]

Dis_A8

P31

低显示

clk

CLK_40M

p16

40M时钟

d_col[1]

Dis_A7

P28

低显示

reset

SYS_RST

p144

低复位

表4-1

六、模块详细设计及功能仿真

1、Freq_div模块设计及功能仿真:

(1)模块设计

分频电路的原理:

分频电路实际上就是一个计数器,根据系统提供的时钟频率和你所需的时钟频率计算出计数的值,当计数值达到设置的值时,使输出变化一次。

系统提供的时钟频率为40MHz,该模块包括三个分频电路:

原理如图2-4所示。

第一步:

将系统时钟40_000分频产生1KHz信号scan_clk;

第二步:

将1KHz进行10分频产生100Hz信号key_clk;

第三步:

将100Hz进行100分频产生1Hz信号s_clk。

图6-1

(2)功能仿真

为了减小仿真时间和难度,把分频值改小进行仿真。

设置clk周期为2ns。

设置对clk进行4分频产生scan_clk;

设置对scan_clk进行3分频产生key_clk;

设置对key_clk进行5分频产生s_clk。

图6-2

有图知,scan_clk周期为:

8ns=4Tclk。

key_clk周期为:

24ns=3Tscan_clk。

S_clk周期为:

120ns=5Tkey_clk=。

分频功能正确。

2、Key_ctl模块设计及功能仿真

该模块主要功能是对异步的按键信号同步处理,并消除按键抖动。

原理:

先用D触发器打两级,然后间隔10ms(key_clk有效)采样,把两次采样值相与,比较两次采样值是否同一,由于直接由触发器输出的信号时间宽度可能过长,所以在触发器后再接一级同步化电路,保证每次输出的有效信号只占有一个时钟周期的宽度。

图6-3是set按键的同步消抖处理电路,up的原理与其相同。

(1)模块设计

图6-3Set按键消抖原理

(2)功能仿真

图6-4

有图6-4知,按键set的前沿抖动时间为120ns,后沿抖动时间为130ns,按键的稳定时间为540ns,故可设置采样间隔为200ns,有set_en波形可知,当两次的采样信号结果相同时,这时输出信号才可能发生变化,对应的按键的稳定闭合或断开,当两次的采样信号结果不同时,认为输入的信号为抖动信号,这时电路输出维持原状态不变,同时由于有同步化的处理,输出信号的高电平宽度只为系统时钟的一个周期。

3、Clcok_ctl模块设计及功能仿真

(1)模块算法设计

图4-7

(2)、功能仿真

有图可知,复位状态后进入:

“正常显示”状态,输出控制信号:

h_set=0,m_set=0,s_set=0;此后set_en按键每按一次状态发生一次变化,从“正常显示”→“时设置”→“分设置”→“秒设置”这样循环变化,并输出相应控制信号,“时设置”状态下输出控制信号:

h_set=1,m_set=0,s_set=0;“分设置”状态下输出控制信号:

h_set=0,m_set=1,s_set=0;“秒设置”状态下输出控制信号:

h_set=0,m_set=0,s_set=1。

工作模式转换和输出都正确。

4、Clock_cnt计数模块设计及功能仿真

(1)模块算法设计

时设置闪烁算法流程图

“分设置”、“秒设置”闪烁原理和“时设置原理一样”。

正常显示算法流程图:

采用BCD码计数,秒计计数值满之后向分进一位,让秒值清零,否则秒值自身加1,分计数值满之后向时进一位,让分值清零,否则分值加1,时计数值满之后,时清零,重新回到秒计数,这样循环执行。

图4-11

时设置算法流程图:

图4-8

分设置和秒设置算法流程和时设置流程类似。

(2)功能仿真

设置复位后时间初值为“23—45—09”。

①“正常显示”:

设置h_set=0,m_set=0,s_set=0;

有图可知,“正常显示”状态下,不管up_en是否按下,时、分、秒的计数都正确。

②“时设置”:

设置h_set=1,m_set=0,s_set=0;

有图知,“时设置”状态下,按键按下一次h_data加1,并间隔一个s_clk周期,输出时计数值h_data,功能正确

③“分设置”:

设置h_set=0,m_set=1,s_set=0;

有图知,“分设置”状态下,按键按下一次m_data加1,并间隔一个s_clk周期,输出分计数值m_data,功能正确

④“秒设置”:

设置h_set=0,m_set=0,s_set=1;

有图知,“秒设置”状态下,按键按下一次s_data加1,并间隔一个s_clk周期,输出时计数值s_data,功能正确。

5、display显示模块设计及功能仿真

(1)模块设计

显示原理:

用1ms的扫描信号循环控制数码的某一位有效,在相应为有效时输出数据经译码后驱动数码管,比如:

d_col=8’b1111_1110,8位数码管的最低位有效,此时将秒的低四位数据(s_data[3:

0])译码,驱动数码管,若此时s_data[3:

0]=4’d9=4’b1001,数码管此时将显示“9”。

数码管译码表:

led

led显示编码(d_out)

4’b0000

8'b0000_0011

4’b0001

8'b1001_1111

4’b0010

8'b0010_0101

4’b0011

8'b0000_1101

4’b0100

8'b1001_1001

4’b0101

8'b0100_1001

4’b0110

8'b0100_0001

4’b0111

8'b0001_1111

4’b1000

8'b0000_0001

4’b1001

8'b0001_1001

4’b1010

8'b1111_1101

4’b1111

8'b1111_1111

说明:

4’b1010,经译码后显示“—”,4’b1111,经译码后,LED不亮。

(2)功能仿真

设置时间初值为“23—45—09”,控制数码管位选择的信号d_col复位状态后为“8’b1111_1110”,然后在扫描频率作用下位选信号循环左移,并输出相应的时间数据译码值,从“秒低四位”→“秒高四位”→“—”→“分低四位”→“分高四位”→“—”→“时第四位”→“时高四位”这样循环送出数据。

显示数据正确。

七、系统功能仿真

计数初始设置:

设置系统复位后时间初值为“23—45—09”;

分频设置:

设置clk周期为2ns。

设置对clk进行5分频产生scan_clk;设置对scan_clk进行5分频产生key_clk;设置对key_clk进行4分频产生s_clk。

(1)正常显示模式

(2)设置模式

有图可以知系统功能正确。

八、系统综合实现及静态时序分析

综合后的RTL级电路

静态时序分析报告

设置建立时间为1ns

九、实际系统测试

设置系统复位后时间初值为“23—45—09”,然后全编译,下载到实验板,按KEY1(set键)可以进行正常的模式选择,从正常显示->时设置->分设置->秒设置,每按下一次循环一次。

并且在设置工作模式时,可以看到被设置相应数字按1秒速率闪烁,其它数字不变,功能正确。

达到了设计的要求。

在设置工作模式时,每按KEY2(UP)键一次,被设置相应数字增加1,加到最大值后再加返回0,如小时加到23后再加就返回0,分和秒加到59后再加返回0。

功能正确。

达到了设计的要求。

十、总结

经过两周的学习,初步掌握了一简单个数字系统的设计方法和设计流程;深入了解了数字系统自顶向下的设计方法,顶层设计、模块详细设计、各个模块仿真、系统仿真和时序分析。

刚开始设计时,忽略了好多细节,比如按键的消抖原理,不能用软件的消抖原理来设计硬件电路,为什么要采用BCD码计数,处于设置模式时怎么控制数码管的闪烁,这问题困扰了好久,通过陈老师讲解,以及和其他同学的相互沟通,把这些难题都解决了。

现在明白了做设计前写设计方案的重要性,只要方案正确可行,后面写代码以及调试,都很简单。

自己在写设计方案方面还有好多不足,以后需多多学习。

在写代码时,要以FPGA的设计规范为准则,比如模块、信号的命名要有一定的意义;使用if...else语句时,必须严格的逐层缩进对齐;代码后必须加入详细、清晰的注释行以增强代码的可读性和可移植性;等等。

附录:

源代码和测试代码

Freq_div模块:

源代码:

moduleFreq_div

//{{ALTERA_ARGS_BEGIN}}DONOTREMOVETHISLINE!

clk,rst_n,scan_clk,s_clk,key_clk

//{{ALTERA_ARGS_END}}DONOTREMOVETHISLINE!

);

//PortDeclaration

//{{ALTERA_IO_BEGIN}}DONOTREMOVETHISLINE!

inputclk;

inputrst_n;

outputscan_clk;

outputs_clk;

outputkey_clk;

//{{ALTERA_IO_END}}DONOTREMOVETHISLINE!

regscan_clk;

regs_clk;

regkey_clk;

reg[15:

0]cnt1;

always@(posedgeclkornegedgerst_n)

begin

if(!

rst_n)beginscan_clk<=0;

cnt1<=16'd0;

end

elseif(cnt1==16'd39_999)

begincnt1<=16'd0;

scan_clk<=1;

end

elsebegincnt1<=cnt1+16'd1;

scan_clk<=0;

end

end

reg[3:

0]cnt2;

always@(posedgeclkornegedgerst_n)

begin

if(!

rst_n)begin

key_clk<=0;

cnt2<=4'd0;

end

elseif(scan_clk)

begin

if(cnt2==4'd9)begin

cnt2<=4'd0;

key_clk<=1;

end

elsebegin

cnt2<=cnt2+4'd1;

key_clk<=0;

end

end

elsekey_clk<=0;

end

reg[6:

0]cnt3;

always@(posedgeclkornegedgerst_n)

begin

if(!

rst_n)begin

s_clk<=0;

cnt3<=7'd0;

end

elseif(key_clk)

begin

if(cnt3==7'd99)begin

cnt3<=7'd0;

s_clk<=1;

end

elsebegin

cnt3<=cnt3+7'd1;

s_clk<=0;

end

end

elses_clk<=0;

end

endmodule

测试代码:

`timescale1ns/1ns

modulefreq_div_tb;

regrst_n,clk;

wirekey_clk,scan_clk,s_clk;

always#1clk=~clk;

initial

begin

clk=0;

rst_n=0;

#3rst_n=1;

#200_000$stop;

end

freq_divfreq_div(clk,rst_n,scan_clk,s_clk,key_clk);

endmodule

Key_ctl模块:

Clock_ctl模块:

源代码:

moduleClock_ctl

//{{ALTERA_ARGS_BEGIN}}DONOTREMOVETHISLINE!

clk,rst_n,set_en,h_set,m_set,s_set

//{{ALTERA_ARGS_END}}DONOTREMOVETHISLINE!

);

//PortDeclaration

//{{ALTERA_IO_BEGIN}}DONOTREMOVETHISLINE!

inputclk;

inputrst_n;

inputset_en;

outputh_set;

outputm_set;

outputs_set;

//{{ALTERA_IO_END}}DONOTREMOVETHISLINE!

regh_set;

regm_set;

regs_set;

parameter[1:

0]normal=2'b00,hour_set=2'b01,

minute_set=2'b10,second_set=2'b11;

reg[1:

0]current_state,next_state;

always@(posedgeclkornegedgerst_n)

begin

if(!

rst_n)begin

current_state<=normal;

end

elsecurrent_state<=next_state;

end

always@(current_stateorset_en)

begin

case(current_state)

normal:

if(set_en)next_state<=hour_set;

elsenext_state<=normal;

hour_set:

if(set_en)next_state<=minute_set;

elsenext_state<=hour_set;

minute_set:

if(set_en)next_state<=second_set;

elsenext_state<=minute_set;

second_set:

i

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

当前位置:首页 > 高等教育 > 经济学

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

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