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

VHDL で関数を使用する方法

関数は、頻繁に使用されるアルゴリズムを実装するために使用できる VHDL のサブプログラムです。関数は 0 個以上の入力値を取り、常に値を返します。戻り値に加えて、プロシージャと関数を区別するのは、Wait ステートメントを含めることができないことです。これは、関数が消費するシミュレーション時間が常にゼロであることを意味します。

他のプログラミング言語の関数やメソッドに精通している場合、VHDL 関数は簡単に理解できるはずです。 VHDL では、戻り値を省略したり void を返したりすることはできません。関数は常に何かを返す必要があり、戻り値を何かに割り当てる必要があります。

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

VHDL には、pure の 2 種類の関数があります。 そして不純 機能。関数が純粋であるということは、外部信号を変更したり読み取ったりすることが許可されないことを意味します。特定の引数で純粋な関数を呼び出すと、常に同じ値が返されることは確実です。関数には副作用がないと言います .

VHDL で関数を宣言するための構文は次のとおりです。

[pure|impure] function <function_name> (<parameter1_name> : <parameter1_type> := <default_value>;
                                        <parameter2_name> : <parameter2_type> := <default_value>;
                                        ... ) return <return_type> is
    <constant_or_variable_declaration>
begin
    <code_performed_by_the_function>
    return <value>
end function;

pure/impure キーワードはオプションですが、キーワードを省略した場合はデフォルトで pure になります。すべてのパラメーターは、関数内で定数として扱われます。したがって、それらを変更することはできません。デフォルト値はオプションであり、関数は常に return で終了する必要があります

関数には、in の間に独自の宣言領域があります。 そして begin キーワード。ここで宣言された定数、シグナル、または変数は、関数自体の中でのみ有効であり、関数への後続の呼び出しでは値を保持しません。

エクササイズ

このチュートリアルでは、純粋関数に焦点を当てます。非純粋関数については、このシリーズの後のチュートリアルで説明します。

前のチュートリアルでは、有限状態マシン (FSM) を使用して信号機コントローラー モジュールを作成しました。ある状態から別の状態へのタイマー計算を含む多くの行をコピーして貼り付け、1 つの定数をわずかに変更しただけです。

関数を使用してステート マシン コードを簡素化する方法を確認します。

関数 testbench の最終的なコード :

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

entity T21_FunctionTb is
end entity;

architecture sim of T21_FunctionTb 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.T21_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 T21_TrafficLights is
generic(ClockFrequencyHz : natural);
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 T21_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;

    -- Calculate the number of clock cycles in minutes/seconds
    function CounterVal(Minutes : integer := 0;
                        Seconds : integer := 0) return integer is
        variable TotalSeconds : integer;
    begin
        TotalSeconds := Seconds + Minutes * 60;
        return TotalSeconds * ClockFrequencyHz -1;
    end function;

    -- Counter for counting clock periods, 1 minute max
    signal Counter : integer range 0 to CounterVal(Minutes => 1) +1;

begin

    process(Clk) is
    begin

        if rising_edge(Clk) then
            if nRst = '0' then
                -- Reset values
                NorthRed    <= '1';
                NorthYellow <= '0';
                NorthGreen  <= '0';
                WestRed     <= '1';
                WestYellow  <= '0';
                WestGreen   <= '0';
                State       <= NorthNext;
                Counter     <= 0;

            else
                -- Default values
                NorthRed    <= '0';
                NorthYellow <= '0';
                NorthGreen  <= '0';
                WestRed     <= '0';
                WestYellow  <= '0';
                WestGreen   <= '0';

                Counter <= Counter + 1;

                case State is

                    -- Red light in all directions
                    when NorthNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= StartNorth;
                        end if;

                    -- Yellow light in north/south directions
                    when StartNorth =>
                        NorthRed    <= '1';
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= North;
                        end if;

                    -- Green light in north/south directions
                    when North =>
                        NorthGreen <= '1';
                        WestRed    <= '1';
                        -- If 1 minute has passed
                        if Counter = CounterVal(Minutes => 1) then
                            Counter <= 0;
                            State   <= StopNorth;
                        end if;

                    -- Red and yellow light in north/south direction
                    when StopNorth =>
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= WestNext;
                        end if;

                    -- Red light in all directions
                    when WestNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        -- If 5 seconds have passedf
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= StartWest;
                        end if;

                    -- Yellow light in west/east direction
                    when StartWest =>
                        NorthRed   <= '1';
                        WestRed    <= '1';
                        WestYellow <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= West;
                        end if;

                    -- Green light in west/east direction
                    when West =>
                        NorthRed  <= '1';
                        WestGreen <= '1';
                        -- If 1 minute has passed
                        if Counter = CounterVal(Minutes => 1) then
                            Counter <= 0;
                            State   <= StopWest;
                        end if;

                    -- Red and yellow light in west/east direction
                    when StopWest =>
                        NorthRed   <= '1';
                        WestYellow <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= NorthNext;
                        end if;

                end case;
            end if;
        end if;

    end process;

end architecture;

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

StartNorth との間のトランジションにカーソルを追加した波形 状態:

分析

前のチュートリアル if Counter = ClockFrequencyHz * 5 -1 then のタイマー計算を置き換えました 新しい CounterVal への呼び出しで 作成した関数:if Counter = CounterVal(Seconds => 5) then .

最初の波形スクリーンショットから、モジュールの機能が変更されていないことがわかります。反復タスクに関数を使用することは、優れた設計手法です。特に、計算を Minutes のような用語を含む読みやすい行に置き換えることができる場合 と Seconds .

関数を使用するもう 1 つの利点は、行ごとに行うのではなく、すべてのタイマーの実装を一度に変更できることです。たとえば、 return TotalSeconds * ClockFrequencyHz; と書いた場合 CounterVal で すべてのタイマーが 1 クロック サイクル持続しすぎた可能性があります。これを return TotalSeconds * ClockFrequencyHz -1; に変更できます CounterVal で 機能し、すべてのタイマーが一度に修正されます。

最後の波形のスクリーンショットを調べると、CounterVal から返されたタイマー値から 1 を引く必要がある理由がわかります。 関数。この波形は StartNorth の継続時間を調べます 状態で、正確に 5 秒間持続する必要があります。 State の場合 信号が StartNorth に変更されました 、Counter 値は 0 で、次のクロック サイクル後にのみ変更されます。したがって、500 クロック サイクルまでカウントした場合、StartNorth 状態は実際には 501 サイクル持続したことになります。テストベンチを 100 Hz で実行すると、500 クロック サイクルはちょうど 5 秒になります。

テイクアウト

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


VHDL

  1. モリブデンはどのように使用しますか?
  2. VHDL で文字列のリストを作成する方法
  3. VHDL テストベンチでシミュレーションを停止する方法
  4. VHDL で PWM コントローラーを作成する方法
  5. VHDL で乱数を生成する方法
  6. VHDL のプロセスでプロシージャを使用する方法
  7. VHDL で不純な関数を使用する方法
  8. VHDL で有限ステート マシンを作成する方法
  9. C ライブラリの realloc() 関数:使い方は?構文と例
  10. C ライブラリの free() 関数:使い方は?例で学ぶ
  11. カッターグラインダーの使い方