Как создать таймер в 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