Verilog assign文を理解する:連続信号代入の仕組み
wire タイプや類似のワイヤライクなデータ型の信号には、値の連続代入が必要です。例えば、ブレッドボード上でピースを接続する電気ワイヤを考えてみてください。片側に +5V の電池を接続し続ける限り、もう片側に接続されたコンポーネントは必要な電圧を得られます。
Verilogでは、この概念は assign 文によって実現されます。ここで、あらゆる wire や類似のワイヤライクなデータ型を、値で継続的に駆動できます。値は定数でも、複数の信号で構成される式でも構いません。
assign構文
代入構文はキーワード assign で始まり、その後に信号名(単一信号または異なる信号ネットの連結)が続きます。駆動強度 と 遅延 はオプションで、主にデータフローモデリングで使用され、実ハードウェアへの合成よりもタイミング振る舞いのモデリングに用いられます。右辺の式または信号が評価され、左辺のネットまたはネットの式に代入されます。
assign = [drive_strength] [delay]
遅延値はゲートの遅延指定に有用で、実ハードウェアのタイミング振る舞いをモデル化するために使用されます。値が評価された値でネットが代入されるタイミングを指定するからです。
ルール
- 左辺(LHS)は常にスカラまたはベクトルネット、またはそれらの連結でなければならず、スカラまたはベクトルレジスタであってはならない
- 右辺(RHS)にはスカラまたはベクトルレジスタと関数呼び出しを含められる
- RHSのオペランドのいずれかが値を変更すると、LHSは新しい値で更新される
assign文は連続代入とも呼ばれ、常にアクティブ
例 #1
以下の例では、out というネットが信号の式によって継続的に駆動されます。i1 と i2 の論理積 & が式を形成します。
これらのワイヤをポートに変換して合成すると、合成後のRTL回路図は以下のようになります。
例 #2
以下のモジュールは2つの入力を取り、assign 文を使って部分選択と複数ビット連結で出力 z を駆動します。各ケースをモジュール内の唯一のコードとして扱ってください。同じ信号に複数の assign 文があると、出力が確実に X になります。
module xyz (
input [3:0] x, // xは4ビットベクトルネット
input y, // yはスカラネット(1ビット)
output [4:0] z // zは5ビットベクトルネット
);
wire [1:0] a;
wire b;
// 以下の代入のうち1つだけを実際の設計で選択すると仮定
// x='hC, y='h1 のとき、zの値を見てみる
// Case #1: xの4ビットとyの1ビットを連結して5ビットネットを作り、zの5ビットに代入
// z = 'b11001 または z = 'h19
assign z = {x, y};
// Case #2: 同じ連結をzの選択された3ビットに代入。残り2ビットは未駆動でハイインピーダンス
// z = 'bZ001Z
assign z[3:1] = {x, y};
// Case #3: 同じ文だが、zのビット4を定数値1で駆動。ビット0のみ未駆動
// z = 'b1001Z
assign z[3:1] = {x, y};
assign z[4] = 1;
// Case #4: ビット3を代わりに駆動。2つのドライバがビット3を駆動し、両方とも同じ値0を駆動
// コンテンションなし → z = 'bZ001Z
assign z[3:1] = {x, y};
assign z[3] = 0;
// Case #5: ビット3を値1で駆動。2つのドライバが異なる値を駆動(1行目はX=0、2行目は1)
// どちらが勝つか不明 → z = 'bZX01Z
assign z[3:1] = {x, y};
assign z[3] = 1;
// Case #6: RHSオペランドの部分選択も可能。xから2ビットのみ選択すると
// z = 'b00001(z[4:3]は0で駆動)
assign z = {x[1:0], y};
// Case #7: zの3ビットのみ明示的に代入し、残りを未接続にすると
// z = 'bZZ001
assign z[2:0] = {x[1:0], y};
// Case #8: 同じ変数を複数回使用可能。z = 'b00111
// 3{y} は {y, y, y} と同じ
assign z = {3{y}};
// Case #9: LHSも連結可能。aは2ビットベクトル、bはスカラ
// RHSは11001と評価され、LHSは3ビット幅なのでRHSの下位3ビットがLHSに代入
// a = 'b00, b = 'b1
assign {a, b} = {x, y};
// Case #10: LHSの順序を逆にしてRHSを同じにすると、a = 'b01, b = 'b0
assign {b, a} = {x, y};
endmodule
reg変数への代入
assign 文で reg タイプの変数を駆動・代入することは 違法 です。これは reg 変数がデータを保持できるため、継続的に駆動される必要がないからです。reg 信号は initial と always などの手続きブロックでのみ駆動できます。
暗黙的連続代入
assign 文を使ってネットに値を代入することを 明示的 代入と呼びます。Verilogでは、ネット宣言時に代入を行うこともでき、これを 暗黙的 代入と呼びます。
wire [1:0] a;
assign a = x & y; // 明示的代入
wire [1:0] a = x & y; // 暗黙的代入
組み合わせ論理設計
以下の組み合わせゲートで構成されるデジタル回路と対応するVerilogコードを考えます。
組み合わせ論理は、順序要素(フリップフロップ)のようにクロックエッジで値を取得・保持するのではなく、入力を継続的に駆動して出力を維持する必要があります。そのため、RHSの入力のいずれかが変化するたびに出力 o が更新される assign 文が最適です。
// 4入力を取り、ブール演算を実行し、出力をoに代入
// 組み合わせ論理はassign文で実現
module combo (
input a, b, c, d,
output o
);
assign o = ~((a & b) | c ^ d);
endmodule
ハードウェア回路図
設計エラボレーションと合成後、assign 文でモデル化されたのと同じように振る舞う組み合わせ回路が得られます。
信号 o は、RHSの組み合わせ式が真になると1になり、偽になると0になります。0ns〜10nsでは入力がXのため、出力 o もXです。
Verilog
- C# switch 文をマスターする:構文、例、ベストプラクティス
- C# break 文:使い方とタイミングを徹底解説
- C# continue 文をマスターする:ループ反復を効果的にスキップする方法
- Verilog連結マスター:実践ガイド
- Verilog代入文の理解:種類、構文、ベストプラクティス
- Verilogブロッキング代入とノンブロッキング代入:違いを徹底解説
- Verilog関数のマスター:効率的なRTL設計のために
- Verilogタスクの理解:関数との違い、構文、使用法
- Verilogクロックジェネレータ:設計と実装ガイド
- Verilog数学関数のマスター:効率的なハードウェア設計のために
- Verilog $timeformatのマスター:精度と表示制御