Menu

Verilog operator:算術、比較、論理、条件

Verilogの主要なoperator(算術、比較、論理、条件?:)と、幅と符号の混在に関するルールと罠。

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

Verilogにおける「Operator」の意味

operatorはsignalを運ぶ式を取り、新しいsignalを運ぶ式を生成します。a + bはハードウェアです。合成ツールはこれをadderに変換します。a == bはハードウェアです。コンパレータを構築します。これは「実行されるコード」ではなく、すべて「operatorが記述する回路」です。

operatorメニュー全体は覚えられるくらい小さいです。このドキュメントは算術、比較、論理、条件のoperatorを扱います。ビット単位とreductionはソフトウェアに直接の対応物がないビットレベルのoperatorを扱います。

算術:+ - * / %

3つの知っておくべきこと:

  1. 除算は整数除算。 7/23.5ではなく3です。Verilogには浮動小数点型がありません(realはありますが、シミュレーション専用です)。
  2. 除算とmoduloはハードウェアで高コスト。 /4は問題なし(合成ツールが右シフトに変換します)。しかしランタイム可変nに対する/nは、ほぼ欲しくない多サイクルの除算器を構築します。
  3. オーバーフローはラップする。 Nビットを超えるunsigned値2つを足すとNビットに切り詰められます。キャリーを捕捉したい場合は、結果を1ビット広く宣言します:
wire [7:0] a, b;
wire [8:0] sum = a + b;   // 9ビットsumがキャリーアウトを捕捉

比較:== != < > <= >=

6つの比較演算子すべてが1ビット結果を返します。真なら1、偽なら0、どちらかのオペランドがxzビットを持てばxです。x/zのケースを扱うには、XとZの値で扱う===!==(ケース等価演算子)に手を伸ばします。

ここでの<=は比較演算子(以下)です。同じ文字は手続きブロック内で非blocking代入(q <= d)も 意味します 。コンテキストで区別します。式の中なら比較、代入される値の左にあれば代入です。重複は紛らわしいですが、パーサには曖昧でありません。

論理:&& || !

論理演算子はオペランドをブール(非0は真、0は偽)として扱い、1ビット結果を生成します:

内面化すべき重要な区別:論理&&はビット単位&ではない。

4'b1100 && 4'b0011   // 1(両方とも非0、論理ANDは真)
4'b1100 &  4'b0011   // 4'b0000(両方で1のビット位置はない)

|| vs |も同様です。if条件や?:の述語には論理、各ビット位置を独立にAND/ORしたいときはビット単位を使います。

&&||はCの意味で短絡評価です。左辺で結果が決まれば右辺は評価されません。これはポインタや関数呼び出しをチェックするtestbenchで重要ですが、すべてが並列に起こる合成可能なRTLではほぼ重要ではありません。

条件演算子:?:

三項はmuxや条件式を構築する最良の友です:

cond ? a : bパターンはハードウェアで1ビット選択の2-to-1 multiplexerです。チェーンは3-/4-wayの選択には問題ありませんが、それを超えるとCase Statementで扱うcase文の方が劇的に読みやすくなります。

?:演算子は、registerに時々だけオーバーライドするデフォルト値を与える標準的な方法でもあります:

next_value = update ? new_data : next_value;

幅ルール:初心者の落とし穴

Verilogの算術演算子の幅ルールは悪名高く驚きをもたらします。短いバージョン:

  • 結果の幅は入力の幅の最大値です。
  • 結果がより広いものに代入されると、ゼロ拡張されます(signedなら符号拡張)。
  • 中間計算の幅も結果の幅 で、中間でオーバーフローが起こります。

最初の掛け算はオペランドの幅が両方とも8ビット、結果の幅もそのため8ビット、そして40000は収まらないのでオーバーフローします。2番目は掛ける前にaを明示的に広げたので動きます。

修正の技:

  • 連結演算子{8'b0, a}でゼロ拡張する。
  • $unsigned(a)または$signed(a)で解釈に影響を与える。
  • 疑わしければ中間式を広い幅にキャストする。

演算子の優先順位

表は暗記しないでしょうが、いくつかのルールに頼ることになります:

  • */%+-より優先順位が高い。
  • 比較は論理(&&||)より優先順位が高い。
  • 条件演算子?:は非常に低い優先順位 - 大きな式では通常分岐の周りに括弧が必要。
  • 疑わしければ括弧をつける。シミュレータは文字数で課金しません。
out = (mode == 2'd0) ? a + b : a - b;   // 括弧があるとより明確

次に読むもの

これでソフトウェアの兄弟分に似たoperatorをすべて見ました。次のドキュメントビット単位とreductionはソフトウェアに直接対応物のないoperatorを扱います。ビット単位のAND/OR/XORと、vector全体を1ビットに畳むreduction形式です。

よくある質問

Verilogがサポートするoperatorは?

Verilogには4つの大きなoperatorファミリーがあります。算術(+, -, *, /, %)、比較(==, !=, <, >, <=, >=)、論理(&&, ||, !)、ビット単位/reduction(&, |, ^, ~, ~&, ~|, ~^)。加えてシフト演算子(<<, >>, <<<, >>>)、連結 {}、繰り返し {N{...}}、条件 ?:

Verilogの&&と&の違いは?

&&は論理ANDで、各オペランドをブール(0か非0)として扱い、1ビットの結果を返します。&はビット単位ANDで、ビット位置ごとにペアにします。4'b1100 && 4'b00111(両方とも非0)、4'b1100 & 4'b00114'b0000です。条件には&&、ビット単位の演算には&を使ってください。

Verilogで除算はどう動きますか?

整数除算で、小数部分は捨てられます。7 / 23.5ではなく3です。%演算子は余りを返します:7 % 21です。0除算はシミュレーションでx(未知)を生成します。両演算子とも技術的には合成可能ですが、FPGAやASICで非常に大きく遅いハードウェアを生成するので、除数が2のべき乗でない限り合成可能なパスでは避けてください。

Verilogの条件演算子とは?

?:はCからコピーされた三項または条件演算子です。cond ? a : bcondが真(非0)ならaに、そうでなければbに評価されます。multiplexer的なロジックで最も使われる構文です:out = sel ? in1 : in0が2-to-1 muxを構築します。?:のチェーンでより広いmuxを作れますが、2入力を超えると通常caseの方が明確です。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める