赞
踩
1、使用说明:
本设计模拟手机时钟实现四个功能,分别为时间显示、秒表、闹钟、计时器。以BUT1~BUT4分别选择这四个功能,四个功能互不冲突,在时间显示时可以继续进行秒表和计时器的工作。实现的各自功能如下:
时间显示:以1HZ频率显示时间,按下BUT5实现设置时间,在设置时间的条件下,按下BUT6实现对哪个位进行修改操作,设置的位闪烁示意正在设置该位,按BUT6可以将位循环左移。在按下BUT6的情况下,按BUT7实现加一操作,按BUT8实现减一操作。秒个位设置范围为09,秒十位设置范围为05,分钟与小时以此类推。设置完数字后按BUT5完成设置。另外,在时间显示界面增加两个涉及秒表的功能键,在没有设置时间时,按下BUT8可以选择是否开启闹钟,开启闹钟时LED8亮,没有开启闹钟时LED8灭。当闹钟时间到时,LED1亮,按下BUT7可以关闭闹钟。
秒表:以100HZ频率显示百分秒,按下BUT5开始,再按一次BUT5实现暂停。按下BUT6实现计数清零(要再次开始计数必须再按一次BUT6取消清零),按下BUT7标记此时的数字,按BUT8可以显示上次标记的数字,在查看标记的数字后,再按一次BUT8可以返回秒表界面显示,在标记数字,查看标记数字的过程中,秒表一直在计数,不会中断。
闹钟:按下BUT6实现对哪个位进行修改操作,设置的位闪烁示意正在设置该位,按BUT6可以将位循环左移。在按下BUT6的情况下,按BUT7实现加一操作,按BUT8实现减一操作。设置完数字之后,按下BUT5确定完成设置,否则不会闹钟生效。闹钟生效的前提是LED8亮。
计时器:按下BUT6实现对哪个位进行修改操作,设置的位闪烁示意正在设置该位,按BUT6可以将位循环左移。在按下BUT6的情况下,按BUT7实现加一操作,按BUT8实现减一操作。秒个位设置范围为0-9,秒十位设置范围为0~5,分钟与小时以此类推。设置完数字后按BUT5完成设置。完成设置后开始倒计时,倒计时到0时LED4亮,模拟手机计时器时间到后响铃,按下BUT5关闭,即LED4灭。
2、整体思路概述
首先明确四个功能都需要用到数码管,所以用一个变量en来区分四个功能,en设置为两位的变量即可。由于BUT1-BUT4用于随时选择使用什么功能,因此在进入某一个功能之后,BUT1-BUT4最好不要用,因此采用BUT5-BUT8为四个功能下的设置键。在设定时间时BUT6-BUT8可以用于设定时间,在没有设定时时BUT6~BUT8可以用于其他功能。因此可以在时间显示界面控制闹钟。在顶层文件中对en的情况分类进行处理,在顶层文件中接收按键产生的信号,进行处理后得到诸如四种情况下的bcddata,led等等信号,送到其他的模块进行结果的显示。因此设计5个模块,一个模块用于时钟的产生,产生1HZ和100HZ两种信号。一个模块用于按键消抖,一个模块用于检测按键,一个模块用于数码管的显示,一个模块用于LED的显示。
1、时钟模块
---------------------------------------- --时钟模块,产生1s和10ms的时钟 ---------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.ALL; use ieee.std_logic_arith.all; entity clock_source IS PORT(clk:IN STD_LOGIC; clk_1s:out std_LOGIC; clk_10ms: out std_LOGIC; clkcnt: buffer STD_LOGIC_VECTOR(30 DOWNTO 0):= (others =>'0'); Stopwatch_clear: in std_LOGIC ); END clock_source; ARCHITECTURE behav OF clock_source IS SIGNAL a: integer range 0 to 24999999 :=0; --秒 SIGNAL q: STD_LOGIC :='0'; --初始化为0 SIGNAL b: integer range 0 to 249999 :=0; --百分秒 SIGNAL p: STD_LOGIC :='0'; --初始化为0 begin process(clk,clkcnt) begin if(rising_edge(clk))then clkcnt<= clkcnt + 1; end if; end process; ------------------------------产生 1S 的时钟信号--------------- process(clk) begin if(clk'event and clk='1' ) then if a=24999999 then --25000000个clk脉冲(20ns)即0.5秒为低电平,0.5秒为高电平,即产生周期1秒的方波信号。 a<=0; q<= not q; else a<=a+1; end if; end if; clk_1s<=q; end process; ------------------------------------ ------------------------------产生 10MS 的时钟信号--------------- process(clk) begin if(clk'event and clk='1' ) then if(Stopwatch_clear='1') then b<=0; p<='0'; else if b=249999 then --250000个clk脉冲(20ns)即0.005秒为低电平,0.005秒为高电平,即产生周期0.01秒的方波信号。 b<=0; p<= not p; else b<=b+1; end if; end if; end if; clk_10ms<=p; end process; ------------------------------------ end architecture behav;
设计原理与分析:FPGA为50MHZ,采用计数分频的方法获得1HZ与100HZ时钟,1HZ与100HZ分别用各自的变量,互不影响,防止秒表和时间显示产生冲突。
值得注意的是,由于数码管显示用到了clkcnt,因此clkcnt设置为buffer,另外,秒表的清零需要将100HZ的信号切断,因此在port中有Stopwatch_clear: in std_LOGIC。
2、按键消抖模块
--按键消抖模块: library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity keyfilt is port (clk : in std_logic; key1 : in std_logic; key1_filt : out std_logic; key2 : in std_logic; key2_filt : out std_logic; key3: in std_logic; key3_filt: out std_logic; key4 : in std_logic; key4_filt : out std_logic; key5 : in std_logic; key5_filt : out std_logic; key6 : in std_logic; key6_filt : out std_logic; key7: in std_logic; key7_filt: out std_logic; key8 : in std_logic; key8_filt : out std_logic ); end keyfilt; architecture behavioral of keyfilt is signal keycnt1 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 signal keycnt2 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 signal keycnt3 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 signal keycnt4 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 signal keycnt5 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 signal keycnt6 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 signal keycnt7 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 signal keycnt8 : integer range 0 to 50000000:=0;--通用cnt,因为正常情况下不可能有两个按键同时按下 constant N :integer := 5000000; --消抖时间,对于50Mhz的基准时钟,这相当于0.1S,一般要在20ms以上 begin process (clk) begin if clk'event and clk = '1' then if key1 = '0' then --当keyX输入低电平,即按键按下 if keycnt1 /= N then --一直计数到N, /= 为不等于 keycnt1<= keycnt1 + 1; end if; if keycnt1 = N-1 then --最后一个计数时输出keyX_filt脉冲 key1_filt<= '1'; else key1_filt<= '0'; end if; else --若keyX输入高电平,表明按键被释放 keycnt1<= 0; end if; if key2 = '0' then if keycnt2 /= N then keycnt2<= keycnt2 + 1; end if; if keycnt2 = N-1 then key2_filt<= '1'; else key2_filt<= '0'; end if; else keycnt2<= 0; end if; if key3 = '0' then if keycnt3 /= N then keycnt3<= keycnt3 + 1; end if; if keycnt3 = N-1 then key3_filt<= '1'; else key3_filt<= '0'; end if; else keycnt3<= 0; end if; if key4 = '0' then if keycnt4 /= N then keycnt4<= keycnt4 + 1; end if; if keycnt4 = N-1 then key4_filt<= '1'; else key4_filt<= '0'; end if; else keycnt4<= 0; end if; if key5 = '0' then if keycnt5 /= N then keycnt5<= keycnt5 + 1; end if; if keycnt5 = N-1 then key5_filt<= '1'; else key5_filt<= '0'; end if; else keycnt5<= 0; end if; if key6 = '0' then if keycnt6 /= N then keycnt6<= keycnt6 + 1; end if; if keycnt6 = N-1 then key6_filt<= '1'; else key6_filt<= '0'; end if; else keycnt6<= 0; end if; if key7 = '0' then if keycnt7 /= N then keycnt7<= keycnt7 + 1; end if; if keycnt7 = N-1 then key7_filt<= '1'; else key7_filt<= '0'; end if; else keycnt7<= 0; end if; if key8 = '0' then if keycnt8 /= N then keycnt8<= keycnt8 + 1; end if; if keycnt8 = N-1 then key8_filt<= '1'; else key8_filt<= '0'; end if; else keycnt8<= 0; end if; end if; --clk'event end process; end behavioral;
设计原理与分析:例化时keyX对应实际的按键,key_filt为keyX按下时产生的对应的脉冲。实际上是采用延时的方法对按键进行消抖。八个按键分别用不同的信号进行操作,避免相互影响。
3、按键检测模块
---------------------------------------- --按键状态检测模块 ---------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.ALL; use ieee.std_logic_arith.all; entity key_state IS PORT(clk:IN STD_LOGIC; key1_filt:in std_LOGIC; key2_filt:in std_LOGIC; key3_filt:in std_LOGIC; key4_filt:in std_LOGIC; key5_filt:in std_LOGIC; key6_filt:in std_LOGIC; key7_filt:in std_LOGIC; key8_filt:in std_LOGIC; en: buffer std_logic_vector(1 downto 0); skey5: buffer std_LOGIC; alarm_key5: buffer std_LOGIC; count_down_clock_skey5: buffer std_LOGIC; skey6: out std_LOGIC; skey7: out std_LOGIC; skey8: buffer std_LOGIC ); END key_state; ARCHITECTURE behav OF key_state IS begin process(clk) begin if(clk'event and clk='1' )then if(key1_filt='1') then en<="00";--时间显示 end if; if(key2_filt='1') then en<="01";--秒表 end if; if(key3_filt='1') then en<="10";--闹钟 end if; if(key4_filt='1') then en<="11";--定时器 end if; if(key5_filt='1') then if(en="00") then--闹钟清除也用到了key5_filt,为了避免对设置时间的影响,加en=00的限制条件 skey5<=not skey5;--设置时间用到反转 end if; if(en="10") then alarm_key5<=not alarm_key5; end if; if(en="11") then count_down_clock_skey5<=not count_down_clock_skey5; end if; end if; if(key6_filt='1') then skey6<='1'; end if; if(key7_filt='1') then skey7<='1'; end if; if(key8_filt='1') then skey8<=not skey8;--秒表用到反转 end if; end if; end process; end architecture behav;
设计原理与分析:对按键消抖后的脉冲进行检测,如果检测到就证明有对应的按键按下,则可以进行对控制变量的翻转或者是跟随脉冲一起变化,形成脉冲控制信号和电平信号两种控制信号,比如说,在时间显示功能时,设否设置时间可以用电平控制信号,而加减1则用脉冲控制信号。key1_filt-key4_filt检测到脉冲时,改变en的值。对于key5_filt~key8_filt有的需要在该条件下判断处于什么功能,进而改变相应的信号。
4、数码管显示模块
---------------------------------------- --数码管显示模块 ---------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.ALL; use ieee.std_logic_arith.all; entity seg_display IS PORT(clk:IN STD_LOGIC; clk_1s: in std_LOGIC; clkcnt: in STD_LOGIC_VECTOR(30 DOWNTO 0); en:in std_logic_vector(1 downto 0); bcddata: in std_logic_vector(23 downto 0); set_time: in std_LOGIC; bcddata_temp:in std_logic_vector(23 downto 0); position: in integer range 0 to 20; Stopwatch_show_savedata:in std_LOGIC:='0'; Stopwatch_save_data:in std_logic_vector(23 downto 0); bcddata_Stopwatch:in std_logic_vector(23 downto 0); bcddata_alarm:in std_logic_vector(23 downto 0); alarm_select:in std_LOGIC:='0'; bcddata_count_down_clock:in std_logic_vector(23 downto 0); count_down_clock_select:in std_LOGIC; segdot:OUT STD_LOGIC; SEG_LED:OUT STD_LOGIC_VECTOR(6 downto 0); SEG_NCS:OUT STD_LOGIC_VECTOR(5 downto 0) ); END seg_display; ARCHITECTURE behav OF seg_display IS SIGNAL bcd_led:STD_LOGIC_VECTOR(3 DOWNTO 0):=(others=>'0'); begin process(clkcnt(17 downto 15)) begin case clkcnt(17 downto 15) is when "000" => if(en="00") then if(set_time='1') then bcd_led<=bcddata_temp(3 downto 0); if(position=0) then if(clk_1s='1') then SEG_NCS <= "111110"; else SEG_NCS <= "111111"; end if; else SEG_NCS <= "111110"; end if; else bcd_led<=bcddata(3 downto 0); SEG_NCS <= "111110"; end if; end if; if(en="01") then if(Stopwatch_show_savedata='1') then bcd_led<=Stopwatch_save_data(3 downto 0); else bcd_led<=bcddata_Stopwatch(3 downto 0); end if; SEG_NCS <= "111110"; end if; if(en="10") then bcd_led<=bcddata_alarm(3 downto 0); if(position=0) then if(clk_1s='1') then SEG_NCS <= "111110"; else if(alarm_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "111110"; end if; end if; if(en="11") then bcd_led<=bcddata_count_down_clock(3 downto 0); if(position=0) then if(clk_1s='1') then SEG_NCS <= "111110"; else if(count_down_clock_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "111110"; end if; end if; segdot<='1'; when "001" => if(en="00") then if(set_time='1') then bcd_led<=bcddata_temp(7 downto 4); if(position=4) then if(clk_1s='1') then SEG_NCS <= "111101"; else SEG_NCS <= "111111"; end if; else SEG_NCS <= "111101"; end if; else bcd_led<=bcddata(7 downto 4); SEG_NCS <= "111101"; end if; end if; if(en="01") then if(Stopwatch_show_savedata='1') then bcd_led<=Stopwatch_save_data(7 downto 4); else bcd_led<=bcddata_Stopwatch(7 downto 4); end if; SEG_NCS <= "111101"; end if; if(en="10") then bcd_led<=bcddata_alarm(7 downto 4); if(position=4) then if(clk_1s='1') then SEG_NCS <= "111101"; else if(alarm_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "111101"; end if; end if; if(en="11") then bcd_led<=bcddata_count_down_clock(7 downto 4); if(position=4) then if(clk_1s='1') then SEG_NCS <= "111101"; else if(count_down_clock_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "111101"; end if; end if; segdot<='1'; when "010" => if(en="00") then if(set_time='1') then bcd_led<=bcddata_temp(11 downto 8); if(position=8) then if(clk_1s='1') then SEG_NCS <= "111011"; else SEG_NCS <= "111111"; end if; else SEG_NCS <= "111011"; end if; else bcd_led<=bcddata(11 downto 8); SEG_NCS <= "111011"; end if; end if; if(en="01") then if(Stopwatch_show_savedata='1') then bcd_led<=Stopwatch_save_data(11 downto 8); else bcd_led<=bcddata_Stopwatch(11 downto 8); end if; SEG_NCS <= "111011"; end if; if(en="10") then bcd_led<=bcddata_alarm(11 downto 8); if(position=8) then if(clk_1s='1') then SEG_NCS <= "111011"; else if(alarm_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "111011"; end if; end if; if(en="11") then bcd_led<=bcddata_count_down_clock(11 downto 8); if(position=8) then if(clk_1s='1') then SEG_NCS <= "111011"; else if(count_down_clock_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "111011"; end if; end if; segdot<='0'; when "011" => if(en="00") then if(set_time='1') then bcd_led<=bcddata_temp(15 downto 12); if(position=12) then if(clk_1s='1') then SEG_NCS <= "110111"; else SEG_NCS <= "111111"; end if; else SEG_NCS <= "110111"; end if; else bcd_led<=bcddata(15 downto 12); SEG_NCS <= "110111"; end if; end if; if(en="01") then if(Stopwatch_show_savedata='1') then bcd_led<=Stopwatch_save_data(15 downto 12); else bcd_led<=bcddata_Stopwatch(15 downto 12); end if; SEG_NCS <= "110111"; end if; if(en="10") then bcd_led<=bcddata_alarm(15 downto 12); if(position=12) then if(clk_1s='1') then SEG_NCS <= "110111"; else if(alarm_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "110111"; end if; end if; if(en="11") then bcd_led<=bcddata_count_down_clock(15 downto 12); if(position=12) then if(clk_1s='1') then SEG_NCS <= "110111"; else if(count_down_clock_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "110111"; end if; end if; segdot<='1'; when "100" => if(en="00") then if(set_time='1') then bcd_led<=bcddata_temp(19 downto 16); if(position=16) then if(clk_1s='1') then SEG_NCS <= "101111"; else SEG_NCS <= "111111"; end if; else SEG_NCS <= "101111"; end if; else bcd_led<=bcddata(19 downto 16); SEG_NCS <= "101111"; end if; end if; if(en="01") then if(Stopwatch_show_savedata='1') then bcd_led<=Stopwatch_save_data(19 downto 16); else bcd_led<=bcddata_Stopwatch(19 downto 16); end if; SEG_NCS <= "101111"; end if; if(en="10") then bcd_led<=bcddata_alarm(19 downto 16); if(position=16) then if(clk_1s='1') then SEG_NCS <= "101111"; else if(alarm_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "101111"; end if; end if; if(en="11") then bcd_led<=bcddata_count_down_clock(19 downto 16); if(position=16) then if(clk_1s='1') then SEG_NCS <= "101111"; else if(count_down_clock_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "101111"; end if; end if; segdot<='0'; when "101" => if(en="00") then if(set_time='1') then bcd_led<=bcddata_temp(23 downto 20); if(position=20) then if(clk_1s='1') then SEG_NCS <= "011111"; else SEG_NCS <= "111111"; end if; else SEG_NCS <= "011111"; end if; else bcd_led<=bcddata(23 downto 20); SEG_NCS <= "011111"; end if; end if; if(en="01") then if(Stopwatch_show_savedata='1') then bcd_led<=Stopwatch_save_data(23 downto 20); else bcd_led<=bcddata_Stopwatch(23 downto 20); end if; SEG_NCS <= "011111"; end if; if(en="10") then bcd_led<=bcddata_alarm(23 downto 20); if(position=20) then if(clk_1s='1') then SEG_NCS <= "011111"; else if(alarm_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "011111"; end if; end if; if(en="11") then bcd_led<=bcddata_count_down_clock(23 downto 20); if(position=20) then if(clk_1s='1') then SEG_NCS <= "011111"; else if(count_down_clock_select='0') then SEG_NCS <= "111111"; end if; end if; else SEG_NCS <= "011111"; end if; end if; segdot<='1'; when others => SEG_NCS <= "111111"; end case; end process; process(bcd_led) begin case bcd_led is -- "abcdefg" WHEN "0000"=>SEG_LED<="0000001"; WHEN "0001"=>SEG_LED<="1001111"; WHEN "0010"=>SEG_LED<="0010010"; WHEN "0011"=>SEG_LED<="0000110"; WHEN "0100"=>SEG_LED<="1001100"; WHEN "0101"=>SEG_LED<="0100100"; WHEN "0110"=>SEG_LED<="0100000"; WHEN "0111"=>SEG_LED<="0001111"; WHEN "1000"=>SEG_LED<="0000000"; WHEN "1001"=>SEG_LED<="0000100"; WHEN OTHERS=>SEG_LED<="1111111"; end case; end process; end ARCHITECTURE behav;
设计原理与分析:对于数码管采用分时显示的方法,通过检测clkcnt的17~15位,分别在不同的组合情况下进行单个数码管的显示。在对应的数码管要显示时,判断en的值,根据en的值将不同的bcddata复制给bcd_led,在时间显示时用bcddata,在秒表时用bcddata_Stopwatch,在闹钟时用bcddata_alarm,在计时器时用bcddata_count_down_clock。对与数码管的片选信号SEG_NCS则在需不需要闪烁时判断复制,通过clk_1s的信号达到闪烁的效果 。
5、LED控制模块
--按键消抖模块: library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity led_contro is port (clk : in std_logic; alarm_clear: in std_logic; led_alarm_not_exit: out std_logic; count_down_clock_select: in std_logic; bcddata_count_down_clock:in std_logic_vector(23 downto 0); led_count_down_clock:out std_logic ); end led_contro; architecture behav of led_contro is begin --闹钟的灯 process(clk) begin if(alarm_clear='1') then led_alarm_not_exit<='1'; else led_alarm_not_exit<='0'; end if; end process; --定时器的灯 process(clk) begin if(count_down_clock_select='1') then if(bcddata_count_down_clock=0) then led_count_down_clock<='0'; end if; else led_count_down_clock<='1'; end if; end process; end architecture behav;
设计原理与分析:在LED的控制中,只有闹钟和定时器会用到。因此在PORT中只有闹钟和定时器的信号传进这个模块。
6、顶层文件
---------------------------------------------------------------------------------- --function : --en=00:时间显示,按5设置时间,6移位,7加,8减,设置完后按5完成设置;在没有设置时间时,按8打开闹钟,指示灯LED8亮,再按一次关闭闹钟,LED8灭 --en=01:秒表,按5开始计时,按6清零,再按6取消清零,按5可以暂停,按7标记此时的时间,按8显示标记的时间,再按8返回秒表计时显示 --en=10:闹钟时间设置,按5设置时间,再按一次完成设置(没有完成设置,及时LED8亮也没有用),6移位,7加,8减,闹钟时间到时LED1亮,按7可以灭灯,只是灭灯,不会关闭闹钟 --en=11:定时器显示,按5设置时间,再按一次完成设置,6移位,7加,8减,计时到0时LED4亮,再次按5设置时间可以灭灯 --------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.ALL; use ieee.std_logic_arith.all; entity clock IS PORT(clk:IN STD_LOGIC; SEG_LED:OUT STD_LOGIC_VECTOR(6 downto 0);--数码管的七段 SEG_NCS:OUT STD_LOGIC_VECTOR(5 downto 0);--4个数码管的选通 segdot:OUT STD_LOGIC:='0';--常亮 key1:IN STD_LOGIC; --选择显示时间 key2:IN STD_LOGIC; --选择秒表 key3:IN STD_LOGIC; --选择闹钟 key4:IN STD_LOGIC; --选择计时器 key5:IN STD_LOGIC; key6:IN STD_LOGIC; key7:IN STD_LOGIC; key8:IN STD_LOGIC; led:out std_LOGIC:='1';--闹钟时间到灯亮 led_alarm_not_exit:out std_LOGIC:='1';--闹钟存在灯亮 led_count_down_clock:out std_LOGIC:='1'--倒计时时间到灯亮 ); END clock; ARCHITECTURE behav OF clock IS SIGNAL bcddata:std_logic_vector(23 downto 0):=(others=>'0'); --初始化为0 SIGNAL bcddata_temp:std_logic_vector(23 downto 0):=(others=>'0'); --初始化为0 SIGNAL bcddata_Stopwatch:std_logic_vector(23 downto 0):=(others=>'0'); --初始化为0 --时钟模块的例化变量begin SIGNAL clk_1s: STD_LOGIC :='0'; --初始化为0 SIGNAL clk_10ms: STD_LOGIC :='0'; --初始化为0 SIGNAL clkcnt:STD_LOGIC_VECTOR(30 DOWNTO 0):= (others =>'0');----初始化为0"00000000000000000"; --时钟模块的例化变量end SIGNAL en :STD_LOGIC_VECTOR(1 DOWNTO 0):="00";--选择四种功能 SIGNAL key1_filt: STD_LOGIC ; SIGNAL key2_filt: STD_LOGIC ; SIGNAL key3_filt: STD_LOGIC ; SIGNAL key4_filt: STD_LOGIC ; SIGNAL key5_filt: STD_LOGIC ; SIGNAL skey5: STD_LOGIC :='0'; SIGNAL key6_filt: STD_LOGIC ; SIGNAL skey6: STD_LOGIC :='0'; SIGNAL key7_filt: STD_LOGIC ; SIGNAL skey7: STD_LOGIC :='0'; SIGNAL key8_filt: STD_LOGIC ; SIGNAL skey8: STD_LOGIC :='0'; signal cs_clk_1s:std_LOGIC:='1'; --显示时间的变量 signal set_time:std_LOGIC:='0'; signal set_time_finish:std_LOGIC:='0'; signal move_left:std_LOGIC:='0';--时间显示和闹钟均用到 signal add:std_LOGIC:='0';--时间显示和闹钟均用到 signal sub:std_LOGIC:='0';--时间显示和闹钟均用到 signal position:integer range 0 to 20:=0;--时间显示和闹钟均用到 --秒表的变量 signal Stopwatch_begin:std_LOGIC:='0'; signal Stopwatch_clear:std_LOGIC:='0'; signal Stopwatch_save:std_LOGIC:='0'; signal Stopwatch_read:std_LOGIC:='0'; SIGNAL Stopwatch_save_data:std_logic_vector(23 downto 0):=(others=>'0'); --初始化为0 signal Stopwatch_show_savedata:std_LOGIC:='0'; --闹钟的变量 SIGNAL bcddata_alarm:std_logic_vector(23 downto 0):=(others=>'0'); --初始化为0 signal alarm_turn_off:std_LOGIC:='0';--闹钟响时关闭 signal alarm_clear:std_LOGIC:='1';--清除闹钟,初始化为关闭闹钟 signal led_blink:std_LOGIC:='0'; signal alarm_select:std_LOGIC:='0'; signal alarm_key5:std_LOGIC:='0'; SIGNAL bcddata_alarm_finally:std_logic_vector(23 downto 0):=(others=>'0'); --初始化为0 --计时器变量 signal count_down_clock_skey5:std_LOGIC:='0'; signal count_down_clock_begin:std_LOGIC:='0'; signal count_down_clock_select:std_LOGIC:='0'; SIGNAL bcddata_count_down_clock:std_logic_vector(23 downto 0):=(others=>'0'); --初始化为0 SIGNAL bcddata_count_down_clock_temp:std_logic_vector(23 downto 0):=(others=>'0'); signal led_count_down_clock_turn_off:std_LOGIC:='0'; --声明要使用到的模块 ---时钟模块申明begin--------- component clock_source is PORT(clk:IN STD_LOGIC; clk_1s:out std_LOGIC; clk_10ms: out std_LOGIC; clkcnt: buffer STD_LOGIC_VECTOR(30 DOWNTO 0):= (others =>'0'); Stopwatch_clear: in std_LOGIC ); end component clock_source; ---时钟模块申明end--------- ---按键状态模块申明begin--------- component key_state is PORT(clk:IN STD_LOGIC; key1_filt:in std_LOGIC; key2_filt:in std_LOGIC; key3_filt:in std_LOGIC; key4_filt:in std_LOGIC; key5_filt:in std_LOGIC; key6_filt:in std_LOGIC; key7_filt:in std_LOGIC; key8_filt:in std_LOGIC; en: buffer std_logic_vector(1 downto 0); skey5: buffer std_LOGIC; alarm_key5: buffer std_LOGIC; count_down_clock_skey5: buffer std_LOGIC; skey6: out std_LOGIC; skey7: out std_LOGIC; skey8: buffer std_LOGIC ); end component key_state; --按键状态模块申明end--------- ---数码管显示模块声明begin--- component seg_display is PORT(clk:IN STD_LOGIC; clk_1s: in std_LOGIC; clkcnt: in STD_LOGIC_VECTOR(30 DOWNTO 0); en:in std_logic_vector(1 downto 0); bcddata: in std_logic_vector(23 downto 0); set_time: in std_LOGIC; bcddata_temp:in std_logic_vector(23 downto 0); position: in integer range 0 to 20; Stopwatch_show_savedata:in std_LOGIC:='0'; Stopwatch_save_data:in std_logic_vector(23 downto 0); bcddata_Stopwatch:in std_logic_vector(23 downto 0); bcddata_alarm:in std_logic_vector(23 downto 0); alarm_select:in std_LOGIC:='0'; bcddata_count_down_clock:in std_logic_vector(23 downto 0); count_down_clock_select:in std_LOGIC; segdot:OUT STD_LOGIC; SEG_LED:OUT STD_LOGIC_VECTOR(6 downto 0); SEG_NCS:OUT STD_LOGIC_VECTOR(5 downto 0) ); end component seg_display; ---数码管显示模块声明end--- ---按键消抖模块声明begin-- component keyfilt is port (clk : in std_logic; key1 : in std_logic; key1_filt : out std_logic; key2 : in std_logic; key2_filt : out std_logic; key3 : in std_logic; key3_filt : out std_logic; key4 : in std_logic; key4_filt : out std_logic; key5 : in std_logic; key5_filt : out std_logic; key6 : in std_logic; key6_filt : out std_logic; key7 : in std_logic; key7_filt : out std_logic; key8 : in std_logic; key8_filt : out std_logic ); end component keyfilt; ---按键消抖模块声明end-- ---led控制模块申明begin-- component led_contro is port (clk : in std_logic; alarm_clear: in std_logic; led_alarm_not_exit: out std_logic; count_down_clock_select: in std_logic; bcddata_count_down_clock:in std_logic_vector(23 downto 0); led_count_down_clock:out std_logic ); end component led_contro; ---led控制模块申明end-- begin --例化按键消抖模块begin--- akeyfilt: keyfilt port map ( clk =>clk, key1=>key1, key1_filt =>key1_filt, key2=>key2, key2_filt =>key2_filt, key3=>key3, key3_filt =>key3_filt, key4=>key4, key4_filt =>key4_filt, key5=>key5, key5_filt =>key5_filt, key6=>key6, key6_filt =>key6_filt, key7=>key7, key7_filt =>key7_filt, key8=>key8, key8_filt =>key8_filt ); --例化按键消抖模块end--- ---时钟模块例化begin--------- aclock_source: clock_source port map ( clk=>clk, clk_1s=>clk_1s, clk_10ms=>clk_10ms, Stopwatch_clear=>Stopwatch_clear, clkcnt=>clkcnt ); ---时钟模块例化end--------- ---按键状态模块例化begin--------- akey_state: key_state port map ( clk=>clk, key1_filt=>key1_filt, key2_filt=>key2_filt, key3_filt=>key3_filt, key4_filt=>key4_filt, key5_filt=>key5_filt, key6_filt=>key6_filt, key7_filt=>key7_filt, key8_filt=>key8_filt, en=>en, skey5=>skey5, alarm_key5=>alarm_key5, count_down_clock_skey5=>count_down_clock_skey5, skey6=>skey6, skey7=>skey7, skey8=>skey8 ); ---按键状态模块例化end--------- ---数码管显示模块例化begin--- aseg_display: seg_display port map ( clk=>clk, clk_1s=>clk_1s, clkcnt=>clkcnt, en=>en, bcddata=>bcddata, set_time=>set_time, bcddata_temp=>bcddata_temp, position=>position, Stopwatch_show_savedata=>Stopwatch_show_savedata, Stopwatch_save_data=>Stopwatch_save_data, bcddata_Stopwatch=>bcddata_Stopwatch, bcddata_alarm=>bcddata_alarm, alarm_select=>alarm_select, bcddata_count_down_clock=>bcddata_count_down_clock, count_down_clock_select=>count_down_clock_select, segdot=>segdot, SEG_LED=>SEG_LED, SEG_NCS=>SEG_NCS ); ---数码管显示模块例化end--- ---例化led控制模块begin-- aled_contro: led_contro port map ( clk =>clk, alarm_clear=>alarm_clear, led_alarm_not_exit=>led_alarm_not_exit, count_down_clock_select=>count_down_clock_select, bcddata_count_down_clock=>bcddata_count_down_clock, led_count_down_clock=>led_count_down_clock ); ---例化led控制模块end-- process(clk) begin if(clk'event and clk='1') then case en is when "00" => if(skey5='1') then set_time<='1'; --set_time_finish<='0'; --if(key5_filt='1') then --set_time_finish<='1';--只有在set_time=1时才为1 --end if; if(key6_filt='1')then move_left<='1'; else move_left<='0'; end if; if(key7_filt='1')then add<='1'; else add<='0'; end if; if(key8_filt='1')then sub<='1'; else sub<='0'; end if; else set_time<='0'; --set_time_finish<='0'; --闹钟的关闭、清除 if(key7_filt='1')then alarm_turn_off<='1'; else alarm_turn_off<='0'; end if; if(key8_filt='1')then alarm_clear<=not alarm_clear; end if; end if; when "01" => if(key5_filt='1') then --开始计数,可暂停,不关闭时钟 Stopwatch_begin<=not Stopwatch_begin; end if; if(key6_filt='1') then --清零键,关闭时钟 Stopwatch_clear<=not Stopwatch_clear; end if; if(key7_filt='1') then --标记键 Stopwatch_save<='1'; else Stopwatch_save<='0'; end if; if(skey8='1') then --读取键,再按一次返回秒表显示 Stopwatch_read<='1'; else Stopwatch_read<='0'; end if; when "10"=> if(alarm_key5='1')then alarm_select<='1';--只是用来让闹钟界面数字不再闪烁,有没有确定实际上还是由alarm_clear决定 else alarm_select<='0'; end if; if(key6_filt='1')then move_left<='1'; else move_left<='0'; end if; if(key7_filt='1')then add<='1'; else add<='0'; end if; if(key8_filt='1')then sub<='1'; else sub<='0'; end if; when "11"=> if(count_down_clock_skey5='1') then--开始计时按钮 count_down_clock_select<='1'; if(key7_filt='1') then --在设定完时间的状态下检测7按键,按下则灭灯 led_count_down_clock_turn_off<='1'; else led_count_down_clock_turn_off<='0'; end if; else count_down_clock_select<='0'; end if; if(key6_filt='1')then move_left<='1'; else move_left<='0'; end if; if(key7_filt='1')then add<='1'; else add<='0'; end if; if(key8_filt='1')then sub<='1'; else sub<='0'; end if; when others=> NULL; end case; end if; end process; process(clk) begin if(clk'event and clk='1') then case en is when "00"=> if(set_time='0') then--没有设置时间时,将bcddata复制到bcddata_temp,是为了按下5时可以从现在时间开始设置 bcddata_temp<=bcddata; position<=0;--清零,下一次设置时间时仍是秒个位闪烁 if(bcddata=bcddata_alarm_finally and alarm_clear='0') then led<='0';--闹钟时间到,led闪烁 end if; if(alarm_turn_off='1') then led<='1'; end if; end if; if(set_time='1') then if(move_left='1')then if(position=20) then position<=0; else position<=position+4; end if; end if; if(add='1')then if(position=0) then if(bcddata_temp(position+3 downto position)=9) then bcddata_temp(position+3 downto position)<=x"9"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)+1; end if; elsif(position=4) then if(bcddata_temp(position+3 downto position)=5) then bcddata_temp(position+3 downto position)<=x"5"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)+1; end if; elsif(position=8) then if(bcddata_temp(position+3 downto position)=9) then bcddata_temp(position+3 downto position)<=x"9"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)+1; end if; elsif(position=12) then if(bcddata_temp(position+3 downto position)=5) then bcddata_temp(position+3 downto position)<=x"5"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)+1; end if; elsif(position=16) then if(bcddata_temp(23 downto 20)=0 or bcddata_temp(23 downto 20)=1) then if(bcddata_temp(position+3 downto position)=9) then bcddata_temp(position+3 downto position)<=x"9"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)+1; end if; else if(bcddata_temp(position+3 downto position)=3) then bcddata_temp(position+3 downto position)<=x"3"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)+1; end if; end if; else if(bcddata_temp(position+3 downto position)=2) then bcddata_temp(position+3 downto position)<=x"2"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)+1; end if; end if; end if; if(sub='1')then if(bcddata_temp(position+3 downto position)=0) then bcddata_temp(position+3 downto position)<=x"0"; else bcddata_temp(position+3 downto position)<=bcddata_temp(position+3 downto position)-1; end if; end if; end if; when "01"=> if(Stopwatch_save='1') then Stopwatch_save_data<=bcddata_Stopwatch; end if; if(Stopwatch_read='1') then Stopwatch_show_savedata<='1'; else Stopwatch_show_savedata<='0'; end if; when "10"=> if(alarm_select='0') then--只有在没有选定之前才可以更改闹钟数字 if(move_left='1')then if(position=20) then position<=0; else position<=position+4; end if; end if; if(add='1')then if(position=0) then if(bcddata_alarm(position+3 downto position)=9) then bcddata_alarm(position+3 downto position)<=x"9"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)+1; end if; elsif(position=4) then if(bcddata_alarm(position+3 downto position)=5) then bcddata_alarm(position+3 downto position)<=x"5"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)+1; end if; elsif(position=8) then if(bcddata_alarm(position+3 downto position)=9) then bcddata_alarm(position+3 downto position)<=x"9"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)+1; end if; elsif(position=12) then if(bcddata_alarm(position+3 downto position)=5) then bcddata_alarm(position+3 downto position)<=x"5"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)+1; end if; elsif(position=16) then if(bcddata_alarm(23 downto 20)=0 or bcddata_alarm(23 downto 20)=1) then if(bcddata_alarm(position+3 downto position)=9) then bcddata_alarm(position+3 downto position)<=x"9"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)+1; end if; else if(bcddata_alarm(position+3 downto position)=3) then bcddata_alarm(position+3 downto position)<=x"3"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)+1; end if; end if; else if(bcddata_alarm(position+3 downto position)=2) then bcddata_alarm(position+3 downto position)<=x"2"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)+1; end if; end if; end if; if(sub='1')then if(bcddata_alarm(position+3 downto position)=0) then bcddata_alarm(position+3 downto position)<=x"0"; else bcddata_alarm(position+3 downto position)<=bcddata_alarm(position+3 downto position)-1; end if; end if; end if; if(alarm_select='1') then position<=0; bcddata_alarm_finally<=bcddata_alarm; else bcddata_alarm_finally<="111111111111111111111111";--让bcddata_alarm_finally不可能与bcddata相等,看起来好像没有选定就不能设置闹钟 end if; when "11"=> if(count_down_clock_select='0') then--只有在没有选定之前才可以更改计时器数字 if(move_left='1')then if(position=20) then position<=0; else position<=position+4; end if; end if; if(add='1')then if(position=0) then if(bcddata_count_down_clock_temp(position+3 downto position)=9) then bcddata_count_down_clock_temp(position+3 downto position)<=x"9"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)+1; end if; elsif(position=4) then if(bcddata_count_down_clock_temp(position+3 downto position)=5) then bcddata_count_down_clock_temp(position+3 downto position)<=x"5"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)+1; end if; elsif(position=8) then if(bcddata_count_down_clock_temp(position+3 downto position)=9) then bcddata_count_down_clock_temp(position+3 downto position)<=x"9"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)+1; end if; elsif(position=12) then if(bcddata_count_down_clock_temp(position+3 downto position)=5) then bcddata_count_down_clock_temp(position+3 downto position)<=x"5"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)+1; end if; elsif(position=16) then if(bcddata_count_down_clock_temp(23 downto 20)=0 or bcddata_count_down_clock_temp(23 downto 20)=1) then if(bcddata_count_down_clock_temp(position+3 downto position)=9) then bcddata_count_down_clock_temp(position+3 downto position)<=x"9"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)+1; end if; else if(bcddata_count_down_clock_temp(position+3 downto position)=3) then bcddata_count_down_clock_temp(position+3 downto position)<=x"3"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)+1; end if; end if; else if(bcddata_count_down_clock_temp(position+3 downto position)=2) then bcddata_count_down_clock_temp(position+3 downto position)<=x"2"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)+1; end if; end if; end if; if(sub='1')then if(bcddata_count_down_clock_temp(position+3 downto position)=0) then bcddata_count_down_clock_temp(position+3 downto position)<=x"0"; else bcddata_count_down_clock_temp(position+3 downto position)<=bcddata_count_down_clock_temp(position+3 downto position)-1; end if; end if; else position<=0; end if; when others=>NULL; end case; end if; end process; process(clk_1s) begin if (clk_1s'event and clk_1s='1') then if(set_time='0') then if bcddata(3 downto 0)=x"9" then --秒的个位(10进制) bcddata(3 downto 0)<=x"0"; else bcddata(3 downto 0)<=bcddata(3 downto 0)+1; end if; if bcddata(7 downto 0)=x"59" then --秒的十位(6进制) bcddata(7 downto 0)<=x"00"; elsif bcddata(3 downto 0)=x"9" then bcddata(7 downto 4)<=bcddata(7 downto 4)+1; end if; if bcddata(11 downto 0)=x"959" then --分的个位(10进制) bcddata(11 downto 0)<=x"000"; elsif bcddata(7 downto 0)=x"59" then bcddata(11 downto 8)<=bcddata(11 downto 8)+1; end if; if bcddata(15 downto 0)=x"5959" then --分的十位(六进制) bcddata(15 downto 0)<=x"0000"; elsif bcddata(11 downto 0) =x"959" then bcddata(15 downto 12)<=bcddata(15 downto 12)+1; end if; if bcddata(19 downto 0)=x"95959" then --小时的十位(10进制) bcddata(19 downto 0)<=x"00000"; elsif bcddata(15 downto 0) =x"5959" then bcddata(19 downto 16)<=bcddata(19 downto 16)+1; end if; if bcddata(23 downto 0)=x"235959" then --小时的十位 bcddata(23 downto 0)<=x"000000"; elsif bcddata(19 downto 0) =x"95959" then bcddata(23 downto 20)<=bcddata(23 downto 20)+1; end if; else bcddata<=bcddata_temp;--至关重要的一句,确保设置时间的时候每时每刻把数据覆盖给bcddata end if; ------------------------------------ if(count_down_clock_select='1') then --倒计时程序 if(bcddata_count_down_clock=0) then --什么都不做 else if bcddata_count_down_clock(3 downto 0)=x"0" then --秒的个位(10进制) bcddata_count_down_clock(3 downto 0)<=x"9"; else bcddata_count_down_clock(3 downto 0)<=bcddata_count_down_clock(3 downto 0)-1; end if; if bcddata_count_down_clock(7 downto 0)=x"00" then --秒的十位(6进制) bcddata_count_down_clock(7 downto 0)<=x"59"; elsif bcddata_count_down_clock(3 downto 0)=x"0" then bcddata_count_down_clock(7 downto 4)<=bcddata_count_down_clock(7 downto 4)-1; end if; if bcddata_count_down_clock(11 downto 0)=x"000" then --分的个位(10进制) bcddata_count_down_clock(11 downto 0)<=x"959"; elsif bcddata_count_down_clock(7 downto 0)=x"00" then bcddata_count_down_clock(11 downto 8)<=bcddata_count_down_clock(11 downto 8)-1; end if; if bcddata_count_down_clock(15 downto 0)=x"0000" then --分的十位(六进制) bcddata_count_down_clock(15 downto 0)<=x"5959"; elsif bcddata_count_down_clock(11 downto 0) =x"000" then bcddata_count_down_clock(15 downto 12)<=bcddata_count_down_clock(15 downto 12)-1; end if; if bcddata_count_down_clock(19 downto 0)=x"00000" then --小时的十位(10进制) bcddata_count_down_clock(19 downto 0)<=x"95959"; elsif bcddata_count_down_clock(15 downto 0) =x"0000" then bcddata_count_down_clock(19 downto 16)<=bcddata_count_down_clock(19 downto 16)-1; end if; if bcddata_count_down_clock(23 downto 0)=x"000000" then --小时的十位 bcddata_count_down_clock(23 downto 0)<=x"235959"; elsif bcddata_count_down_clock(19 downto 0) =x"00000" then bcddata_count_down_clock(23 downto 20)<=bcddata_count_down_clock(23 downto 20)-1; end if; end if; else bcddata_count_down_clock<=bcddata_count_down_clock_temp; end if; end if; end process; process(clk_10ms) begin if Stopwatch_clear = '1' then --异步清零 bcddata_Stopwatch(23 downto 0)<= x"000000"; else if clk_10ms'event and clk_10ms='1' and Stopwatch_begin='1' then if bcddata_Stopwatch(3 downto 0)=x"9" then --百分秒的个位(十进制) bcddata_Stopwatch(3 downto 0)<=x"0"; else bcddata_Stopwatch(3 downto 0)<=bcddata_Stopwatch(3 downto 0)+1; end if; if bcddata_Stopwatch(7 downto 0)=x"99" then --百分秒的十位(十进制) bcddata_Stopwatch(7 downto 0)<=x"00"; elsif bcddata_Stopwatch(3 downto 0)=x"9" then bcddata_Stopwatch(7 downto 4)<=bcddata_Stopwatch(7 downto 4)+1; end if; if bcddata_Stopwatch(11 downto 0)=x"999" then --秒的个位(十进制) bcddata_Stopwatch(11 downto 0)<=x"000"; elsif bcddata_Stopwatch(7 downto 0)=x"99" then bcddata_Stopwatch(11 downto 8)<=bcddata_Stopwatch(11 downto 8)+1; end if; if bcddata_Stopwatch(15 downto 0)=x"5999" then --秒的十位(六进制) bcddata_Stopwatch(15 downto 0)<=x"0000"; elsif bcddata_Stopwatch(11 downto 0) =x"999" then bcddata_Stopwatch(15 downto 12)<=bcddata_Stopwatch(15 downto 12)+1; end if; if bcddata_Stopwatch(19 downto 0)=x"95999" then --小时的十位(10进制) bcddata_Stopwatch(19 downto 0)<=x"00000"; elsif bcddata_Stopwatch(15 downto 0) =x"5999" then bcddata_Stopwatch(19 downto 16)<=bcddata_Stopwatch(19 downto 16)+1; end if; if bcddata_Stopwatch(23 downto 0)=x"595999" then --小时的十位 bcddata_Stopwatch(23 downto 0)<=x"000000"; elsif bcddata_Stopwatch(19 downto 0) =x"95999" then bcddata_Stopwatch(23 downto 20)<=bcddata_Stopwatch(23 downto 20)+1; end if; end if; -- end clk_10ms end if; --end clear end process; end behav;
设计原理与分析:在顶层文件中,首先对各个模块进行声明,为了概念明确一些,各个模块中的变量名与顶层文件中的变量名是一样的。顶层文件的作用是先对按键检测模块产生的信号进行判断(273行开始的进程),在en为不同值的情况下分别对按键检测到的信号进行判断,不直接用按键检测到的信号去控制四个功能下的各种设置作用是因为四个功能所用的键都是BUT5BUT7。因此在顶层文件中添加一个进程实现en为00,01,10,11情况下信号的变化赋值。接下来对不同en情况下对应的bcddata进行赋值以及相应功能的实现(384行开始的进程)。以设置时间为例,在设置时间时,用到了一个position整形变量,这个变量的范围为020,每按一下按键,position+4,对应要设置的bcddata为bcddata(position+3 downto position).当position超过20时,让position赋值为0。最后的两个进程分别以1HZ与100HZ作为触发信号,在1HZ的进程中进行时间bcddata数值的变化以及计时器的倒计时的bcddata_count_down_clock的数值的变化。
三、技术流程图
1、功能流程图
2、程序流程图
四、仿真
1、仿真四个按键BUT1~BUT4按下时en的变化情况
激励文件主要部分为:
仿真结果:
2、仿真定时器时间到时LED变为低电平,即点亮。激励文件中按key4后按两下key7,再按key5确定,计时两秒后led_count_down_clock变为低电平。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。