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

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

プロシージャは、コードの繰り返しを避けるのに役立つ VHDL のサブプログラムの一種です。場合によっては、設計全体のいくつかの場所で同じ操作を実行する必要が生じることがあります。モジュールの作成はマイナーな操作にはやり過ぎかもしれませんが、多くの場合、手順が必要です。

プロシージャは、任意の宣言領域内で宣言できます。プロシージャのスコープは、宣言されている場所、アーキテクチャ、パッケージ、またはプロセスに限定されます。プロシージャを呼び出すたびに、プロシージャのコードが呼び出された場所に挿入されたように動作します。

プロシージャは関数のように値を返しませんが、out を宣言することで値を返すことができます または inout パラメータリストの信号。

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

プロシージャを作成するための基本的な構文は次のとおりです。
procedure <procedure_name> (signal|variable|constant <name1> : in|out|inout <type>;
                            signal|variable|constant <name2> : in|out|inout <type>;
                            ... ) is
    <declarations_for_use_within_the_procedure>
begin
    <code_performed_by_the_procedure_here>
end procedure;

プロシージャのパラメータ リストは、ミニ モジュールのような入力と出力を定義します。シグナルまたは定数の場合がありますが、モジュールとは異なり、変数の場合もあります。プロシージャ内でのみ有効な「is」キーワードと「begin」キーワードの間でオブジェクトを宣言できます。これらには、定数、変数、型、サブタイプ、およびエイリアスが含まれる場合がありますが、シグナルは含まれません。

関数とは異なり、プロシージャには待機ステートメントが含まれる場合があります。そのため、インターフェースをシミュレートするため、または被試験デバイス (DUT) からの出力をチェックするために、単純な BFM のようなテストベンチでよく使用されます。

エクササイズ

前のチュートリアルでは、ネストされた If-Then-Else ステートメントを使用してタイマー モジュールを作成しました。別の If-Then-Else 内の If-Then-Else の各レベルにより、設計が複雑になり、読みにくくなります。ロジックの各レベルでは、基本的に異なる信号セットに対して同じ操作を行っています。これを行うためのより良い方法はありませんか?

このビデオ チュートリアルでは、VHDL でプロシージャを作成する方法を学習します。

手順 testbench の最終的なコード :

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

entity T19_ProcedureTb is
end entity;

architecture sim of T19_ProcedureTb is

    -- We're slowing down the clock to speed up simulation time
    constant ClockFrequencyHz : integer := 10; -- 10 Hz
    constant ClockPeriod : time := 1000 ms / ClockFrequencyHz;

    signal Clk     : std_logic := '1';
    signal nRst    : std_logic := '0';
    signal Seconds : integer;
    signal Minutes : integer;
    signal Hours   : integer;

begin

    -- The Device Under Test (DUT)
    i_Timer : entity work.T19_Timer(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
        Clk     => Clk,
        nRst    => nRst,
        Seconds => Seconds,
        Minutes => Minutes,
        Hours   => Hours);

    -- 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 T19_Timer is
generic(ClockFrequencyHz : integer);
port(
    Clk     : in std_logic;
    nRst    : in std_logic; -- Negative reset
    Seconds : inout integer;
    Minutes : inout integer;
    Hours   : inout integer);
end entity;

architecture rtl of T19_Timer is

    -- Signal for counting clock periods
    signal Ticks : integer;

    procedure IncrementWrap(signal   Counter   : inout integer;
                            constant WrapValue : in    integer;
                            constant Enable    : in    boolean;
                            variable Wrapped   : out   boolean) is
    begin
        Wrapped := false;
        if Enable then
            if Counter = WrapValue - 1 then
                Wrapped := true;
                Counter <= 0;
            else
                Counter <= Counter + 1;
            end if;
        end if;
    end procedure;

begin

    process(Clk) is
        variable Wrap : boolean;
    begin
        if rising_edge(Clk) then

            -- If the negative reset signal is active
            if nRst = '0' then
                Ticks   <= 0;
                Seconds <= 0;
                Minutes <= 0;
                Hours   <= 0;
            else

                -- Cascade counters
                IncrementWrap(Ticks, ClockFrequencyHz, true, Wrap);
                IncrementWrap(Seconds,             60, Wrap, Wrap);
                IncrementWrap(Minutes,             60, Wrap, Wrap);
                IncrementWrap(Hours,               24, Wrap, Wrap);

            end if;
        end if;
    end process;

end architecture;

Minutes のタイムラインを拡大した ModelSim の波形ウィンドウ 信号がラッピングされています:

分析

波形から、前のチュートリアルと同様に信号のラッピングが機能していることがわかります。これは、モジュールの関数を実際に変更したのではなく、実装方法のみを変更したためです。

IncrementWrap のパラメータ リストの最初の項目 手順は Counter です 信号。方向 inout を使用して宣言されています プロシージャがその値の読み取りと設定の両方を行えるようにします。

パラメータ リストの 2 番目と 3 番目の項目は定数です。これは、ここに入力した値が内部の定数として表示されることを意味します 手順の。 WrapValue Enable と一緒に入力 入力が Counter かどうかを決定します 信号がインクリメントまたはラップされます。

パラメータ リストの最後の項目は、方向が out の変数です。 .この出力の目的は、カウンターがラップしたプロシージャーを呼び出し元に通知することです。ここでは、戻り値のようなものを使用します。

メイン プロセスでは、IncrementWrap への呼び出しが 4 つあります。 手順。後続の各呼び出しは Wrap を使用します カウントを有効にする変数。シグナルの値はプロセスがスリープ状態になったときにのみ更新されるため、変数の代わりにシグナルを使用した場合は機能しません。 1 つのプロシージャー呼び出しからの出力値を、次の行の呼び出しへの入力として使用する必要があります。したがって、変数でなければなりません。

テイクアウト

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


VHDL

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