動きを表すために、入力条件に従って、状況を切り替えていくロジックをステートマシンと言います。
一般的には、入力条件に従う切り替え回路は if や case 文で、状況を記憶させるにはFFを使います。
VHDLではこの切り替え回路と、記憶させるにはFFを分けて、2つのprocess文にすることで見やすい設計となります。
4つの状況がある簡単なステートマシンの例を次に示します。
library IEEE;
use IEEE.std_logic_1164.all;
entity State is
port (
Clk :in std_logic; --FF clock
Rst_n :in std_logic; --asynchronous reset
StrtSt :in std_logic;
MoveSt :in std_logic;
EndSt :in std_logic;
StatOut :out std_logic_vector (2 downto 0));
end State;
architecture RTL of State is
constant c_idle : std_logic_vector (2 downto 0) := "000"; --各ステータスは定数設定する
constant c_wait : std_logic_vector (2 downto 0) := "001";
constant c_move : std_logic_vector (2 downto 0) := "010";
constant c_end : std_logic_vector (2 downto 0) := "100";
signal timSts : std_logic_vector (2 downto 0);
signal nxtSts : std_logic_vector (2 downto 0);
begin
StatOut <= timSts;
process (Clk, Rst_n) begin --状況記憶用のFF
if (Rst_n = '0') then
timSts <= c_idle;
elsif (Clk'event and Clk = '1') then
timSts <= nxtSts;
end if;
end process;
process (timSts, StrtSt, MoveSt, EndSt) begin --状況切替回路
case timSts is
when c_idle => if (StrtSt = '1') then --状況切替条件が合ったら
nxtSts <= c_wait; --切り替える
else --合わなかったら
nxtSts <= c_idle; --切り替えない
end if;
when c_wait => if (MoveSt = '1') then
nxtSts <= c_move;
else
nxtSts <= c_wait;
end if;
when c_move => if (EndSt = '1') then
nxtSts <= c_end;
else
nxtSts <= c_move;
end if;
when c_end => if (StrtSt = '1') then
nxtSts <= c_wait;
elsif (MoveSt = '1') then
nxtSts <= c_move;
else
nxtSts <= c_end;
end if;
when others => nxtSts <= c_idle;
end case;
end process;
end RTL;