Как создать синхронизированный процесс в VHDL
В подавляющем большинстве проектов VHDL используется логика синхронизации. , также известный как синхронная логика или последовательная логика . Синхронизированный процесс запускается только главным тактовым сигналом, а не при изменении любого другого входного сигнала.
Основным строительным блоком тактовой логики является компонент, называемый триггером. . Существуют разные его варианты, и в этом уроке мы сосредоточимся на триггере, запускаемом положительным фронтом, с отрицательным сбросом:
Триггер представляет собой схему выборки и хранения, что означает, что он копирует значение со входа на выход, когда поступает нарастающий фронт тактового сигнала. Затем выходной сигнал остается стабильным на выбранном значении до следующего нарастающего фронта тактового сигнала или до импульсного сигнала сброса.
Эта запись в блоге является частью серии учебных пособий по основам VHDL.
Все синхронизированные процессы запускаются одновременно и сразу считывают свои входные данные. При этом они будут выводить результаты последней итерации. Тактовый сигнал эффективно создает временные шаги в потоке данных. Это позволяет дизайнеру легко создавать сложную, глубокую логику. Он или она может разбить действия алгоритма на события, происходящие в тактовых циклах.
Триггеры или массивы триггеров иногда называют регистрами. , это то же самое.
Список чувствительности для тактовых процессов обычно содержит только тактовый сигнал. Это связано с тем, что тактовый процесс запускается только фронтом тактового сигнала, другие входные сигналы вообще не заставят его проснуться.
Это шаблон для создания синхронизированного процесса с синхронным сбросом:process(Clk) is
begin
if rising_edge(Clk) then
if nRst = '0' then
<reset all output signals here>
else
<main logic here>
end if;
end if;
end process;
Упражнение
В этом видеоуроке мы узнаем, как создать синхронизируемый процесс в VHDL:
Окончательный код для триггера testbench :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T17_ClockedProcessTb is end entity; architecture sim of T17_ClockedProcessTb is constant ClockFrequency : integer := 100e6; -- 100 MHz constant ClockPeriod : time := 1000 ms / ClockFrequency; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal Input : std_logic := '0'; signal Output : std_logic; begin -- The Device Under Test (DUT) i_FlipFlop : entity work.T17_FlipFlop(rtl) port map( Clk => Clk, nRst => nRst, Input => Input, Output => Output); -- Process for generating the clock Clk <= not Clk after ClockPeriod / 2; -- Testbench sequence process is begin -- Take the DUT out of reset nRst <= '1'; wait for 20 ns; Input <= '1'; wait for 22 ns; Input <= '0'; wait for 6 ns; Input <= '1'; wait for 20 ns; -- Reset the DUT nRst <= '0'; wait; end process; end architecture;
Окончательный код модуля триггера. :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T17_FlipFlop is port( Clk : in std_logic; nRst : in std_logic; -- Negative reset Input : in std_logic; Output : out std_logic); end entity; architecture rtl of T17_FlipFlop is begin -- Flip-flop with synchronized reset process(Clk) is begin if rising_edge(Clk) then if nRst = '0' then Output <= '0'; else Output <= Input; end if; end if; end process; end architecture;
Окно сигнала в ModelSim после того, как мы нажали кнопку «Выполнить» и увеличили временную шкалу:
Анализ
Из формы сигнала видно, что выходной сигнал обновляется только при каждом переднем фронте тактового сигнала. Входной сигнал дискретизируется только тогда, когда тактовый сигнал изменяется с «0» на «1». Отрицательный провал входного сигнала, начиная примерно с 45 нс, полностью исчезает. Он не копируется в выходной файл, поскольку находится между двумя нарастающими фронтами тактового сигнала и, следовательно, игнорируется.
Эта анимация показывает, как выход реагирует на изменение входных и тактовых сигналов:
Вертикальные линии показывают, как входной сигнал соотносится с нарастающими фронтами тактового сигнала.
Обратите особое внимание на один положительный импульс входного сигнала, начиная с 20 нс. Он синхронен с часами и имеет длину ровно один такт. Выход срабатывает не мгновенно, а с задержкой на один такт.
Когда я изучал VHDL, мне было особенно трудно это понять. Нарастающий фронт часов синхронен с нарастающим фронтом входа, так как же триггер может выбрать то или иное значение?
Симулятор использует временные шаги для моделирования событий предсказуемым образом, а сигналы распространяются в нулевое время. Поскольку триггер считывает входные данные в тот же самый временной интервал, что и обновление выходных данных, он видит старое значение входных данных и копирует его в выходные данные.
Подробнее о временных шагах VHDL читайте здесь:Объяснение дельта-циклов
Я должен добавить к этому ответу, что это не на самом деле как это работает. В физическом мире сигналу нужно время для распространения, мы не знаем точно, когда он достигает триггера. Эти задержки распространения автоматически оцениваются для нас программным процессом (место и маршрут), который преобразует код VHDL в список соединений.
На самом деле вход должен оставаться стабильным в течение нескольких наносекунд до и после нарастающего фронта тактового сигнала:
Эти критические периоды времени известны как время установки и удержания. К счастью, это не то, что вы обычно должны принимать во внимание. При работе исключительно с синхронизируемой логикой эти проблемы решаются программным обеспечением, которое превращает код VHDL в список соединений.
Вывод
- Синхронизированные процессы с синхронизированным сбросом имеют только сигнал часов в списке чувствительности
if rising_edge(Clk)
гарантирует, что процесс просыпается только по переднему фронту тактового импульса- В синхронном дизайне все происходит только на активном фронте часов.
Пройдите базовый тест VHDL – часть 3 »
или
перейдите к следующему руководству »
VHDL
- Как создать список строк в VHDL
- Как создать управляемый Tcl тестовый стенд для модуля кодовой блокировки VHDL
- Как остановить симуляцию в тестовом стенде VHDL
- Как создать ШИМ-контроллер на VHDL
- Как генерировать случайные числа в VHDL
- Как создать кольцевой буфер FIFO в VHDL
- Как создать самопроверяющийся тестовый стенд
- Как создать связанный список в VHDL
- Как использовать процедуру в процессе в VHDL
- Как использовать функцию в VHDL