VHDL秒表功能.docx

上传人:b****8 文档编号:11313591 上传时间:2023-02-26 格式:DOCX 页数:15 大小:248.86KB
下载 相关 举报
VHDL秒表功能.docx_第1页
第1页 / 共15页
VHDL秒表功能.docx_第2页
第2页 / 共15页
VHDL秒表功能.docx_第3页
第3页 / 共15页
VHDL秒表功能.docx_第4页
第4页 / 共15页
VHDL秒表功能.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

VHDL秒表功能.docx

《VHDL秒表功能.docx》由会员分享,可在线阅读,更多相关《VHDL秒表功能.docx(15页珍藏版)》请在冰豆网上搜索。

VHDL秒表功能.docx

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程序应该有复位信号,本除没有加。

可在上面进程里面加,按下后说有变量清零。

以上程序已经验证。

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

当前位置:首页 > 求职职场 > 简历

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

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