サーチ…


備考

以前のVHDL 1993では、2つの並行プロセスは信号としか通信できませんでした。シミュレーションステップ間の信号のみを更新する言語のシミュレーションセマンティクスのおかげで、シミュレーションの結果は決定的でした。プロセスを実行するためにシミュレーションスケジューラが選択した順序に依存しませんでした。

[実際には、これは100%真実ではありません。プロセスはファイル入出力を使用して通信することもできます。しかし、デザイナーがファイルを使って決定論を妥協していたのであれば、間違いではありませんでした。]

言語はこのように安全でした。目的を除いて、非決定論的なVHDLモデルを設計することはほとんど不可能でした。

VHDL 1993は共有変数を導入し、非決定論的なVHDLモデルの設計は非常に簡単になりました。

VHDL 2000では、保護されたタイプと、共有変数が保護されたタイプでなければならないという制約が導入されました。

VHDLでは、保護された型は、オブジェクト指向言語(OO)のオブジェクトの概念のほとんどに似ています。彼らは、データ構造とそのメソッドのカプセル化を実装しています。また、データメンバーへの排他的アクセスとアトミックアクセスも保証します。これは非決定論を完全に防ぐのではなく、少なくとも排他性とアトミック性を共有変数に追加します。

保護されたタイプは、シミュレーション専用の高水準VHDLモデルを設計する場合に非常に便利です。彼らはOO言語のいくつかの非常に良い特性を持っています。それらを頻繁に使用すると、コードを読みやすく、保守しやすく、再利用できるようになります。

ノート:

  • 一部のシミュレーションツールチェーンは、デフォルトでは、共有変数が保護されていないタイプの場合にのみ警告を発行します。
  • いくつかの合成ツールは保護されたタイプをサポートしていません。
  • いくつかの合成ツールには、共有変数のサポートが限られています。
  • 共有変数はハードウェアをモデル化するのに使用できず、副作用なしにコード計測用に予約されていると考えることができます。しかし、複数のEDAベンダーがマルチポートRAM(Multi-Access Random Access Memory)のメモリプレーンをモデル化するようにアドバイスしたVHDLパターンは、共有変数を使用します。したがって、特定の状況で共有変数を合成することができます。

擬似ランダム発生器

Peudo-randomジェネレータは、シミュレーション環境を設計するときによく使用されます。次のVHDLパッケージは、保護された型を使用してbooleanbitおよびbit_vector疑似ランダムジェネレータを設計する方法を示しています。それは簡単に拡張して、ランダムなstd_ulogic_vectorsignedunsigned生成することもできます。任意の境界と一様な分布を持つランダムな整数を生成するように拡張するのは少し難解ですが実行可能です。

パッケージ宣言

保護タイプには、すべてのパブリック・サブプログラム・アクセサが宣言されている宣言があります。私たちのランダムジェネレータでは、1つのシード初期化プロシージャと、3つのbit_vectorな関数がランダムなbooleanbitまたはbit bit_vectorます。同じパラメータを持つ異なる呼び出しが異なる値を返す可能性があるため、関数は純粋なものではないことに注意してください。

-- file rnd_pkg.vhd
package rnd_pkg is
    type rnd_generator is protected
        procedure init(seed: bit_vector);
        impure function get_boolean return boolean;
        impure function get_bit return bit;
        impure function get_bit_vector(size: positive) return bit_vector;
    end protected rnd_generator;
end package rnd_pkg;

パッケージ本体

保護タイプ本体は、内部データ構造(メンバー)とサブプログラム本体を定義します。私たちのランダムジェネレータは、4タップの128ビット線形フィードバックシフトレジスタ(LFSR)に基づいています。 state変数は、LFSRの現在の状態を格納します。プライベートthrow手順は、ジェネレータが使用されるたびにLFSRをシフトします。

-- file rnd_pkg.vhd
package body rnd_pkg is
    type rnd_generator is protected body
        constant len: positive := 128;
        constant default_seed: bit_vector(1 to len) := X"8bf052e898d987c7c31fc71c1fc063bc";
        type tap_array is array(natural range <>) of positive range 1 to len;
        constant taps: tap_array(0 to 3) := (128, 126, 101, 99);

        variable state: bit_vector(1 to len) := default_seed;

        procedure throw(n: positive := 1) is
            variable tmp: bit;
        begin
            for i in 1 to n loop
                tmp := '1';
                for j in taps'range loop
                    tmp := tmp xnor state(taps(j));
                end loop;
                state := tmp & state(1 to len - 1);
            end loop;
        end procedure throw;

        procedure init(seed: bit_vector) is
            constant n:   natural            := seed'length;
            constant tmp: bit_vector(1 to n) := seed;
            constant m:   natural            := minimum(n, len);
        begin
            state         := (others => '0');
            state(1 to m) := tmp(1 to m);
        end procedure init;

        impure function get_boolean return boolean is
            constant res: boolean := state(len) = '1';
        begin
            throw;
            return res;
        end function get_boolean;

        impure function get_bit return bit is
            constant res: bit := state(len);
        begin
            throw;
            return res;
        end function get_bit;

        impure function get_bit_vector(size: positive) return bit_vector is
            variable res: bit_vector(1 to size);
        begin
            if size <= len then
                res := state(len + 1 - size to len);
                throw(size);
            else
                res(1 to len) := state;
                throw(len);
                res(len + 1 to size) := get_bit_vector(size - len);
            end if;
            return res;
        end function get_bit_vector;
    end protected body rnd_generator;
end package body rnd_pkg;

ランダムジェネレータは、次のようにOOスタイルで使用できます。

-- file rnd_sim.vhd
use std.env.all;
use std.textio.all;
use work.rnd_pkg.all;

entity rnd_sim is
end entity rnd_sim;

architecture sim of rnd_sim is
    shared variable rnd: rnd_generator;
begin
    process
        variable l: line;
    begin
        rnd.init(X"fe39_3d9f_24bb_5bdc_a7d0_2572_cbff_0117");
        for i in 1 to 10 loop
            write(l, rnd.get_boolean);
            write(l, HT);
            write(l, rnd.get_bit);
            write(l, HT);
            write(l, rnd.get_bit_vector(10));
            writeline(output, l);
        end loop;
        finish;
    end process;
end architecture sim;
$ mkdir gh_work
$ ghdl -a --std=08 --workdir=gh_work rnd_pkg.vhd rnd_sim.vhd
$ ghdl -r --std=08 --workdir=gh_work rnd_sim
TRUE    1    0001000101
FALSE   0    1111111100
TRUE    1    0010110010
TRUE    1    0010010101
FALSE   0    0111110100
FALSE   1    1101110010
TRUE    1    1011010110
TRUE    1    0010010010
TRUE    1    1101100111
TRUE    1    0011100100
simulation finished @0ms


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow