module のインスタンス化 (Module instances)

概要

インスタンス化について説明します。
ポート接続に関して、SVでは、簡易な接続方法が追加になっています。このルールについて説明します。

インスタンス化とは何か?

module 本体は、テンプレートにすぎません。C++や、JAVA等の他のプログラミング言語でのクラスや構造体は、宣言するだけでは、メモリを占有しませんが、そういう意味では、同じことです。
テンプレートに過ぎないので、コンパイルの過程で、テンプレートから、実体化する作業が必要になります。これを moduleのインスタンス化と呼んでいます。実体化とは、コンピュータのメモリ上に、moduleオブジェクトとして展開することです。つまり、インスタンス化されたモノは、メモリに置かれることになります。このインスタンス化されたモノは、同じテンプレートから生成されたとしても、別のアドレス上に配置されているので、それぞれ別物になります。一つとして、(同じmoduleを由来としますが、)同じアドレスはないのでインスタンスは別になります。ユニークなモノになります。

次の記述では、sub moduleを4個インスタンス化しています。module sub というテンプレートから、それぞれdut0,1,2,3 という名前でインスタンス化されます。

module top;

	sub   dut0();
	sub   dut1();
	sub   dut2();
	sub   dut3();

endmodule
module sub;

	initial $display("ようこそ! %m");
endmodule






この実行結果は、次です。%mで、実行中のインスタンス名を出力することが出来ます。同じmodule sub からインスタンス化したものですが、
それぞれ、インスタンス名が異なることが分かります。逆に言うと、インスタンス名がインスタンスを区別するためのものですから、同じSCOPE中に同じインスタンス名を記述するとコンパイルエラーとなります。

***** Veritak SV32 Engine Version 433 Build Jan  8 2013*****

ようこそ! top.dut3
ようこそ! top.dut2
ようこそ! top.dut1
ようこそ! top.dut0

---------- シミュレーションを終了します。time=0ns


ScopeTreeViewで見ると、topの子どもとして4個の子どもが生成されていることが分かります。



C++,JAVA等の言語では、new しないとインスタンス化されることはありません。つまり、コンパイルが終わった状態からのスタート点では、実体化したインスタンスは、ありません。しかし、ハードウェア記述言語においては、moduleは、静的にインスタンス化されます。"静的に"とは、=コンパイル時という意味です。コンパイルが終わって、これからシミュレーションがスタートするというときには、インスタンス化は、終了しています。ハードウェアというのは、最初から存在するものでシミュレーション中に 生まれたり(new )死んだり(delete) しないということから来ています。これを指して、moduleは、静的(static)なオブジェクトである、という言い方をします。SVでは、moduleの他にもprogram やinterfaceといったブロックがありますが、これらは、静的なオブジェクトになります。またSVでは、他の言語と同じようにクラスを定義、生成できるように拡張されています。こちらは、動的(dynamic)なオブジェクトで、ハードウェアではなく、ハードウェアを検証するための部品としてテストベンチ用途で使用されます。他の言語と同様に newするまで使えません。


トップmodule :

T.B.D.
$root と $unit::

T.B.D.



module間のポート接続

SVでは、新たに二つのポート接続方式が追加されました。下の4つの接続形式があります。

宣言順と名前指定は、混在させることができません。名前指定においては、暗黙接続とワイルドカード接続を混在させることができます。

暗黙接続

名前指定の場合、子どもと親で同じ名前で接続するのを簡略化するものです。


module if27;
	reg clk,reset;
	wire [8:0] out;

	sub dut(.clk, .reset,.out);//名前指定だとsub dut(.clk(clk), .reset(reset),.out(out));
endmodule

module sub(input clk, reset, output bit [7:0] out);



endmodule

当然のことながら、名前が親のスコープ空間内にある必要があります。(見つからないとパッケージや$unit::空間まで探してしまいます。)
見つからない場合は、物騒ぎな1ビットの暗黙ネットが生成されることはなくエラーとなります。

見つかった場合、ビット幅のチェックが行われます。違っているとWarningではなく、コンパイルエラーとなります。上の例ではoutのビット幅が違うのでエラーとなります。


C:\Users\Public\sv_test\interface\if27.sv(8):: Info: 構文解析中です。
構文解析が終了しました。
スコープを生成中です。Loading vpi.dll
parameterを評価中です。
reg/wire..を評価中です。
moduleを評価中です。
C:\Users\Public\sv_test\interface\if27.sv(5)::Error : ポート   .out(  ) は、ピン数が一致していません。上位ポートピン数:9 下位ポートピン数:8
リンクフェーズでエラーが生じたためコンパイルできませんでした。
ワイルドカードによる接続

上の暗黙接続をさらに簡略化したもので大変便利です。ビット幅が合わなければ、コンパイルエラーとなるのは、上に同じです。


module if27;
	reg clk,reset;
	wire [7:0] out;

	sub dut(.*);//名前指定だと 	sub dut(.clk(clk), .reset(reset),.out(out));
endmodule

module sub(input clk, reset, output bit [7:0] out);



endmodule


上の3種は、混在させることができます。名前とビット幅が異なるところは名前指定を使い、残りは、.* で接続するスタイルが出来ます。



module if27;
	reg clk,reset;
	wire [7:0] out;

	sub dut(.clk(clk), .reset,.*);//名前指定だと 	sub dut(.clk(clk), .reset(reset),.out(out));
endmodule

module sub(input clk, reset, output bit [7:0] out);



endmodule