Подавление влияния дребезга контактов на ПЛИС
Пример программы на языке VDHL для ПЛИС, которая устраняет влияние дребезга контактов путем выполнения специального алгоритма (его использовали при обучении в моём универе).
Суть работы:
- опрос происходит 50 раз в секунду (то есть каждые 20 мс)
- создается некая переменная (удобно использовать имя вывода к которому подключена кнопка)
- когда кнопка нажата, то к переменной добавляется единица, если не нажата, то ей присваивается ноль
- когда значение переменной достигает 4 (то есть 4*20мс =
200 мс80 мс (Исправлено от 23.09.2025) кнопка была нажата, а дребезг происходит меньшее время), то выполняем что нужно
Что можно изменить:
- опрос может происходить 30-60 раз в секунду (то есть каждые 33.3 - 16.6 мс)
- количество подтверждений также может быть 3-6 раз
- можно также смещать биты
Что вообще происходит в программе
Здесь создается ШИМ-сигнал (код взят с хабра), а его ширина импульса (значение porog) прибавляется на 10% по нажатию тактовой кнопки (её то контакты и дребезжат), причем при достижении 90% коэффициент заполнения опять становится 10%.
Симуляция работы
В третье строке отображается логический уровень на кнопке. Пока высокий уровень (нажата), то увеличивается значение в
porog, причём каждые 200 мс 80 мс (Исправлено от 23.09.2025), ну а когда низкий уровень (не нажата), ничего не происходит. В железе это всё прекрасно работает, проверено.

А вот во второй строке видно собственно изменение ширины импульса сигнала, согласно значению в переменной porog.

Весь код программы
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Goon is
Port ( clk : in STD_LOGIC; -- Входной тактовый вывод
pwm : out STD_LOGIC; -- Вывод для вывода сигнала
button : in STD_LOGIC -- Вывод для кнопки (подтянута к минусу)
);
end Goon;
architecture Behavioral of Goon is
---------------------------- Переменные для ШИМ-сигнала --------------------------
constant clk_freq : integer := 100_000_000; -- частота кварца
constant pwm_freq : integer := 25_000; -- частота ШИМ
constant max_count : integer := clk_freq / pwm_freq; -- разрядность ШИМ
signal count: integer range 0 to max_count := 0; -- счетчик делителя частоты
signal porog: integer := max_count / 10; -- ширина импульса логической единицы
----------------------------------------------------------------------------------
---------------------------- Переменные для дребезга ----------------------------
signal low_frequency : std_logic_vector(20 downto 0) := (others => '0');
signal count_bounce : std_logic_vector(7 downto 0) := (others => '0');
-------------------------------------------------------------------------
begin
----------------------- Собственно процесс генерирования ШИМ-сигнала------------
process(clk)
begin
if rising_edge(clk) then
if count = max_count then
count <= 0;
else
count <= count + 1;
end if;
end if;
end process;
led1 <= '1' when count < porog else '0';
------------------------------------------------------------------------------
--------------------------Дребезг-----------------------------
process(clk)
begin
if rising_edge(clk) then
low_frequency <= low_frequency + 1;
if low_frequency = 2000000 then
low_frequency <= (others => '0');
if button = '1' then
count_bounce <= count_bounce + 1;
if count_bounce = 4 then
count_bounce <= (others => '0');
porog <= porog + max_count/10;
if porog >= max_count*9/10 then
porog <= max_count/10;
end if;
end if;
else
count_bounce <= (others => '0');
end if;
end if;
end if;
end process;
---------------------------------------------------------------
end Behavioral;
> 4*20мс = 200 мс
4*20 == 80
Спасибо, исправил.