VHDL秒表功能.docx
- 文档编号:11313591
- 上传时间:2023-02-26
- 格式:DOCX
- 页数:15
- 大小:248.86KB
VHDL秒表功能.docx
《VHDL秒表功能.docx》由会员分享,可在线阅读,更多相关《VHDL秒表功能.docx(15页珍藏版)》请在冰豆网上搜索。
VHDL秒表功能
本程序利用VHDL实现功能:
按下键开始计时,再次按下停止计时,再次按下清零,再次按下开始计时
4位数码管显示,最大99.99秒。
程序分为分频模块,按键消抖模块/数码管显示转换模块和top模块
--通用偶数分频器—输入时钟和复位信号,输出分频后的时钟
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitygen_divis
generic(div_param:
integer:
=1);--分频因子,分频为2*div_param,默认2分频
port
(
clk:
instd_logic;--输入时钟
bclk:
outstd_logic;--分频输出
resetb:
instd_logic--复位信号
);
endgen_div;
architecturebehaveofgen_divis
signaltmp:
std_logic;--输出暂存寄存器
signalcnt:
integerrange0todiv_param:
=0;--计数寄存器
begin
------------------------------
process(clk,resetb)
begin
ifresetb='1'then--reset有效时,bclk始终是0
cnt<=0;
tmp<='0';
elsifrising_edge(clk)then
cnt<=cnt+1;
ifcnt=div_param-1then
tmp<=nottmp;--取反信号
cnt<=0;
endif;
endif;
endprocess;
bclk<=tmp;--输出
--------------------------------
endbehave;
--按键消抖模块--输入时钟和复位信号,按键信号,输出按键标识
--确定按下之后输出一个值
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitysig_keyis
port
(clkin,resetin:
instd_logic;--时钟,复位信号输入
key:
instd_logic;--键输入
key_out:
outstd_logic—输出按键标识
);
endsig_key;
architecturebehaveofsig_keyis
componentgen_divis--分频元件调用声明
generic(div_param:
integer:
=2);--默认是4分频
port
(
clk:
instd_logic;
bclk:
outstd_logic;
resetb:
instd_logic
);
endcomponent;
----
typekey_stateis(check_down,off_twitter,re_check_down);
signalsk_state_key0:
key_state:
=check_down;--定义按键3状态,分别是等待按下确定按下
signalclk_1k:
std_logic;--1k时钟,T=1ms—用于延时
begin
gen_1k:
--分频产生1k脉冲
gen_divgenericmap(24000)--48000分频的,产生1k脉冲
portmap--分频元件例化
(
clk=>clkin,
resetb=>notresetin,
bclk=>clk_1k
);
---
check_key0_state:
process(clk_1k,resetin,key)
variablecnt:
integerrange0to63:
=0;
begin
ifresetin='0'then
key_out<='0';
sk_state_key0<=check_down;
cnt:
=0;
else
ifrising_edge(clk_1k)then
casesk_state_key0is
whencheck_down=>
ifkey='1'then--=0位按下,1位松开
sk_state_key0<=check_down;
key_out<='0';--松开了,输出0
elsifkey='0'then--有键按下,准备消抖
sk_state_key0<=off_twitter;
cnt:
=0;
endif;
whenoff_twitter=>--延时10ms,消抖
cnt:
=cnt+1;
ifcnt>=10then
sk_state_key0<=re_check_down;
cnt:
=0;
endif;
whenre_check_down=>
ifkey='1'then
sk_state_key0<=check_down;--重新检测
elsifkey='0'then--确实有键按下
key_out<='1';--输出1
sk_state_key0<=check_down;--进入下一次检测
endif;
whenothers=>null;
endcase;
endif;
endif;
endprocess;
endbehave;
数码管显示转换模块—输入时钟复位信号和数字,输出段码
--把输入的整型转变为对应显示段码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityled_changeis
port
(clkin,resetin:
instd_logic;--时钟,复位信号输入
data_in:
inintegerrange0to21;--输入整型
data_out:
outstd_logic_vector(7downto0)--数码管段码输出
);
endled_change;
architecturebehaveofled_changeis
begin
process(clkin,resetin,data_in)
begin
ifresetin='1'then
data_out<=X"FF";---复位后全灭
else
ifrising_edge(clkin)then
casedata_inis
when0=>data_out<=X"03";
when1=>data_out<=X"9F";
when2=>data_out<=X"25";
when3=>data_out<=X"0d";
when4=>data_out<=X"99";
when5=>data_out<=X"49";
when6=>data_out<=X"41";
when7=>data_out<=X"1F";
when8=>data_out<=X"01";
when9=>data_out<=X"09";
when10=>data_out<=X"02";--0带点,用于区分秒和毫秒
when11=>data_out<=X"9E";--1带点,下同
when12=>data_out<=X"24";
when13=>data_out<=X"0C";
when14=>data_out<=X"98";
when15=>data_out<=X"48";
when16=>data_out<=X"40";
when17=>data_out<=X"1E";
when18=>data_out<=X"00";
when19=>data_out<=X"08";
whenothers=>data_out<=X"FF";
endcase;
endif;
endif;
endprocess;
endbehave;
top模块,输入总时钟,总复位,按键,输出段码和位码
--秒计数器,按下开始计时,按下停止,按下清零,按下开始
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitystopwatchis
port
(
clk_init,reset_init:
instd_logic;
sw:
instd_logic;
led:
outstd_logic;--指示状态
data:
outstd_logic_vector(7downto0);--数码管段码输出
com:
outstd_logic_vector(3downto0)--位码输出
);
endstopwatch;
architecturebehaveofstopwatchis
---申明分频模块gen_div
componentgen_divis
generic(div_param:
integer:
=1);--分频因子,分频为2*div_param,默认2分频
port
(
clk:
instd_logic;--输入时钟
bclk:
outstd_logic;--分频输出
resetb:
instd_logic--复位信号
);
endcomponent;
--申明数码管数据转换模块led_change
componentled_changeis--段码转换调用
port
(
clkin,resetin:
instd_logic;--时钟,复位信号输入
data_in:
inintegerrange0to21;--输入整型
data_out:
outstd_logic_vector(7downto0)--数码管段码输出
);
endcomponent;
--申明按键消抖模块sig_key
componentsig_keyis
port
(
clkin,resetin:
instd_logic;--时钟,复位信号输入
key:
instd_logic;--键输入
key_out:
outstd_logic
);
endcomponent;
--定义信号
----承接转化之前的数字
signaldata_1_tmp:
integerrange0to21;--段码个位
signaldata_10_tmp:
integerrange0to21;--段码十位
signaldata_100_tmp:
integerrange0to21;--段码百位
signaldata_1000_tmp:
integerrange0to21;--段码千位
---承接经转化后的段码
signaldata_1:
std_logic_vector(7downto0);--段码个位
signaldata_10:
std_logic_vector(7downto0);--段码十位
signaldata_100:
std_logic_vector(7downto0);--段码百位
signaldata_1000:
std_logic_vector(7downto0);--段码千位
signalclk_sm:
std_logic;--50k扫描周期
signalkey_out_init:
std_logic;--承接按键消抖模块传出来的按键信号
signalcnt_50k:
std_logic_vector(1downto0);--对clk_sm计数,产生4种状态,对应位码
typesw_state_wichis(sw_1,sw_2,sw_3);--按钮状态,1清零等待启动,2计时中,3停止
signalsw_state:
sw_state_wich:
=sw_1;
begin
--例化
gen_100k:
--分频产生50k脉冲
gen_divgenericmap(480)—48M晶振,960分频,得到50k时钟
portmap--分频元件例化
(
clk=>clk_init,
resetb=>notreset_init,
bclk=>clk_sm
);
gen_data_1:
--个位段码转换
led_changeportmap
(
clkin=>clk_init,
resetin=>notreset_init,
data_in=>data_1_tmp,
data_out=>data_1
);
gen_data_10:
--十位段码转换
led_changeportmap
(
clkin=>clk_init,
resetin=>notreset_init,
data_in=>data_10_tmp,
data_out=>data_10
);
gen_data_100:
--百位段码转换
led_changeportmap
(
clkin=>clk_init,
resetin=>notreset_init,
data_in=>data_100_tmp,
data_out=>data_100
);
gen_data_1000:
--千位段码转换
led_changeportmap
(
clkin=>clk_init,
resetin=>notreset_init,
data_in=>data_1000_tmp,
data_out=>data_1000
);
key_sig:
--调用按键消抖程序
sig_keyportmap
(
clk_init,reset_init,sw,key_out_init
);
gen_cnt_50k:
--cnt_50k循环计数,四个状态的循环周期是20us*4=80us,即为扫描周期
process(clk_sm,reset_init,data_1000,data_100,data_10,data_1)
begin
ifreset_init='0'then
cnt_50k<="00";
else
ifrising_edge(clk_sm)then
cnt_50k<=cnt_50k+'1';
endif;
endif;
endprocess;
Display:
--根据上面的计数将转换后的段码送给对应的位
process(cnt_50k,data_1,data_10,data_100,data_1000)
begin
casecnt_50kis--循环扫描
when"00"=>com<="0111";data<=data_1000;--千位
when"01"=>com<="1011";data<=data_100;--百位
when"10"=>com<="1101";data<=data_10;--十位
when"11"=>com<="1110";data<=data_1;--个位
whenothers=>com<="1111";--全灭
endcase;
endprocess;
process(key_out_init,clk_sm)
variablecnt_clk_1k:
integerrange0to3000000:
=0;--用于计时
variablekey_flog:
std_logic:
='0';--用于判断按键是否松开,0表示松开
begin
ifrising_edge(clk_sm)then
casesw_stateis
whensw_1=>
ifkey_out_init='0'then–松开,置1
key_flog:
='1';
endif;
ifkey_out_init='1'andkey_flog='1'then—按下,且之前是松开转到状态2开始计时,按下后flog置0
sw_state<=sw_2;
key_flog:
='0';
endif;
whensw_2=>
ifkey_out_init='0'then--松开健开始计时,且置1
key_flog:
='1';
cnt_clk_1k:
=cnt_clk_1k+1;
data_1_tmp<=(cnt_clk_1k/50/10)rem10;
data_10_tmp<=(cnt_clk_1k/50/100)rem10;
data_100_tmp<=(cnt_clk_1k/50/1000)rem10+10;
data_1000_tmp<=(cnt_clk_1k/50/10000)rem10;
endif;
ifkey_flog='1'then–置1表示已经松开
ifkey_out_init='1'then–再次按下
sw_state<=sw_3;
key_flog:
='0';
endif;
endif;
whensw_3=>
ifkey_out_init='0'then
key_flog:
='1';
endif;
ifkey_flog='1'then
ifkey_out_init='1'then
sw_state<=sw_1;
key_flog:
='0';
cnt_clk_1k:
=0;
data_1_tmp<=0;--清零
data_10_tmp<=0;
data_100_tmp<=0;
data_1000_tmp<=0;
endif;
endif;
whenothers=>sw_state<=sw_1;
endcase;
endif;
endprocess;
endbehave;
--top程序应该有复位信号,本除没有加。
可在上面进程里面加,按下后说有变量清零。
以上程序已经验证。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VHDL 秒表 功能