初めてでも使えるVHDL文法ガイド ―― 記述スタイル編
tag: 半導体 ディジタル・デザイン
技術解説 2009年7月27日
3. パッケージ
ハードウェア・システムを設計するうえで,共有化できる部分をまとめたものがパッケージです.
実際の設計では次のような目的でパッケージが使われます.
(1) 標準パッケージ
論理値,演算子,型などを定義して,多くの設計や各種ツール間で共通に使えるようにしたパッケージ.
(2) 設計支援グループが供給するパッケージ
論理合成に適した形で設計されたHDLライブラリ.
(3) 設計者が構築するパッケージ
設計対象に固有の定数や型を定義したり,シミュレーション記述のための各種ルーチン(プロシージャ)を定義するパッケージ.
● パッケージの定義
設計者みずからパッケージを構築する際には,パッケージの定義を行います(図6(a)).まず,パッケージの定義で必要なほかのパッケージを呼び出します.パッケージは,宣言部と本体(body)で定義されます.パッケージ宣言部(図6(b))では,定数やタイプ,信号などが宣言されます.またプロシージャやファンクションは入出力の宣言のみで,処理本体はパッケージ本体で定義します.
パッケージ本体(図6(c))では,プロシージャやファンクションの処理のほかに,これらで用いるローカルな定数や型を宣言できます.プロシージャやファンクションがないパッケージの場合,このパッケージ本体は不要です.
図6 パッケージの定義
● パッケージの所在と可視範囲
パッケージは,ライブラリの中に存在します.例えば,std_logic_unsignedパッケージはIEEEライブラリの中に存在します.したがってパッケージを呼び出す際には,ライブラリを指定してから,use節で呼び出します(図7).このとき,パッケージに含まれるすべての宣言を用いるなら,
use IEEE.std_logic_unsigned.all;
とall指定し,一つの宣言だけなら,
use IEEE.std_logic_unsigned.conv_integer;
と指定します.
図7 パッケージの呼び出し
設計者が記述したパッケージは,デフォルトでworkライブラリに含まれます.したがって,
use work.MYPAC.all;
のように呼び出します.workライブラリのlibrary宣言は不要です.
回路記述やシミュレーションの記述には,パッケージ呼び出しが必須です.パッケージの可視範囲は,パッケージの定義部や,エンティティに付随するアーキテクチャおよびコンフィグレーションまでだったからです(図8).一度呼び出せばずっと有効というわけではありません.
図8 パッケージの可視範囲
● 代表的なパッケージ
VHDLで設計するとき,最初に接するのがstd_logic_unsignedなどの「標準パッケージ」でしょう.これらは別途定義され,シミュレーション起動時に自動で読み込まれるので,呼び出すだけで使用できました.
これらのパッケージの中では,論理値,演算子,型,単位,変換関数などが細部に至るまで定義されています.std_logicなども,これらの中で定義されている一つの型にすぎません.しかし,回路記述のうえで標準的に使われています.
代表的な標準パッケージには,次のものがあります.
- std_logic_1164 :基本パッケージ
- std_logic_unsigned :符号なし演算用(std_logic_1164の補足)
- std_logic_signed :符号付き演算用(std_logic_1164の補足)
- std_logic_arith :符号付き,符号なし混在演算用(std_logic_1164の補足)
- textio :ファイル・アクセス用
- std_logic_textio :textioの補足パッケージ
● 型(データ・タイプ)
VHDLには,数多くのデータ・タイプがあります.また設計者みずからデータ・タイプを作り出すことが可能です.タイプ宣言により,無限のデータ・タイプを定義できます.
しかし,現実の回路設計の場合,論理合成のことを考えると,使うデータ・タイプは限られます.さまざまなデータ・タイプを用いて記述しても,論理合成後のネットリストでは,特定のデータ・タイプに固定されてしまいます.データ・タイプを駆使しても,ゲート・レベル検証を考えると無駄になってしまうことがあります.
実際のところVHDLに標準で備えられているデータ・タイプは,回路記述ではあまり使いません(表1).例えば標準のbitは,2値(0,1)しかなく,不定もハイ・インピーダンスもありません.これでは回路記述に使えないので,std_logicとstd_logic_vectorをおもに使います.これらは9値で'X'や'Z'もあり,std_logic_1164パッケージで定義されています.
表1 データ・タイプ
![]() (a) 回路記述でよく使う型 |
|
● 型が合わないとエラー
代入や演算のときには型を合わせなければなりません.次のように型を合わせるためのくふうが必要な場合があります.図9は4 to 1のセレクタです.入力はそれぞれ1ビットなので,ビット選択(リスト3)を用いて1行で記述したいところです.しかし,
q <= d(sel);
と記述すると文法エラーになります.selはstd_logic_vector型ですが,ビット選択で記述できるのはinteger型だからです.したがってstd_logic_vector型からinteger型への型変換が必要になります.パッケージstd_logic_unsignedで用意されているのが型変換関数conv_integerです.
図9 型変換は必須 |
||
リスト3 多ビット信号のビット選択と部分選択
これとは逆に,一見型が合わなくてもエラーにならない場合があります.例えば,
signal a, b: std_logic_vector(3 downto 0);
のとき,パッケージstd_logic_unsignedを用いれば,
a <= b + 1;
a <= b + '1';
a <= b + "0001";
のいずれも,エラーではなく同じ動作(同じ回路)になります.
これは,パッケージstd_logic_unsignedの中で,さまざまな型に対する加算演算を定義してあるからです.これをオーバロードと呼びます(リスト4).
リスト4 オーバーロード