Тоже в связи с частыми вопросами про дребезг я решил выложить сюда свой модуль антидребезга.
Параметрами модуля можно ностроить:
1. Разрядность счетчика - определяющее время интегрирования.
2. Количество регистров-синхронизаторов для синхронизации с клоковым доменом.
3. Какой лог. уровень соответствует нажатой кнопке.
Как всегда приветствуются все замечания и предложения.
CODE
-- ————————————————— ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | File name | KAA_button_debouncer |
-- ————————————————— ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Properties | Tab type = space | HDL type = VHDL2008 | Languege - Russian | Syntesis tool = Quartus 13.1 | Sim = Modelsim ASE
-- ————————————————— ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Author | Клементьев Алексей Александрович | Email = KJIEMEHTbEB@gmail.com
-- ————————————————— ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Description | Антидребезг кнопки с синхронизатором CDC и выбором активного уровня нажатой кнопки.
-- ————————————————— ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Notes | 1. В модуле предусмотрена настройка какому лог. уровню соответствует нажатая кнопка.
-- | | За счет этого у нас сигнал-флаг нажатой кнопки всегда имеет логический уровень "1"
-- | | 2. Сдвиговый регистр-синхронизатор не может быть менше 2 разрядов.
-- | |
-- ————————————————— ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Change history |
-- | |
-- | |
-- ————————————————— ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- KAA_button_debouncer_comp : entity work.KAA_button_debouncer
-- generic map
-- (
-- active_level => "Negative", --"Positive" / "Negative" Активный уровень нажатой кнопки
-- sync_stages => 3, -- Количество стадий синхронизации с клоковым доменом
-- debouncer_width => 7 -- Разрядность счетчика, который досчитав до конца выдаст фалг нажатой кнопки
-- )
-- port map
-- (
-- clk =>
-- debouncer_in =>
-- button_pressed =>
-- );
--————————————————————————————————————————————————————————————————————————————————
——————————————————————————————————————————————————————
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity KAA_button_debouncer is
generic
(
active_level : string := "Positive"; -- "Positive" / "Negative" Активный уровень нажатой кнопки
sync_stages : natural := 3; -- Количество стадий синхронизации с клоковым доменом
debouncer_width : natural := 6 -- Разрядность счетчика, который досчитав до конца выдаст фалг нажатой кнопки
);
port
(
clk : in std_logic;
debouncer_in : in std_logic;
button_pressed : out std_logic
);
end entity;
architecture rtl of KAA_button_debouncer is
--=====================================================================
-- Константы для удобства
--=====================================================================
constant up : std_logic := '1'; -- Нажатая кнопка - счетчик считает вверх
constant down : std_logic := '0'; -- Кнопка отпущна - счетчик считает вниз
signal shreg : std_logic_vector(sync_stages - 1 downto 0) := (others => '0'); -- Регистр - синхронизатор
signal up_dissable : std_logic -- Сигнал отключения счета вверх
signal down_dissable : std_logic -- Сигнал отключения счета вниз
signal counter_unsigned : unsigned(debouncer_width -1 Downto 0) := (others => '0'); -- Счетчик
begin
--=====================================================================
-- Синхронизируем сигнал с клоковым доменом.
-- Так-же автоматически переводим активный уровень сигнала в лог.1
-- Это позволит на выходе иметь сигнал-флаг нажатой кнопки лог.1
--=====================================================================
meta_harden_reg : process(clk)
begin
if (rising_edge(clk)) then
if (active_level = "Positive") then -- Если активный уровнь лог.1
shreg <= shreg(shreg'left - 1 downto 0) & debouncer_in; -- То записываем сигнал в регистр как есть.
end if;
if (active_level = "Negative") then -- Если активный уровнь лог.1
shreg <= shreg(shreg'left - 1 downto 0) & (not debouncer_in); -- То записываем в ренгистр инверсию сигнала
end if;
end if;
end process;
--=====================================================================
-- Сигналы отключения счета счетчика
--=====================================================================
up_dissable <= '1' when (counter_unsigned = (counter_unsigned'left downto 0 => '1')) else '0'; -- Если все единички - запрети счетчику считать вверх
down_dissable <= '1' when (counter_unsigned = (counter_unsigned'left downto 0 => '0')) else '0'; -- Если все нолики - запрети счетчику считать вниз
--=====================================================================
-- Собственно сам счетчтик
--=====================================================================
cnt_proc : process(clk)
begin
if (rising_edge(clk)) then
case shreg(shreg'left) is -- Анализируем сигнал перенесенный в наш клоковый домен
when up => -- Если кнопка нажата
if (up_dissable = '0') then -- Если счетчику не запрещено считать вверх
counter_unsigned <= counter_unsigned + "1"; -- Инкрементируем счетчтик
end if;
when down => -- Если кнопка отпущена
if (down_dissable = '0') then -- Если счетчику не запрещено считать вниза
counter_unsigned <= counter_unsigned - "1"; -- Декрементируем счетчтик
end if;
when others => null;
end case;
end if;
end process;
--=====================================================================
-- Выходной триггер для формирования сигнала-флага нажатой кнопки
--=====================================================================
output_flip_flop : process(clk)
begin
if (rising_edge(clk)) then
case counter_unsigned is
when (counter_unsigned'left downto 0 => '1') => button_pressed <= '1'; -- Счетчик досчитал до конца(все единцы) - значит кнопка была нажата
when (counter_unsigned'left downto 0 => '0') => button_pressed <= '0'; -- Счетчик досчитал до конца(все нули) - считаем что была отпущена
when others => null; -- В оостальных случаях триггер хранит свое значение
end case;
end if;
end process;
--================================================================================
===========
-- Счетчик не может быть равен 0 !!
--================================================================================
===========
assert (debouncer_width /= 0)
report LF&
"Incorrect parametr 'debouncer_width'. Check the syntax !" &LF&
"Note : parametr Must be > 0 !"&LF severity error;
--================================================================================
===========
-- Проверка правильности параметров active_level
--================================================================================
===========
assert (active_level = "Negative" or active_level = "Positive")
report LF&
"Incorrect parametr 'active_level'. Check the syntax !" &LF&
"Note : parametr case-sensitive !"&LF severity failure;
-- ================================================================================
===========
-- Разрядность регистра-синхронизатора не может быть меньше 2 !
--================================================================================
===========
assert (sync_stages >= 2)
report LF&
"Incorrect parametr 'sync_stages'. Check the syntax !" &LF&
"Note : parametr Must be > 2 !"&LF severity error;
end architecture;
Нажмите для просмотра прикрепленного файла