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

VHDL のプロセスでプロシージャを使用する方法

プロシージャから外部信号を駆動することができます。シグナルがプロシージャのスコープ内にある限り、パラメーター リストに記載されていなくても、読み取りまたは書き込みのためにアクセスできます。

アーキテクチャの宣言領域で宣言されたプロシージャは、外部信号を駆動できません。これは、コンパイル時にスコープにシグナルがないためです。一方、プロセス内で宣言されたプロシージャは、プロセスが認識できるすべてのシグナルにアクセスできます。

このブログ投稿は、基本的な VHDL チュートリアル シリーズの一部です。

このような手順は、同じ操作が複数回発生するプロセスでアルゴリズムを整理するために使用できます。呼び出し時にすべての入力と出力がローカル信号に割り当てられる通常の手順を使用できますが、それは重要ではありません。プロシージャ コールからの入力信号と出力信号を省略することで、タイプする必要が少なくなり、さらに重要なことに、コードが読みやすくなります。

複雑な通信プロトコルを実装するプロセスを想像してください。一部の操作が RequestToSend() のようなプロシージャ コールに置き換えられた場合、メイン アルゴリズムの実行フローを理解しやすくなります。 または SendAutorizationHeader() .プロシージャ名を見れば、これらの行が何をしたかがわかります。

エクササイズ

前のチュートリアルでは、不純な関数を使用して有限状態マシン (FSM) コードを単純化しました。私たちは Counter を運転していました 不純な関数からのシグナルであり、戻り値を使用して状態をいつ変更するかを決定しました。しかし、State の割り当てを移動したい場合はどうでしょうか。 関数にもシグナルを送信し、戻り値を無視しますか?

戻り値を VHDL の何かに割り当てずに関数を呼び出すことはできません。そうしようとすると、ModelSim はコンパイル エラーを生成します:サブプログラム「CounterExpired」の実行可能なエントリがありません。

代わりに、これにはプロシージャを使用できます。プロセス内で宣言されたプロシージャは、そのプロセスのスコープ内の任意のシグナルにアクセスできます。これは不純な関数に似ていますが、手続きなので戻り値はありません。

このビデオ チュートリアルでは、プロセスで宣言されたプロシージャを使用して FSM コードを簡素化します。

Procedure in Process テストベンチの最終的なコード :

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T23_ProcedureInProcessTb is
end entity;

architecture sim of T23_ProcedureInProcessTb 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.T23_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 T23_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 T23_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

        -- Procedure for changing state after a given time
        procedure ChangeState(ToState : t_State;
                              Minutes : integer := 0;
                              Seconds : integer := 0) is
            variable TotalSeconds : integer;
            variable ClockCycles  : integer;
        begin
            TotalSeconds := Seconds + Minutes * 60;
            ClockCycles  := TotalSeconds * ClockFrequencyHz -1;
            if Counter = ClockCycles then
                Counter <= 0;
                State   <= ToState;
            end if;
        end procedure;

    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';
                        ChangeState(StartNorth, Seconds => 5);

                    -- Red and yellow in north/south direction
                    when StartNorth =>
                        NorthRed    <= '1';
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        ChangeState(North, Seconds => 5);

                    -- Green in north/south direction
                    when North =>
                        NorthGreen <= '1';
                        WestRed    <= '1';
                        ChangeState(StopNorth, Minutes => 1);

                    -- Yellow in north/south direction
                    when StopNorth =>
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        ChangeState(WestNext, Seconds => 5);

                    -- Red in all directions
                    when WestNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        ChangeState(StartWest, Seconds => 5);

                    -- Red and yellow in west/east direction
                    when StartWest =>
                        NorthRed   <= '1';
                        WestRed    <= '1';
                        WestYellow <= '1';
                        ChangeState(West, Seconds => 5);

                    -- Green in west/east direction
                    when West =>
                        NorthRed  <= '1';
                        WestGreen <= '1';
                        ChangeState(StopWest, Minutes => 1);

                    -- Yellow in west/east direction
                    when StopWest =>
                        NorthRed   <= '1';
                        WestYellow <= '1';
                        ChangeState(NorthNext, Seconds => 5);

                end case;

            end if;
        end if;
    end process;

end architecture;

run 5 minに入った後の波形 ModelSim コンソールのコマンド:

分析

モジュールの動作を変更していないため、波形が変更されていないことがわかります。

最初にトラフィック ライト モジュールを作成したチュートリアルのコードと比較すると、FSM コードははるかに読みやすくなっています。コードを読むことで、実装されているアルゴリズムを簡単にたどることができます。タイマーと状態変更ロジックを 1 つの手順で持つことは、それが使用されるすべての場所で均等に実装されることが保証されるため、有益です。

テイクアウト


VHDL

  1. チュートリアル - VHDL の紹介
  2. プロシージャ ステートメント - VHDL の例
  3. モリブデンはどのように使用しますか?
  4. VHDL で文字列のリストを作成する方法
  5. VHDL で不純な関数を使用する方法
  6. VHDL で関数を使用する方法
  7. VHDL でプロシージャを使用する方法
  8. VHDL でタイマーを作成する方法
  9. VHDL でクロック プロセスを作成する方法
  10. VHDL でポート マップのインスタンス化を使用する方法
  11. カッターグラインダーの使い方