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

Использование процедур в VHDL: упростите свой дизайн с повторно используемым кодом

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

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

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

Эта статья является частью серии базовых уроков VHDL.

Канонический синтаксис для определения процедуры показан ниже:

 procedure <procedure_name> (signal|variable|constant <name1> : in|out|inout <type>; signal|variable|constant <name2> : in|out|inout <type>; ... ) is <declarations_for_use_within_the_procedure> begin <code_performed_by_the_procedure_here> end procedure; 

Список параметров определяет входы и выходы процедуры — очень похоже на мини-модуль. Параметры могут быть сигналами, переменными или константами. Внутри процедуры вы можете объявлять дополнительные объекты (константы, переменные, типы, подтипы, псевдонимы), которые действительны только внутри этого блока; сигналы не могут быть объявлены локально.

Поскольку процедуры могут содержать операторы wait, они особенно полезны в тестбенчах — например, как простые BFM-драйверы или для проверки выходов DUT.

Упражнение

В предыдущем уроке модуль таймера был построен с использованием глубоко вложенных операторов if-then-else. Каждый вложенный уровень добавлял сложность и снижал читаемость, даже если одна и та же операция выполнялась на разных наборах сигналов. Лучший подход — инкапсулировать повторяющуюся логику внутри процедуры.

Следующее видео-урок проведет через создание VHDL-процедуры:

Пример: Таймер на основе процедуры

Код тестбенча остается неизменным, за исключением добавления вызова процедуры для управления DUT:

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T19_ProcedureTb is end entity; architecture sim of T19_ProcedureTb is constant ClockFrequencyHz : integer := 10; -- 10 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal Seconds : integer; signal Minutes : integer; signal Hours : integer; begin i_Timer : entity work.T19_Timer(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, Seconds => Seconds, Minutes => Minutes, Hours => Hours); Clk <= not Clk after ClockPeriod / 2; process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); nRst <= '1'; wait; end process; end architecture; 

Сам модуль таймера теперь использует процедуру для инкремента счетчиков:

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T19_Timer is generic(ClockFrequencyHz : integer); port( Clk : in std_logic; nRst : in std_logic; -- Negative reset Seconds : inout integer; Minutes : inout integer; Hours : inout integer); end entity; architecture rtl of T19_Timer is signal Ticks : integer; procedure IncrementWrap( signal Counter : inout integer; constant WrapValue : in integer; constant Enable : in boolean; variable Wrapped : out boolean) is begin Wrapped := false; if Enable then if Counter = WrapValue - 1 then Wrapped := true; Counter <= 0; else Counter <= Counter + 1; end if; end if; end procedure; begin process(Clk) is variable Wrap : boolean; begin if rising_edge(Clk) then if nRst = '0' then Ticks <= 0; Seconds <= 0; Minutes <= 0; Hours <= 0; else IncrementWrap(Ticks, ClockFrequencyHz, true, Wrap); IncrementWrap(Seconds, 60, Wrap, Wrap); IncrementWrap(Minutes, 60, Wrap, Wrap); IncrementWrap(Hours, 24, Wrap, Wrap); end if; end if; end process; end architecture; 

Волновая форма ниже подтверждает, что счетчик минут корректно переносится, когда таймер достигает 60 минут:

Использование процедур в VHDL: упростите свой дизайн с повторно используемым кодом

Анализ

Из волновой формы видно, что функциональность переноса ведет себя идентично оригинальной вложенной реализации if. Изменение чисто структурное — никаких изменений в базовой логике.

Первый параметр, Counter, является сигналом inout, позволяя процедуре читать и обновлять его значение. Второй и третий параметры, WrapValue и Enable, являются константами; они рассматриваются как константы времени компиляции внутри процедуры.

Последний параметр, Wrapped, является variable, объявленным как out. Он служит псевдо-возвращаемым значением, указывая, перенесся ли счетчик во время этого вызова.

В основном процессе четыре последовательных вызова IncrementWrap каскадно соединяют счетчики. Переменная Wrap из предыдущего вызова подается на вход Enable следующего вызова. Использование переменной здесь существенно, потому что обновления сигналов видны только после приостановки процесса; переменная обеспечивает немедленный процедурный поток данных.

Использование процедур в VHDL: упростите свой дизайн с повторно используемым кодом

Выводы

Переходите к следующему уроку »

VHDL

  1. Пример процедуры VHDL: инкремент std_logic_vector
  2. Как молибден формирует современную промышленность: применение, преимущества и динамика поставок
  3. Создание списков строк в VHDL: лучшие практики и пример
  4. Корректное завершение симуляции VHDL-тестбенча
  5. Реализация PWM-контроллера в VHDL: проектирование, симуляция и FPGA-демо
  6. Генерация случайных чисел в VHDL: от Uniform к OSVVM
  7. Использование внутрипроцессных процедур для более чистого проектирования FSM на VHDL
  8. Использование нечистых функций в VHDL: повышение читаемости и поддерживаемости FSM
  9. Освоение функций VHDL: практическое руководство по эффективному дизайну
  10. Освоение техник шлифовального станка для режущих инструментов: практическое руководство