Package
packageは、定数の宣言やtypdefなどの定義を、複数のファイルやモジュールで共用するのに使用される。JAVAのpackageやC++のnamespaceと似ている。
Verilogでは、includeとdefineによる定数宣言の場合、デザイン全体で定数宣言の重複に気を配らなければならなかったが、packageを使用すれば、package名の重複にさえ気をつければ、その中身の宣言の重複に気を使う必要がなくなる。大規模なデザインには便利な機能だ。
packageは以下のように宣言する。
File: PackageA.sv
package PackageA;
const int VALUE1 = 32'h0;
const int VALUE2 = 32'h41;
endpackage
File: PackageB.sv
package PackageB;
const int VALUE1 = 32'hf;
const int VALUE2 = 32'h42;
endpackage
宣言したパッケージ内の定義を参照するには二種類の方法がある。
一つは、importにより、デフォルトの参照パッケージを宣言するもので、C++のusingに相当する。
もう一つは::によりパッケージ内の個々の宣言を参照する方法で、C++の::と同じになる。
module mod1();
import PackageA::*;
initial begin
$display("imported VALUE1 = 0x%x", VALUE1);
$display("imported VALUE2 = 0x%x", VALUE2);
$display("PackageB VALUE1 = 0x%x", PackageB::VALUE1);
$display("PackageB VALUE2 = 0x%x", PackageB::VALUE2);
end
endmodule
実行結果は以下の通り。
# 6.5e
# vsim -do {run -all; quit} -c mod1
# Loading sv_std.std
# Loading work.PackageB
# Loading work.PackageA
# Loading work.mod1
# run -all
# imported VALUE1 = 0x00000000
# imported VALUE2 = 0x00000041
# PackageB VALUE1 = 0x0000000f
# PackageB VALUE2 = 0x00000042
# quit
一つのモジュール内で、複数importを記述することにより、複数のパッケージを同時に参照することもできるのだが、この場合、パッケージ内で同じ宣言があると、エラーとして処理される。このあたりの細かいルールについては、LRMのほうを参照してほしい。ただ、現実問題としては、複数のimportは混乱の元となる。上記の例のように、一つのスコープの中で、宣言するimportは一つのみとし、それ以外のパッケージを参照する場合には::を使用するのが現実的だろう。
package内には、この他typdefやclass/task/functionの定義も含めることができる。ただし、functionとtaskはautomaticでなければならないため、通常の論理合成ツールでは合成できない。テストベンチ用の定義のみの使用となる。