Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> VHDL

Пример создания дебаунсера операторов

Оператор generate в VHDL может автоматически дублировать блок кода в замыкания с идентичными сигналами, процессами и экземплярами. Это цикл for для региона архитектуры, который может создавать связанные процессы или экземпляры модулей.

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

Создать синтаксис инструкции

Синтаксис оператора генерации следующий:

[label :] for <constant_name> in <range> generate
  [declarations_local_to_each_loop_iteration]
[begin]
  <processes_and_instantiations>
end generate [label];

Части, заключенные в квадратные скобки, являются необязательными. Таким образом, вы можете опустить декларативную область и begin ключевое слово, если вы не хотите объявлять какие-либо локальные объекты. <диапазон> заполнитель представляет собой стандартный целочисленный диапазон с использованием to или downto .

Однобитный коммутатор

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

Чтобы его можно было использовать для любой тактовой частоты, я добавил общий ввод с именем timeout_cycles. . Эта константа указывает, сколько тактов будет тайм-аут после изменения входа переключателя. Средство устранения дребезга будет игнорировать любые дополнительные изменения значения переключателя в течение периода ожидания.

В приведенном ниже листинге показана сущность дебаунсера. модуль. Есть прыгучий переключатель ввод, а затем чистый switch_debounced вывод.

entity debouncer is
  generic (
    timeout_cycles : positive
    );
  port (
    clk : in std_logic;
    rst : in std_logic;
    switch : in std_logic;
    switch_debounced : out std_logic
  );
end debouncer;

Модуль debouncer использует целочисленный счетчик для достижения периода ожидания. Длина счетчика сигнал следует за общей константой. Это то, что делает время ожидания, указанное во время создания экземпляра.

Потому что нам нужно прочитать значение switch_debounced внутреннего вывода, я объявил теневой сигнал с именем debounced , который мы будем использовать вместо него. Это более чистое решение, чем другой вариант, который заключается в установке inout режим на switch_debounce в объекте.

Наконец, мы реализуем поведение устранения дребезга в одном процессе, как показано в приведенном ниже коде.

architecture rtl of debouncer is

  signal debounced : std_logic;
  signal counter : integer range 0 to timeout_cycles - 1;

begin

  -- Copy internal signal to output
  switch_debounced <= debounced;

  DEBOUNCE_PROC : process(clk)
  begin
    if rising_edge(clk) then
      if rst = '1' then
        counter <= 0;
        debounced <= switch;
        
      else
        
        if counter < timeout_cycles - 1 then
          counter <= counter + 1;
        elsif switch /= debounced then
          counter <= 0;
          debounced <= switch;
        end if;

      end if;
    end if;
  end process;

end architecture;

На приведенной ниже волновой форме показано моделирование debounce модуль в ModelSim. Мы видим, что switch_debounced вывод следует за переключателем ввод, но игнорирует немедленную дребезг после первого изменения — устраняет дребезг сигнала.

Используйте форму ниже, чтобы загрузить код VHDL из этой статьи. Когда вы введете свой адрес электронной почты, вы получите Zip-файл, содержащий весь проект ModelSim с тестовыми стендами и скриптом быстрого запуска. Вы будете получать будущие обновления от VHDLwhiz и можете отказаться от подписки в любое время.

Создать цикл for с экземплярами

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

В приведенном ниже листинге показана сущность нашего нового модуля подавления дребезга массивов или векторов. Он похож на однобитный дебаунсер, но имеет дополнительный общий ввод:switch_count. . Он указывает, сколько экземпляров модуля debouncer нужно создать. Для каждого переключателя должно быть по одному.

Кроме того, я переименовал вход и выход переключателя во множественное число, и теперь они представляют собой векторы, а не отдельные биты.

entity debouncer_gen_inst is
  generic (
    switch_count : positive;
    timeout_cycles : positive
    );
  port (
    clk : in std_logic;
    rst : in std_logic;
    switches : in std_logic_vector(switch_count - 1 downto 0);
    switches_debounced : out std_logic_vector(switch_count - 1 downto 0)
  );
end debouncer_gen_inst;

В архитектуре пришло время использовать оператор generate. Он работает как обычный цикл for, только слово «генерировать» заменяет слово «цикл». Но в отличие от обычного цикла for, он может содержать экземпляры модулей.

Цикл for запускается во время компиляции и генерирует один экземпляр модуля debouncer для каждой итерации. Но поскольку константа «i» будет разной для каждой итерации, мы можем использовать ее для сопоставления входных и выходных данных дебаунсеров с отдельными битами векторов переключателей, как показано ниже.

architecture rtl of debouncer_gen_inst is
begin

  MY_GEN : for i in 0 to switch_count - 1 generate

    DEBOUNCER : entity work.debouncer(rtl)
    generic map (
      timeout_cycles => timeout_cycles
    )
    port map (
      clk => clk,
      rst => rst,
      switch => switches(i),
      switch_debounced => switches_debounced(i)
    );

  end generate;

end architecture;

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

На приведенной ниже волновой форме показано моделирование векторного дебаунсера. Мы видим, что здесь снова появляется метка «MY_GEN» с добавленными индексами для каждого из восьми экземпляров дебаунсера.

Этот тестовый стенд изменяет только вход переключателя номер 3, это то, что вы видите на осциллограмме, и поэтому я расширил только группу MY_GEN(3).

Вы можете быстро запустить этот пример на своем компьютере, если у вас установлен ModelSim. Используйте форму ниже, чтобы загрузить исходный код и проект ModelSim!

Создать цикл for, содержащий процессы

В последнем примере этой статьи мы будем использовать оператор generate для создания серии идентичных процессов. Вместо того, чтобы создавать экземпляры однобитного модуля debouncer, я взял из него код VHDL. Сущность та же, что и в предыдущем примере, как и поведение, но реализация другая.

Мы видим, что я переместил процесс DEBOUNCE_PROC в инструкцию generate и немного изменил его в приведенном ниже коде. На этот раз я объявляю два локальных сигнала в инструкции generate:debounced и счетчик .

Каждая итерация цикла for будет создавать дополнительную копию сигналов и процесса. Использование этих имен сигналов в процессе будет ссылаться на те, которые относятся к вложению этой конкретной итерации цикла.

Наконец, я назначаю debounced std_logic сигнал к правильному биту switches_debounced вывод модуля с использованием параллельного оператора над процессом.

architecture rtl of debouncer_gen_proc is
begin

  MY_GEN : for i in 0 to switch_count - 1 generate

    signal debounced : std_logic;
    signal counter : integer range 0 to timeout_cycles - 1;

  begin

    switches_debounced(i) <= debounced;

    DEBOUNCE_PROC : process(clk)
    begin
      if rising_edge(clk) then
        if rst = '1' then
          counter <= 0;
          debounced <= switches(i);

        else

          if counter < timeout_cycles - 1 then
            counter <= counter + 1;
          elsif switches(i) /= debounced then
            counter <= 0;
            debounced <= switches(i);
          end if;

        end if;
      end if;
    end process;

  end generate;

end architecture;

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

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

Оставьте комментарий ниже, если у вас есть другое полезное приложение для генерации выписок, которым вы можете поделиться! ?


VHDL

  1. Оператор процедуры — пример VHDL
  2. Записи — пример VHDL
  3. Переменные — пример VHDL
  4. Схема с переключателем
  5. Параметры анализа
  6. Типы переключения
  7. Оператор переключения C#
  8. Оператор C# break
  9. C# оператор продолжения
  10. Оператор C++ Switch Case с ПРИМЕРОМ