pp.259-260
非公式訳:
これは、コンカレントコードについて前に述べた2つの特殊なケースの2つめです。演算回路に関することです。演算回路を実装する場合にお奨めの手法を以下に示します。
演算回路は、セクション1.5、1.6で復習したように、符号が問題になる回路です。そのため、たとえばinteger
型を使うのは良い考えではありません。なぜならコードを見ただけでは符号つきか符号なしかがはっきりとはわからないからです(符号つきか符号なしかは、関係する整数に指定された範囲をコンパイラーが調べて決定します)。
演算回路に推奨される型と、その型が定義されている個々のパッケージとを以下に示します(パッケージはコードのパッケージリストの部分にインクルードしなければなりません。以下のリストには、パッケージが2つ示してあるものがありますが、2つめはデフォルトパラメータ用です)。
- 整数演算用:
unsigned
型またはsigned
型 (numeric_std
パッケージ) - 固定小数点演算用:
ufixed
型またはsfixed
型 (fixed_generic_pkg
パッケージまたはfixed_pkg
パッケージ) - 浮動小数点演算用:
float
型 (float_generic_pkg
パッケージまたはfloat_pkg
パッケージ)
このセクションでは、表現を簡潔にするため上記の各型を「演算型」と呼ぶことにします。
ただし、インターフェイス信号(回路ポートのこと)には同じ型を使おうといつも心がけることが大切です。そうすれば大規模プロジェクトでシステムブロック同士が直接接続できるうえ、再利用性という点でも効果的であるからです。その用途には一般に標準ロジック型(std_ulogic
、std_logic
、std_ulogic_vector
、std_logic_vector
)を用います。演算型を回路ポートに直接使用するのは、限られた場合だけにしてください(単独回路であって再利用性が問題ならない場合や、ポート型をユーザー定義型にしなければならない場合など)。
お奨めの手順
VHDLコードを記述する前にしておくべきこと:
- 設計しようとしている回路が演算回路であることを確認し、どの演算型を使うのかを決めます(整数と浮動小数点との比較に関するコメントをあとで示しますので見てください)。
必要な演算子をすべて列挙します(セクション9.1.2で見たように、事前定義演算子は
+
、-
、*
、/
、**
、rem
、mod
、abs
です)。そのあと、表9.4を使って各演算子の制約事項を確認します。たとえばunsigned
型、signed
型の場合、+
演算子および-
演算子による演算結果は、最大のオペランドと同じビット数が必要です。一方で*
演算子による演算結果は、両オペランドのビット数を足し合わせたビット数が必要です。上記の制約事項によってオーバーフローの発生する可能性のある場合は、そのオーバーフローをどう処理するのかを決めます(セクション1.6.1)。オーバーフローが起きてはならない場合の解決方法の1つは、オペランド、演算結果のいずれもビット数を増やすことです(セクション7.9.3の
resize
函数)。オーバーフローが起きてもかまわないがフラグを立てなければならない場合は、どのようにしてフラグを立てるのかを決めます。
VHDLコードのなかですべきこと:
一般的なルールとして、回路ポートには標準ロジック型のみを使用します(前述したように例外もあります)。
architecture
ボディのなかで、std_ulogic_vector
入力またはstd_logic_vector
入力を演算型の1つに変換します。1ビットの標準ロジック型(std_ulogic
およびstd_logic
)は変換は不要です。計算を実行します。
複数ビットの演算結果を標準ロジックベクタ型へ変換して出力します(当然、シングルビットの標準ロジック型の演算結果も出力します)。
設計した回路を入念にシミュレートします。
上記の推奨事項に従って実装した演算回路の例は以下のコメントのあとに示します。
整数(または固定小数点数)と浮動小数点数と
浮動小数点数は極力避けてください。リソースが大量に消費されるからです(主にハードウェアですが、消費電力も若干増え、速度の低下するおそれもあります)。(以下略)