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