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?

回路のPythonプログラミング課題

Last updated at Posted at 2025-09-16

(1) RC回路の伝達関数を導出し、周波数特性を描画せよ

RC回路の出力電圧 $V_{out}(\omega)$ は入力 $V_{in}(\omega)$ に対して次式で表されます:

$$
H(j\omega) = \frac{V_{out}(\omega)}{V_{in}(\omega)} = \frac{1}{1 + j\omega RC}
$$

Pythonを使って次を行いなさい:

  1. $R = 1\text{k}\Omega, C = 100\text{pF}$ とする。
  2. 周波数 $f = 10^2$ Hz ~ $10^8$ Hz の範囲で、
    ゲイン $|H(j\omega)|$ と位相 $\angle H(j\omega)$ を計算せよ。
  3. Matplotlibを用いてボード線図(ゲイン[dB], 位相[deg])を描画せよ。
  4. -3 dBとなるカットオフ周波数を求め、グラフ上にマーカーを描け。

(2) ステップ応答をシミュレーションせよ

入力電圧が単位ステップ(0から1に立ち上がる)としたときの微分方程式は次式です:

$$
RC \frac{dV_{out}(t)}{dt} + V_{out}(t) = V_{in}(t)
$$

  1. Pythonでこの微分方程式をシミュレーションし、$V_{out}(t)$ を数値的に解け。
    (Scipyの signal.ltisignal.step を使ってもよい)
  2. 応答波形を時間領域で描画せよ。
  3. $V_{out}(t)$ が 0.9 に到達する時間を数値的に求めよ。
    (NumPyで条件を満たすインデックスを探索)

(3) 発展課題

  1. $R$ と $C$ を変数にし、複数の組み合わせで周波数特性とステップ応答を比較せよ。
  2. 実際のADC入力回路のように「有限インパルス応答」を持つことを確認せよ。


import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# ================== Parameters / パラメータ ==================
R = 1e3        # Resistance [ohm]
C = 100e-12    # Capacitance [F]
RC = R * C

fmin, fmax = 1e2, 1e8   # Frequency range [Hz]
f = np.logspace(np.log10(fmin), np.log10(fmax), 1000)
omega = 2 * np.pi * f

# ================== (1) Frequency Response / 周波数特性 ==================
H = 1 / (1 + 1j * omega * RC)  # Transfer function
gain = 20 * np.log10(np.abs(H))  # Gain [dB]
phase = np.angle(H, deg=True)    # Phase [deg]

# Cutoff frequency (-3 dB point)
fc = 1 / (2 * np.pi * RC)
wc = 2 * np.pi * fc
Hc = 1 / (1 + 1j * wc * RC)
gain_c = 20 * np.log10(np.abs(Hc))
phase_c = np.angle(Hc, deg=True)

plt.figure(figsize=(10,6))
plt.subplot(2,1,1)
plt.semilogx(f, gain, 'b', label="Gain [dB]")
plt.axvline(fc, color='r', linestyle='--')
plt.plot(fc, gain_c, 'ro', label="-3 dB point")
plt.title("RC Low-Pass Filter Frequency Response")
plt.ylabel("Gain [dB]")
plt.grid(True, which="both")
plt.legend()

plt.subplot(2,1,2)
plt.semilogx(f, phase, 'g', label="Phase [deg]")
plt.axvline(fc, color='r', linestyle='--')
plt.plot(fc, phase_c, 'ro')
plt.xlabel("Frequency [Hz]")
plt.ylabel("Phase [deg]")
plt.grid(True, which="both")
plt.legend()
plt.tight_layout()
plt.show()

print(f"Cutoff frequency fc = {fc:.2e} Hz")

# ================== (2) Step Response / ステップ応答 ==================
# Transfer function H(s) = 1 / (RC s + 1)
num = [1]
den = [RC, 1]
system = signal.lti(num, den)

t = np.linspace(0, 5*RC, 1000)
t, y = signal.step(system, T=t)

plt.figure(figsize=(8,4))
plt.plot(t, y, 'b', label="Step Response Vout(t)")
plt.axhline(0.9, color='r', linestyle='--', label="0.9 level")
plt.title("RC Circuit Step Response")
plt.xlabel("Time [s]")
plt.ylabel("Vout(t)")
plt.grid(True)
plt.legend()
plt.show()

# Find time when output reaches 0.9
idx = np.where(y >= 0.9)[0][0]
t_90 = t[idx]
print(f"Vout(t) reaches 0.9 at t = {t_90:.4e} s")

# ================== (3) Advanced: Compare different R, C ==================
R_list = [1e3, 5e3]      # [ohm]
C_list = [100e-12, 1e-9] # [F]

plt.figure(figsize=(10,6))
for R in R_list:
    for C in C_list:
        RC = R*C
        H = 1 / (1 + 1j*omega*RC)
        gain = 20*np.log10(np.abs(H))
        plt.semilogx(f, gain, label=f"R={R:.0e}Ω, C={C:.0e}F")
plt.title("Frequency Response with Different R,C")
plt.xlabel("Frequency [Hz]")
plt.ylabel("Gain [dB]")
plt.grid(True, which="both")
plt.legend()
plt.show()

plt.figure(figsize=(10,6))
for R in R_list:
    for C in C_list:
        RC = R*C
        num = [1]
        den = [RC, 1]
        system = signal.lti(num, den)
        t = np.linspace(0, 5*RC, 1000)
        t, y = signal.step(system, T=t)
        plt.plot(t, y, label=f"R={R:.0e}Ω, C={C:.0e}F")
plt.title("Step Response with Different R,C")
plt.xlabel("Time [s]")
plt.ylabel("Vout(t)")
plt.grid(True)
plt.legend()
plt.show()

1. フーリエ級数による矩形波の生成

フーリエ級数の積和を用いて、振幅が [0V, 1V] となる矩形波を作成してください。
ヒント:奇数次高調波を足し合わせて矩形波を近似します。


2. for文を使わずに実装

課題1で作成した矩形波を、for文を使わずにベクトル演算(NumPy配列のブロードキャストやsum関数) で実装してください。


3. 一部が欠けた円の描画

半径1の円をプロットしてください。ただし、90°~180°の部分は欠けるようにしてください。
ヒント:極座標で角度 θ を制御して、該当区間をマスクして描画します。


4. PythonでADCを模擬的に作成

簡単なADCをPythonで作成してください。

  • 入力レンジは [-1V, 1V]
  • 分解能は 4bit (16レベル)
  • (ライブラリに依存せず、自作で量子化処理を行う)

課題内容:

  1. 振幅が1Vの正弦波をADCに入力した場合、入力波形量子化後の出力波形を同じグラフに表示してください。
  2. -1.5V~+1.5V のランプ波をADCに入力した場合も同様に、入力波形と出力を表示してください。


import numpy as np
import matplotlib.pyplot as plt

# ================== Parameters / パラメータ ==================
fs = 1000               # Sampling frequency [Hz]
T = 1                   # Duration [s]
N = fs * T              # Number of points
t = np.linspace(0, T, N, endpoint=False)  # Time axis

harmonics = 25          # Number of harmonics for Fourier series
A_square = 0.5          # Square wave amplitude offset
Vpp = 1.0               # Peak-to-peak = 1V, range [0,1]

circle_radius = 1.0     # Circle radius
theta = np.linspace(0, 2*np.pi, 1000)

adc_bits = 4            # ADC resolution
adc_min = -1.0          # ADC input range minimum
adc_max = 1.0           # ADC input range maximum

# ================== 1. Fourier Series Square Wave ==================
n = np.arange(1, harmonics*2, 2)[:, None]   # odd harmonics as column vector
terms = (1/n) * np.sin(2*np.pi*n*t)         # broadcast to (harmonics, N)
square_wave = A_square + (2/np.pi) * np.sum(terms, axis=0) * (Vpp/2)

plt.figure(figsize=(10,4))
plt.plot(t, square_wave, label="Fourier Square Wave [0-1V]")
plt.title("Square Wave Approximation by Fourier Series")
plt.xlabel("Time [s]")
plt.ylabel("Amplitude [V]")
plt.grid(True)
plt.legend()
plt.show()

# ================== 2. Circle with missing sector (through origin) ==================
x = circle_radius * np.cos(theta)
y = circle_radius * np.sin(theta)
mask = ~((theta >= np.pi/2) & (theta <= np.pi))  # exclude 90°–180°

plt.figure(figsize=(5,5))
plt.plot(x[mask], y[mask], 'b')             # 円弧
# 欠け部分を原点で結ぶ線を追加 / Add lines from origin
plt.plot([0, -circle_radius], [0, 0], 'r--')  # negative x-axis
plt.plot([0, 0], [0, circle_radius], 'r--')  # positive y-axis

plt.gca().set_aspect("equal", adjustable="box")
plt.title("Circle with Missing 90°–180° Sector (through origin)")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True)
plt.show()

# ================== 3. Simple ADC Function ==================
def adc_quantize(x, bits, vmin, vmax):
    """
    自作ADC量子化処理 / Manual ADC quantization
    """
    levels = 2**bits
    step = (vmax - vmin) / levels
    q = np.round((x - vmin)/step) * step + vmin
    q = np.clip(q, vmin, vmax - step)
    return q

# --- (a) Sine input ---
f_in = 5  # [Hz]
x_sin = np.sin(2*np.pi*f_in*t)
y_sin_q = adc_quantize(x_sin, adc_bits, adc_min, adc_max)

plt.figure(figsize=(10,4))
plt.plot(t, x_sin, label="Input Sine [V]")
plt.step(t, y_sin_q, where="mid", label="Quantized Output [V]")
plt.title("4-bit ADC with Sine Input")
plt.xlabel("Time [s]")
plt.ylabel("Amplitude [V]")
plt.grid(True)
plt.legend()
plt.show()

# --- (b) Ramp input ---
x_ramp = np.linspace(-1.5, 1.5, N)
y_ramp_q = adc_quantize(x_ramp, adc_bits, adc_min, adc_max)

plt.figure(figsize=(10,4))
plt.plot(t, x_ramp, label="Input Ramp [V]")
plt.step(t, y_ramp_q, where="mid", label="Quantized Output [V]")
plt.title("4-bit ADC with Ramp Input")
plt.xlabel("Time [s]")
plt.ylabel("Amplitude [V]")
plt.grid(True)
plt.legend()
plt.show()
% ================== Parameters / パラメータ ==================
fs = 1000;              % Sampling frequency [Hz]
T = 1;                  % Duration [s]
N = fs * T;             % Number of points
t = linspace(0, T, N);  % Time axis

harmonics = 25;         % Number of harmonics for Fourier series
A_square = 0.5;         % Square wave amplitude offset
Vpp = 1.0;              % Peak-to-peak = 1V, range [0,1]

circle_radius = 1.0;    % Circle radius
theta = linspace(0, 2*pi, 1000);

adc_bits = 4;           % ADC resolution
adc_min = -1.0;         % ADC input range minimum
adc_max = 1.0;          % ADC input range maximum

% ================== 1. Fourier Series Square Wave ==================
n = (1:2:(harmonics*2-1))';      % odd harmonics as column vector
terms = (1./n) * sin(2*pi*n*t); % broadcasting
square_wave = A_square + (2/pi) * sum(terms, 1) * (Vpp/2);

figure;
plot(t, square_wave);
title("Square Wave Approximation by Fourier Series");
xlabel("Time [s]"); ylabel("Amplitude [V]");
grid on;

% ================== 2. Circle with missing sector ==================
x = circle_radius * cos(theta);
y = circle_radius * sin(theta);
mask = (theta < pi/2) | (theta > pi); % exclude 90°–180°

figure;
plot(x(mask), y(mask), 'b'); hold on;
% 欠け部分を原点で結ぶ線
plot([0, -circle_radius], [0, 0], 'r--'); % negative x-axis
plot([0, 0], [0, circle_radius], 'r--'); % positive y-axis
axis equal;
title("Circle with Missing 90°–180° Sector (through origin)");
xlabel("x"); ylabel("y");
grid on;

% ================== 3. Simple ADC Function ==================
function q = adc_quantize(x, bits, vmin, vmax)
    levels = 2^bits;
    step = (vmax - vmin) / levels;
    q = round((x - vmin)/step) * step + vmin;
    q(q > vmax - step) = vmax - step; % clipping
    q(q < vmin) = vmin;
end

% --- (a) Sine input ---
f_in = 5;  % [Hz]
x_sin = sin(2*pi*f_in*t);
y_sin_q = adc_quantize(x_sin, adc_bits, adc_min, adc_max);

figure;
plot(t, x_sin, 'b'); hold on;
stairs(t, y_sin_q, 'r');
title("4-bit ADC with Sine Input");
xlabel("Time [s]"); ylabel("Amplitude [V]");
grid on;

% --- (b) Ramp input ---
x_ramp = linspace(-1.5, 1.5, N);
y_ramp_q = adc_quantize(x_ramp, adc_bits, adc_min, adc_max);

figure;
plot(t, x_ramp, 'b'); hold on;
stairs(t, y_ramp_q, 'r');
title("4-bit ADC with Ramp Input");
xlabel("Time [s]"); ylabel("Amplitude [V]");
grid on;


(1) ΔΣ変調器のシミュレーション

  1. Python(NumPy + Matplotlib)を用いて、1次の ΔΣ変調器を実装せよ。

    • 入力信号: 正弦波 sin(2π f_in t)
    • サンプリング周波数 Fs = 2^14
    • 入力振幅 1V
    • 入力周波数 f_in = 17 Hz
  2. 変調器は以下の構造を持つ:

    • 加算器 (入力 - 1ビットDACの出力)
    • 積分器(離散時間積分)
    • 量子化器(sign関数で ±1 に変換)
    • 1ビットDAC(量子化結果をアナログ側に戻す)

(2) 出力波形の確認

  1. 入力正弦波と ΔΣ出力を時間波形として同じグラフに描け。
  2. ΔΣ出力は ±1 の矩形パルス系列になることを確認せよ。

(3) スペクトル解析

  1. ΔΣ出力を高速フーリエ変換(FFT)してパワースペクトルを描け。
  2. 信号帯域(低周波成分)に入力信号が存在することを確認し、
    高周波に量子化雑音が押し出される(ノイズシェーピング)ことを示せ。


import numpy as np
import matplotlib.pyplot as plt

# ======================== Parameters / パラメータ ========================
Fs = 2**14          # Sampling frequency [Hz] / サンプリング周波数
f_in = 17           # Input sine frequency [Hz] / 入力信号周波数
A = 1.0             # Input amplitude [V] / 入力振幅
N = 8192            # Number of samples / サンプル数

# ======================== Input Signal / 入力信号 ========================
n = np.arange(N)                      # time index / 離散時間インデックス
x = A * np.sin(2*np.pi*f_in*n/Fs)     # input sinewave / 入力サイン波

# ======================== Delta-Sigma Modulator / ΔΣ変調器 ========================
v_int = 0.0               # integrator state / 積分器の状態
y_out = np.zeros(N)       # output sequence / 出力信号系列
dac_out = 0.0             # 1-bit DAC output / 1ビットDAC出力

for i in range(N):
    e = x[i] - dac_out             # adder: input - DAC / 加算器
    v_int += e                     # integrator / 積分器
    y_q = 1 if v_int >= 0 else -1  # quantizer: sign / 量子化器
    y_out[i] = y_q                 # output assignment / 出力保存
    dac_out = y_q                  # 1-bit DAC feedback / 1ビットDAC出力

# ======================== (2) Time-domain Waveform / 時間領域波形 ========================
plt.figure(figsize=(10,5))
plt.plot(n[:500]/Fs, x[:500], label="Input Sinewave")
plt.step(n[:500]/Fs, y_out[:500], where='post', label="ΔΣ Output (±1)")
plt.xlabel("Time [s]")
plt.ylabel("Amplitude")
plt.title("Time-Domain Waveform of Delta-Sigma Modulator")
plt.legend()
plt.grid(True)
plt.show()

# ======================== (3) Spectrum Analysis / スペクトル解析 ========================
Xf = np.fft.rfft(y_out * np.hanning(N))   # apply window / 窓関数を適用
f_axis = np.fft.rfftfreq(N, d=1/Fs)       # frequency axis / 周波数軸
Pxx = 20*np.log10(np.abs(Xf)/np.max(np.abs(Xf)))  # normalized dB / 正規化dB

plt.figure(figsize=(10,5))
plt.plot(f_axis, Pxx)
plt.xlim(0, 2000)  # show baseband region / 基本帯域を表示
plt.ylim(-120, 5)
plt.xlabel("Frequency [Hz]")
plt.ylabel("Magnitude [dB]")
plt.title("Spectrum of ΔΣ Output (Noise Shaping Demonstration)")
plt.grid(True)
plt.show()

Pythonプログラミング問題

問題:SAR-ADCの二分探索アルゴリズムを実装せよ

背景

逐次比較型ADC(SAR-ADC)は、入力電圧を 二分探索(Binary Search) によって量子化する方式のADCである。
NビットのSAR-ADCは、上位ビットから順に比較を行い、入力値がDACの出力より大きいか小さいかを判定しながら、最終的にNビットのデジタルコードを決定する。


問題文

次の条件に従って、SAR-ADCのアルゴリズムをPythonで実装せよ。

  • 入力アナログ電圧 Vin が与えられる。範囲は Vmin = 0.0 [V]Vmax = 1.0 [V] とする。
  • 分解能は N = 4 ビットとし、量子化レベル数は 2^N = 16
  • SAR-ADCの逐次比較アルゴリズムを模擬し、入力電圧を 4ビットのデジタルコード に変換せよ。

アルゴリズムは以下の手順に従うこと。

  1. SARレジスタのMSBを1に設定する(例: 1000)。

  2. 内部DACの出力値と入力Vinを比較する。

    • Vin >= Vdac ならビットを保持。
    • Vin < Vdac ならビットを0に戻す。
  3. 次のビットを1に設定して比較する。

  4. 全ビットについて繰り返し、最終的なデジタルコードを求める。




import numpy as np
import matplotlib.pyplot as plt

# ======================
# SAR-ADC Function
# ======================
def sar_adc(Vin, N=4, Vmin=0.0, Vmax=1.0):
    """
    SAR-ADC 二分探索アルゴリズム
    Vin   : 入力アナログ電圧
    N     : 分解能(ビット数)
    Vmin  : 入力範囲最小値
    Vmax  : 入力範囲最大値
    """
    code = 0
    steps = []
    for i in range(N):
        # 試しにこのビットを立てる
        trial_code = code | (1 << (N - 1 - i))
        Vdac = Vmin + (Vmax - Vmin) * trial_code / (2**N)
        if Vin >= Vdac:
            code = trial_code
            decision = "keep"
        else:
            decision = "clear"
        steps.append((format(trial_code, f"0{N}b"), Vdac, decision))
    return code, steps

# ======================
# Example Run
# ======================
Vin = 0.7
N = 4
Vmin, Vmax = 0.0, 1.0

final_code, steps = sar_adc(Vin, N, Vmin, Vmax)

# 結果表示
print(f"Vin = {Vin:.2f} V")
print("SAR steps:")
for bincode, Vdac, decision in steps:
    print(f"Trial {bincode} -> Vdac={Vdac:.4f} V → {decision}")
print(f"\nFinal code = {format(final_code, f'0{N}b')} (binary) = {final_code} (decimal)")

# ======================
# Visualization
# ======================
plt.figure(figsize=(8,5))
plt.axhline(Vin, color="g", linestyle="--", label=f"Vin = {Vin:.2f} V")
trial_indices = np.arange(1, N+1)
Vdacs = [V for _, V, _ in steps]

plt.step(trial_indices, Vdacs, where="mid", label="DAC trial value", color="b")
plt.plot(trial_indices, Vdacs, "o", color="b")
plt.xticks(trial_indices, [f"Step {i}" for i in trial_indices])
plt.title("SAR-ADC Binary Search Process")
plt.xlabel("Comparison Step")
plt.ylabel("Voltage [V]")
plt.legend()
plt.grid(True)
plt.show()


(1) RC回路の周波数特性とステップ応答

理論式

  • 伝達関数:

    $$
    H(j\omega) = \frac{1}{1 + j\omega RC}
    $$

  • ゲイン:

    $$
    |H(j\omega)| = \frac{1}{\sqrt{1 + (\omega RC)^2}}
    $$

  • 位相:

    $$
    \angle H(j\omega) = -\tan^{-1}(\omega RC)
    $$

  • カットオフ周波数(−3 dB点):

    $$
    f_c = \frac{1}{2\pi R C}
    $$

  • ステップ応答:
    微分方程式

    $$
    RC \frac{dV_{out}(t)}{dt} + V_{out}(t) = 1
    $$

    初期条件 $V_{out}(0) = 0$ の解:

    $$
    V_{out}(t) = 1 - e^{-t/(RC)}
    $$

課題

  1. $R = 1\text{k}\Omega, C = 100\text{pF}$ のとき、周波数範囲 $10^2$ Hz ~ $10^8$ Hz で $ |H(j\omega)|$ と $\angle H(j\omega)$ を計算し、ボード線図を描け。
  2. 上の回路のカットオフ周波数を理論式で求め、それをプロットにマークせよ。
  3. 単位ステップ入力 $u(t)$ を入力として、応答 $V_{out}(t)$ を数値的にシミュレーションし、理論的時定数 $\tau = R C$ と比較せよ。

(2) MOSFET の Id-Vds 特性(NMOS / PMOS)

素子レベルの理論式

  • デバイス定数:

    $$
    k = \mu C_{ox} \frac{W}{L}
    $$

    NMOS 用 $k_n$、PMOS 用 $k_p$。

  • NMOS のドレイン電流式(チャネル長変調 無し/有り):

    $$
    I_{d,n} =
    \begin{cases}
    0, & V_{gs} < V_{thn} \
    k_n\left[(V_{gs}-V_{thn})V_{ds} - \frac{V_{ds}^2}{2}\right], & 0 \le V_{ds} < V_{gs}-V_{thn} \quad (\text{線形領域}) \
    \frac{k_n}{2}(V_{gs}-V_{thn})^2, & V_{ds} \ge V_{gs}-V_{thn} \quad (\text{飽和領域})
    \end{cases}
    $$

    チャネル長変調を含めると飽和領域で:

    $$
    I_{d,n} = \frac{k_n}{2}(V_{gs}-V_{thn})^2 (1 + \lambda_n V_{ds})
    $$

  • PMOS の式は符号を反転し、ゲート‐対‐ソース電圧 $V_{sg}$、ソース‐ドレイン電圧 $V_{sd}$ を使う類似形式。

  • トランスコンダクタンス:

    $$
    g_{m,n} = \frac{\partial I_{d,n}}{\partial V_{gs}} = k_n (V_{gs} - V_{thn}) \quad (\text{飽和領域})
    $$

課題

  1. NMOS および PMOS の $I_d - V_{ds}$ 特性を、複数の $V_{gs}$(または $V_{sg}$)でプロットせよ。
  2. $g_m$ を飽和領域で計算し、$V_{gs} - V_{thn}$ の関数としてプロットせよ。

(3) NMOSソース接地アンプ

理論式

  • 入力信号:

    $$
    v_{in}(t) = 0.025 \sin(2\pi \cdot 1000 t)
    $$

  • 増幅率(小信号近似):

    $$
    A_v = - g_m R_D
    $$

    ただし $g_m = k_n (V_{gs} - V_{thn})$, $R_D$ はドレイン抵抗。

  • 出力電圧:

    $$
    v_{out}(t) = A_v \cdot v_{in}(t)
    $$

    ただし電源電圧 $V_{DD}$ による制限(クリッピング)がある場合を考慮する。

課題

  • パラメータ例として $k_n, V_{thn}, R_D$ を仮定せよ(例:$k_n = 200\ \mu A/V^2, V_{thn} = 0.7V, R_D = 1\text{ k}\Omega$)。
  • Python で入力波形と出力波形を生成し、クリップを入れた結果をプロットせよ。

(4) NMOS差動アンプ

理論式

  • 差動入力:

    $$
    v_{id}(t) = 0.01 \sin(2\pi \cdot 10^6 t)
    $$

  • 出力(理想差動増幅):

    $$
    v_{out}(t) = A_v \cdot v_{id}(t), \quad A_v = g_m R_D
    $$

  • テール電流制約:
    差動ペアに流せる電流 $I_{tail}$ が2 mA とすると、各トランジスタの $I_d$ は合計でこれを超えないようにする。

課題

  • NMOS 差動対のパラメータ(例:$k_n, V_{thn}, R_D, I_{tail}$)を仮定せよ。
  • Python で入力‐差動信号と出力信号をシミュレーションし、テール電流制約による飽和やクリッピングが起きる領域も観察せよ。

(5) CMOS NAND回路

理論式

  • 真理値表: $Y = \overline{A \cdot B}$

  • プルアップ(PMOS 並列)、プルダウン(NMOS 直列)による構成。

  • 遅延時間近似:

    $$
    t_{pd} = 0.69 R_{eq} C_L
    $$

    ここで $R_{eq}$ は入力が変化したときの等価抵抗、$C_L$ は負荷容量。

課題

  • 真理値表を Python で生成せよ。
  • 複数の $C_L$(例:1 pF、10 pF、100 pF)を仮定し、遅延時間を計算・プロットせよ。

また、NOT回路(CMOSインバータ)をシグモイド関数で近似し,電源電圧 (V_{DD}),トランジスタ寸法 (W/L) を含めて表すと以下になる。
(1) 基本式(電圧入力 → 電圧出力)
Vout = VDD * (1 - 1 / (1 + exp(-k * (Vin - VM))))

(2) パラメータ定義
VDD : 電源電圧 例) 1.8 V, 3.3 V
VM : 反転点(スイッチング閾値) NMOS/PMOS比で決定
k : 遷移の鋭さを決める係数 k ∝ sqrt( μp * (W/L)p / (μn * (W/L)n) )

(3) MOS寸法との関係(スイッチング点近似)
μn * ((W/L)n / (W/L)p) * ((VM - Vtn) / (VDD - VM - |Vtp|))^2 = 1

μn, μp : 電子・正孔移動度
Vtn, Vtp : NMOS/PMOSのしきい値電圧

(4) 解釈
(W/L)n ↑ → VM ↓ (NMOS強 → 出力0側に寄る)
(W/L)p ↑ → VM ↑ (PMOS強 → 出力1側に寄る)
VDD ↑ → 出力スイング幅が拡大し、シグモイドの上下限が広がる

(6) CMOSインバータ(NOT回路)

理論式

  • NMOS と PMOS が補完的動作する回路。静的電流は通常ゼロ(入力が定常状態のとき)。

  • 電流平衡条件で VTC を導出:NMOS の漏れ電流/飽和電流式と、PMOS の式を使って $I_{d,n}(V_{in}, V_{out}) = I_{d,p}(V_{in}, V_{out})$ と設定する。

  • 簡略な転移特性例:

    $$
    V_{out} \approx \frac{k_p (V_{DD}-V_{in}-|V_{thp}|)^2}{k_n (V_{in}-V_{thn})^2 + k_p (V_{DD}-V_{in}-|V_{thp}|)^2} ; V_{DD}
    $$

  • 理想スイッチモデル(しきい値による出力の変化):

    $$
    V_{out} =
    \begin{cases}
    V_{DD}, & V_{in} < V_{th} \
    0, & V_{in} > V_{th}
    \end{cases}
    $$

課題

  • NMOS と PMOS のデバイス定数 $k_n, k_p$、しきい値 $V_{thn}, |V_{thp}|$ を仮定せよ(例:$k_n = 200\ \mu A/V^2, k_p = 100\ \mu A/V^2, V_{thn} = 0.7V, |V_{thp}| = 0.7V$)。
  • 矩形波入力を与えたときの過渡応答も Python でシミュレーションせよ。


import numpy as np
import matplotlib.pyplot as plt

# ================== (2) MOSFET Id-Vds ==================
# Device parameters
kn = 200e-6   # NMOS [A/V^2]
kp = 100e-6   # PMOS [A/V^2]
Vthn = 0.7    # NMOS threshold [V]
Vthp = -0.7   # PMOS threshold [V]
lambda_n = 0.02   # Channel-length modulation (example)
lambda_p = 0.02

Vds = np.linspace(0, 5, 200)
Vgs_list = [1.0, 2.0, 3.0, 4.0]

def Id_nmos(Vgs, Vds):
    Id = np.zeros_like(Vds)
    for i, vds in enumerate(Vds):
        if Vgs < Vthn:
            Id[i] = 0
        elif vds < (Vgs - Vthn):
            Id[i] = kn*((Vgs-Vthn)*vds - 0.5*vds**2)   # linear
        else:
            Id[i] = 0.5*kn*(Vgs-Vthn)**2*(1+lambda_n*vds) # saturation
    return Id

plt.figure(figsize=(8,5))
for Vgs in Vgs_list:
    plt.plot(Vds, Id_nmos(Vgs,Vds), label=f"Vgs={Vgs} V")
plt.xlabel("Vds [V]")
plt.ylabel("Id [A]")
plt.title("NMOS Id-Vds Characteristics")
plt.legend()
plt.grid(True)
plt.show()

# Transconductance in saturation
Vgs = np.linspace(Vthn, 3, 100)
gm = kn*(Vgs-Vthn)
plt.figure()
plt.plot(Vgs-Vthn, gm)
plt.xlabel("Vgs - Vthn [V]")
plt.ylabel("gm [A/V]")
plt.title("NMOS Transconductance in Saturation")
plt.grid(True)
plt.show()

# ================== (3) NMOS Common-Source Amplifier ==================
Vin_t = np.linspace(0, 2e-3, 1000) # time ~2 ms
vin = 0.025*np.sin(2*np.pi*1e3*Vin_t)  # 1 kHz input

RD = 1e3
Vgs_bias = 2.0
gm_bias = kn*(Vgs_bias-Vthn)
Av = -gm_bias*RD
vout = Av*vin

VDD = 5.0
vout_clipped = np.clip(vout, -VDD, VDD)

plt.figure(figsize=(8,4))
plt.plot(Vin_t*1000, vin, label="Input Vin [V]")
plt.plot(Vin_t*1000, vout_clipped, label="Output Vout [V]")
plt.xlabel("Time [ms]")
plt.ylabel("Voltage [V]")
plt.title("NMOS Common-Source Amplifier (with clipping)")
plt.legend()
plt.grid(True)
plt.show()

# ================== (4) NMOS Differential Amplifier ==================
t = np.linspace(0, 2e-6, 2000)
vid = 0.01*np.sin(2*np.pi*1e6*t)
Itail = 2e-3
Id_single = Itail/2 + kn*(vid/2)*(1.0)  # crude approx
Id_single = np.clip(Id_single, 0, Itail) # tail current constraint
vout_diff = (Id_single - Itail/2)*RD

plt.figure(figsize=(8,4))
plt.plot(t*1e6, vid, label="Differential Input [V]")
plt.plot(t*1e6, vout_diff, label="Output Vout [V]")
plt.xlabel("Time [us]")
plt.ylabel("Voltage [V]")
plt.title("NMOS Differential Amplifier with Tail Current Constraint")
plt.legend()
plt.grid(True)
plt.show()

# ================== (5) CMOS NAND Gate ==================
import itertools

def nand_gate(A,B):
    return int(not(A and B))

print("CMOS NAND Truth Table")
print("A B | Y")
for A,B in itertools.product([0,1],[0,1]):
    print(f"{A} {B} | {nand_gate(A,B)}")

CL_values = [1e-12, 10e-12, 100e-12]
Req = 1e3
tpd = [0.69*Req*CL for CL in CL_values]

plt.figure()
plt.loglog(CL_values, tpd, 'o-')
plt.xlabel("Load Capacitance CL [F]")
plt.ylabel("Propagation Delay [s]")
plt.title("CMOS NAND Propagation Delay vs Load Capacitance")
plt.grid(True, which="both")
plt.show()

# ================== (6) CMOS Inverter ==================
Vin = np.linspace(0,5,500)
VDD = 5.0
Vout = (kp*(VDD-Vin-Vthp)**2) / (kn*(Vin-Vthn)**2 + kp*(VDD-Vin-Vthp)**2) * VDD
Vout[Vin<Vthn] = VDD
Vout[Vin>VDD+Vthp] = 0

plt.figure()
plt.plot(Vin, Vout)
plt.xlabel("Vin [V]")
plt.ylabel("Vout [V]")
plt.title("CMOS Inverter Voltage Transfer Characteristic")
plt.grid(True)
plt.show()

# Transient response with square wave input
t = np.linspace(0, 2e-6, 2000)
vin_square = (np.sign(np.sin(2*np.pi*1e6*t))+1)/2*VDD
vout_square = VDD - vin_square  # ideal inverter

plt.figure()
plt.plot(t*1e6, vin_square, label="Vin")
plt.plot(t*1e6, vout_square, label="Vout")
plt.xlabel("Time [us]")
plt.ylabel("Voltage [V]")
plt.title("CMOS Inverter Transient Response")
plt.legend()
plt.grid(True)
plt.show()

演習問題(定電流負荷差動アンプの伝達関数解析)

【目的】
定電流負荷差動増幅器の小信号動作を理解し、周波数応答(伝達関数)を理論式とシミュレーションの両面から検証する。

【問題文】

図の定電流負荷差動アンプについて、次の設問に答えよ。

(1) 小信号等価回路を描け。
入力:vid = v1 - v2
出力:vo = vout

(2) 小信号解析により、出力電圧 vo と入力差電圧 vid の関係式(伝達関数)を導け。
H(s) = Vout(s) / Vid(s)

(3) 次の式をもとに、低周波ゲイン Av0 と極(ポール)周波数 ωp を求めよ。

 H(s) = -gmN * (roN || roP) / (1 + s * (roN || roP) * (Cgs + Cgd))

 Av0 = -gmN * (roN || roP)
 ωp = 1 / ((roN || roP) * (Cgs + Cgd))

(4) パラメータ gmN, roN, roP を以下の式で定義し、設計値から数値計算せよ。

 gmN = μn * Cox * (W/L)n * (VGSN - VthN)
 roN = 1 / (λn * ID)
 roP = 1 / (λp * ID)

(5) 伝達関数を近似式で表し、シミュレーションのボード線図と比較せよ。

 H(s) ≈ Av0 / (1 + s / ωp)
 ≈ (-gmN * (roN || roP)) / (1 + s * (roN || roP) * Ceff)
 (Ceff ≈ Cgs + Cgd)

(6) 図の周波数特性(ゲイン特性)を読み取り、低周波ゲイン [dB] と
-3 dB 周波数 fp [Hz] を求め、理論値と比較せよ。


!pip install numpy matplotlib scipy

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# ==============================
# パラメータ設定 / Parameters
# ==============================
mu_n = 300e-4         # 電子移動度 [m^2/Vs]
Cox  = 3.45e-3        # 酸化膜容量 [F/m^2]
W_Ln = 100e-6 / 1e-6  # (W/L)n
VGSN = 1.2            # ゲート・ソース電圧 [V]
VthN = 0.6            # しきい値電圧 [V]
lam_n = 0.02          # λn [1/V]
lam_p = 0.03          # λp [1/V]
ID = 50e-6            # ドレイン電流 [A]
Cgs = 0.2e-12         # ゲート・ソース容量 [F]
Cgd = 0.1e-12         # ゲート・ドレイン容量 [F]

# ==============================
# 小信号パラメータ計算 / Parameter calculation
# ==============================
gmN = mu_n * Cox * W_Ln * (VGSN - VthN)
roN = 1 / (lam_n * ID)
roP = 1 / (lam_p * ID)
ro_eq = (roN * roP) / (roN + roP)
Ceff = Cgs + Cgd

Av0 = -gmN * ro_eq
wp = 1 / (ro_eq * Ceff)
fp = wp / (2 * np.pi)

print(f"gmN = {gmN:.3e} [S]")
print(f"ro_eq = {ro_eq:.3e} [Ω]")
print(f"Av0 = {Av0:.2f} (linear), {20*np.log10(abs(Av0)):.2f} [dB]")
print(f"fp = {fp/1e6:.2f} [MHz]")

# ==============================
# 伝達関数生成 / Transfer function
# ==============================
num = [Av0]
den = [1/(wp), 1]
sys = signal.TransferFunction(num, den)

# ==============================
# 周波数特性プロット / Frequency response
# ==============================
w = np.logspace(4, 9, 500)  # 10 kHz〜1 GHz
w, mag, phase = signal.bode(sys, w)

plt.figure(figsize=(6,4))
plt.semilogx(w/(2*np.pi), mag)
plt.title("Differential Amplifier Frequency Response")
plt.xlabel("Frequency [Hz]")
plt.ylabel("Gain [dB]")
plt.grid(True, which="both", ls="--")
plt.show()

【出力項目】

  • ( g_m ):トランスコンダクタンス [S]
  • ( r_o ):等価出力抵抗 [Ω]
  • ( A_{v0} ):低周波利得(線形・dB)
  • ( f_p ):極(ポール)周波数 [Hz]

【結果の考察】

  • 低周波域でゲイン ≈ ( 20\log_{10}|A_{v0}| )
  • 約 ( f_p ) 以降、-20 dB/dec の傾きで減衰
  • 理論式
    [
    H(s) = \frac{-g_m (r_{on} || r_{op})}{1 + s (r_{on} || r_{op})(C_{gs}+C_{gd})}
    ]
    と一致する一次ローパス特性を確認できる。

自由演習:オペアンプの開ループ周波数特性とステップ応答解析

【目的】
CMOSオペアンプの開ループ周波数特性およびステップ応答(過渡応答)を理論とシミュレーションにより解析し,
設計パラメータ(トランジスタ寸法,バイアス電流,容量)との関係を理解する。

【課題】

(1) 以下のオペアンプ回路について,AC解析により開ループ利得特性 |Av(f)| [dB] と位相特性を求めよ。
- 低周波利得 Av0 [dB]
- 利得交点周波数 (unity gain frequency) fu [Hz]
- 位相余裕 (phase margin) [deg]

(2) 小信号等価回路を描き,伝達関数 H(s) = Vout(s) / Vin(s) を導出せよ。

  H(s) = Av0 / (1 + s/ωp1)(1 + s/ωp2)

  ここで ωp1, ωp2 は1段目および2段目の極(ポール)とする。

(3) 1段目差動増幅段と2段目増幅段のゲインをそれぞれ gm1·ro1,gm2·ro2 として,
直流利得 Av0 を次式で表せ。

  Av0 ≈ (gm1·ro1) · (gm2·ro2)

(4) 周波数応答を近似的に次式で表せ。

  |Av(f)| ≈ Av0 / √{ [1 + (f/fp1)^2] [1 + (f/fp2)^2] }

  fp1 = 1 / (2π·R1·C1)
  fp2 = 1 / (2π·R2·C2)

(5) 図(a)の検証回路を用い,開ループゲインおよび帯域を理論計算せよ。

  f1 = 1 / (2π·R1·C1)
  f2 = Av0 / (2π·R2·C2)
  (条件:f1 < f2 < fu)

  例:
  Av0 = 60 dB (≈ 1000)
  f1 = 1 / (2π·16 kΩ·10 μF) ≈ 1 Hz
  f2 = Av0 / (2π·160 kΩ·1 mF) ≈ 10 Hz

(6) 過渡解析によりステップ応答(立上り時間・立下り時間・オーバーシュート)を求め,
開ループゲインおよびポール位置との関係を考察せよ。

(7) ステップ応答の理論式(一次系近似)を示せ。

  vo(t) = Vfinal·(1 - e^{-t/τ})
  τ = 1 / ωp1

(8) PMOS/NMOSのSPICEモデルパラメータ(Level=2)を用いてシミュレーションを実施し,
モデル式に基づく gm, ro の概算を示せ。

  gm = 2·ID / (VGS - Vth)
  ro = 1 / (λ·ID)

【補足】

.model pmos-X PMOS (Level=2 ... )
.model nmos-X NMOS (Level=2 ... )

上記パラメータを回路シミュレータ(例:LTspice, NGspice)に入力し,解析を行うこと。

# Program Name: opamp_openloop_response.py
# Creation Date: 20251021
# Overview: Open-loop frequency response and step response analysis of CMOS operational amplifier
# Usage: Run in Google Colab or Jupyter → observe Bode plot and transient response

!pip install numpy matplotlib scipy

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# ======================================
# Parameters / パラメータ設定
# ======================================

# トランジスタ・回路パラメータ(例)
gm1 = 1e-3       # [S] 1段目トランスコンダクタンス
gm2 = 2e-3       # [S] 2段目トランスコンダクタンス
ro1 = 100e3      # [Ω] 1段目出力抵抗
ro2 = 200e3      # [Ω] 2段目出力抵抗
R1  = 16e3       # [Ω]
R2  = 160e3      # [Ω]
C1  = 10e-6      # [F]
C2  = 1e-3       # [F]
Vstep = 1.0      # ステップ入力 [V]

# ======================================
# Derived values / 派生値計算
# ======================================
Av0 = (gm1 * ro1) * (gm2 * ro2)
fp1 = 1 / (2 * np.pi * R1 * C1)
fp2 = Av0 / (2 * np.pi * R2 * C2)
wp1, wp2 = 2*np.pi*fp1, 2*np.pi*fp2

print("=== Open-Loop Parameters ===")
print(f"Av0  = {Av0:.2e} (linear) = {20*np.log10(Av0):.2f} dB")
print(f"fp1  = {fp1:.2f} Hz")
print(f"fp2  = {fp2:.2f} Hz")

# ======================================
# Transfer Function / 伝達関数
# ======================================
num = [Av0]
den = [1/(wp1*wp2), (1/wp1 + 1/wp2), 1]
sys = signal.TransferFunction(num, den)

# ======================================
# Frequency Response / 周波数応答解析
# ======================================
f = np.logspace(0, 8, 500)   # 1 Hz ~ 100 MHz
w = 2 * np.pi * f
w, mag, phase = signal.bode(sys, w)

plt.figure(figsize=(7,4))
plt.semilogx(f, mag)
plt.title("Open-Loop Gain (Bode Magnitude)")
plt.xlabel("Frequency [Hz]")
plt.ylabel("Gain [dB]")
plt.grid(which='both')
plt.show()

plt.figure(figsize=(7,4))
plt.semilogx(f, phase)
plt.title("Open-Loop Phase Response")
plt.xlabel("Frequency [Hz]")
plt.ylabel("Phase [deg]")
plt.grid(which='both')
plt.show()

# ======================================
# Step Response / ステップ応答解析
# ======================================
t, y = signal.step(sys)
y = y * Vstep / np.max(y) * Vstep  # 正規化(ステップ入力振幅を考慮)

plt.figure(figsize=(6,4))
plt.plot(t, y)
plt.title("Step Response (Transient)")
plt.xlabel("Time [s]")
plt.ylabel("Vout [V]")
plt.grid(True)
plt.show()

# ======================================
# Time constant and comparison / 時定数比較
# ======================================
tau = 1 / wp1
print("\n=== Step Response (First-Order Approximation) ===")
print(f"Time constant τ = {tau:.3e} [s]")
print("Expected vo(t) ≈ Vfinal * (1 - exp(-t/τ))")

【Python課題】AD/DA変換器の特性評価(ランプ波入力)

次の仕様に基づき、Pythonでプログラムを作成せよ。

(1) A/D変換器の評価プログラム
• A/D変換器は 8 ビット、基準電圧 Vref = 2.0 V とする。
• 1LSB の理論値を計算すること。
• 入力信号はランプ波(0 V → Vref まで直線的に増加)とする。
• 例えば、100 サンプルに分割して入力を生成すること。
• 各入力値に対する理論的デジタル出力を計算し、グラフにプロットせよ。
• 測定値が与えられた場合は理論値との差(誤差)を計算せよ。

(2) D/A変換器の評価プログラム
• D/A変換器は 8 ビット、基準電圧 Vref = 2.0 V とする。
• 1LSB の理論値を計算すること。
• 入力信号はランプ波に対応するデジタルコード列とする。
• 例: CODE = 0, 1, 2, …, 255
• 各コードに対する出力電圧(理論値)を計算し、グラフにプロットせよ。
• 測定値が与えられた場合は理論値との差(誤差)を計算せよ。

(3) 発展課題
• A/D → D/A を直列接続したシステムをシミュレーションする。
• 入力信号をランプ波(0 V → Vref)とした場合、最終的な出力波形を描画せよ。
• 理論値と比較して、システム全体の誤差を評価せよ。


import numpy as np
import matplotlib.pyplot as plt

# ===================== Parameters / パラメータ =====================
Vref = 2.0           # Reference voltage [V] / 基準電圧
Nbit = 8             # Number of bits / ビット数
Nsamples = 100       # Number of samples for ramp input / ランプ波の分割数

# ===================== 1 LSB Calculation / 1LSB計算 =====================
LSB = Vref / (2**Nbit)   # 1LSB voltage value / 1LSBの電圧
print("1 LSB =", LSB, "V")

# ===================== (1) ADC Evaluation / A/D変換器評価 =====================
# Generate ramp input signal / ランプ波入力信号生成
Vin = np.linspace(0, Vref, Nsamples)   # 0V → Vrefまで直線的に増加

# Ideal ADC output code / 理論的デジタル出力
ADC_code = np.floor(Vin / Vref * (2**Nbit - 1)).astype(int)

# Plot ADC transfer characteristic / ADC伝達特性の描画
plt.figure(figsize=(8,4))
plt.plot(Vin, ADC_code, "bo-", label="ADC Output Code")
plt.title("ADC Ramp Response")
plt.xlabel("Input Voltage [V]")
plt.ylabel("Digital Output Code")
plt.grid(True)
plt.legend()
plt.show()

# ===================== (2) DAC Evaluation / D/A変換器評価 =====================
# Generate digital codes / デジタルコード生成
DAC_code = np.arange(0, 2**Nbit)

# Ideal DAC output / 理論的出力電圧
Vout_DAC = DAC_code * LSB

# Plot DAC transfer characteristic / DAC伝達特性の描画
plt.figure(figsize=(8,4))
plt.plot(DAC_code, Vout_DAC, "r-", label="DAC Output Voltage")
plt.title("DAC Ramp Response")
plt.xlabel("Digital Input Code")
plt.ylabel("Output Voltage [V]")
plt.grid(True)
plt.legend()
plt.show()

# ===================== (3) Cascade ADC→DAC / ADC→DAC直列システム =====================
# ADC output codes fed into DAC / ADC出力コードをDACに入力
Vout_cascade = ADC_code * LSB

# Error evaluation / 誤差評価
error = Vin - Vout_cascade

# Plot comparison / 比較プロット
plt.figure(figsize=(10,5))
plt.plot(Vin, Vin, "k--", label="Ideal Input (Vin)")
plt.plot(Vin, Vout_cascade, "g.-", label="ADC→DAC Output")
plt.title("ADC→DAC Cascade Response")
plt.xlabel("Input Voltage [V]")
plt.ylabel("Voltage [V]")
plt.grid(True)
plt.legend()
plt.show()

# Plot error / 誤差プロット
plt.figure(figsize=(8,4))
plt.plot(Vin, error, "m.-", label="Error (Vin - Vout)")
plt.title("System Error (ADC→DAC)")
plt.xlabel("Input Voltage [V]")
plt.ylabel("Error [V]")
plt.grid(True)
plt.legend()
plt.show()

【技術解説:A/D・D/A変換器の1LSB理論式と評価】

  1. はじめに
    アナログ・デジタル変換器(ADC)およびデジタル・アナログ変換器(DAC)は、連続信号と離散信号を相互変換する装置である。その性能指標の一つに1LSB(Least Significant Bit:最小有効ビット)電圧がある。本稿では、AD/DA変換器の1LSB理論式を導出し、実験値との関係を整理する。

  1. A/D変換器(ADC)の1LSB理論式

(1) 定義式
V_LSB = (2 × V_ref) / (2^n - 1)

ここで、
V_ref:基準電圧(Reference Voltage)
n:分解能(ビット数)

「2×Vref」は入力範囲が±Vref(差動入力)であることを意味する。範囲は −Vref ~ +Vref、全振幅2Vref。

(2) 数値例
V_ref = 1.23 [V], n = 8
V_LSB = (2 × 1.23) / 255 = 9.647 [mV]

1カウントあたりの入力電圧変化量は約9.65mV。

(3) 意味
・V_LSBはデジタル出力1カウントに対応する最小の入力電圧変化量。
・(2^n - 1)は255段階の間隔を表す(8ビットの場合)。
・ADCは入力振幅2Vrefを255分割する。


  1. D/A変換器(DAC)の1LSB理論式

(1) 定義式
V_LSB = V_ref / (2^n - 1)

(2) 出力電圧の一般式
V_out = V_ref × (1/2^1 × b1 + 1/2^2 × b2 + … + 1/2^n × bn)
ここで bi ∈ {0,1}

各ビットは2進加重抵抗分圧回路(R-2Rラダー等)により実現される。

(3) 数値例
V_ref = 2.0 [V], n = 8
V_LSB = 2.0 / 255 = 7.843 [mV]
出力電圧は0〜2Vの範囲を255等分。


  1. ADCとDACの比較表
項目 A/D変換器 D/A変換器
入力信号 アナログ電圧 デジタル値
出力信号 デジタル値 アナログ電圧
分解能 2^n 段階 2^n 段階
1LSB電圧 (2V_ref)/(2^n - 1) (V_ref)/(2^n - 1)
入力・出力範囲 ±Vref 0〜Vref
数値例 (n=8, Vref=1.23V) 9.647 mV 7.843 mV (Vref=2V時)

  1. 物理的意味と誤差要因

(1) 物理的意味
・ADCは±Vrefの差動入力を2Vrefで換算。
・DACは0〜Vrefの単極変換で基準電圧1倍。

(2) 主な誤差要因
・抵抗精度:R-2Rラダーの抵抗誤差
・オペアンプ誤差:オフセット電圧、バイアス電流
・基準電圧誤差:Vrefの温度ドリフトや電源ノイズ
・スイッチング遅延:サンプリング保持遅延
・ノイズ:外部電源や量子化ノイズの影響


  1. まとめ

理論的な1LSB電圧式:
V_LSB(ADC) = (2V_ref)/(2^n - 1)
V_LSB(DAC) = (V_ref)/(2^n - 1)

ADCは正負両振幅(±Vref)の差動入力を扱い、
DACは0〜Vrefの単極出力を扱うため、係数が異なる。

実験では、上式の理論値を基準に、実測値との差から
非直線性誤差、オフセット誤差などを評価する。


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?