論理合成を実際にやってみる

(1) ここで学ぶ内容

概要

  • 論理合成の動作を理解し、論理合成の方針立てについて学ぶ
  • 階層やクロックスキューなどの対処方法について学ぶ

目標

以下の項目を理解し説明できる

  • 論理合成の方針
  • 論理式とゲートの最適化
  • 平坦化と構造化
  • 階層合成
  • クロックスキューとその対策

LSIの開発に論理合成ツールを使う場合は今まで学んだこと以外に注意すべきことがあります。ここでは大規模な回路を論理合成するときに考え方や注意点を教えます。

(2) 論理合成の方針

  • チップ全体の中で、論理合成対象と対象外のブロックに分ける
  • 論理合成対象外のブロックは、最上位階層で接続する
  • 回路検証(RTL検証、ゲートレベル検証)は、チップ全体で行う
論理合成対象ブロック
論理合成対象外ブロック
チップ全体
ユーザ回路ブロック
CPUハードマクロ
ROM/RAMハードマクロ
I/Oバッファ

LSIを開発する場合、論理合成ツールはすべての回路を合成できるわけではありません。

論理合成できる部分とできない部分を切り分けなければなりません。

論理合成できない部分はASICベンダが提供するメモリやCPUなどのハードマクロ、パッドを含めたI/Oバッファです。

論理合成できるのはHDLで作成したユーザ回路ブロックです。

これらのブロックは最上位階層で接続し、LSI全体のネットリストを完成させます。

回路の検証は論理合成前と後にチップ全体で行います。

ASICベンダのハードマクロを使用する場合には、検証用のモデルを提供してもらいましょう。

(3) 論理式とゲートの最適化

always @( posedge CK
        or posedge RES )
begin
    if ( RES==1'b1 )
        Q <= 8'h00;
    else
        Q <= Q + 8'h01;
end

最適化は
論理式の最適化
ゲートレベルの最適化
の2段階で行われる

回路の最適化は compile コマンドを使用

        graph TD
            V[~.v] --> COM[compile]
            DB[~.db] --> COM
            COM --> FLAT[平坦化]
            FLAT --> STRUC[構造化]
            STRUC --> GATE[ゲート最適化]
            COM --> GATE
            GATE --> OUT1[平坦化合成]
            GATE --> OUT2[構造化合成]
            GATE --> OUT3[インクリメンタル合成]
        

論理式の最適化には
平坦化
構造化
の2つの方法がある

compile -incremental

回路の最適化には compile コマンドを使用します。

compile コマンドは論理式の最適化とゲートレベルの最適化の2段階で最適化を行います。

論理式の最適化には平坦化と構造化の2種類があります。平坦化は同時に構造化も行います。

それぞれ平坦化:set_flatten コマンド、構造化:set_structure コマンドを使用します。

compile コマンドを実行すると論理式の抽出をして論理式の最適化を行います。

その後ゲートマッピングを行いゲートの最適化をします。

合成済みの回路に対して2回目以降の最適化を行う場合には、コンパイルコマンドにインクリメンタルオプションをつけて最適化を行います。

インクリメンタルオプションをつけると論理式の最適化は行わずにゲートレベルの最適化のみ行います。

論理式レベルの最適化を2回目以降に行うと結果が悪くなることがあります。

2回目以降の最適化はゲートレベルのみで行うようにしましょう。

(4) 平坦化と構造化

Y = A ⊕ B ⊕ C

平坦化

  • 回路を2段論理で構成
  • 回路規模は増大する
  • 遅延時間は小さい
        graph LR
            A((A))
            B((B))
            C((C))
            Y((Y))
            
            notA[INV]
            notB[INV]
            notC[INV]
            
            A --> notA
            B --> notB
            C --> notC
            
            and1[AND]
            and2[AND]
            and3[AND]
            and4[AND]
            
            A --> and1
            B --> and1
            C --> and1
            
            notA --> and2
            notB --> and2
            C --> and2
            
            A --> and3
            notB --> and3
            notC --> and3
            
            notA --> and4
            B --> and4
            notC --> and4
            
            or1[OR]
            
            and1 --> or1
            and2 --> or1
            and3 --> or1
            and4 --> or1
            or1 --> Y
        

構造化

  • 回路を多段論理で構成
  • 回路規模は小さくなる
  • 遅延時間が大きくなりやすい
        graph LR
            A((A))
            B((B))
            C((C))
            Y((Y))
            
            notA1[INV]
            notB1[INV]
            and1[AND]
            and2[AND]
            or1[OR]
            
            A --> notA1
            B --> notB1
            notA1 --> and1
            B --> and1
            A --> and2
            notB1 --> and2
            and1 --> or1
            and2 --> or1
            
            notX[INV]
            notC1[INV]
            and3[AND]
            and4[AND]
            or2[OR]
            
            or1 --> notX
            C --> notC1
            notX --> and3
            C --> and3
            or1 --> and4
            notC1 --> and4
            and3 --> or2
            and4 --> or2
            or2 --> Y
        

論理式の最適化には平坦化と構造化の二つの方法があります。

平坦化とは回路を2段階論理で構成する方法です。

例としてA、B、Cの3つの変数の排他的論理和を求める回路を考えてみましょう。

2段論理の回路はANDゲートとORゲートの二段で回路を構成することができます。

このため回路規模は大きくなりますが、遅延時間は小さくなります。

構造化とは回路を多段論理で構成する方法です。

多段論理で回路を構成した場合、平坦化した回路にくらべ回路規模は小さくなりますが、ゲートの段数が増えるため遅延時間は大きくなります。

平坦化するためのコマンドは set_flatten、構造化のコマンドは set_structure です。

これらのコマンドの特徴をよく理解し、状況に応じて使い分けてください。

(5) 階層合成

入力遅延値
ドライブ能力
➡
CLOCK24
MIN
BCD60
─
HOUR
BCD24
➡
出力遅延値
負荷容量
下位階層が合成済みでも上位階層の条件に合うように再合成が必要

階層をもった回路を論理合成する場合を24時間時計CLOCK24を例に考えてみましょう。

このCLOCK24は下位階層として二つのモジュールがあります。

分のカウンタMIN、時間のカウンタHOURの二つです。

CLOCK24はこの二つのモジュールを接続して構成されています。

下位階層と上位階層の最適化の制約条件は違うので上位階層の制約条件を設定して再度最適化します。

この場合下位階層はすでにゲート回路になっているので、compile –incremental コマンドでゲートレベルの最適化のみ行います。

(6) 階層合成用のコマンド

下位階層に同じモジュールが複数個ある場合、compile コマンドは動作しない

BCD60が2個あるので最適化できない

CLOCK24
SEC
BCD60
─
MIN
BCD60
─
HOUR
BCD24

ungroup

最良の結果が得られるが、合成時間が長い

CLOCK24
D-FF ─ D-FF ─
HOUR
BCD24

※SECとMINの枠が消え、フラットになっている

uniquify

set_dont_touch コマンドよりも合成時間が長い

CLOCK24
SEC
BCD60_0
─
MIN
BCD60_1
─
HOUR
BCD24

set_dont_touch

uniquify コマンドに比べて合成時間が短い

CLOCK24
SEC
BCD60⃠
─
MIN
BCD60⃠
─
HOUR
BCD24

回路を論理合成するとき、下位階層で同じモジュールが複数個ある場合は compile コマンドは動作しません。

前のページの24時間時計CLOCK24に秒のカウンタSECを追加した例をみてみましょう。

このCLOCK24は下位階層として3つのモジュールがあります。

これらの下位階層は論理合成済みです。

この中でSECとMINはBCD60という同じモジュールで構成されています。

このように同じモジュールが2個ある場合には、このままでは最適化できません。

このような場合最適化するための3つのコマンドがあります。

uniquify コマンド、ungroup コマンド、set_dont_touch コマンドです。

uniquify コマンドは複数つかわれているモジュールをコピーして違う名前のモジュールを作ります。

この例ではBCD60をコピーしてBCD60_0とBCD60_1という二つのモジュールをつくります。

ungroup コマンドは複数使われているモジュールを指定して階層を破壊し、フラットな回路にします。

set_dont_touch コマンドは複数使われているモジュールを指定して、最適化の対象から外します。

これらの方法はそれぞれ長所、短所があります。

set_dont_touch → uniquify → ungroup の順で合成時間が長くなります。

回路規模や遅延時間などの回路品質は ungroup が一番よく、uniquify、set_dont_touch と続きます。

※後述の実測値で、面積だけを見ると set_dont_touch(339)が最小ですが、これはタイミング制約を満たせていない(スラック −19.45ns)回路のままだからです。制約を満たした2つで比べると ungroup(430)のほうが uniquify(441)より小さく、遅延時間は同じです。

下位階層がすでに十分最適化されている場合など状況に応じて、set_dont_touch コマンドを使用しましょう。

これらの特徴をよく理解して状況に応じて使い分けましょう。

(7) クロックスキューとは

クロックスキュー
配線長の違いなどで FF ごとにクロック信号のタイミングがずれる現象
チップ全体
    graph TD
        CLK((CLK)) --> BUF[INV]
        BUF --> N1(( ))
        N1 --> FF1[FF]
        N1 --> N2((赤い点))
        N2 --> FF2[FF]
        
        style N2 fill:red,stroke:red
        style FF1 fill:#b3e5fc
        style FF2 fill:#b3e5fc
    
クロックスキューは
誤動作の原因になる

クロックの配線の長さの違い等によりフリップフロップごとにクロック信号のタイミングがずれることをクロックスキューといいます。

このクロックスキューは回路の誤作動の原因になります。

クロックスキューがどのような誤作動を引き起こすかみてみましょう。

クロックのずれなし(正常)

        graph LR
            D((D)) --> U1[U1]
            U1 --> U1Q((U1Q))
            U1Q --> U2[U2]
            U2 --> Q((Q))
            
            CLK((CLK)) --> inv1[INV]
            inv1 --> inv2[INV]
            inv2 --> U1
            
            CLK --> inv3[INV]
            inv3 --> inv4[INV]
            inv4 --> U2
        

タイミング

  • D       : __/‾‾‾‾\__
  • U1のクロック: _/‾\_/‾\_
  • U1Q     : ____/‾‾‾‾\
  • U2のクロック: _/‾\_/‾\_
  • Q       : ________/‾

クロックのずれあり(誤動作)

        graph LR
            D((D)) --> U1[U1]
            U1 --> U1Q((U1Q))
            U1Q --> U2[U2]
            U2 --> Q((Q))
            
            CLK((CLK)) --> inv1[INV]
            inv1 --> inv2[INV]
            inv2 --> U1
            
            CLK --> U2
        

タイミング

D _____/‾‾‾‾‾‾‾‾‾‾\_____
U1のクロック ___/‾‾‾\___/‾‾‾\___
U1Q ________/‾‾‾‾‾‾‾‾‾‾\__
U2のクロック _____/‾‾‾\___/‾‾‾\___
Q __________/‾‾‾‾‾‾‾‾‾‾\
クロックのずれ

左はクロックスキューがない場合の動作です。

クロック信号は二つのフリップフロップに同時に到着します。入力Dはクロックの二回目の立ち上がりエッジ後に出力Qに伝わります。

それに対して右はクロックスキューがある場合の動作です。

U2に対するクロック信号が遅れると入力DがU1Qに伝わった後で、U2のクロックが立ち上がり出力Qが変化します。

一つのクロックの立ち上がりで二つのフリップフロップをデータが突き抜け誤動作しています。

このようにクロックスキューは回路の誤動作の原因になるので対策が必要です。

もふねこ

もふねこ:
クロックスキュー(Clock Skew)は、大きなLSIを作るときに絶対避けられない「タイミングのズレ」のことだよ🐾
ツールに「スキューがある前提で安全に作ってね」って教える set_clock_uncertainty と set_fix_hold は、実務でも必須のおまじないだから、しっかり覚えておこうね!

(8) クロックスキューによる誤動作防止

クロックスキューによる誤動作を防止するためのコマンド

  • set_clock_uncertainty スキュー値 クロック名
    スキューの値を与える
  • set_fix_hold クロック名
    スキューによる誤動作を回避するために遅延を調整する
    graph LR
        D((D)) --> U1[U1]
        U1 --> buf1[BUF]
        buf1 --> buf2[BUF]
        buf2 --> U2[U2]
        U2 --> Q((Q))
        
        CLK((CLK)) --> inv1[INV]
        inv1 --> inv2[INV]
        inv2 --> U1
        
        CLK --> inv3[INV]
        inv3 --> inv4[INV]
        inv4 --> U2
    
大規模な回路では必ずクロックスキューが発生する ➡ set_clock_uncertainty と set_fix_hold は 必ず設定する

クロックスキューによる誤動作を防止するためのコマンドを紹介します。

一つは set_clock_uncertainty コマンドです。これはクロックスキューの値を与えるコマンドです。クロックスキューの値を推定し、このコマンドで設定します。このコマンドを指定しないとクロックスキューの値は0になります。

もう一つは set_fix_hold コマンドです。これはクロックスキューによる誤動作を回避するために遅延を調整するコマンドです。

これらのコマンドを設定すると論理合成ツールは必要な部分に誤動作防止用にバッファを挿入します。

大規模な回路ではスキューの発生は避けられないので、この二つのコマンドは必ず設定しましょう。

どちらか一方だけの設定ではバッファは挿入されません。

(9) 確認問題1:平坦化 vs 構造化

確認問題 7セグメントデコーダの記述を平坦化合成と構造化合成をしたとき、結果にどのような違いが出るだろうか?
以下の合成結果レポートを見て、回路規模と遅延時間の違いを確認しよう。
SEG7
Y
/
4
A
B
C
D
E
F
G
A F B G E C D
Y Y
0000 0 1000 8
0001 1 1001 9
0010 2 1010 A
0011 3 1011 b
0100 4 1100 c
0101 5 1101 d
0110 6 1110 E
0111 7 1111 F
平坦化回路記述 : seg7_flatten.v
平坦化スクリプト : seg7_flatten.scr
構造化回路記述 : seg7_structure.v
構造化スクリプト : seg7_structure.scr
平坦化
(flatten)
構造化
(structure)
回路規模
53
52
遅延時間
14.10
21.16

合成結果レポートの確認

平坦化 (flatten) のレポート

****************************************
レポート : area
回路     : SEG7_FLATTEN
****************************************

ポート数:                11
ネット数:                37
セル数:                  33
セル種類:                 8

組み合わせ回路:           53
非組み合わせ回路:          0

合計:                     53

****************************************
レポート : timing
回路     : SEG7_FLATTEN
****************************************

ライブラリ:      hd350s
配線遅延モデル: hd350s_05k
コンディション: MAX567

-----------------------------------------------------------
Y[0] (in)                               0.00       0.00
D (out)                                 0.00      14.10
データ到着時刻                                      14.10
-----------------------------------------------------------
平坦化 (flatten) 回路図の構造詳細(img_11)
  • 入力ポート: Y[3:0] (左端に配置)
  • 出力ポート: A, B, C, D, E, F, G (右端に配置)
  • 構造的特徴: 多数のANDゲートとORゲートが並列に並び、入力から出力までの経路が浅い「2段論理」構造。
  • 結線状態: 各入力 Y[3]〜Y[0] とその反転信号が、中央の多数のANDゲートに分配され、その出力が最終段のORゲートで集約されて各セグメント(A~G)に出力される。回路図全体が縦に非常に長く、平坦な構成。

構造化 (structure) のレポート

****************************************
レポート : area
回路     : SEG7_STRUCTURE
****************************************

ポート数:                11
ネット数:                41
セル数:                  37
セル種類:                11

組み合わせ回路:           52
非組み合わせ回路:          0

合計:                     52

****************************************
レポート : timing
回路     : SEG7_STRUCTURE
****************************************

ライブラリ:      hd350s
配線遅延モデル: hd350s_05k
コンディション: MAX567

-----------------------------------------------------------
Y[0] (in)                               0.00       0.00
B (out)                                 0.00      21.16
データ到着時刻                                      21.16
-----------------------------------------------------------
構造化 (structure) 回路図の構造詳細(img_12)
  • 入力ポート: Y[3:0] (左下端に配置)
  • 出力ポート: F, G, E, D, B, A (右端に分散して配置)
  • 構造的特徴: ゲートが横方向に何段も連なる「多段論理」構造。回路図全体が階段状に深い階層を持っている。
  • 結線状態: 共通の論理式(サブ式)が抽出され、あるゲートの出力が次のゲートの入力として再利用されるため、入力から出力までの経路が長く、入り組んだ接続となっている。

(10) 確認問題2:24時間時計の合成比較

確認問題 24時間時計の記述を3種類の合成スクリプトで合成したとき、結果にどのような違いが出るだろうか?
以下の合成結果レポートを見て、回路規模と遅延時間の違いを確認しよう。
回路記述1 : clock24_dont_touch.v
スクリプト1: clock24_dont_touch.scr
回路記述2 : clock24_uniquify.v
スクリプト2: clock24_uniquify.scr
回路記述3 : clock24_ungroup.v
スクリプト3: clock24_ungroup.scr
CLOCK24
SEC
BCD60
─
MIN
BCD60
─
HOUR
BCD24
スクリプト1
(dont_touch)
スクリプト2
(uniquify)
スクリプト3
(ungroup)
回路規模
339
441
430
遅延時間
37.65
18.19
18.19

合成結果レポートの比較

スクリプト1:set_dont_touch合成

dont_touch 回路図の構造詳細(img_15)
  • 入力ポート: CLK(logic_1), RESET, MODE24
  • 出力ポート: SECLSB[3:0], MINLSB[3:0], MINMSB[2:0], HOURLSB[3:0], HOURMSB[1:0], SECMSB[2:0]
  • 構造的特徴: BCD60COUNT (SEC用), BCD60COUNT (MIN用), BCD24COUNT (HOUR用) の3つの大きなブラックボックスがそのまま維持されている。階層構造は破壊されていない。
  • 結線状態: 1段目のBCD60COUNTのキャリー出力が、2段目のBCD60COUNTの入力へ直列に繋がり、さらに3段目のBCD24COUNTへ繋がる構成。
****************************************
レポート : area
回路     : CLOCK24
****************************************
ポート数:                23
ネット数:                27
セル数:                   4
セル種類:                 3
組み合わせ回路:          158
非組み合わせ回路:        181
合計:                    339
****************************************
レポート : timing
回路     : CLOCK24
****************************************
クロック CLK (rise edge)                0.00       0.00
HOUR/LSB_reg[3]/D (FD2)                 0.00      37.65
データ到着時刻                                      37.65

クロック CLK (rise edge)                20.00      20.00
クロックスキュー                        -1.00      19.00
ライブラリのセットアップタイム          -0.80      18.20
データ到着要求時刻                                 18.20
-----------------------------------------------------------
データ到着要求時刻                                 18.20
データ到着時刻                                    -37.65
-----------------------------------------------------------
タイミング余裕                                    -19.45

スクリプト2:uniquify合成

uniquify 回路図の構造詳細(img_18)
  • 入力ポート: CLK(logic_1), RESET, MODE24
  • 出力ポート: MINLSB[3:0], MINMSB[2:0], HOURLSB[3:0], HOURMSB[1:0], SECLSB[3:0], SECMSB[2:0]
  • 構造的特徴: dont_touch時と同じく3つのブラックボックスがあるが、1段目の名前が「BCD60COUNT_1」、2段目が「BCD60COUNT」となっており、同じモジュールが別々の名前(固有化)として展開されている。
****************************************
レポート : area
回路     : CLOCK24
****************************************
ポート数:                23
ネット数:                26
セル数:                   3
セル種類:                 3
組み合わせ回路:          251
非組み合わせ回路:        190
合計:                    441
****************************************
レポート : timing
回路     : CLOCK24
****************************************
クロック CLK (rise edge)                0.00       0.00
HOUR/LSB_reg[2]/D (FD2)                 0.00      18.19
データ到着時刻                                      18.19

クロック CLK (rise edge)                20.00      20.00
クロックスキュー                        -1.00      19.00
ライブラリのセットアップタイム          -0.80      18.20
データ到着要求時刻                                 18.20
-----------------------------------------------------------
データ到着要求時刻                                 18.20
データ到着時刻                                    -18.19
-----------------------------------------------------------
タイミング余裕                                      0.01

スクリプト3:ungroup合成

ungroup 回路図の構造詳細(img_21)
  • 入力ポート: CLK(logic_1), RESET, MODE24 (左端に配置)
  • 出力ポート: MINLSB[3:0], MINMSB[2:0], HOURLSB[3:0], HOURMSB[1:0], SECLSB[3:0], SECMSB[2:0] (右端に配置)
  • 構造的特徴: BCD60COUNTなどの階層枠(ブラックボックス)が完全に消滅し、すべてのフリップフロップと組み合わせ論理(AND, OR, INVなど)が平坦に展開されている。
  • 結線状態: 回路全体にわたって細かいゲートが数百個レベルで複雑に絡み合う、非常に巨大な多段ゲート回路となっている。遅延時間が大幅に最適化(37.65 → 18.19)されているのが視覚的にも複雑さから読み取れる。
****************************************
レポート : area
回路     : CLOCK24
****************************************
ポート数:                23
ネット数:               111
セル数:                  91
セル種類:                23
組み合わせ回路:          240
非組み合わせ回路:        190
合計:                    430
****************************************
レポート : timing
回路     : CLOCK24
****************************************
クロック CLK (rise edge)                0.00       0.00
HOUR/LSB_reg[2]/D (FD2)                 0.00      18.19
データ到着時刻                                      18.19

クロック CLK (rise edge)                20.00      20.00
クロックスキュー                        -1.00      19.00
ライブラリのセットアップタイム          -0.80      18.20
データ到着要求時刻                                 18.20
-----------------------------------------------------------
データ到着要求時刻                                 18.20
データ到着時刻                                    -18.19
-----------------------------------------------------------
タイミング余裕                                      0.01