VHDL で有限ステート マシンを作成する方法
有限状態マシン (FSM) は、出力が入力の現在の状態だけでなく、過去の入力値と出力値にも依存するメカニズムです。
VHDL である種の時間依存アルゴリズムを作成する必要がある場合、または FPGA にコンピューター プログラムを実装する際の問題に直面した場合、通常は FSM を使用して解決できます。
VHDL のステート マシンは、ステート信号の値によって出力が制御されるクロック プロセスです。状態信号は、前の反復で何が起こったかの内部メモリとして機能します。
このブログ投稿は、基本的な VHDL チュートリアル シリーズの一部です。
この交差点の信号機の状態を考えてみましょう:
信号機には有限数の状態があり、識別可能な名前が付けられています。この例のステート マシンには制御入力がなく、出力は北/南および西/東方向のライトの状態です。このステートマシンを進めるのは、経過時間と出力の以前の状態です。
列挙型を使用して VHDL で状態を表すことができます .これらは signed
のようなデータ型です または unsigned
ですが、整数の代わりに、可能な値のカスタム リストを指定できます。実際、std_logic_1164 パッケージを見ると、std_ulogic
が type は、値が 'U'
の列挙型にすぎません 、 'X'
、 '0'
、 '1'
、 'Z'
、 'W'
、 'L'
、 'H'
、および '-'
列挙値としてリストされます。
列挙型を取得したら、FSM の現在の状態を追跡するために使用できる新しい型のシグナルを宣言できます。
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;
注:
VHDL で FSM を作成するには、いくつかの方法があります。さまざまなスタイルについては、こちらをご覧ください:
1 プロセス、2 プロセス、3 プロセスのステート マシン
エクササイズ
このビデオ チュートリアルでは、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;
ステート マシン module の最終的なコード :
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 コンソールのコマンド:
分析
信号機の 8 つの異なる状態すべてを持つ列挙型を宣言しました。次に、state
を宣言しました 私たちが作成したこの新しいタイプの信号。これは、信号が 8 つの名前付き状態値の 1 つだけを持つことができ、他の値を持つことができないことを意味します。
FSM は、クロック プロセス内で Case ステートメントを使用して実装されました。クロックの各立ち上がりエッジで、プロセスがウェイクアップし、state
信号が評価されます。 when
のちょうど 1 つに含まれるコード 現在の状態に応じて、選択肢 (分岐) の実行が許可されます。
私たちのコードでは、それは Counter
の値です 状態変化を引き起こす信号。カウンターが 5 秒または 1 分を表す定義済みの値に達すると、新しい状態エンコードが State
に割り当てられます。 信号。次に、状態値が更新された後、クロックの次の立ち上がりエッジでプロセスがウェイクアップすると、FSM は別の状態になります。
'0'
を割り当てていないことに注意してください when
のいずれかのシグナルに 選択肢。これは、すべての出力信号にデフォルト値 '0'
を指定したためです。 プロセスの最初に。前のチュートリアルで、信号に割り当てられた最後の値が有効になることを覚えているかもしれません。シグナルの割り当ては、プロセスが終了した後にのみ有効になります。 '0'
を割り当てた場合 プロセスの最初のシグナル、そして '1'
when
のいずれかで 選択すると、シグナルは値 '1'
を取得します .
波形から、State
が 信号は 8 つの状態を循環します。緑色の点灯状態が 1 分間続くため、波形イメージは North
でカットされています。 と West
テイクアウト
- アルゴリズムは通常、有限状態マシン (FSM) として実装されます
- 時計付きプロセスで case ステートメントを使用して FSM を実装できます
- FSM 状態は列挙型で実装できます
次のチュートリアルに進む »
VHDL