VHDL で乱数を生成する方法
VHDL には疑似乱数ジェネレーターが組み込まれていますが、生成できるのは 0 から 1 の間の浮動小数点数のみです。幸いなことに、このジェネレーターから、必要な他の種類の乱数データ形式を派生させることができます。 real
を生成する方法については、この記事を読み続けてください。 または integer
任意の範囲の値、およびランダム std_logic_vector
シーケンスと time
uniform
IEEE MATH_REAL パッケージのプロシージャは、この記事で説明するアルゴリズムの基礎です。 uniform
に注意してください ソフトウェアに依存して乱数を生成します。したがって、これらのアルゴリズムは合成できません。テストベンチでのみ使用できます。
procedure UNIFORM(variable SEED1, SEED2 : inout POSITIVE; variable X : out REAL);
上記のリストは uniform
のプロトタイプを示しています 手順。機能するには 2 つのシード変数が必要であり、プロシージャを呼び出すたびにそれらを変更します。出力 X は、常に 0 から 1 の間の値を持つ乱数です。
他の疑似乱数ジェネレーターと同様に、uniform
同じ初期シード値で呼び出されると、同じ一連の数字が生成されます。この動作により、同じシード値を使用すると、テストベンチを再実行して同じ結果を得ることができます。
このアルゴリズムの仕組みの詳細については、Pierre L'Ecuyer による Efficient and Portable Combined Random Number Generators の論文を参照してください。また、GHDL オープンソース VHDL シミュレーターでアルゴリズムの実際の実装を表示することもできます。
テスト ケース
この記事のすべての例では、両方のシードに値 999 を使用しています。プロセスの宣言領域で、以下に示すようにシード変数を宣言します。次に、カスタムのランダム化アルゴリズムを同じプロセス内の純粋でない関数として実装します。
variable seed1, seed2 : integer := 999;
以下のフォームを使用して、この記事のすべての例を含む完全なテストベンチをダウンロードできます。 Zip ファイルには、シミュレーションをコンパイルして実行するスクリプトを含む ModelSim プロジェクトも含まれています。
ランダム実数値
uniform
プロシージャはランダムな real
を生成します 0.0 ~ 1.0 の値。 real
type は VHDL の浮動小数点形式です。ただし、乱数を別の範囲にしたい場合があります。
impure function rand_real(min_val, max_val : real) return real is variable r : real; begin uniform(seed1, seed2, r); return r * (max_val - min_val) + min_val; end function;
幸いなことに、uniform
からの出力を簡単に翻訳できます。 スケールで乗算し、それにオフセットを追加します。上記のコードは、ランダムな real
を返す関数を示しています 最小/最大範囲内の値。
乱数の整数値
ランダムな integer
を生成するには 指定された範囲内の値の場合、スケールを掛けてオフセットを追加する必要があります。しかし、避けなければならない落とし穴があります。ランダムな real
を単純に生成することはできません 範囲内の値を取得し、integer
に丸めます .
上の図は問題を示しています。この例では、ランダムな integer
を生成するつもりです -1 から 1 の範囲の値。 integer
をベースにする場合 ランダムな real
エンドポイントに正確に到達すると、最小整数と最大整数が選択される確率は半分しか得られません。 0 に丸める integer
数値の選択肢が 3 つあるにもかかわらず、値は半分の確率で発生します。
impure function rand_int(min_val, max_val : integer) return integer is variable r : real; begin uniform(seed1, seed2, r); return integer( round(r * real(max_val - min_val + 1) + real(min_val) - 0.5)); end function;
上記のコードでは、ランダムな real
を調整することで、エンドポイントの丸めの問題を修正しています。 エンドポイントの上下に追加の 0.5 を含める値。
ランダムな std_logic_vector
ベクトルをランダムな値で埋める方法はたくさんありますが、この方法は任意の長さのベクトルで機能します。 for ループを使用してベクトルをトラバースし、すべてのビットにランダムな値を選択しています。以下のコードでは、len
パラメータは、ランダムな std_logic_vector
の長さを決定します 戻る。
impure function rand_slv(len : integer) return std_logic_vector is variable r : real; variable slv : std_logic_vector(len - 1 downto 0); begin for i in slv'range loop uniform(seed1, seed2, r); slv(i) := '1' when r > 0.5 else '0'; end loop; return slv; end function;
ランダム時間値
ランダムな time
を生成する必要がある場合があります テストベンチでの値。おそらく、データのバーストをランダムに書き込む外部インターフェイスをシミュレートしたいでしょう。理由が何であれ、ランダム time
値は簡単に生成できます。
impure function rand_time(min_val, max_val : time; unit : time := ns) return time is variable r, r_scaled, min_real, max_real : real; begin uniform(seed1, seed2, r); min_real := real(min_val / unit); max_real := real(max_val / unit); r_scaled := r * (max_real - min_real) + min_real; return real(r_scaled) * unit; end function;
ランダムな time
を生成するには VHDL で値を指定する場合、最初に目的の最小値と最大値を real
に変換する必要があります 種類。次に、ランダム化式が魔法のように機能した後、結果を VHDL time
に変換します。 タイプ。上記のコードに示すように、シミュレーターで使用しているシミュレーション時間単位をこの関数の引数として指定する必要があることに注意してください。
OSVVM Random パッケージ
最後に、ランダム化アルゴリズムを手作りする代わりに、OSVVM ライブラリの Random パッケージを使用できます。あらゆる種類の VHDL タイプのランダムな値を生成するためのオーバーロードされた関数が複数あります。
Open Source VHDL Verification Methodology (OSVVM) は、構造化されたテストベンチを作成するための VHDL ライブラリです。 Random パッケージは、このライブラリの多くの便利なパッケージの 1 つにすぎません。
library osvvm; use osvvm.RandomPkg.all;
上記のコードは、OSVVM パッケージをインポートする方法を示しています。 ModelSim にはすぐに使えるライブラリが含まれているため、このシミュレータ用にダウンロードする必要はありません。 OSVVM GitHub リポジトリの RandomPck.vhd ファイルを参照して、ニーズに適したランダム化関数を見つけてください。
VHDL