工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> VHDL

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

テイクアウト

次のチュートリアルに進む »


VHDL

  1. 有限状態マシン
  2. 最高のQtステートマシンパフォーマンスを確保する方法
  3. VHDL で文字列のリストを作成する方法
  4. VHDL コード ロック モジュール用の Tcl 駆動型テストベンチを作成する方法
  5. VHDL テストベンチでシミュレーションを停止する方法
  6. VHDL で PWM コントローラーを作成する方法
  7. VHDL で乱数を生成する方法
  8. VHDL でリング バッファー FIFO を作成する方法
  9. セルフチェック テストベンチの作成方法
  10. VHDL でリンク リストを作成する方法
  11. OMNI CNCレーザーマシンはどのようにパーソナライズされたクリスマスプレゼントを作成しますか?