Как создать таймер в VHDL
В предыдущих уроках мы использовали wait for
оператор для задержки времени в моделировании. А как же производственные модули? wait for
оператор не может быть использован для этого. Это работает только в моделировании, потому что мы не можем просто сказать электронам в цепи остановиться на заданное время. Итак, как мы можем отслеживать время в модуле дизайна?
Ответ заключается в простом подсчете тактов. Каждый цифровой дизайн имеет доступ к тактовому сигналу, который колеблется с фиксированной известной частотой. Следовательно, если мы знаем, что тактовая частота составляет 100 МГц, мы можем измерить одну секунду, сосчитав сто миллионов тактовых циклов.
Эта запись в блоге является частью серии учебных пособий по основам VHDL.
Для подсчета секунд в VHDL мы можем реализовать счетчик, который подсчитывает количество прошедших тактов. Когда этот счетчик достигает значения тактовой частоты, например 100 миллионов, мы знаем, что прошла секунда и пришло время увеличить другой счетчик. Назовем это счетчиком секунд.
Для подсчета минут мы можем реализовать еще один счетчик минут, который увеличивается по прошествии 60 секунд. Точно так же мы можем создать счетчик часов для подсчета часов, который увеличивается по истечении 60 минут.
Мы можем продолжить этот подход и для подсчета дней, недель и месяцев. Мы ограничены доступными физическими ресурсами базовой технологии, а также длиной счетчика по сравнению с тактовой частотой.
По мере увеличения длины счетчиков, очевидно, потребляется больше ресурсов. Но он также будет реагировать медленнее, потому что цепочка событий становится длиннее.
Упражнение
В этом видеоуроке мы узнаем, как создать модуль таймера на VHDL:
Окончательный код таймера testbench :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T18_TimerTb is end entity; architecture sim of T18_TimerTb is -- We're slowing down the clock to speed up simulation time 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 -- The Device Under Test (DUT) i_Timer : entity work.T18_Timer(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, Seconds => Seconds, Minutes => Minutes, Hours => Hours); -- Process for generating the clock Clk <= not Clk after ClockPeriod / 2; -- Testbench sequence process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); -- Take the DUT out of reset nRst <= '1'; wait; end process; end architecture;
Окончательный код для модуля таймера :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T18_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 T18_Timer is -- Signal for counting clock periods signal Ticks : integer; begin process(Clk) is begin if rising_edge(Clk) then -- If the negative reset signal is active if nRst = '0' then Ticks <= 0; Seconds <= 0; Minutes <= 0; Hours <= 0; else -- True once every second if Ticks = ClockFrequencyHz - 1 then Ticks <= 0; -- True once every minute if Seconds = 59 then Seconds <= 0; -- True once every hour if Minutes = 59 then Minutes <= 0; -- True once a day if Hours = 23 then Hours <= 0; else Hours <= Hours + 1; end if; else Minutes <= Minutes + 1; end if; else Seconds <= Seconds + 1; end if; else Ticks <= Ticks + 1; end if; end if; end if; end process; end architecture;
Форма сигнала увеличена на Seconds
сигнал:
Форма сигнала увеличена на Minutes
сигнал:
Форма волны увеличена на Hours
сигнал:
Анализ
Чтобы запустить 50-часовую симуляцию, мы дали команду run 50 hr
в консоли ModelSim. Пятьдесят часов — это очень долгая симуляция, и поэтому нам пришлось понизить тактовую частоту в тестовом стенде до 10 Гц. Если бы мы оставили его на частоте 100 МГц, симуляция заняла бы дни. Такие адаптации иногда необходимы, чтобы мы могли смоделировать дизайн.
Мы щелкнули правой кнопкой мыши временную шкалу в форме волны и выбрали «Сетка, временная шкала и управление курсором». При изменении единицы измерения времени с нс на секунды, минуты и часы мы могли видеть, что таймер действительно работает в режиме реального времени.
Время таймера немного смещено от времени моделирования из-за сброса модуля в начале моделирования. Это видно на первой осциллограмме, где 60-секундная отметка на временной шкале находится немного раньше, чем сигнал секунд переходит в 0.
Обратите внимание, что в моделировании значения счетчика обновляются в нулевое время на нарастающем фронте часов. В реальном мире значению счетчика потребуется некоторое время, чтобы распространиться от первого бита счетчика к последнему. Поскольку мы увеличиваем длину счетчиков, мы потребляем доступное время тактового периода.
Если суммарная длина всех каскадных счетчиков станет слишком большой, после компиляции на шаге места и маршрута будет выдана ошибка. Как долго вы можете реализовать счетчик, прежде чем использовать весь тактовый период, зависит от архитектуры FPGA или ASIC и тактовой частоты.
Повышенная тактовая частота означает, что цепь счетчика будет длиннее. Это также означает, что период времени будет короче, что даст цепочке счетчиков еще меньше времени для завершения.
Вывод
- Измерение времени в модулях VHDL достигается путем подсчета тактов.
- Уменьшение тактовой частоты в тестовом стенде ускорит симуляцию.
Перейти к следующему руководству »
VHDL
- Как создать список строк в VHDL
- Как создать управляемый Tcl тестовый стенд для модуля кодовой блокировки VHDL
- Как остановить симуляцию в тестовом стенде VHDL
- Как создать ШИМ-контроллер на VHDL
- Как генерировать случайные числа в VHDL
- Как создать кольцевой буфер FIFO в VHDL
- Как создать самопроверяющийся тестовый стенд
- Как создать связанный список в VHDL
- Как использовать процедуру в процессе в VHDL
- Как использовать функцию в VHDL