0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MDAC: Multiplying DACの解説

0
Posted at

image.png

これは典型的な パイプラインADCの1段目(MDAC: Multiplying DAC)SAR ADCのキャパシタアレイ残差生成部 に相当する回路トポロジーです。
「ビットから生まれた Vdac」「スイッチ」「キャパシタ」「増幅器」を組み合わせ、サンプリングと増幅を交互に切り替えて残差を出力します。

1. 回路構成

  • Vdac

    • ビット判定から生成された基準電圧。
    • 典型的には $0, V_{DD}/2, V_{DD}$ のような値をとる。
    • 「入力との差」を表現するために使う。
  • スイッチ (SW: samp / amp)

    • 2つの位相で交互に動作。
    • samp位相: キャパシタに入力電圧 $V_{in}$ をサンプル。
    • amp位相: キャパシタを再接続し、Vdacを差し引いた電圧を増幅器に渡す。
  • キャパシタ

    • サンプリング用 $C_S$ とフィードバック用 $C_F$。
    • 電荷保存の原理で残差が生成される。
  • 増幅器 (Op-Amp)

    • 理想では無限利得 → 完全な「仮想接地」が成り立つ。
    • 現実では有限利得 ($A_{ol} \approx 10^4$)。
    • フィードバック制御により 理想ゲイン 2倍 → 実効ゲイン ≈ 1.9998 程度。

2. 動作原理(2フェーズ)

(1) samp フェーズ(サンプリング)

  • 入力電圧 $V_{in}$ をキャパシタ $C_S$ にサンプル。
  • 下側は共通モードまたは基準点に接続される。

(2) amp フェーズ(増幅)

  • $C_S$ の上端を Vdac に切り替える。

  • オペアンプ+フィードバック容量 $C_F$ が動作し、電荷保存から残差電圧が出力される。

  • 理想式:

    $$
    V_{res} = \left(1+\frac{C_S}{C_F}\right) V_{in} - \frac{C_S}{C_F} V_{DAC}
    $$

    $C_S = C_F$ なら

    $$
    V_{res} = 2(V_{in} - V_{DAC})
    $$


3. 有限利得アンプの効果

  • アンプ利得 $A_{ol}=10000$

  • フィードバック係数 $\beta = 1/2$(ゲイン=2構成)

  • 実効クローズドループゲイン:

    $$
    G_{eff} = \frac{A_{ol}}{1+A_{ol}\beta} \cdot \frac{1}{\beta}
    \approx 2 \cdot \frac{10000}{10001} \approx 1.9998
    $$

  • 誤差は約 0.01% 程度。


4. ADC動作への意味

  • 各ステージで「入力-Vdac」を 2倍して次段へ残差として渡す。
  • これにより 逐次的に量子化誤差を削り、全体で高ビット精度を達成
  • 有限利得やセットリング不足により誤差(DNL, INL)が発生。

✅ まとめ

このトポロジーは スイッチトキャパシタMDAC回路

  • Vdac: ビット判定からの基準電圧
  • SW: サンプリングと増幅を切替
  • C: 電荷保存で残差生成
  • OpAmp: フィードバックで約2倍のゲイン

理想残差式:

$$
V_{res} = 2(V_{in} - V_{DAC})
$$

現実残差式:

$$
V_{res} \approx G_{eff}(V_{in} - V_{DAC}), \quad G_{eff} \approx 1.9998
$$


  1. 記号
    $V_{in}$:入力,$V_{DAC}$:ビットDAC,$V_{cm}=V_{DD}/2$(基準),$V_x$:比較節点,$V_{res}$:残差出力,容量は等容量 $C_S=C_F=C$,アンプ開ループ利得 $A_{ol}\approx10^4$,フィードバック係数 $\beta=1/2$(ゲイン2構成)。

  2. サンプル→増幅(電荷保存)
    サンプル位相で上板に $V_{in}$ を蓄え,増幅位相で上板を $V_{DAC}$ に切替:

$$
2C,(V_{in}-V_{cm})=2C,(V_{DAC}-V_x)
\quad\Rightarrow\quad
V_x-V_{cm}=(V_{DAC}-V_{cm})-(V_{in}-V_{cm}) \tag{1}
$$

  1. 比較器入力(基準との差)

$$
\Delta_x \equiv V_x-V_{cm}=(V_{DAC}-V_{cm})-(V_{in}-V_{cm}) \tag{2}
$$

  1. アンプ出力(残差):開ループ近似

$$
V_{res}^{(\mathrm{ol})}\approx A_{ol},\Delta_x \tag{3}
$$

  1. アンプ出力(残差):閉ループ(等容量・理想は係数2と1)
    有限利得で理想係数にスケール $k$ が掛かる近似:

$$
k ;\equiv; \frac{A_{ol}}{1+A_{ol}\beta}
;;\xrightarrow{;A_{ol}=10^4,;\beta=\tfrac12;};;
k\approx \frac{10000}{1+5000}\approx 1.9996
$$

$$
V_{res};\approx; k\Big[,2,(V_{in}-V_{cm})-(V_{DAC}-V_{cm}),\Big] \tag{4}
$$

  1. 理想(参考)

$$
V_{res}^{(\mathrm{ideal})}=2,(V_{in}-V_{cm})-(V_{DAC}-V_{cm})
= 2(V_{in}-V_{DAC}) \tag{5}
$$

  1. フィードバック動作(増幅位相)
    増幅位相では $C_F$ が出力 $V_{res}$ と節点 $V_x$ を結び,(4) で得た残差が $C_F$ 経由で $V_x$ に帰還($\beta=1/2$)して仮想接地点を形成。次段へは $V_{res}$ が「差分を2倍(≒$k$)」した残差として渡る。
# Program Name: mdac_residue_demo.py
# Creation Date: 20250821
# Overview: Simulate an MDAC (Multiplying DAC) residue generator for a switched-capacitor ADC stage. Plots ideal vs finite-gain residue curves and time-domain settling.
# Usage: Run as-is. Adjust parameters in the block below (VDD, A_ol, GBW_Hz, Cs, Cf, Vin range, Vdac set). Requires numpy and matplotlib.

!pip install numpy matplotlib -q

import numpy as np
import matplotlib.pyplot as plt

# =========================
# Parameters / パラメータ一元管理
# =========================
VDD        = 1.2                  # Supply voltage [V] / 電源電圧
Vcm        = VDD/2                # Common-mode [V] / 共通モード
Cs         = 1e-12                # Sampling cap [F] / サンプリング容量
Cf         = 1e-12                # Feedback cap [F] / フィードバック容量
A_ol       = 1.0e4                # Op-amp open-loop gain / オペアンプ開ループ利得
GBW_Hz     = 50e6                 # Op-amp gain-bandwidth [Hz] / GBW(1極モデル)
Vin_min    = 0.0                  # Vin sweep min [V] / 入力掃引最小
Vin_max    = VDD                  # Vin sweep max [V] / 入力掃引最大
N_pts      = 401                  # Sweep points / 掃引点数
Vdac_set   = [0.0, VDD/2, VDD]    # DAC candidate levels / DAC電圧の候補
Vin_demo   = 0.73                 # Time demo Vin [V] / 時間応答デモ用Vin
Vdac_demo  = VDD/2                # Time demo Vdac [V] / 時間応答デモ用Vdac
T_set      = 200e-9               # Plot horizon [s] / 表示する時間の長さ
Nt         = 1000                 # Time samples / 時間サンプル数

# =========================
# Helpers / ヘルパー関数
# =========================
def beta_feedback(Cs: float, Cf: float) -> float:
    # Feedback factor for equal-cap SC MDAC (approx) / 等容量SC-MDACの近似β
    # 直感的には「出力のどれだけが負入力へ戻るか」→ Cf/(Cs+Cf)
    return Cf / (Cs + Cf)

def k_scale(A_ol: float, beta: float) -> float:
    # Finite-gain scaling factor / 有限利得によるスケーリング係数
    # 一様に係数が縮む近似:k = A_ol / (1 + A_ol * beta)
    return A_ol / (1.0 + A_ol * beta)

def residue_ideal(Vin: np.ndarray, Vdac: float, Cs: float, Cf: float, Vcm: float) -> np.ndarray:
    # Ideal residue around Vcm (single-ended, Vcm-subtracted) / 理想残差(Vcm基準で単端・Vcm差し引き)
    # Ṽ_res = (1 + Cs/Cf)*(Ṽ_in) - (Cs/Cf)*(Ṽ_DAC)
    Vin_t  = Vin - Vcm
    Vdac_t = Vdac - Vcm
    return (1.0 + Cs/Cf)*Vin_t - (Cs/Cf)*Vdac_t

def residue_finite(Vin: np.ndarray, Vdac: float, Cs: float, Cf: float, Vcm: float, A_ol: float) -> np.ndarray:
    # Finite-gain residue (uniform shrink by k) / 有限利得残差(kで一様に縮小)
    b  = beta_feedback(Cs, Cf)
    k  = k_scale(A_ol, b)
    return k * residue_ideal(Vin, Vdac, Cs, Cf, Vcm)

def tau_closed_loop(GBW_Hz: float, Cs: float, Cf: float) -> float:
    # First-order closed-loop time constant / 1次近似の閉ループ時定数
    # 1極OPAMP: ω_p = 2π*GBW/A_ol, 閉ループ極: ω_cl ≈ 2π*GBW*β → τ = 1/ω_cl
    b = beta_feedback(Cs, Cf)
    w_cl = 2.0*np.pi*GBW_Hz*b
    return 1.0 / w_cl

# =========================
# Static transfer: sweep Vin / 静特性:Vin掃引
# =========================
Vin = np.linspace(Vin_min, Vin_max, N_pts)

plt.figure(figsize=(8,4))
for Vdac in Vdac_set:
    v_id  = residue_ideal(Vin, Vdac, Cs, Cf, Vcm)
    v_fin = residue_finite(Vin, Vdac, Cs, Cf, Vcm, A_ol)
    # Plot ideal / 理想
    plt.plot(Vin, v_id, linestyle='--', label=f"Ideal, Vdac={Vdac:.3f} V")
    # Plot finite-gain / 有限利得
    plt.plot(Vin, v_fin, label=f"Finite gain, Vdac={Vdac:.3f} V")
plt.title("MDAC Residue vs Vin (about Vcm)")
plt.xlabel("Vin [V]")
plt.ylabel("Residue (single-ended, about Vcm) [V]")
plt.legend()
plt.grid(True)
plt.show()

# =========================
# Time-domain settling / 時間応答(セットリング)
# =========================
t   = np.linspace(0.0, T_set, Nt)
v_inf = residue_finite(np.array([Vin_demo]), Vdac_demo, Cs, Cf, Vcm, A_ol)[0]  # Final residue / 最終残差
tau = tau_closed_loop(GBW_Hz, Cs, Cf)
v_t = v_inf * (1.0 - np.exp(-t / tau))  # 1st-order settling / 1次の指数応答

plt.figure(figsize=(8,4))
plt.plot(t, v_t, label="Residue(t)")
plt.plot(t, np.full_like(t, v_inf), linestyle='--', label="Final residue")
plt.title("MDAC Residue Settling (first-order)")
plt.xlabel("Time [s]")
plt.ylabel("Residue (about Vcm) [V]")
plt.legend()
plt.grid(True)
plt.show()

# =========================
# Print key numbers / 主要数値の表示
# =========================
b   = beta_feedback(Cs, Cf)                 # β
k   = k_scale(A_ol, b)                      # k縮小係数
Gid = 1.0 + Cs/Cf                           # 理想ゲイン(Ṽ_in係数)
Geff = k * Gid                              # 実効ゲイン(Ṽ_in係数)
print("# MDAC key numbers / 主要数値")
print(f"beta = {b:.6f}")
print(f"k (finite-gain shrink) = {k:.6f}")
print(f"G_ideal (coeff of Ṽ_in) = {Gid:.6f}")
print(f"G_effective (coeff of Ṽ_in) = {Geff:.6f}")
print(f"tau (s) = {tau:.3e}")
print(f"Residue_final (Vin={Vin_demo:.3f} V, Vdac={Vdac_demo:.3f} V) = {v_inf:.6f} V  (about Vcm)")
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?