library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; entity DigitalClock is port ( CLK_6MHz: in std_logic; RST : in std_logic; KEY_IN : in std_logic_vector(3 downto 0); KEY_OUT : out std_logic_vector(3 downto 0); SEG_DATA: out std_logic_vector(7 downto 0); SEG_CHOOSE: out std_logic_vector(2 downto 0); FOUT : out std_logic ); end; architecture archSegment2 of DigitalClock is constant KEY_DIV : integer := 120000; --按键延时长度 type KEY_STATE is(KS0,KS1,KS2,KS3); type ARRAY8x1 is array(7 downto 0)of integer range 255 downto 0; --8个8位的数据 signal timeValue : ARRAY8x1; --记录时间 signal keyInBak : std_logic_vector(3 downto 0); --保存按键的读入值 signal keyOutBak : std_logic_vector(3 downto 0); --记录按键扫描的输出值 signal delayCount : integer range 16383 downto 0 := 0; --音符周期计数 signal delay : integer range 16383 downto 0 := 0; --音符周期 signal clk4Hz : std_logic := '0'; --4Hz计数 signal foutTemp : std_logic := '1'; signal songData : integer range 255 downto 0 := 0; --用2位10进制数来表示音符,其中十位的1、2、3分别表示音符的低、中、高 --个位的1~7分别表示音符1~7 signal songStartFlag : integer range 255 downto 0 := 0; signal songStopFlag : integer range 255 downto 0 := 0; begin KeyScan:process(CLK_6MHz,KEY_IN,RST,songStopFlag) --按键扫描 variable keyCount : integer range 140000 downto 0 := 0; --用于按键去抖 variable keyState : KEY_STATE := KS0; --记录按键扫描的状态 variable keyFlag : integer range 1 downto 0 := 0; --记录去抖时间是否已到 variable i : integer range 255 downto 0 := 0; --用于普通的for loop中 variable outIndex : integer range 3 downto 0 := 0; --用于扫描输出信号的计数 variable temp : integer range 255 downto 0 := 0; variable timeCount : integer range 255 downto 0 := 0; --记录是否达到1s variable secondCount : integer range 255 downto 0 := 0; --记录秒钟 variable minuteCount : integer range 255 downto 0 := 0; --记录秒钟 variable hourCount : integer range 255 downto 0 := 0; --记录秒钟 begin case outIndex is --产生扫描信号 when 0 => KEY_OUT <= "0001"; keyOutBak <= "0001"; when 1 => KEY_OUT <= "0010"; keyOutBak <= "0010"; when 2 => KEY_OUT <= "0100"; keyOutBak <= "0100"; when 3 => KEY_OUT <= "1000"; keyOutBak <= "1000"; when others => KEY_OUT <= "0001"; keyOutBak <= "0001"; end case; if(RST = '1')then keyState := KS0; outIndex := 0; for i in 0 to 7 loop timeValue(i) <= 0; end loop; elsif(rising_edge(CLK_6MHz))then --计时 if(songStopFlag = 1)then songStartFlag <= 0; end if; keyCount := keyCount + 1; if(keyCount = KEY_DIV)then --达到20ms keyCount := 0; keyFlag := 1; timeCount := timeCount + 1; if(timeCount >= 50)then --达到1s timeCount := 0; secondCount := secondCount + 1; if(secondCount >= 60)then --达到1min secondCount := 0; minuteCount := minuteCount + 1; if(minuteCount >= 60)then --达到1h songStartFlag <= 1; minuteCount := 0; hourCount := hourCount + 1; if(hourCount >= 24)then --达到1day hourCount := 0; end if; end if; end if; end if; timeValue(0) <= secondCount mod 10; timeValue(1) <= secondCount/10; timeValue(2) <= 15; timeValue(3) <= minuteCount mod 10; timeValue(4) <= minuteCount/10; timeValue(5) <= 15; timeValue(6) <= hourCount mod 10; timeValue(7) <= hourCount/10; end if; if(keyFlag = 1)then --按键扫描 case keyState is when KS0 => if(KEY_IN /= "0000")then keyState := KS1; else outIndex := outIndex + 1; if(outIndex >= 4)then outIndex := 0; end if; end if; when KS1 => if(KEY_IN /= "0000")then keyState := KS2; keyInBak <= KEY_IN; else keyState := KS0; end if; when KS2 => if(KEY_IN = "0000")then keyState := KS3; end if; when KS3 => if(KEY_IN = "0000")then --辨别按键 case conv_integer(keyInBak&keyOutBak) is when 2#00010001# => --0 temp := 0; when 2#00010010# => --1 temp := 1; when 2#00010100# => --2 temp := 2; when 2#00011000# => --3 temp := 3; when 2#00100001# => --4 temp := 4; when 2#00100010# => --5 temp := 5; when 2#00100100# => --6 temp := 6; when 2#00101000# => --7 temp := 7; when 2#01000001# => --8 temp := 8; when 2#01000010# => --9 temp := 9; when 2#01000100# => --A temp := 10; when 2#01001000# => --B temp := 11; when 2#10000001# => --C temp := 12; when 2#10000010# => --D temp := 13; when 2#10000100# => --E temp := 14; when 2#10001000# => --F temp := 15; when others => temp := 0; end case; keyState := KS0; if(temp = 10)then --按下A键,时钟加1 hourCount := hourCount + 1; if(hourCount >= 24)then hourCount := 0; end if; elsif(temp = 11)then --按下B键,时钟减1 if(hourCount = 0)then hourCount := 24; end if; hourCount := hourCount - 1; elsif(temp = 12)then --按下C键,分钟加1 minuteCount := minuteCount + 1; if(minuteCount >= 60)then minuteCount := 0; end if; elsif(temp = 13)then --按下D键,分钟减1 if(minuteCount = 0)then minuteCount := 60; end if; minuteCount := minuteCount - 1; elsif(temp = 14)then --按下E键,秒钟加1 secondCount := secondCount + 1; if(secondCount >= 60)then secondCount := 0; end if; elsif(temp = 15)then --按下F键,秒钟减1 if(secondCount = 0)then secondCount := 60; end if; secondCount := secondCount - 1; end if; else KeyState := KS3; end if; when others => KeyState := KS0; end case; keyFlag := 0; end if; end if; end process; SegDisplay:process(RST,CLK_6MHz,timeValue) --数码管显示 variable disCount : integer range 7 downto 0 := 0; --位选计数 begin if(RST = '1')then SEG_DATA <= (others =>'0'); SEG_CHOOSE <= (others =>'0'); disCount := 0; elsif(rising_edge(CLK_6MHz))then case timeValue(disCount) is --显示数组里面的数据 when 0 => --0 SEG_DATA <= "00111111"; when 1 => --1 SEG_DATA <= "00000110"; when 2 => --2 SEG_DATA <= "01011011"; when 3 => --3 SEG_DATA <= "01001111"; when 4 => --4 SEG_DATA <= "01100110"; when 5 => --5 SEG_DATA <= "01101101"; when 6 => --6 SEG_DATA <= "01111101"; when 7 => --7 SEG_DATA <= "00000111"; when 8 => --8 SEG_DATA <= "01111111"; when 9 => --9 SEG_DATA <= "01101111"; when 10 => --A SEG_DATA <= "01110111"; when 11 => --B SEG_DATA <= "01111100"; when 12 => --C SEG_DATA <= "00111001"; when 13 => --D SEG_DATA <= "01011110"; when 14 => --E SEG_DATA <= "01111001"; when 15 => --横 SEG_DATA <= "01000000"; when others => SEG_DATA <= "00111111"; end case; if(disCount >= 8)then disCount := 0; end if; SEG_CHOOSE <= conv_std_logic_vector(disCount,3);--片选信号 disCount := disCount + 1; end if; end process; process(CLK_6MHz,RST) variable count4Hz : integer range 750000 downto 0 := 0; begin if(RST = '1')then delayCount <= 0; foutTemp <= '1'; count4Hz := 0; clk4Hz <= '0'; elsif(rising_edge(CLK_6MHz))then delayCount <= delayCount + 1; if((delayCount >= delay)and(delay/=16383))then foutTemp <= foutTemp xor '1'; delayCount <= 0; elsif(delay = 16383)then foutTemp <= '0'; delayCount <= 0; end if; count4Hz := count4Hz + 1; -- if(count4Hz >= 750000)then --分频后产生8Hz信号 count4Hz := 0; clk4Hz <= clk4Hz xor '1'; --产生4Hz信号 end if; end if; FOUT <= foutTemp; end process; process(clk4Hz,RST) begin if(RST = '1')then delay <= 16383; elsif(rising_edge(clk4Hz))then case songData is when 15=> delay <= 15306; when 21=> delay <= 11465; when 22=> delay <= 10216; when 23=> delay <= 9100; when 24=> delay <= 8589; when 25=> delay <= 7653; when 26=> delay <= 6818; when others => delay <= 16383; end case; end if; end process; process(clk4Hz,songStartFlag) variable count : integer range 255 downto 0 := 0; begin if(songStartFlag = 1)then if(rising_edge(clk4Hz))then count := count + 1; if(count >= 64)then count := 0; songStopFlag <= 1; end if; case count is --两只老虎乐谱 when 0=> songData <= 21; when 1=> songData <= 21; when 2=> songData <= 22; when 3=> songData <= 22; when 4=> songData <= 23; when 5=> songData <= 23; when 6=> songData <= 21; when 7=> songData <= 21; when 8=> songData <= 21; when 9=> songData <= 21; when 10=> songData <= 22; when 11=> songData <= 22; when 12=> songData <= 23; when 13=> songData <= 23; when 14=> songData <= 21; when 15=> songData <= 21; when 16=> songData <= 23; when 17=> songData <= 23; when 18=> songData <= 24; when 19=> songData <= 24; when 20=> songData <= 25; when 21=> songData <= 25; when 22=> songData <= 25; when 23=> songData <= 25; when 24=> songData <= 23; when 25=> songData <= 23; when 26=> songData <= 24; when 27=> songData <= 24; when 28=> songData <= 25; when 29=> songData <= 25; when 30=> songData <= 25; when 31=> songData <= 25; when 32=> songData <= 25; when 33=> songData <= 26; when 34=> songData <= 25; when 35=> songData <= 24; when 36=> songData <= 23; when 37=> songData <= 23; when 38=> songData <= 21; when 39=> songData <= 21; when 40=> songData <= 25; when 41=> songData <= 26; when 42=> songData <= 25; when 43=> songData <= 23; when 44=> songData <= 23; when 45=> songData <= 23; when 46=> songData <= 21; when 47=> songData <= 21; when 48=> songData <= 21; when 49=> songData <= 21; when 50=> songData <= 25; when 51=> songData <= 25; when 52=> songData <= 21; when 53=> songData <= 21; when 54=> songData <= 21; when 55=> songData <= 21; when 56=> songData <= 21; when 57=> songData <= 21; when 58=> songData <= 15; when 59=> songData <= 15; when 60=> songData <= 21; when 61=> songData <= 21; when 62=> songData <= 21; when 63=> songData <= 21; when others => songData <= 0; end case; end if; else count := 0; songData <= 0; songStopFlag <= 0; end if; end process; end;