設計・検証の手引きと早見表

コードを書き始めるとき、警告で止まったとき、レビュー前に使える手引きだよ。note教材の特典に分かれていた内容を、教科書と実習へつながる形でまとめたよ。

1. assign / alwaysを選ぶ

まず「状態を持つか」「いつ更新するか」を決めるよ。クロックで状態を更新するなら always @(posedge clk)、現在の入力だけで決まる組合せなら assign または always @* を選ぶ。短い式にはassign、複数の条件や出力を整理したいときにはalwaysが読みやすいことが多いんだ。

条件が2個以上ならassign禁止、という言語規則はないよ。三項演算の入れ子も合法。読者が優先順位を追えるか、全経路で出力が決まるかを基準に、チームの規約に合わせよう。

目的 書き方の例 確認すること
配線や短い論理式 assign y = a & b; 幅、符号、駆動元
条件で選ぶ組合せ always @* と = すべての出力に全経路で代入
エッジで保持・更新 always @(posedge clk) と <= リセット、enable、優先順位
意図したラッチ 対象設計の規約に従う 透明期間、対象資源、タイミング

エディタのスニペットは入力補助だよ。リセット値や信号名の空欄を埋めたら、必ずコンパイルと試験を行おう。動作するテンプレート を小さく変更して始める方法もあるよ。

2. Warningを理由付きで処理する

最初のエラーのファイル・行・信号名を読み、その行の少し前も調べる。文法エラーはセミコロン、begin/end、括弧、モジュール境界の欠落が原因のこともあるよ。後続のエラーは最初の不備から連鎖しているかもしれないんだ。

次の文言は診断の種類を示す例。特定ツールで実測したログではなく、番号や重要度は製品・版・設定によって異なるよ。

診断の種類 まず見るもの 対処と再確認
Latch inferred 組合せ出力に代入しない経路 全経路への代入。意図した保持ならタイミング仕様を確認
Multiple drivers 同じ信号を書くassign/always/接続 RTL変数の更新元を一つへ集約。外部バスの三態制御とは区別
Combinational loop / feedback 記憶素子なしで出力が入力計算へ戻る経路 接続・式・階層を追って循環を除く
Pin assignment / I/O standard 基板の回路図、対象デバイス、電圧規格 ピン番号と規格を合わせる。一般例の制約を流用しない
Implicit net 未宣言名、タイポ、include漏れ 宣言と名前を修正しdefault_nettype noneで確認
Unused / truncated / width mismatch 未接続、使わないビット、ポート幅 意図的なら根拠を明示。必要な上位ビットは保存
CDC 送信・受信クロックと信号の性質 同期化、パルス転送、バス整合性を方式ごとに検証
Timing violation / negative slack 制約、最長/最短経路、setup/hold 誤制約を修正、構造を改善し配置配線後も再確認
Memory inferred 配列の用途、容量、読み出し遅延 推論そのものは異常とは限らない。期待するRAM資源か確認

警告を一律に消すための抑制設定を先に入れないでね。原因、仕様への影響、修正または許容する理由を残すよ。判断に迷ったら、ツール名・版・正確な診断番号と文言で公式ドキュメントを探そう。ログ、Timing Report、SDC/XDC、ピン定義を一緒に読むと切り分けやすいんだ。

3. 20のコード確認ポイント

項目 確認と修正の入口
1. ifの代入漏れ 組合せはelseまたは先頭の既定値で全経路を覆う。FFのenable保持は別
2. caseの代入漏れ 空のdefaultだけでは解決しない。各出力の代入を確認
3. FFでのブロッキング代入 更新順・他プロセスとの競合を確認し、状態更新を<=へ
4. 組合せでのNBA 不要なデルタサイクルや依存関係を避けるため=へ
5. 感度リスト漏れ always @*。入力単独の変化も試す
6. 暗黙ネット default_nettype none。宣言済みの別信号へのタイポは試験でも確認
7. 初期化 仕様で必要な状態・validをリセット。無効なデータ部まで一律リセットするかは資源と仕様で判断
8. RTLの#遅延 TB用の時間記述を混ぜない。待ちサイクルはカウンタや状態で表す
9. CDC直結 単ビット、パルス、複数ビットで転送方式を分ける
10. 幅の不一致 拡張と切り捨てを明示し、境界値を試す
11. 論理式のクロック生成 一般ロジックのANDよりenable、必要なら専用クロック資源
12. ==と=== RTLの機能比較とTBのX/Zを含む厳密判定を区別
13. 除算・剰余 幅・符号・定数か可変かを確認し、面積と遅延を測る。符号なしの2のべき乗除算はシフトで表せるが、負値の丸めは単純置換できない
14. wire/reg ネットと手続き変数を区別。型だけで回路は決まらない
15. タイムアウト クロック停止でも有限時間で失敗終了できるTBへ
16. TBの競合 刺激・取り込み・判定の時刻を分ける
17. リセット解除忘れ 極性と解除後に実際に動作する試験を確認
18. 合成対象にTB トップ名とファイルリストを分離
19. 周波数と周期 MHzとnsを換算し実際のクロックへ適用
20. casez/casex 入力側のZ/Xまで無視しないか、無効入力を試す

切り分けの練習: FSMが動かないなら、リセット→クロック→入力イベント→state→next_stateを追おう。出力が更新されないなら、enable・代入経路・接続・幅を順に見る。RTLだけ通って実機で不安定なら、タイミング制約、CDC、リセット解除、ピンとボード条件を確認する。ただし症状だけで原因を断定せず、各段の観測結果を残してね。

CIにコンパイル、自己判定TB、必要なLintを組み込むと、同じ不具合の再発に気づきやすくなるよ。Warningを失敗にする規約と、理由付きで許容する診断を分けよう。単なる文字列検索は点検の入口にはなるけれど、RTLの構造解析やCDC検証の代わりにはならないんだ。

4. SystemVerilog対応表

記法 意味とVerilogとの関係
logic 4値のデータ型。ネット/変数の区分とは別。多重駆動を解決する配線にはwireなどのネット型が必要
always_ff FFとして使う手続きブロックの意図と制約を表す。状態更新は<=を基本にする
always_comb 組合せの意図、時刻0の評価、代入先の制約などを持つ。always @*の単なる別名ではない
always_latch 意図したラッチを表す。対象ツールと設計規約に従う
'0 代入などの文脈に合わせた全ビット0。Verilogの複製記法より短く書ける
interface / modport 関連信号をまとめ、役割ごとのアクセス方向を表す
class / rand / randomize() 検証用のオブジェクトと制約付き刺激生成。ツールの対応範囲を確認
logic [7:0] data_q;
always_ff @(posedge clk or negedge rst_n)
    if (!rst_n) data_q <= '0;
    else        data_q <= data_d;

これは負論理非同期リセット付きの8ビットFFだよ。logic と書いても自動で回路が安全になるわけではなく、駆動元と更新条件の設計は必要。always_comb でも全経路に代入しよう。診断の厳しさはツールで異なるんだ。

always_comb begin
    case (sel)
        2'd0: out = a;
        2'd1: out = b;
        2'd2: out = c;
        default: out = '0;
    endcase
end

bus_if.data は宣言を調べて、interfaceの信号、構造体のメンバー、階層参照のどれかを確認しよう。ドットがあるだけでinterfaceと決めつけないでね。モジュール接続の .clk(clk) はポート名を指定する構文だよ。

input logic / output logic の宣言では方向と幅に加え、ネットか変数かの規則、どこから駆動するかも読む。クラス・ランダム制約はRTL設計の代わりではなく検証を組み立てる機能だよ。ランダム試験にも期待値、カバレッジ、再現用シードが必要なんだ。

5. 次の学習を選ぶ

最初は AND → カウンタとTB → 電子錠 の順に、ひとつずつ自分で実行しよう。その後、使うデバイスの公式資料を読み、ボードのクロックとI/O条件を確認して実機へ進むよ。

目標 次に確かめること
FPGAでセンサーや制御 UARTの送受信、SPIのクロック位相/極性、I2Cのオープンドレインと応答
データ処理・高性能FPGA パイプライン、valid/ready、同期FIFO、非同期FIFOとCDC
SoC接続 AXI4-Liteのレジスタアクセス、AXI4のバースト、AXI4-Streamの転送規則
ASIC/LSI設計 合成と制約、リセット、CDC、SystemVerilog設計、実装フロー
検証 自己判定TB、SystemVerilogの制約付きランダムとカバレッジ、必要に応じてUVMや形式検証

非同期FIFOのグレイコードは、ポインタ転送時の変化を扱いやすくする仕組みだよ。グレイコードだけでCDCが完成するわけではなく、同期化、full/empty判定、リセット、配線の制約まで学ぼう。通信やAXIも、信号名を覚えるだけでなく「いつ受理されたか」を仕様に沿って検証してね。

資料を調べる入口

対象の製品・バージョンの資料へ切り替えて確認してね。このサイトの実行確認は各実習に記した環境と範囲を示していて、すべてのツールや実機での動作を保証するものではないよ。

配布教材と検証範囲

各ZIPに回路、テストベンチ、実行手順をまとめたよ。Windows / Icarus Verilog 13.0でコンパイルとRTLシミュレーションを確認。合成・配置配線・FPGA実機の結果は含まないよ。PASSの範囲は各ページとREADMEで確認してね。

書き換えたコードでは、元の実行ファイルを使わずにコンパイルからやり直そう。テストの期待値まで回路の誤りに合わせないよう、仕様を基準に確認するんだ。

テーマから移管先を探す

noteの41本の無料原稿で扱っていたテーマを、教科書の各章へまとめた索引だよ。同じ話は重ねず、必要な補足と実験へつないでいるよ。

テーマ読む場所
学習の入口STの解説・実習
意図しないラッチO5の解説・実習
複数出力の代入漏れO5の解説・実習
Sim/SynthミスマッチO2の解説・実習
ラッチとD-FFL3の解説・実習
ブロッキングとノンブロッキングE2の解説・実習
HDL設計の全体像E3の解説・実習
RTLとテストベンチT1の解説・実習
Warningと論理合成E3の解説・実習
RTL・GLS・実機の違いT6の解説・実習
論理ゲートL1の解説・実習
ブール代数L1の解説・実習
真理値表L1の解説・実習
回路記号L1の解説・実習
タイミングチャートL1の解説・実習
代入順序とシフト動作O2の解説・実習
組合せ回路と順序回路L2の解説・実習
全加算器C3の解説・実習
論理式の簡単化L2の解説・実習
リップルキャリーC3の解説・実習
キャリー・ルックアヘッドC3の解説・実習
セレクタC1の解説・実習
7セグと条件漏れC2の解説・実習
ラッチの透過とFFL3の解説・実習
カウンタとクロックC6の解説・実習
シフトレジスタの遅延C6の解説・実習
タイミング制約S2の解説・実習
FSMの未使用状態O3の解説・実習
ゲートプリミティブの接続順E5の解説・実習
functionの戻り値幅E5の解説・実習
可変ビット選択と範囲E6の解説・実習
casexと未知値O6の解説・実習
ifの優先順位C2の解説・実習
wireとregE4の解説・実習
エンコーダとvalidC2の解説・実習
感度リストO2の解説・実習
ビット幅の不一致E4の解説・実習
X伝搬と検査T4の解説・実習
位置接続と名前付き接続C7の解説・実習
signedとunsignedE4の解説・実習
Xを含む比較O8の解説・実習