Как создать конечный автомат на VHDL
Конечный автомат (FSM) — это механизм, выходные данные которого зависят не только от текущего состояния ввода, но и от прошлых входных и выходных значений.
Всякий раз, когда вам нужно создать какой-то зависящий от времени алгоритм на VHDL или если вы сталкиваетесь с проблемой реализации компьютерной программы на FPGA, ее обычно можно решить с помощью FSM.
Конечные автоматы в VHDL — это синхронизируемые процессы, выходы которых контролируются значением сигнала состояния. Сигнал состояния служит внутренней памятью о том, что произошло в предыдущей итерации.
Эта запись в блоге является частью серии учебных пособий по основам VHDL.
Рассмотрим состояния светофоров на этом перекрестке:
Светофоры имеют конечное число состояний, которым мы дали идентифицируемые имена. В нашем примере конечный автомат не имеет управляющих входов, выходом является состояние огней в направлениях север/юг и запад/восток. Это прошедшее время и предыдущее состояние выходов, которые продвигают этот конечный автомат.
Мы можем представить состояния в VHDL, используя нумерованный тип . Это такие же типы данных, как и signed
. или unsigned
, но вместо целых чисел мы можем предоставить собственный список возможных значений. На самом деле, если вы посмотрите на пакет std_logic_1164, вы обнаружите, что std_ulogic
type — это не что иное, как перечисляемый тип со значениями 'U'
, 'X'
, '0'
, '1'
, 'Z'
, 'W'
, 'L'
, 'H'
и '-'
перечислены как значения перечисления.
Получив перечисляемый тип, мы можем объявить сигнал нового типа, который можно использовать для отслеживания текущего состояния конечного автомата.
Синтаксис объявления сигнала перечислимого типа в VHDL:type <type_name> is (<state_name1>, <state_name2>, ...);
signal <signal_name> : <type_name>;
Затем, используя сигнал состояния, можно реализовать конечный автомат в процессе с оператором Case. Оператор Case содержит оператор When для каждого из возможных состояний, заставляя программу выбирать разные пути для каждого состояния. Оператор When также может содержать код, который должен быть выполнен в этом конкретном состоянии. Затем состояние обычно изменяется при выполнении предопределенного условия.
Это шаблон для конечного автомата с одним процессом:process(Clk) is
begin
if rising_edge(Clk) then
if nRst = '0' then
State <= <reset_state>;
else
case State is
when <state_name> =>
<set_outputs_for_this_state_here>
if <state_change_condition_is_true> then
State <= <next_state_name>;
end if;
...
end case;
end if;
end if;
end process;
Примечание.
Существует несколько способов создания FSM в VHDL. Подробнее о различных стилях читайте здесь:
Конечный автомат с одним, двумя и тремя процессами
Упражнение
В этом видеоуроке мы научимся создавать конечный автомат на VHDL:
Окончательный код конечного автомата testbench :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T20_FiniteStateMachineTb is end entity; architecture sim of T20_FiniteStateMachineTb is -- We are using a low clock frequency to speed up the simulation constant ClockFrequencyHz : integer := 100; -- 100 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal NorthRed : std_logic; signal NorthYellow : std_logic; signal NorthGreen : std_logic; signal WestRed : std_logic; signal WestYellow : std_logic; signal WestGreen : std_logic; begin -- The Device Under Test (DUT) i_TrafficLights : entity work.T20_TrafficLights(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, NorthRed => NorthRed, NorthYellow => NorthYellow, NorthGreen => NorthGreen, WestRed => WestRed, WestYellow => WestYellow, WestGreen => WestGreen); -- Process for generating 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 T20_TrafficLights is generic(ClockFrequencyHz : integer); port( Clk : in std_logic; nRst : in std_logic; -- Negative reset NorthRed : out std_logic; NorthYellow : out std_logic; NorthGreen : out std_logic; WestRed : out std_logic; WestYellow : out std_logic; WestGreen : out std_logic); end entity; architecture rtl of T20_TrafficLights is -- Enumerated type declaration and state signal declaration type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest); signal State : t_State; -- Counter for counting clock periods, 1 minute max signal Counter : integer range 0 to ClockFrequencyHz * 60; begin process(Clk) is begin if rising_edge(Clk) then if nRst = '0' then -- Reset values State <= NorthNext; Counter <= 0; NorthRed <= '1'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '1'; WestYellow <= '0'; WestGreen <= '0'; else -- Default values NorthRed <= '0'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '0'; WestYellow <= '0'; WestGreen <= '0'; Counter <= Counter + 1; case State is -- Red in all directions when NorthNext => NorthRed <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = ClockFrequencyHz * 5 -1 then Counter <= 0; State <= StartNorth; end if; -- Red and yellow in north/south direction when StartNorth => NorthRed <= '1'; NorthYellow <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = ClockFrequencyHz * 5 -1 then Counter <= 0; State <= North; end if; -- Green in north/south direction when North => NorthGreen <= '1'; WestRed <= '1'; -- If 1 minute has passed if Counter = ClockFrequencyHz * 60 -1 then Counter <= 0; State <= StopNorth; end if; -- Yellow in north/south direction when StopNorth => NorthYellow <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = ClockFrequencyHz * 5 -1 then Counter <= 0; State <= WestNext; end if; -- Red in all directions when WestNext => NorthRed <= '1'; WestRed <= '1'; -- If 5 seconds have passed if Counter = ClockFrequencyHz * 5 -1 then Counter <= 0; State <= StartWest; end if; -- Red and yellow in west/east direction when StartWest => NorthRed <= '1'; WestRed <= '1'; WestYellow <= '1'; -- If 5 seconds have passed if Counter = ClockFrequencyHz * 5 -1 then Counter <= 0; State <= West; end if; -- Green in west/east direction when West => NorthRed <= '1'; WestGreen <= '1'; -- If 1 minute has passed if Counter = ClockFrequencyHz * 60 -1 then Counter <= 0; State <= StopWest; end if; -- Yellow in west/east direction when StopWest => NorthRed <= '1'; WestYellow <= '1'; -- If 5 seconds have passed if Counter = ClockFrequencyHz * 5 -1 then Counter <= 0; State <= NorthNext; end if; end case; end if; end if; end process; end architecture;
Форма волны после того, как мы ввели run 5 min
команда в консоли ModelSim:
Анализ
Мы объявили перечисляемый тип со всеми восемью различными состояниями наших светофоров. Затем мы объявили state
сигнал этого нового типа, который мы создали. Это означает, что сигнал может иметь только одно из восьми именованных значений состояния и никаких других значений.
FSM был реализован с использованием оператора Case внутри синхронизируемого процесса. При каждом переднем фронте тактового сигнала процесс просыпается, и state
сигнал оценивается. Код ровно в одном из when
варианты (ветки) разрешено запускать в зависимости от текущего состояния.
В нашем коде это значение Counter
сигнал, запускающий изменение состояния. Когда счетчик достигает предопределенного значения, представляющего 5 секунд или 1 минуту, State
присваивается новое кодирование состояния. сигнал. Затем, когда процесс просыпается по следующему переднему фронту тактового сигнала после обновления значения состояния, FSM находится в другом состоянии.
Обратите внимание, что мы не назначаем '0'
на любой сигнал в любом из when
выбор. Это потому, что мы присвоили всем выходным сигналам значение по умолчанию '0'
. в начале процесса. Возможно, вы помните из предыдущего урока, что последнее значение, присвоенное сигналу, становится эффективным. Назначение сигналов вступает в силу только после завершения процесса. Если мы назначим '0'
к сигналу в начале процесса, а затем '1'
в одном из when
вариантов, сигнал получит значение '1'
.
Из формы волны видно, что State
сигнал циклически проходит через восемь состояний. Постоянные зеленые состояния длятся одну минуту, поэтому изображение сигнала было вырезано в North
и West
состояния.
Вывод
- Алгоритмы обычно реализуются в виде конечных автоматов (FSM)
- Конечный автомат можно реализовать с помощью оператора case в синхронизируемом процессе.
- Состояния FSM могут быть реализованы в перечисляемом типе
Перейти к следующему руководству »
VHDL
- Конечный автомат
- Как обеспечить максимальную производительность конечного автомата Qt
- Как создать список строк в VHDL
- Как создать управляемый Tcl тестовый стенд для модуля кодовой блокировки VHDL
- Как остановить симуляцию в тестовом стенде VHDL
- Как создать ШИМ-контроллер на VHDL
- Как генерировать случайные числа в VHDL
- Как создать самопроверяющийся тестовый стенд
- Как создать связанный список в VHDL
- Как лазерный станок с ЧПУ OMNI создает персонализированные рождественские подарки?