1. 目的(Purpose)
AD変換(Analog-to-Digital Conversion)は、
アナログ信号を離散化(サンプリング)・量子化・符号化の3段階でデジタル信号に変換する。
本稿では、その性能指標である DNL(微分非線形性)と INL(積分非線形性)を
数式レベルで明示し、ADCの直線性を定量的に理解する。
2. AD変換の基本構造(Fundamental Process)
AD変換は次の3段階で表される。
(1) サンプリング(Sampling)
Vsample[n] = Vin(nT)
T = 1 / fs はサンプリング周期
fs はサンプリング周波数
(2) 量子化(Quantization)
Δ = (Vref_H - Vref_L) / (2^N)
D[n] = round( (Vsample[n] - Vref_L) / Δ )
Δ は 1 LSB(Least Significant Bit)あたりの理想ステップ幅
Vref_H, Vref_L は基準電圧
N は分解能(bit数)
(3) 符号化(Encoding)
Vout_ideal(D) = Vref_L + D * Δ
D は出力コード(整数:0, 1, 2, ... , 2^N - 1)
3. 微分非線形性(Differential Non-Linearity, DNL)
DNL は「隣接するコード間のステップ幅のずれ」を表す。
定義式
DNL(k) = ( Vth(k+1) - Vth(k) ) / Δ - 1
ここで
Vth(k) :コード k のしきい値電圧
Δ :理想ステップ幅(理想ではすべて等しい)
物理的意味
- 各コードの実ステップ幅が理想幅 Δ からどれだけずれているか。
- 単位は LSB(1ステップあたりの理想量子化幅)。
評価基準
| 条件 | 意味 |
|---|---|
| DNL = 0 | 完全理想(すべてのステップが均一) |
| DNL > 0 | ステップが広い(出力変化が大きい) |
| DNL < 0 | ステップが狭い(出力変化が小さい) |
| DNL < -1 | 欠落コード(missing code)発生 |
例計算
Δ = 1.0 mV
実際のステップ幅 = 0.8 mV
DNL = (0.8 / 1.0) - 1 = -0.2 LSB
→ 量子化ステップが理想より狭く、DNL = -0.2 LSB の誤差。
4. 積分非線形性(Integral Non-Linearity, INL)
INL は「理想的な直線」からの累積偏差を表す。
つまり、ADC全体の非線形歪みを示す。
定義式(直接定義)
INL(k) = ( Vth(k) - Vth_ideal(k) ) / Δ
ここで
Vth(k) :実際のしきい値電圧
Vth_ideal(k) :理想的直線上のしきい値電圧
Δ :理想ステップ幅
定義式(DNLの累積形)
INL(k) = Σ_{i=0}^{k-1} DNL(i)
(k=0 の場合 INL(0)=0)
物理的意味
- 各コード境界の「ずれ」を累積した値。
- 大域的なADCの非線形性を表す。
- DNLがランダムでも、累積すればINLが増加していく。
評価基準
| 条件 | 意味 | ||
|---|---|---|---|
| INL = 0 | 完全に理想直線 | ||
| INL | ≤ 0.5 LSB | 高直線性ADC(一般的な許容範囲) | |
| INL | > 1 LSB | 明確な非線形歪み |
5. DNLとINLの関係式
ΔV_k = Vth(k+1) - Vth(k)
Δ = (Vref_H - Vref_L) / 2^N
DNL(k) = ΔV_k / Δ - 1
INL(k) = Σ DNL(i)
6. 設計・評価上の目安
-
欠落コードを防ぐには
DNL(k) ≥ -1 LSB -
高直線性ADCの条件
|INL(k)| ≤ 0.5 LSB -
実機では、
コンパレータオフセット、キャパシタ比誤差、DAC非線形性が主な原因。
7. PythonによるDNL・INL計算例
# ============================================================
# Program Name: adc_dnl_inl_noise.py
# Creation Date: 20251105
# Overview: Simulate ADC DNL/INL with random noise on thresholds
# Usage: Run directly (numpy + matplotlib)
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
# ==== パラメータ設定 ====
N = 6 # 分解能 [bit]
Vref_H = 1.0 # 上側基準電圧 [V]
Vref_L = -1.0 # 下側基準電圧 [V]
Δ = (Vref_H - Vref_L) / (2**N) # 理想LSB幅
σ = 0.05 * Δ # しきい値誤差の標準偏差(5% LSBノイズ)
# ==== 理想しきい値 + ノイズ ====
ideal_Vth = np.linspace(Vref_L, Vref_H, 2**N + 1)
noise = np.random.normal(0, σ, size=ideal_Vth.shape)
Vth = ideal_Vth + noise # ノイズ付与
Vth.sort() # 昇順に並べ替え(実ADCでは順序保証)
# ==== DNL・INL計算 ====
Δ_meas = np.diff(Vth)
DNL = (Δ_meas / Δ) - 1
INL = np.cumsum(DNL)
# ==== 結果表示 ====
print("=== ADC Linearity Evaluation (with Noise) ===")
print(f"N = {N} bits")
print(f"Ideal LSB Δ = {Δ*1e3:.3f} mV")
print(f"Noise σ = {σ*1e3:.3f} mV")
print()
print("DNL [LSB]:", np.round(DNL[:8], 3), " ...")
print("INL [LSB]:", np.round(INL[:8], 3), " ...")
# ==== プロット ====
plt.figure(figsize=(10,6))
plt.subplot(2,1,1)
plt.stem(DNL, use_line_collection=True)
plt.ylabel("DNL [LSB]")
plt.title("Differential Non-Linearity with Noise")
plt.subplot(2,1,2)
plt.plot(INL, marker='o')
plt.ylabel("INL [LSB]")
plt.xlabel("Code")
plt.title("Integral Non-Linearity with Noise")
plt.tight_layout()
plt.show()
