yosysへの入力Verilog-HDL記法
yosysで論理合成する際に,タイミングエラーになる条件を洗い出す.
FO4を意識した実装をすることでタイミングエラーを回避する.
FO4(Fan-Out of 4)と製造プロセス
- Fan-Out
- ある出力が駆動する負荷の大きさを「同じゲート何個分か」で表したもの.
- 出力が次段のゲート入力をいくつ駆動するか,という扇型(fan)に広がる接続数のこと.
- FO4は遅延の単位.
- ただし絶対時間(ps)でなく相対的な遅延の単位.
- FO4の定義
- 「あるインバーターが,自分同じインバーター4個分の負荷を駆動するときの遅延.」これを基準の遅延とする.
- 「基準インバーター遅延の何倍か」という倍数で表している.
- psで書くとプロセス依存で遅延の値が変わるが,FO4数(18や54.3)は論理構造で決まりプロセスが変わってもほぼ一定.
- 「論理がどれだけ深いか」と「1段が何
ps速いか」を分離できる. - 考え方の例
- ある部屋があるとき「18歩」分だととして,歩数(18)は部屋の広さで決まり誰が歩いても同じ.
- 1歩が何秒かは歩く人(=プロセス)で変わる.
- 所要時間(秒)=1歩の秒数.FO4数=歩数,1歩の秒数=
ps/FO4.
- 「論理がどれだけ深いか」と「1段が何
- プロセスの数値(
30ps/18ps/.../5ps)は回路の遅延ではなく,「1FO4が何psか」という換算レート.- FO4数は論理構造のみで決まるためプロセス非依存.
- 以下サンプルコードでは54.3FO4.
- 1FO4の
psは製造プロセスで決まり設計非依存.- 微細・新しいプロセスほどインバーターが速く,1FO4が少ない
psでこれが「65nm:30ps,...,2nm:5ps」
- 微細・新しいプロセスほどインバーターが速く,1FO4が少ない
- FO4数は論理構造のみで決まるためプロセス非依存.
-
実際の遅延(ns)=FO4数×1FO4のps
-FO4と1FO4のpsを掛け算で初めて絶対時間となり,以下サンプルでは54.3FO4となる.
製造プロセスにおけるFO4の遅延目安
| 製造プロセス | 1 FO4のps目安 |
|---|---|
| 2nm | ~5ps |
| 3nm | ~6ps |
| 5nm | ~7ps |
| 7nm | ~8ps |
| 10nm | ~10ps |
| 16nm | ~12ps |
| 28nm | ~18ps |
| 65nm | ~30ps |
FO4構文対応表
| 構文 | おおよそのFO4 | 備考 |
|---|---|---|
| 構文おおよそのFO4備考2入力ゲート(AND/OR/XOR) | ~1.3 FO4 | 基本単位 |
2:1 mux / 単発 if( ) 選択 |
~1.5–2 FO4 | if 1個=mux 1個 |
N:1 mux(case=並列) |
~log₂N × 1.5 FO4 | 16:1 ≈ 6 FO4 |
if-else 連鎖(M分岐=優先) |
~M × 1.5 FO4 | これが高い。16分岐≈24 FO4 |
Nbit 等価比較 ==
|
~(log₂N+1) × 1.3 FO4 | 32bit ≈ 8 FO4 |
Nbit 大小比較 <
|
~5–7 FO4(32bit) | 加算器並み |
| Nbit 加算(合成器=prefix) | ~4–6 FO4 | 32bit≈5。意外に浅い |
| Nbit 加算(ripple) | ~N FO4 | ツールは普通使わない |
| バレルシフタ Nbit | ~log₂N × 1.5 FO4 | 32bit ≈ 8 FO4 |
| N×N 乗算 | ~15–25 FO4 | 16×16≈18。桁違いに重い |
一般的なFO4について
周波数を製造プロセス上限に対してどれだけ攻めるかで大きく変わるが、代表的な目安.
| 設計クラス | 1段あたり論理(FO4) | 性格 |
|---|---|---|
| 性能最適(理論値) | 6〜8 FO4 | スループット最大の点 |
| 実際の高性能CPUコア | ~12〜25 FO4 | 上記より深め(電力・複雑度の都合) |
| 電力考慮の最適 | ~20〜25 FO4 | 段を減らし1段を厚く=低電力 |
| 一般的なASIC/SoC | ~30〜60 FO4 | 周波数を攻めないので1段に多く積む |
Fmaxについて
Fmax=Maximum Frequency(最大周波数)の略で,回路がタイミング違反を起こさずに動ける上限のクロック周波数のこと.
- 定義
Slack = 0となる点 = Fmax
Fmax(MHz) = 1000 ÷ (実遅延 + オーバーヘッド)
= 1000 ÷ (パス遅延 + t_cq + t_setup + uncertainty)
- Fmaxの周波数値までは全パスが間に合う(MET).
- Fmaxの周波数値を超えると周期が足りない(VIOLATION).
- Fmaxは一番遅いパス(クリティカルパス)で決まる.
- クリティカルパスの遅延で決まる.
- 使い方
-
目標周波数≦Fmaxなら,回路はそのプロセスで目標を満たせており回路修正不要. -
目標周波数>Fmaxなら,回路をパイプライン化などでバス遅延を縮めてFmaxを引き上げる修正が必要.
-
オーバーヘッドについて
オーバヘッドはクロック周期Tの内,組み合わせ論理に使えない固定の取り分で3つの項の合算.
| 項 | 中身 | 記載箇所 | 目安 |
|---|---|---|---|
| t_cq | 起点フリップフロップのclk→Q遅延 | .libから読む | ~0.04[ns] |
| t_setup | 終点フリップフロップのsetup時間 | .libから読む | ~0.03[ns] |
| uncertainty | skew + jitter + margin | set_clock_uncertaintyで置く | ~0.08[ns] |
| 合計 | - | - | ~0.15[ns] |
Fmax算出式で実遅延(パス遅延)に0.15[ns]を加算しているのは,これら組み合わせ論理に使えない固定の取り分を加算し回路の上限クロック周波数を出せる.
なお,目安の値は概算でt_cqおよびt_setupはセル遅延のため,速いノード(2nmなど)であれば0.15nsより小さくなる.以降では,簡略化のため一律0.15nsにして算出する.
- 起点フリップフロップのclk→Q遅延
- clock-to-Q delayのこと.
- フリップフロップのクロックエッジが出てから出力Qが新しい値になるまでの遅延.
- 「Q」はフリップフロップの出力ピン名(D=入力,Q=出力).
- クロックが来た瞬間に出力が変わるわけではなく,内部のトランジスタを通る分だけ遅れる.
- Q遅延はフリップフロップの.libに書いてある値で,CK→Qのタイミングアークとして格納されている.
- 負荷やslewで多少変わり,STAがテーブルから引いて使う.
- 終点フリップフロップのsetup時間
- データを受け取る側(終点)のフリップフロップが,クロックエッジの前にデータを安定させておく必要がある時間.
- 終点フリップフロップはクロックエッジでデータを取り込み,そのエッジが来る少し前から入力Dが変化せず安定している必要があり,それに必要な時間がsetup時間.
- エッジの直前にデータがまだ動いていると,フリップフロップが正しく値を捕まえられない(あるいは準安定=メタステーブルとなる).
- 「エッジのt_setup前までにデータを届けること」という制約となる.
- setup時間はフリップフロップセルの**.libに書いてある**制約値で,CK↑に対するDの拘束として格納されている.
- 入力データやクロックのslewで変わり,STAがテーブルから引いて使用する.
- uncertainty
- クロックの不確かさ
- 「クロックエッジが理想通りに来ない」分を見込む安全余裕で原因が複数ある.
- skew=クロックが場所によって着く時刻がズレる
- 同じクロックエッジが,起点フリップフロップと終点フリップフロップに着く時間の差.
- 原因
- クロックを全フリップフロップに配る配線(クロックツリー)の長さや負荷が,フリップフロップ毎に異なるため.
- チップ上の近いフリップフロップと遠いフリップフロップで,物理的に到着時間が揃わない.
- 決め方
- CTS(クロックツリー合成前)は実配線がないため,想定する最悪スキューを見積もって置く(実測値ではない).
- CTS完成後にこれくらいにおさまるだろうという目標値で置く.
- 方法①:周期に対する割合で置く(最初期の定番)
- 設計したクロックツリーのスキューは周期の数%に収まることが多いため,その目安で置く.
- プロジェクト標準や過去設計の実績値があればそれを使う.
- 根拠は弱いが当たりをつけるには十分.
- 方法②:過去の類似設計の実測スキューを流用
- 同じプロセス・同じツール・近い規模の過去プロジェクトでCTS後に出た実スキューを,そのままもしくは少し悲観側に持って置く.
- ライブラリー・フロー・フリップフロップ数が近いほど精度が高い.
- 社内に「このノードのこの規模ならスキューn[ps]」という蓄積があれば,それが最も信頼できる初期値.
- 方法③CTSの想定段数から見積もる
- スキューの要因はクロックバッファの段数ばらつきのため,ツリーの深さから概算できる.
skew = (バッファ1段の遅延ばらつき) × (ツリー段数)- フリップフロップからツリーの段数を見積もる(フリップフロップが多いほど深い).
- 1段当たりの遅延ばらつき(OCV/負荷差)を掛ける.
- 「絶対遅延が大きいツリーほどスキューも大きい」という比例関係を使う近似.
- 方法④:ディレート/OCVを併用する(より精密)
- スキューを固定値で置く代わりに,クロックパスにディレート(タイミング劣化係数)を掛けて,ばらつきを表現.
- CTS後は実際のクロックツリーができるため,本物のskewがSTAに入る.
- 本物のskewがSTAに入ると,uncertaintyからskew分は外し,jitter中心に減らせる.
- CTS(クロックツリー合成前)は実配線がないため,想定する最悪スキューを見積もって置く(実測値ではない).
- jitter=クロックエッジの間隔が毎サイクル揺れる
- クロック周期そのものが一定でなく,サイクル毎で微妙に伸び縮みする分.
- 原因
- クロックを作るPLL/発振器の電気的なゆらぎ(電源ノイズ,位相雑音など).
- 配線ではなくクロック源側の問題のため,CTSをしても消えない.
- 決め方
- クロック源(PLL)のスペックから決まる固定値で,データシートのジッタ値を見込む.
- skewと異なりレイアウトが進んでも残るため,最後までuncertaintyに残る項.
- margin=解析で捉えきれない誤差への保険
- skew/jitterのような物理的に定義できる量ではなく,「単一コーナーのSTAでは見えない不確実性」へのガードバンドとして設計者が積む余裕.
- 何を積むか
- OCV(On-Chip-Valiation):オンチップばらつき(同じチップ内でもセル毎に速さが異なる)
- 同じチップの中でも,セルやネットの実遅延が場所毎に異なる現象.
- 原因
- 製造ばらつき(トランジスタの微妙な個体差),電源電圧の局所(IRドロップ),温度の局所差.
- 結果
- 設計上は同じはずのバッファでも,チップAの左端と右端で速さが異なる.
- 1つのPVTコーナーの代表値だけではこの局所差を表せない.
- P(Process/プロセス)は製造ばらつき.トランジスタが「速くできたロット/遅くできたロット」の差.
- V(Voltage/電圧)は電源電圧.高いほど速く,低いほど遅い.
- T(Temperature/温度)は動作温度.一般に高温ほど遅い(先端ノードでは逆転もあるが基本は高温=遅い).
- STAは「この回路がどんなPVT条件でもタイミングを満たすか」を確認する必要があるため,複数のPVT条件で解析する.PVTの組み合わせ毎にライブラリーは特化されている.この内容は別途まとめる予定.
- モデル誤差(NLDM近似,レイアウト前の配線推定の誤差)
- 経年劣化(aging),電圧/温度ドリフト
- ECO(後からの修正)用ヘッドルーム
- OCV(On-Chip-Valiation):オンチップばらつき(同じチップ内でもセル毎に速さが異なる)
- 決め方
- 設計者が選ぶ.
- 固定値(例:0.05ns)を置くこともあれば,クロック遅延の%(例:クロック遅延の15%)で置くこともある.
- フェーズが進むほど,確度が上がるため小さくできる.
- skew=クロックが場所によって着く時刻がズレる
Slackについて
Slackは2つの層で考える.
- Slackそのものは「計算結果」で選ぶものではない.
- STAがこれを以下で算出し,正ならMET,負ならVIOLATION.
- 「予算-実遅延」がこのSlackで,自分で決めた値ではなくパス遅延から算出する.
Slack = Required(必要時間) − Arrival(到達時間)
= (T - t_setup - uncertainty) - (t_cq + パス遅延)
-「どれだけ正のSlackを残すか(=マージン)」が設計判断
- Slackは0を狙わず,正のマージンを残す.
- これは、単一コーナーのSTAでは捉えきれない要素を吸収するため.
- 合成/レイアウト前
- P&Rと寄生で取られる前提で,大きめの正Slackを残す.
- クロック不確かさ(set_clock_uncertainty)を周期の数%多めに置くなど.
- サインオフ
- 全MMMCコーナー(PVTコーナーのこと)で Slack≧0(多くは小さな正のマージン込み)を満たすようにする.
- マイナスになるとチップになるとデータの取り込みが失敗して誤った値が回路に入る.
- チップが取りうる複数の動作状態のことで,同じチップでもモードによってクロックや有効パスが変わる.
- モード×コーナーの全組み合わせでタイミングが成立しないと出荷はできない.
- 全MMMCコーナー(PVTコーナーのこと)で Slack≧0(多くは小さな正のマージン込み)を満たすようにする.
- 合成/レイアウト前
サンプルのVerilogおよびコメントでFO4見積もり記載
// =============================================================================
// FO4 早見表の全構文を 1 本のクリティカルパスに通すデモ
// 各行: 「自+FO4」= その演算の深さ / 「到達」= そこまでの累積(=入力到達のmax+自分)
// ★ = クリティカルパス上。FO4値は概算(ライブラリ依存)。
// =============================================================================
module fo4_delay_demo #(
parameter W = 32
,parameter MW = 16
)(
input clk
,input rst_n
,input [MW-1:0] a // 乗算入力
,input [MW-1:0] b
,input [W-1:0] c
,input [4:0] shamt // バレルシフタ量(可変)
,input [1:0] sel // case 選択
,output reg [W-1:0] y
,output reg [W-1:0] rip_ref // 参考: ripple加算の出力
);
localparam [W-1:0] MASK = 32'h0F0F_0F0F;
localparam [W-1:0] KEY = 32'hA5A5_5A5A;
localparam [W-1:0] THRESH = 32'h8000_0000;
reg [2*MW-1:0] prod;
reg [W-1:0] sum;
reg [W-1:0] shf;
reg [W-1:0] xr;
reg ltf;
reg [W-1:0] mx2;
reg eqf;
reg [W-1:0] mx4;
reg msbf;
reg [W-1:0] w;
// ---- 主パス(全構文を直列に通す)----
always @(*) begin
prod = a * b; // 乗算16×16 自+18.0 到達 18.0 ★
sum = prod + c; // prefix加算32b 自+ 5.0 到達 23.0 ★
shf = sum << shamt; // バレルシフタ32b 自+ 8.0 到達 31.0 ★
xr = shf ^ MASK; // 2入力XOR 自+ 1.3 到達 32.3 ★
ltf = (xr < THRESH); // 大小比較<32b 自+ 6.0 到達 38.3 ★
mx2 = ltf ? xr : (xr | c); // 2:1 mux/単発if 自+ 2.0 到達 40.3 ★
// └ 2入力OR(並列, 到達33.6 で select の ltf が律速)
eqf = (mx2 == KEY); // 等価比較==32b 自+ 8.0 到達 48.3 ★
case( sel ) // 4:1 mux(case) 自+ 3.0 到達 43.3
2'd0: mx4 = mx2; // (mx2から; 並列で 43.3 < 48.3 なので非critical)
2'd1: mx4 = mx2 >> 1;
2'd2: mx4 = mx2 << 1;
default: mx4 = ~mx2;
endcase
msbf = mx4[W-1]; // ビット抽出 自+ 0.0 到達 43.3
if( eqf ) begin // if-else連鎖 自+ 6.0 到達 54.3 ★
w = mx4; // 4分岐=優先mux列。select の eqf(48.3)が律速
end else if( ltf ) begin
w = mx4 + 32'd1;
end else if( msbf ) begin
w = mx4 ^ 32'hFFFF_FFFF;
end else begin
w = mx4;
end
end
// ---- 出力 FF(ここで初めて順序)----
always @(posedge clk or negedge rst_n) begin
if( !rst_n ) begin
y <= {W{1'b0}};
end else begin
y <= w; // D ピン: 到達 54.3 → ここで確定(+setup)
end
end
// ---------------------------------------------------------------------------
// 参考: ripple加算32b(手書き桁上げ連鎖) ── 通常は使わない
// `+` は合成器が prefix(自+5.0 FO4)にする。手書き ripple は桁上げが
// 1bit ずつ伝播し 単体 ~32 FO4 = prefix の約6倍。入力直結なので主パス(54.3)
// よりは短いが、これ自体が「なぜ + で書くか」の理由。
// ---------------------------------------------------------------------------
integer i;
reg [W:0] carry;
always @(*) begin
carry[0] = 1'b0;
for( i=0; i<W; i=i+1 ) begin // ripple加算32b 単体 ~32.0 FO4
rip_ref[i] = c[i] ^ MASK[i] ^ carry[i];
carry[i+1] = (c[i]&MASK[i]) | (c[i]&carry[i]) | (MASK[i]&carry[i]);
end
end
endmodule
yosysで論理合成した場合サンプルにおけるVerilogのタイミングエラー見積もり
65nmプロセス
65nmプロセスのタイミングエラーが発生する周波数は以下計算で算出できる.
実遅延 = 54.3×30[ps] = 1.63[ns]
Fmax = 1000÷(遅延+0.15)[ns] = 1000÷(1.63+1.5)[ns] = 1000÷1.78[ns] = 562[MHz]
| 周波数 | 実遅延(54.3×30ps) | slack | 判定 |
|---|---|---|---|
| 100MHz | 1.63 | 8.22 | MET |
| 200MHz | 1.63 | 3.22 | MET |
| 300MHz | 1.63 | 1.55 | MET |
| 400MHz | 1.63 | 0.72 | MET |
| 500MHz | 1.63 | 0.22 | MET |
| 600MHz | 1.63 | -0.11 | VIOLATION |
| 700MHz | 1.63 | -0.35 | VIOLATION |
| 800MHz | 1.63 | -0.53 | VIOLATION |
| 900MHz | 1.63 | -0.67 | VIOLATION |
| 1000MHz(1GHz) | 1.63 | -0.78 | VIOLATION |
10nmプロセス
10nmプロセスのタイミングエラーが発生する周波数は以下計算で算出できる.
実遅延 = 54.3×10[ps] = 0.54[ns]
Fmax = 1000÷(遅延+0.15)[ns] = 1000÷(0.54+1.5)[ns] = 1000÷0.69[ns] = 1449[MHz]
| 周波数 | 実遅延(54.3×10ps) | slack | 判定 |
|---|---|---|---|
| 100MHz | 0.54 | 9.31 | MET |
| 200MHz | 0.54 | 4.31 | MET |
| 300MHz | 0.54 | 2.64 | MET |
| 400MHz | 0.54 | 1.81 | MET |
| 500MHz | 0.54 | 1.31 | MET |
| 600MHz | 0.54 | 0.98 | MET |
| 700MHz | 0.54 | 0.74 | MET |
| 800MHz | 0.54 | 0.56 | MET |
| 900MHz | 0.54 | 0.42 | MET |
| 1000MHz(1GHz) | 0.54 | 0.31 | MET |
2nmプロセス
2nmプロセスのタイミングエラーが発生する周波数は以下計算で算出できる.
実遅延 = 54.3×5[ps] = 0.27[ns]
Fmax = 1000÷(遅延+0.15)[ns] = 1000÷(0.27+1.5)[ns] = 1000÷0.42[ns] = 2381[MHz]
| 周波数 | 実遅延(54.3×5[ps]) | slack | 判定 |
|---|---|---|---|
| 100MHz | 0.27 | 9.58 | MET |
| 200MHz | 0.27 | 4.58 | MET |
| 300MHz | 0.27 | 2.91 | MET |
| 400MHz | 0.27 | 2.08 | MET |
| 500MHz | 0.27 | 1.58 | MET |
| 600MHz | 0.27 | 1.25 | MET |
| 700MHz | 0.27 | 1.01 | MET |
| 800MHz | 0.27 | 0.83 | MET |
| 900MHz | 0.27 | 0.69 | MET |
| 1000MHz(1GHz) | 0.27 | 0.58 | MET |