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個の子どもが生成されていることが分かります。
トップmodule :
T.B.D.
$root と $unit::
T.B.D.
宣言順と名前指定は、混在させることができません。名前指定においては、暗黙接続とワイルドカード接続を混在させることができます。
暗黙接続
名前指定の場合、子どもと親で同じ名前で接続するのを簡略化するものです。
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