-- Filename ﹕ SW_DEBOUNCE.vhd
-- Author ﹕ wuhouhang
-- Description ﹕ 三個獨立按鍵控制四個LED流水燈工作/停止或者左移/右移
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity JOHNSON is
port(
Clk: in STD_LOGIC; --50MHz輸入時鐘
Rst_n: in STD_LOGIC; --低電平復位信號
Key_in: in STD_LOGIC_VECTOR (2 downto 0); --三個獨立按鍵,低表示按下
--Key_in(2): 控制流水燈工作/停止
--Key_in(1): 控制流水燈右移
--Key_in(0): 控制流水燈左移
Led_out: buffer STD_LOGIC_VECTOR (3 downto 0) --發光二極管,分別由按鍵控制
);
end entity JOHNSON;
--20ms按鍵消抖處理
--消抖后按鍵下降沿檢測
--按鍵控制LED控制位狀態
--LED顯示控制
architecture KEY_CONTROL_OF_LED of JOHNSON is
signal key_inr0: STD_LOGIC_VECTOR (2 downto 0); --第一拍按鍵鎖存寄存器
signal key_inr1: STD_LOGIC_VECTOR (2 downto 0); --第二拍按鍵鎖存寄存器
signal key_posedge: STD_LOGIC_VECTOR (2 downto 0); --按鍵上升沿標志位,高電平有效一個時鐘周期
signal key_negedge: STD_LOGIC_VECTOR (2 downto 0); --按鍵下降沿標志位,高電平有效一個時鐘周期
signal cnt20ms: STD_LOGIC_VECTOR (19 downto 0); --20ms計數寄存器
signal key_value: STD_LOGIC_VECTOR (2 downto 0); --消抖后的鍵值鎖存寄存器
signal key_valuer0: STD_LOGIC_VECTOR (2 downto 0); --消抖后第一拍按鍵鎖存寄存器
signal key_valuer1: STD_LOGIC_VECTOR (2 downto 0); --消抖后第二拍按鍵鎖存寄存器
signal key_valueneg: STD_LOGIC_VECTOR (2 downto 0); --消抖后按鍵下降沿標志位,高電平有效一個時鐘周期
signal led_display: STD_LOGIC; --LED流水燈工作,1--開啟,0--停止
signal led_direction: STD_LOGIC; --LED流水燈方向,1--右移,0--左移
signal cnt320ms: STD_LOGIC_VECTOR (23 downto 0); --320ms計數寄存器
begin
--第一拍按鍵鎖存
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
key_inr0 <= "111";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
key_inr0 <= Key_in; --鎖存上一拍鍵值
end if;
end process;
--第二拍按鍵鎖存
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
key_inr1 <= "111";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
key_inr1 <= key_inr0; --鎖存上一拍鍵值
end if;
end process;
--按鍵邊沿檢測
key_posedge <= (NOT key_inr1) AND key_inr0; --按鍵上升沿標志位,高電平有效一個時鐘周期
key_negedge <= key_inr1 AND (NOT key_inr0); --按鍵下降沿標志位,高電平有效一個時鐘周期
--20ms計數
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
cnt20ms <= x"00000";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
if ((key_posedge /= "000") OR (key_negedge /= "000")) then --鍵值邊沿標志位復位計數器,此處理目的為消除抖動
cnt20ms <= x"00000";
elsif (cnt20ms < 10#1000000#) then --20ms計數
cnt20ms <= cnt20ms+1;
else
cnt20ms <= x"00000";
end if;
end if;
end process;
--消抖后鍵值鎖存
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
key_value <= "111";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
if (cnt20ms = 10#1000000#) then --計數值到20ms
key_value <= key_inr1; --鎖存鍵值
end if;
end if;
end process;
--消抖后第一拍按鍵鎖存
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
key_valuer0 <= "111";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
key_valuer0 <= key_value; --鎖存上一拍鍵值
end if;
end process;
--消抖后第二拍按鍵鎖存
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
key_valuer1 <= "111";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
key_valuer1 <= key_valuer0; --鎖存上一拍鍵值
end if;
end process;
--消抖后按鍵下降沿檢測
key_valueneg <= key_valuer1 AND (NOT key_valuer0); --消抖后按鍵下降沿標志位,高電平有效一個時鐘周期
--按鍵控制LED控制位狀態(流水燈工作/停止)
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
led_display <= '0';
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
if (key_valueneg(2) = '1') then --控制流水燈工作/停止
led_display <= NOT led_display; --鎖存鍵值
end if;
end if;
end process;
--按鍵控制LED控制位狀態(流水燈左移/右移)
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
led_direction <= '0';
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
if (key_valueneg(1) = '1') then --控制流水燈工作/停止
led_direction <= '1'; --鎖存鍵值
elsif (key_valueneg(0) = '1') then --控制流水燈工作/停止
led_direction <= '0'; --鎖存鍵值
end if;
end if;
end process;
--320ms計數
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
cnt320ms <= x"000000";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
if (cnt320ms < 10#16000000#) then --320ms計數
cnt320ms <= cnt320ms+1;
else
cnt320ms <= x"000000";
end if;
end if;
end process;
--LED顯示控制
process(Clk,Rst_n)
begin
if (Rst_n = '0') then --異步復位
Led_out <= "0001";
elsif (Clk'event AND Clk = '1') then --時鐘上升沿
if (cnt320ms = 10#16000000# AND led_display = '1') then --每320ms做一次LED移位判斷
if (led_direction = '1') then --右移
Led_out <= Led_out(0) & Led_out(3) & Led_out(2) & Led_out(1);
--Led_out <= Led_out SLA 1;
else --左移
Led_out <= Led_out(2) & Led_out(1) & Led_out(0) & Led_out(3);
--Led_out <= Led_out SRA 1;
end if;
end if;
end if;
end process;
end architecture KEY_CONTROL_OF_LED;
評論
查看更多