VHDL: отладка кнопки внутри конечного автомата Мили

Привет! Я пытаюсь реализовать слабый компьютер с использованием VHDL, но мне нужно отменить нажатие кнопки. Моя проблема в том, что я не уверен, где мне следует применять устранение ошибок. Моя текущая работа такова:

process(clk)
begin
    if(clk' event and clk = '1') then
        if rst = '1' then
            curr_state <= state0;
        else
            curr_state <= next_state;
        end if;
    end if;
end process;

process(curr_state, op1,op0,rst)  --here op1,op0 and rst are all physical buttons and I need to debounce op1 and op0
begin
    if rst = '1' then
        ...some implementation
    else
        ...implement the debounce logic first
        ...process some input
        case curr_state is
            when state0=>...implementation
            ...similar stuff
        end case; 
end process;

Я не уверен, правильно ли я поступаю или нет. Во втором процессе я должен поместить первую обработку, как это, или я должен поместить ее внутрь, когда блок state0? Кроме того, поскольку обработка debounce требует подсчета, я должен поместить это вне блока case, как это? Спасибо!

2 ответа

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

Вы можете использовать такой процесс, чтобы отменить ввод. Конечно, вы можете обменять переменные на сигналы в этом примере (с соответствующими заменами операторов присваивания).

process (clk)
  constant DEBOUNCE_CLK_PERIODS : integer := 256;  -- Or whatever provides enough debouncing
  variable next_button_state : std_logic := '0';  -- Or whatever your 'unpressed' state is
  variable debounce_count : integer range 0 to DEBOUNCE_CLK_PERIODS-1 := 0;
begin
  if (rising_edge(clk)) then
    if (bouncy_button_in /= next_button_state) then
      next_button_state := bouncy_button_in;
      debounce_count := 0;
    else
      if (debounce_count /= DEBOUNCE_CLK_PERIODS-1) then
        debounce_count := debounce_count + 1;
      else
        debounced_button_out <= next_button_state;
      end if;
    end if;
  end if;
end process;

Другим вариантом было бы попробовать bouncy_button_in с низкой скоростью:

process (clk)
  constant DEBOUNCE_CLK_DIVIDER : integer := 256;
  variable debounce_count : integer range 0 to DEBOUNCE_CLK_DIVIDER-1 := 0;
begin
  if (rising_edge(clk)) then
    if (debounce_count /= DEBOUNCE_CLK_DIVIDER-1) then
      debounce_count := debounce_count + 1;
    else
      debounce_count := 0;
      debounced_button_out <= bouncy_button_in;
    end if;
  end if;
end process;

Преимущество первого метода состоит в том, что он будет отклонять сбои на входе. В любом случае вы бы использовали debounced_button_out (или как вы хотите это назвать, возможно, rst) в вашем конечном компьютере, код которого затем содержит только основные функциональные возможности конечного автомата.

Если вы хотите еще больше устранения неполадок, вы можете использовать другой счетчик, чтобы создать сигнал включения для вышеуказанных процессов, чтобы эффективно разделить тактовую частоту. Это может быть лучше, чем установка константы деления на очень большое число, потому что вы не сможете выполнить синхронизацию, если счетчик выйдет за пределы определенного размера.

Вы даже можете создать объект debounce в отдельном файле, который может быть создан для каждой кнопки. Это может иметь общий для константы в вышеуказанном процессе.

Есть также аппаратное устранение неполадок, но я полагаю, что это выходит за рамки этого вопроса.

Во втором процессе я должен поместить первую обработку, как это, или я должен поместить ее внутрь, когда блок state0?

Только поместите это в блок State0

Кроме того, поскольку обработка debounce требует подсчета, я должен поместить это вне блока case, как это?

Подсчет должен быть сделан в синхронизированном процессе. Поскольку вы выполняете двухпроцессную машину состояний, вы не можете сделать это в блоке case. В любом случае я обычно помещаю подобные ресурсы в отдельный синхронизированный процесс.

Для состояний вам нужно: IS_0, TO_1, IS_1, TO_0.
TO_1 и TO_0 - ваши переходные состояния. Я перехожу с TO_1 на IS_1, когда вижу 1 в течение 16 мс. Я перехожу с TO_0 на IS_0, когда вижу 0 в течение 16 мс. Запустите свой счетчик, когда вы находитесь в состоянии TO_1 или TO_0. Очистите свой счетчик, когда вы находитесь в состоянии IS_1 или IS_0.

Это должно вас заявить.

Другие вопросы по тегам