Altifigence Academy

10 / 37 · 概念

組合せ RTL と完全な代入

条件演算子と always_comb で同じ関数を表し、ラッチを生む代入漏れを見つけます。

組合せ回路は現在の入力で出力が決まります

MUXマルチプレクサ 選択信号に従い、複数の入力から一つを出力に接続する組合せ回路です。選択ビットと入力番号の対応を仕様で定めます。 詳しく見る を最も直接に書く方法は assign y = sel ? b : a; です。複数出力をまとめて計算するときは always_comb を使えます。

SystemVerilog
always_comb begin
  y = a;
  if (sel) y = b;
end

先にデフォルト値を代入したので、sel=0 の経路も定義されています。逆に if (sel) y = b; だけを残すと、sel=0 で過去の y を保持する必要があり、純粋な組合せ関数ではなくなります。ツールの警告を無視したり、always_comb というキーワードだけを信用したりしないでください。

y=a をデフォルトとし、sel=1 のときだけ b を選ぶコードは、下の回路と同じ 0/1 組合せ機能です。sel=0 でも出力は必ず決まります。

デフォルト代入が覆う二つの経路

y = sel ? b : a

手続き型の構文をソフトウェアの実行順だけで読まない

組合せブロックでは通常、ブロッキング代入 = で中間結果を計算します。同じブロックの後の式が先の代入結果を読むなら、その依存関係が組合せ経路になります。順序レジスタレジスタ 複数ビットの状態を記憶する回路です。このコースの同期式レジスタは、クロックエッジで定められた入力を記憶します。 詳しく見るの更新で使うノンブロッキングノンブロッキング代入 順序 RTL で <= と書く代入です。右辺を評価して更新を予約するので、同じエッジのレジスタが更新前の状態に基づいて計算できます。 詳しく見る代入 <= とは役割を区別してください。

SystemVerilog
always_comb begin
  next_y = sel ? b : a;
  inverted_y = ~next_y;
end

一つの出力を複数ブロックで駆動しないことも基本です。モジュールを分けるほど、「この信号の唯一の駆動元は誰か」をインターフェースで追跡する必要があります。

幅の異なるデータは先にそろえます

8 ビットと 12 ビットを選択するなら、y の幅と符号拡張を明示します。暗黙の拡張が意図に合うかを波形で偶然確かめるのではなく、設計段階で入力範囲を決めます。0/1 モデルの外では、sel が X のときの条件演算子は単純な if と異なる場合があるため、このコースの 2 状態の結果を 4 状態全体へ一般化しません。

自分で考えてみましょう

always_comb 内に if(en) y=d; だけがあります。enable が無効なら 0 を出す組合せ回路にするには、どう書きますか。

解説を見る

ブロックの先頭で y に 0 を代入し、en のとき d で上書きするか、assign y = en ? d : 0 に相当する幅が明確な式を使います。en=0 で以前の値を保持するのはレジスタ・ラッチの別仕様であり、0 出力と同じ機能ではありません。

選択はこのブラウザに適用されます。フッターからいつでも変更できます。