通过检测下降沿来临,延时计数再次检测,如果为低电平则为按键按下。
检测下降沿:设置一个和,分别代表之前的之前和之前的信号状态,若两个信号key_in_d2=1,key_in_d1=0,他俩的not key_in_d2 and key_in_d1为1,则说明下降沿产生,把它设置为标志位key_flag。
延时计数:50MHz的板子每次计数需要20ns,而抖动时间大约为5-10ms。所以取7ms,作为延时时间。也就是计数350000次。为了在quartus II 9.1方便观察波形,选择计数20次。仿真波形如下:
可以看见当检测到下降沿时,开始计数计数计满再次检测,若为低电平则为按下按键,否则为抖动。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity debounce_detector is
Port (
clk : in STD_LOGIC;
key_in : in STD_LOGIC;
led_out : out STD_LOGIC
);
end debounce_detector;
architecture Behavioral of debounce_detector is
type state_type is (idle, S1, S2);
signal current_state, next_state : state_type;
signal key_in_d1, key_in_d2, key_fall : STD_LOGIC;
signal cnt : integer range 0 to 350000;
signal cnt_en, clr : STD_LOGIC;
signal key_flag : STD_LOGIC;
signal led: std_logic := '0';
begin
-- State transition process
state_transition: process(clk)
begin
if rising_edge(clk) then
current_state <= next_state;
end if;
end process state_transition;
-- Debouncing logic
debounce_logic: process(clk)
begin
if rising_edge(clk) then
key_in_d1 <= key_in;
key_in_d2 <= key_in_d1;
key_fall <= not key_in_d1 and key_in_d2;
end if;
end process debounce_logic;
-- State machine logic
state_machine: process(current_state, key_fall, cnt)
begin
case current_state is
when idle =>
key_flag <= '0';
clr <= '1';
cnt_en <= '0';
if key_fall = '1' then
next_state <= S1;
else
next_state <= idle;
end if;
when S1 =>
clr <= '0';
cnt_en <= '1';
if cnt = 350000 then
next_state <= S2;
else
next_state <= S1;
end if;
when S2 =>
clr <= '0';
if key_in = '0' then
key_flag <= '1';
else
key_flag <= '0';
end if;
next_state <= idle;
end case;
end process state_machine;
-- Counter logic
counter_logic: process(clk)
begin
if rising_edge(clk) then
if clr = '1' then
cnt <= 0;
elsif cnt_en = '1' then
cnt <= cnt + 1;
end if;
end if;
end process counter_logic;
process(clk)
begin
if(clk'event and clk='1') then
if(key_flag='1') then
led <= not led;
end if;
end if;
end process;
led_out <= led;
end Behavioral;