工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> Verilog

Verilogモジュールインスタンス化のベストプラクティス:階層設計のために

前回の記事で見たように、より大規模で複雑な設計は、複数のモジュールを階層的に統合することで構築されます。モジュールは他のモジュール内で インスタンス化 でき、これらの インスタンス のポートを親モジュール内の他の信号と接続できます。

これらのポート接続は、順序付きリストまたは名前による方法で行えます。

順序付きリストによるポート接続

モジュールインスタンス化時のポート式リストと、親モジュール内の信号を接続する方法の1つは 順序付きリスト です。

mydesign は module で、別のモジュール tb_top 内で d0 という名前でインスタンス化されます。ポートは、モジュール宣言のポートリストでの位置によって決まる順序で接続されます。例えば、テストベンチの b が設計の y に接続されるのは、両方ともポートリストの第2位置にあるからです。

module mydesign (
    input x, y, z,  // xは位置1, yは2, zは3
    output o        // oは位置4
);
endmodule

module tb_top;
wire [1:0] a;
wire b, c;
mydesign d0 (a[0], b, a[1], c);  // a[0]→x, b→y, a[1]→z, c→o
endmodule
注意: 設計モジュールのポート順序を知っている必要があります。

これは非常に不便です。ポート順序が新しいポート追加で変わったり、ポート数が非常に多い場合に対応が困難になるからです。

名前によるポート接続

より良い方法は、両側のポートを ポート名 で明示的にリンクすることです。

ドット . は、その後に続くポート名が設計側のものであることを示します。設計ポートを接続する信号名を、続いて括弧 ( ) 内で指定します。

module design_top;
wire [1:0] a;
wire b, c;
mydesign d0 (
    .x (a[0]),  // mydesignの"x"をこのモジュール(design_top)の"a[0]"に接続
    .y (b),     // mydesignの"y"をこのモジュールの"b"に接続
    .z (a[1]),
    .o (c)
);
endmodule

各ポート接続を別行に記述することを推奨します。そうすれば、コンパイルエラーメッセージがエラー発生行を正しく指し示し、デバッグと解決が容易になります。同じ行にすべて書いていた場合、どのポートがエラーの原因か特定しにくいためです。

これらの接続は名前で行われるため、記述順序は無関係です。複数のモジュールインスタンスポート接続は許可されません。

module design_top;
mydesign d0 (
    .x (a[0]),
    .z (a[1]),  // zが2番目でもOK(明示的接続のため)
    .y (a[1]),
    .x (b),     // 違法 - xは既にa[0]に接続済み
    .o (c)
);
endmodule

未接続/フローティングポート

インスタンス化モジュール内でどのワイヤにも接続されていないポートは、ハイインピーダンス値を持ちます。

module design_top;
mydesign d0 (
    // xは入力だが未接続 → a[0]はZ
    .y (a[1]),
    .z (a[1]),
    .o ()  // oはmydesign内で有効な値だが、design_topの"c"に未接続 → cはZ
);
endmodule

例:シフトレジスタでの未接続ポート

以前のシフトレジスタ例で、一部のポートを未接続にしてみます。

module shift_reg (
    input d, input clk, input rstn, output q
);
wire [2:0] q_net;
dff u0 (.d(d), .clk(clk), .rstn(rstn), .q(q_net[0]));
dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q());  // 出力qをフローティング
dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q());  // 出力qをフローティング
dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
endmodule

合成後のRTL回路図では、インスタンス u1 と u2 の出力が未接続であることがわかります。インスタンス u2 と u3 の入力 d が何にも駆動されていないネットに接続されているため、グラウンドされます。

シミュレーションでは、このような未接続ポートはハイインピーダンス('hZ)で表され、波形では通常オレンジ色の垂直線として中央に表示されます。

すべてのポート宣言は暗黙的に wire と宣言されるため、ポート方向の指定だけで十分な場合があります。しかし、値を保持する必要がある output ポートは reg データ型で宣言し、always や initial などの手続きブロックでのみ使用できます。

input または inout タイプのポートを reg で宣言することはできません。これらは外部から継続的に駆動されるため値を保持せず、外部信号の変化をできるだけ早く反映すべきだからです。ベクトルサイズが異なる2つのポートを接続することは合法ですが、ベクトルサイズが小さい方が優先され、大きい方の上位ビットは無視されます。

// Case #1: 入力はデフォルトで暗黙的に"wire"型
module des0_1 (input wire clk ...);  // wireはここで指定不要
module des0_2 (input clk, ...);      // デフォルトでclkはwireタイプ

// Case #2: 入力はreg型にできない
module des1 (input reg clk, ...);    // 違法: 入力はreg型不可

// Case #3: 異なるポート幅の2モジュール
module des2 (output [3:0] data, ...); // 4ビットベクトル出力
module des3 (input [7:0] data, ...);  // 8ビットベクトル入力
module top (...);
wire [7:0] net;
des2 u0 (.data(net) ...);  // netの上位4ビットは未駆動
des3 u1 (.data(net) ...);
endmodule

// Case #4: 出力を親モジュールのregに接続不可
module top_0 (...);
reg [3:0] data_reg;
des2 (.data(data) ...);  // 違法: data出力ポートがreg型信号"data_reg"に接続
endmodule

Verilog

  1. Verilogマスター:デジタル回路設計のための完全チュートリアル
  2. Verilog連結マスター:実践ガイド
  3. Verilogエッセンシャル:簡潔な概要
  4. Verilog代入文の理解:種類、構文、ベストプラクティス
  5. Verilogブロッキング代入とノンブロッキング代入:違いを徹底解説
  6. Verilog関数のマスター:効率的なRTL設計のために
  7. Verilogタスクの理解:関数との違い、構文、使用法
  8. Verilog階層参照スコープのマスター:モジュールとブロックでの名前衝突回避
  9. Verilogクロックジェネレータ:設計と実装ガイド
  10. Verilog数学関数のマスター:効率的なハードウェア設計のために
  11. Verilog $timeformatのマスター:精度と表示制御