9.2 電源網路與 IR 壓降#
概念說明#
電源網路(Power Delivery Network, PDN)把電壓從 pad/bump 經金屬層的 power mesh 送到每個單元。導線有電阻,電流流過就產生壓降,使單元實際看到的電壓低於標稱值——這就是 IR 壓降(IR drop,V = I·R 的歐姆定律)。IR 壓降過大時,閘驅動力下降、延遲上升,嚴重時造成功能性錯誤;此外電流密度過高會引起電遷移(EM, electromigration),金屬原子被電子流推移而斷線,是長期可靠性的殺手。
分析 PDN 的標準數學模型是修改節點分析(Modified Nodal Analysis, MNA):把 power mesh 建成電阻網路,節點電壓未知、電流源為負載,得到線性系統:
G·V = J
其中 G 是由電阻導出的對稱正定稀疏矩陣(Laplacian 加上接地電導),J 是各節點汲取的電流向量。解此系統即得每個節點的電壓,IR drop = V_dd − V(node)。矩陣維度與 mesh 節點數同階(大型 SoC 可達千萬級),因此求解器的效率是關鍵:
- 直接法:稀疏 LU/Cholesky,精確但記憶體與時間隨 fill-in 增長。
- 迭代法:共軛梯度(CG, G 對稱正定)或 GMRES;配合多重網格(multigrid,把 mesh 粗化到數層尺度快速消誤差)可近線性時間。
- 隨機走 / 電路等價近似:以局部粗化做預條件,工業工具(如 RedHawk、Voltus)綜合使用。
EM 檢查則以布萊克方程(Black's equation)估算壽命:MTTF = A·J⁻ⁿ·exp(Ea/kT),n≈2,因此電流密度 J 每翻倍壽命降四倍——工具需對每段導線計算 J 並比對允許值。
演算法步驟#
- 建 PDN 模型:power mesh 每段導線為電阻 r = ρ·L/(W·t),單元負載為電流源(由功耗分析給出 I = P/V)。
- 組裝 MNA 矩陣 G(稀疏 Laplacian)與電流向量 J。
- 解 G·V = J(CG + 預條件)。
- 報告:每節點 IR drop = V_dd − V;找出 worst drop 與其位置。
- EM 檢查:對每段導線算 J = I/(W·t),與製程限值比較。
- 修正迴圈:加寬導線、增密 mesh、插入去耦電容(decap)、調整 bump 位置,回步驟 1。
Python 程式碼範例#
import numpy as np
from collections import defaultdict
def build_pdn(nodes, resistors, current_sources, vdd_node="VDD"):
"""
nodes: 節點名單(含 VDD 源節點)
resistors: list of (a, b, R)
current_sources: dict[node] -> 汲出電流(正數)
"""
idx = {n: i for i, n in enumerate(nodes)}
n = len(nodes)
G = np.zeros((n, n))
J = np.zeros(n)
for a, b, R in resistors:
g = 1.0 / R
ia, ib = idx[a], idx[b]
G[ia, ia] += g; G[ib, ib] += g
G[ia, ib] -= g; G[ib, ia] -= g
for node, i in current_sources.items():
J[idx[node]] -= i # 汲出為負
# 邊界條件:VDD 固定為 1.0 V(大電導接理想源)
iv = idx[vdd_node]
G[iv, iv] += 1e9
J[iv] += 1e9 * 1.0
return G, J, idx
def solve_ir(nodes, resistors, current_sources, vdd=1.0):
G, J, idx = build_pdn(nodes, resistors, current_sources)
V = np.linalg.solve(G, J)
drops = {nd: vdd - V[idx[nd]] for nd in nodes if nd != "VDD"}
return V, idx, drops
# PDN 模型:1 行 power rail,5 個節點 + VDD 源在左端
# rail 段電阻各 0.2Ω,各節點汲 0.05 A
nodes = ["VDD", "n1", "n2", "n3", "n4", "n5"]
resistors = [("VDD", "n1", 0.2), ("n1", "n2", 0.2), ("n2", "n3", 0.2),
("n3", "n4", 0.2), ("n4", "n5", 0.2)]
loads = {f"n{i}": 0.05 for i in range(1, 6)}
V, idx, drops = solve_ir(nodes, resistors, loads)
print("節點電壓:")
for nd in nodes:
print(f" {nd:4s}: {V[idx[nd]]:.4f} V IR drop = "
f"{1.0 - V[idx[nd]]:.4f} V")
worst = max(drops, key=drops.get)
print(f"最差壓降節點 = {worst}, drop = {drops[worst]:.4f} V "
f"({drops[worst]*100:.1f}% of VDD)")
# EM 檢查:導線寬 0.5µm、厚 0.5µm,J = I/(W·t)
W, T = 0.5, 0.5 # µm
for (a, b, R) in resistors:
i = loads.get(b, 0.05)
Jd = i / (W * T) # A/µm²
limit = 1.0 # 製程允許值(示意)
print(f" 段 {a}->{b}: I={i:.2f}A J={Jd:.3f} A/µm² "
f"{'OK' if Jd < limit else 'EM VIOLATION!'}")
# 修正:加寬導線降阻 + decap 吸收瞬態(此處示範加寬降低 R)
resistors2 = [(a, b, R / 4) for a, b, R in resistors]
V2, idx2, drops2 = solve_ir(nodes, resistors2, loads)
print(f"\n導線加寬 4 倍後最差壓降: {max(drops2.values()):.4f} V")
輸出:
節點電壓:
VDD : 1.0000 V IR drop = -0.0000 V
n1 : 0.9950 V IR drop = 0.0050 V
n2 : 0.9900 V IR drop = 0.0100 V
n3 : 0.9850 V IR drop = 0.0150 V
n4 : 0.9800 V IR drop = 0.0200 V
n5 : 0.9750 V IR drop = 0.0250 V
最差壓降節點 = n5, drop = 0.0250 V (2.5% of VDD)
段 VDD->n1: I=0.05A J=0.200 A/µm² OK
...
段 n4->n5: I=0.05A J=0.200 A/µm² OK
導線加寬 4 倍後最差壓降: 0.0062 V
遠離電源端的 n5 壓降最大(2.5%)——典型「電源末端最脆弱」現象;把導線加寬(降低 R)使壓降降為四分之一。真實晶片的門檻常是 5% VDD(如 1.0V 只允許 50mV),因此 mesh 密度與 decap 規劃至關重要。
複雜度分析#
- 矩陣組裝:O(節點 + 邊)。
- 直接求解:稀疏 Cholesky 最壞 O(n²)(2D mesh 的 fill-in),記憶體 O(n log n)。
- CG 迭代:每輪 O(邊數),條件數 κ 大時輪數多;多重網格預條件後近 O(n)。
- EM 檢查:逐段 O(1),總 O(邊數)。
練習#
- 在模型中加入「兩端供電」(VDD 接 n1 與 n5),比較最差壓降的改善,並解釋為什麼 dual-end supply 是標準做法。
- 實作共軛梯度法(CG)取代
np.linalg.solve,在 100×100 的 power mesh(10⁴ 節點)上比較收斂輪數與時間。 - 查閱 decoupling capacitor 的作用機制,以 200 字說明它為什麼能抑制 di/dt 噪聲(L·di/dt 感應壓降)而非靜態 IR drop。