Menu

Verilog wire vs reg:どちらをいつ使うか(例つき)

Verilogの2つの主要なデータ型 - 連続接続のwireと手続きストレージのreg - そして毎回どちらを選ぶかのルール。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

2つの名前、1つの役割

Verilogのすべてのsignalには型があります。最初に出会う2つはwireregです。両方とも値を保持できます。両方ともシングルビットでもマルチビットでも可能です。違いはsignalが 何であるか ではなく、 誰が駆動するか です。

  • wire signalは手続きブロックの 外側 から駆動されます。assign文、サブmoduleの出力、またはmoduleの入力ポートからです。
  • reg signalは手続きブロックの 内側 から駆動されます。initialまたはalwaysです。

それがルールの全部です。キーワード名はモダンなVerilogの書き方より前のものなので不格好です。reg常に ハードウェアのregisterになるわけではありません。理由は読み進めてください。

Wire:連続的な接続

wireは電気的なwireです。ドライバが生成しているものを連続的に運びます。wireが駆動される2つの方法:

3つの注目点:

  • yzはmodule内でwire、testbenchでも再びwireと宣言されています。
  • それらはassignで駆動されます。連続代入形式です。=の右辺はそこにあるsignalが変わるたびに再計算されます。
  • alwaysブロック内でywireのままにしてy = a & bと書くことは できません 。コンパイラが拒否します。

wireキーワードを忘れると、Verilogはsignalを暗黙的に1ビットwireとして宣言します。便利なこともあれば、静かなバグの原因にもなります。多くのチームは暗黙的なwireでエラーにするツールオプションを有効にしています。明示的にして、罠を避けましょう。

Reg:手続きブロック内のストレージ

reginitialまたはalways内で代入するsignalです。名前は言語の初期に「register」のように聞こえた名残です。モダンな使い方では、regは単に 手続き的コードが書き込むsignalの型 です。

countはmodule内ではregalwaysブロックが書き込むから)で、testbench内ではwire(DUTの出力ポートが駆動するから)です。同じsignal、異なる役割、各スコープで異なる型です。

なぜ「Reg」が常に「Register」を意味しないか

これは最もよくある初心者の罠です。このmoduleはyregとして宣言していますが、合成されたハードウェアにはflip-flopが含まれません:

always @(*)ブロックは どの 入力変化にも感応します。組み合わせです。合成ツールはこのパターンを見てAND gateを生成します。flip-flopもクロックもなく、ロジックだけです。regキーワードは、yalways内で代入されるから純粋に構文上の要件として必要なだけです。

実際のflip-flopを得るには、alwaysブロックがクロックエッジに感応する必要があります:

always @(posedge clk) begin
    q <= d;
end

これが「合成ツールよ、flip-flopを作って」パターンです。クロック同期の感応リスト、非blocking代入。同じregキーワード、まったく異なるハードウェア。区別はAlways BlockBlocking vs Non-blockingで扱います。

実用上の判断

signalを宣言するたびに自問してください:「どう駆動するか?」

  • assignで駆動? → wire
  • サブmoduleの出力ポートに接続? → wire
  • moduleの入力ポート? → wire。(inputは常にwire。)
  • initialまたはalwaysから駆動? → reg
  • 手続き的コードで駆動するmoduleの出力ポート? → output reg
  • assignで駆動するmoduleの出力ポート? → output wire。(または単にoutput。方向だけでwireをデフォルトとする。)

この判断木はプレーンVerilogで出会うすべての状況をカバーします。

ドライバの競合

wiresignalは理論上 複数 のドライバを持てます。それがtri-stateバスの動作で、複数のmoduleが同じwireを駆動でき、非アクティブのものはハイインピーダンス(z)になります。通常のロジックでは、同じwireに2つのassignを書くと未定義動作になります:

assign y = a;
assign y = b;   // 悪い - yに2つのドライバ

シミュレータは片方を選ぶかもしれないし、signalをxにするかもしれず、ツール次第です。どちらにせよバグです。バスを明示的に作る場合以外、1つのwireに1つのドライバ。

regsignalは1つの手続きブロックからしか駆動できません。2つのalwaysブロックが同じregに代入することは合成エラーで、シミュレーションでも奇妙です。同じルール:1つのドライバ。

SystemVerilogのアップデート:logic

SystemVerilog(Verilogが進化したスーパーセット)は、両方を置き換える単一のキーワードlogicを追加しました。logicsignalはassignまたは手続きブロックで駆動できます(ただし両方ではない)。コンパイラは多ドライバのバグを誤って作るのを止めてくれます。

module modern(input logic a, input logic b, output logic y);
    assign y = a ^ b;
endmodule

新しいプロジェクトを始めて、ツールがSystemVerilogをサポートしている(このページのエディタは-g2012でサポート)なら、どこでもlogicを使えばルールが簡単になります。プレーンの.vファイルは依然としてwire/regの分割が必要で、両スタイルとも今後ずっと現場で見られるでしょう。

次に読むもの

次のドキュメントVectors and Arraysでは、同じ2つの型をマルチビット化する方法を示します。バス幅、range、packedディメンション、ビットのvectorとvectorの配列の違い。1ビット加算器より大きなものを作る前に必要なすべてです。

よくある質問

Verilogのwireとregの違いは?

wireregはどちらもシミュレーションのどの瞬間もsignal値を保持しますが、選び方は誰がsignalを駆動するかに基づきます。wireは手続きブロックの外側から駆動されます。assignまたはサブmoduleの出力です。reginitialまたはalwaysブロックの内側から駆動されます。名前は歴史的なもので誤解を招きます。regは常に「register」を意味するわけではありません。

Verilogのregはflip-flopを意味しますか?

必ずしもそうではありません。regは、そのalwaysブロックがクロックエッジに感応し、非blocking代入を使うときにのみflip-flopに合成されます。組み合わせalways @(*)ブロック内で代入されるregは、純粋な組み合わせ論理に合成されます。このキーワードはハードウェアではなくVerilogのデータ型を選択します。

wireとregはいつ使い分けるべき?

経験則:signalをassignで駆動するか、サブmoduleの出力ポートに接続するならwirealwaysまたはinitialブロックの内側でsignalに代入するならreg。moduleへのinputは常にwire。outputは、assignで駆動ならwire、手続きブロックで駆動ならreg

alwaysブロック内でwireに代入できますか?

いいえ - 構文エラーです。wireは連続代入(assign)またはサブmoduleインスタンスの出力としての接続でのみ駆動できます。initialまたはalwaysの内側のものはreg(SystemVerilogならlogic)をターゲットにしなければなりません。コンパイラはこれを検出し「左辺の型不一致」を訴えます。

SystemVerilogのlogicとは?

logicはSystemVerilogによるwireregの統一です。連続代入または手続きブロックで駆動できます(ただし両方同時には不可)。モダンなコードではlogicをどこでも使い、wire/regの区別を忘れる傾向が増えています。プレーンVerilogのファイルは依然として選択する必要があります。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める