Программируемая логика - это не так уж и сложно. Разберемся вместе.
Ответить

Антидребезг (VHDL)

Вт июл 25, 2017 15:30:41

Возникла проблема.Есть устройство,на выходе которого 4 светодиода (led).Они поочерёдно загораются и тухнут с частотой 1Гц . К устройству подключена кнопка (btn). Когда она нажата, сигнал должен идти на светодиоды (как показано на диаграмме). Так вот, при нажатии возникает дребезг, диоды горят хаотично, при чём даже могут гореть, когда кнопка отпущена. Код вроде простой.но никак не могу правильно этот антидребезг добавить. Заранее благодарен.

ВЕРХНИЙ ФАЙЛ

Код:
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

entity led_blink is
  port (
    clk : in  std_logic; -- синхросигнал
    btn : in  std_logic; --кнопка
    led : out std_logic_vector(3 downto 0) --выход на светодиоды
  );
end led_blink;

architecture rtl of led_blink is
  signal ONN_OFF : std_logic                    := '1';
  signal state   : std_logic_vector(3 downto 0) := "0001";
  signal divider : unsigned(23 downto 0)        := (others => '0'); --делитель частоты
begin
  main_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (divider < 5000000) then  ---если меньше 5 млн. тактов, то счётчик наращивает 1
        divider <= divider + 1;
      else
        divider <= (others => '0');--если больше,то счётчик сбрасывается в 0
        if (btn = '1') then --если нажата кнопка
          ONN_OFF <= not(ONN_OFF);--светодиоды загораются
          if (ONN_OFF = '1') then
            state <= state(2 downto 0) & state(3);
            led   <= state;
          else --если НЕ нажата
            led   <= (others => '0');--сигнал на выход светодиодов не идёт
          end if;
        else
          ONN_OFF <= '1';
          led     <= (others => '0');
        end if;
      end if;
    end if;
  end process;
end rtl;


ТЕСТБЕНЧ

Код:
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;

entity led_blink_tb is
end;

architecture bench of led_blink_tb is

  component led_blink
    port (
      clk : in  std_logic;
      btn : in  std_logic;
      led : out std_logic_vector(3 downto 0)
    );
  end component;

  signal clk: std_logic;
  signal btn: std_logic;
  signal led: std_logic_vector(3 downto 0) ;


constant PERIOD : TIME := 100 ns;
constant DUTY_CYCLE : real := 0.5;
constant OFFSET : time := 3 ns;

begin
btn <= '0' after 500 ms, '1' after 3000  ms, '0' after 5000 ms, '1'after 9000 ms, '0' after 14000 ms, '1'after 20000 ms ;

  uut: led_blink port map ( clk => clk,
                            btn  => btn,
                            led => led );

clk_gen: PROCESS
BEGIN
WAIT for OFFSET;
CLOCK_LOOP : LOOP
CLK <= '0';
WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE));
CLK <= '1';
WAIT FOR (PERIOD * DUTY_CYCLE);
END LOOP CLOCK_LOOP;
END PROCESS;
end;
Вложения
DR.jpg
ременная диаграмма работы устройства.
При загрузке в устройсво, кнопка конечно же без антидребезга так идеально не работает (((
(74 KiB) Скачиваний: 670

Re: Антидребезг (VHDL)

Ср авг 09, 2017 16:15:53

Кнопка с антидребезгом и автоповтором:
Код:
entity manual is
    Port ( clk : in  STD_LOGIC;
           key : in  STD_LOGIC;
           set : out  STD_LOGIC);
end manual;

architecture Behavioral of manual is
signal countdown: STD_LOGIC_VECTOR (4 downto 0) := conv_std_logic_vector(31,5);
constant start:  std_logic_vector := conv_std_logic_vector(31,5);
constant repeat: std_logic_vector := conv_std_logic_vector(10,5);

begin

    process (clk, key)
    begin
    
        if (clk'event and clk='1') then
            if key='0' then
                countdown <= start;
            else
                if (countdown = 0) then
                    countdown <= repeat;
                else
                    countdown <= countdown - 1;
                End IF;
            End if;
        End if;
    
    end process;

set <= '1' when ((countdown = 0) or (countdown = (start-2))) else '0';

end Behavioral;
на клок подаётся 32 Гц (или масштабируйте для своих целей) на кей - кнопка, а на сет - чистые импульсы.
Этот модуль обеспечивает подавление дребезга контактов кнопки и автоповтор срабатывания. Это обеспечивается следующим образом. Главный элемент - пятиразрядный счетчик с обратным отсчетом (можно и с прямым, но мне так удобнее). Пока кнопка не нажата счетчик принудительно устанавливается в значение 31 (все лог.1). Как только кнопка будет нажата, счетчик начнёт свой обратный отсчет. Если кнопка будет удерживаться досточно долго (2/32 секунды), счетчик досчитает до 29 - пройдет импульс позволяющий инкрементировать счетчик часов или минут. Если кнопка будет отпущена, то вся система возвратится в исходное состояние, если нет - то счетчик продолжит свой обратный отсчет. Если счетчик досчитает до 0 (примерно через секунду) - пройдет следующий импульс установки времени. Однако, после того как счетчик достигнет нуля он не перейдет в состояние 31, а установится в значение 10, и уже с этого значения опять повторится обратный отсчет. Это обеспечит то, что повторные импульсы будут следовать с частотой, приблизительно, 3 импульса в секунду. В любой момент отпустив кнопку, система возвращается в исходное состояние.
Ответить