第1部: Implementationの始まり (Front-end Bridge)
序文: RTLコードがシリコンになるまでの、最初の関門
現代の半導体設計、特に数十億個のトランジスタが集積されるSoC(System on Chip)設計プロセスにおいて、「RTLコーディング」は巨大な旅の出発点に過ぎません。学部や修士課程でVerilog HDLを初めて学ぶ際に最もよくある誤解は 「テストベンチシミュレーションで波形(Waveform)が意図通りに出力されれば設計は完了した」と信じることです。

しかしシミュレーション環境は物理的制約が存在しない、理想的な論理世界です。
初めてデジタル工学を学び、Verilogハードウェア記述言語を学ぶ大学生は、 「これでチップ設計ができる!」と考えます。しかし大学院に進みテープアウトを経験するうちに、半導体の深い深淵に足を踏み入れることになるのです。
実際の半導体には、以下のような回路が膨大な数で組み込まれます。

そのような回路が非常に多く組み込まれており、

実際に生産された半導体上で電子が動き動作するチップを作るためには、タイミング、 電力、ノイズ、面積、そしてばらつきという厳しい物理的現実を克服しなければなりません。
本稿「実装の始まり(フロントエンドブリッジ)」では、RTLコードが合成ツールに入力される前後の段階について説明します。
Verilogコーディングスタイル:合成可能なコードか?
設計フローの最初の関門で学ぶのはVerilogコーディングスタイルです。
半導体設計は非常に複雑で、チップ製造には1000万米ドル以上が費やされ、製造後に修正する方法はありません。 そのため、「量産が可能な、非常に安全な方法のハードウェアコーディングが必要です。」

1. ハードウェアの本質: "コードではなく回路だ"
学生たちはVerilogをC言語のようなプログラミング言語と誤解します。しかし量産用設計の鉄則は以下の通りです。
- 物理の理解: 電子は移動に時間がかかります(Gate Delay + Net delay)。シミュレーションは'0'の時間で計算しますが、 実際のシリコンでは、温度や電圧によってこの時間が変化します。
- 単純さの美学: 華やかな文法はシミュレーション用です。実際のチップはCombination + Sequential logicの組み合わせに過ぎないことを肝に銘じる必要があります。
- 非常に良く作ってもSilicon Failureは発生します。 簡単に作らないと、原因のデバッグもできません。
2. シーケンシャルロジック(FF)設計ルール
フリップフロップはチップの骨格です。 最も保守的で標準的な構造のみが許可されます。もちろん、以下の約束を守らなくても、実際にチップの生産は可能です。
しかし、大企業では歩留まりを少しでも上げるため、Silicon failureが発生した場合に迅速に分析するために、非常に厳格なコーディングスタイルを採用しています。
- クロック/リセットの約束:
- Positive Edge Clock: セルライブラリの基礎であるため、
posedge clkのみを使用します。 1つのチップ内でnegedge clkを混在させることは推奨しません。- チップが完成する前に、すべての信号が時間通りに到達するかどうかを計算(スタティックタイミング解析)する必要があります。
posedgeとnegedgeを混在して使用すると、「ハーフサイクルパス」が発生し、タイミングマージンが半分に減少してしまいます。 - クロックのHigh区間とLow区間が正確に50:50でない場合(ジッタ/スキュー)、
posedgeとnegedgeが混在する区間でノイズ問題が発生する確率が高くなります。 - 実際、大企業ではこれよりも厳しい基準で設計します。 超高速通信ブロックを除き、ほとんどのシステムICは
posedgeで設計します。
- チップが完成する前に、すべての信号が時間通りに到達するかどうかを計算(スタティックタイミング解析)する必要があります。
- 非同期リセット: リセットは非同期で行いますが、可能であれば
negedgeを使用します。- 多くのファウンドリのライブラリセルは、アクティブロー非同期リセットに最適化されています。
- 確実な初期化: チップに電源が投入された瞬間(パワーアップ)、クロックがまだ安定していない状態でも、チップを安全な「アイドル」状態に強制的に固定するために、非同期リセットが好まれます。
- ノーゲーティング: クロックラインに直接論理ゲート(AND、OR)を接続せず、ファウンドリが推奨するICGを使用してください。
- グリッチ地獄: 一般的な
ANDゲートでクロックをオンオフすると、短いノイズが発生する可能性があります。 これがフリップフロップに入るとデータが破損し、チップは「原因不明の動作停止」状態になります。 - ファウンドリ公認: ICGセルは、ファウンドリが「これはグリッチよりもはるかに安全である」と保証した専用部品です。 大企業では、クロックラインに一般的なロジックゲートが1つでも混ざっていると、「Lint Error」として処理し、設計を却下します。
- グリッチ地獄: 一般的な
- Positive Edge Clock: セルライブラリの基礎であるため、
標準構文の遵守:Verilog
always @(posedge clk or negedge rst_n) begin if (!rst_n) data_q <= 8'd0; else data_q <= next_data;
end 3. 組み合わせ論理: regよりもwire
ご提出いただいた文書で最も強調されている部分です。always @(*)ブロック内でregを使用して組み合わせ回路を設計する方式には注意が必要です。
一般的なデジタル回路設計では、ラッチを使用せず、フリップフロップを使用します。
- 危険性:
always @(*)ブロックで条件文(if、case)の処理が不十分だと、意図しないラッチが生成されます。シミュレーションでは動作しても、実際の量産時に特定温度で動作が停止する原因となります。 - 安全な代替案: 可能な限り
assignとwireを使用した連続割り当て文 を使用してください。- Bad (避けるべき):
always @(*)内でregを使用した組み合わせ回路設計 (ラッチの危険性) - Good (Safe):
assign out = (cond) ? a : b;(物理回路が明確に見える)
- Bad (避けるべき):
4. FSM(状態マシン)設計の定石
量産用FSMは「華麗なcase文」ではなく「明確な信号分離」が核心です。
- 状態遷移と出力ロジックの分離:
- State Register:
alwaysブロック (Sequential) - Next State Logic:
assign文 (Combinational) - 出力ロジック:
assign文 (Combinational)
- State Register:
5. ミスを防ぐディテール
- ビット幅の一致:
10'd5をリセットする際に、9'd0と書くミスを絶対にしないでください。ツールが適当に調整してくれると期待した瞬間、量産は失敗します。 - デフォルト値の落とし穴: 「やらなくても大丈夫だろう」という考えは捨ててください。すべての
case文にはdefaultを、すべてのif文にはelseを記述し、回路のすべての経路を確定的(Deterministic)にしなければなりません。
おすすめ書籍: Verilog coding style for mass production

繰り返しになりますが、Verilogコーディングスタイルを守らなくても生産は可能です。しかし、歩留まりを少しでも上げ、量産失敗の可能性を少しでも低くし、失敗した場合は原因を少しでも見つけやすくするために、大企業がこのようなルールを適用しているのです。
- Reuse Methodology Manual (RMM): 最も有名な書籍
- STARC Design Style Guide: 日本の半導体だけでなく、韓国の半導体大手企業の日本留学エンジニアたちがこの本をもとにVerilogコーディングスタイルのルールを多く作成したと聞いています。
- Verilogの大家、Cliff Cummingsの発表論文。

以下はRTL Lintingです。 ソフトウェア開発におけるLintが単純な文法エラーやスタイルをチェックするレベルであるならば、ハードウェア設計におけるLintingは「このコードが実際の回路に変換可能か?」を問う生存の問題です。
シミュレータは文法的には許容されるものの、実際のハードウェアでは実装不可能、あるいは実装されたとしても致命的な不具合を引き起こすコードを寛容に受け入れます。このような「シミュレーションと合成の不一致(Simulation-Synthesis Mismatch)」を捕捉することがRTL Lintの核心的な目標です。1
1.1 シンセサイザビリティ:シミュレーションと物理的実装の乖離
合成ツール(例:Synopsys Design Compiler)は、RTLコードを読み込み、これをGTECH(Generic Technology)と呼ばれるツール内部の抽象的な論理ゲートに変換します。 この過程で最も頻繁に発生する問題は、設計者の意図とは異なるハードウェアが解釈される場合です。
1.1.1 ラッチ推論:意図しないメモリ素子の危険性
デジタル回路設計の禁忌の一つは、「推論されたラッチ」の生成です。 組み合わせ論理を記述する際、if文やcase文で全ての可能な条件に対する出力値を明示しないと、合成ツールは条件が明示されていない状況で前の値を保持すべきと判断します。組み合わせ回路は自ら値を保持できないため、ツールはデータを保持するために透過ラッチを強制的に挿入します。
なぜラッチを使わないのか?
- STA(静的タイミング解析)の複雑性増加: フリップフロップはクロックエッジでのみデータが移行するため、タイミング解析が明確です。 一方、ラッチはクロックが透過ウィンドウの間、入力変化が出力に伝達されるタイム・ボローイング特性を持っています。これはタイミング経路解析を非常に複雑にし、ツールがセットアップ/ホールド時間を正確に計算することを困難にし、タイミング・クロージャーを妨げます。
- DFT(Design for Test) カバレッジ低下: 量産テストのためのスキャンチェーン挿入時、ラッチは制御および観測が困難で、テストパターン生成を妨げ、フォールトカバレッジを低下させます。
- グリッチ伝播: ラッチのイネーブル信号がグリッチに晒された場合、意図しないデータが保存され、機能エラーを引き起こす可能性があります。
解決策: 防御的コーディングスタイル
最も確実な予防策は、すべてのalways_comb (SystemVerilog) またはalways @(*) (Verilog) ブロックの最上部にデフォルト代入を割り当てることです。 これにより、条件文で特定のパスが欠落してもデフォルト値が割り当てられるため、値を維持する必要がなくラッチが生成されません。
例1: enableが0のときにdata_outの定義がないためラッチが生成される
always @(*) begin if (enable) data_out = data_in;
end 例2: ブロック進入時に0で初期化するため、if文を経由しなくても値が決定される -> 組み合わせ論理(MUX)で合成
always_comb begin data_out = 1'b0; // デフォルト割り当て if (enable) data_out = data_in;
end
また、case文を使用する場合も、default構文を必ず含めて、未定義の状態を防ぐ必要があります。 default 構文がない場合、ツールは case 条件に該当しない入力が入力されたときに、以前の値を保持しようとしてラッチを生成します。
1.1.2 フルケースとパラレルケースの落とし穴: "邪悪な双子"
Verilog設計の歴史において最も議論を呼び危険なトピックの一つが、// synopsys full_case parallel_caseのようなSynthesis Pragmaの使用です。著名なVerilog専門家Clifford Cummingsはこれを"The Evil Twins of Verilog Synthesis"と名付け、その危険性を警告しました。
これを上手に使えばコードは少し短くなりますが、私自身も使用しないスタイルです。Synthesis Pragmaというものが存在するという程度に留めておいてください。


通常、大学の研究室にも小さなVerilogコーディングスタイルがあります。
スタートアップにもあり、大企業になるほどより強力なVerilogコーディングスタイルが存在し、そのコーディングスタイルを検査するチェッカーもあります。
次の記事ではRTL Lintについて見ていきましょう。