https://kobaweb.ei.st.gunma-u.ac.jp/lecture/2009lecture-4.pdf
# NMOSソース接地回路の設計計算
import numpy as np
# 与えられたパラメータ
Vth = 0.6 # 閾値電圧 [V]
k_prime = 160e-6 # k' = μCox [A/V^2]
Vdd = 3.3 # 電源電圧 [V]
W_L_1 = 100 / 0.5 # 初期の W/L
W_L_2 = 200 / 0.5 # 変更後の W/L
Id_1 = 1e-3 # 初期のドレイン電流 [A]
Id_2 = 2e-3 # 変更後のドレイン電流 [A]
# (VGS - VTH) を求める
VGS_minus_VTH_1 = np.sqrt((2 * Id_1) / (k_prime * W_L_1))
VGS_1 = VGS_minus_VTH_1 + Vth
# gm を求める
gm_1 = (2 * Id_1) / VGS_minus_VTH_1
# Rd を求める (ゲイン 20dB の条件より)
gain_1 = 10 # 20dB = 10倍
Rd = gain_1 / gm_1
# W/L を変更した場合
gm_2 = (2 * Id_2) / VGS_minus_VTH_1
gain_2 = gm_2 * Rd
gain_2_dB = 20 * np.log10(gain_2)
# 結果を表示
print(f"初期状態: W/L = 100/0.5um")
print(f" VGS = {VGS_1:.2f} V")
print(f" gm = {gm_1:.2e} S")
print(f" Rd = {Rd:.2f} Ω")
print(f" ゲイン = {gain_1:.2f} 倍 = {20 * np.log10(gain_1):.2f} dB")
print("\n")
print(f"変更後: W/L = 200/0.5um")
print(f" gm = {gm_2:.2e} S")
print(f" ゲイン = {gain_2:.2f} 倍 = {gain_2_dB:.2f} dB")
import numpy as np
import matplotlib.pyplot as plt
from sympy import symbols, Eq, solve
# シンボリック変数の定義
mu_Cox, W, L, Veff, Vds, VA = symbols('mu_Cox W L Veff Vds VA')
# Ids の式
Ids_expr = (mu_Cox / 2) * (W / L) * Veff**2 * (1 + Vds / VA)
# 数値計算用パラメータ
Vth = 0.6 # 閾値電圧 [V]
k_prime = 160e-6 # k' = μCox [A/V^2]
Vdd = 3.3 # 電源電圧 [V]
W_L_1 = 100 / 0.5 # 初期の W/L
W_L_2 = 200 / 0.5 # 変更後の W/L
Id_1 = 1e-3 # 初期のドレイン電流 [A]
Id_2 = 2e-3 # 変更後のドレイン電流 [A]
VA_value = 10 # チャネル長変調係数 (仮の値)
# VGS の範囲を設定
VGS_values = np.linspace(0.4, 2.0, 100)
Id_values = []
# Ids を計算
for VGS in VGS_values:
if VGS > Vth:
Veff = VGS - Vth
Id = (k_prime * W_L_1 / 2) * Veff**2 * (1 + Vdd / VA_value)
else:
Id = 0
Id_values.append(Id)
# プロット
plt.figure(figsize=(8, 5))
plt.plot(VGS_values, Id_values, label="Id vs Vgs", color='b')
plt.axvline(x=Vth, color='r', linestyle='--', label="Vth")
plt.xlabel("Vgs [V]")
plt.ylabel("Ids [A]")
plt.title("NMOS Saturation Region: Id vs Vgs with Channel Length Modulation")
plt.legend()
plt.grid()
plt.show()
# (VGS - VTH) を求める
VGS_minus_VTH_1 = np.sqrt((2 * Id_1) / (k_prime * W_L_1))
VGS_1 = VGS_minus_VTH_1 + Vth
# gm を求める
gm_1 = (2 * Id_1) / VGS_minus_VTH_1
# Rd を求める (ゲイン 20dB の条件より)
gain_1 = 10 # 20dB = 10倍
Rd = gain_1 / gm_1
# W/L を変更した場合
gm_2 = (2 * Id_2) / VGS_minus_VTH_1
gain_2 = gm_2 * Rd
gain_2_dB = 20 * np.log10(gain_2)
# 結果を表示
print(f"初期状態: W/L = 100/0.5um")
print(f" VGS = {VGS_1:.2f} V")
print(f" gm = {gm_1:.2e} S")
print(f" Rd = {Rd:.2f} Ω")
print(f" ゲイン = {gain_1:.2f} 倍 = {20 * np.log10(gain_1):.2f} dB")
print("\n")
print(f"変更後: W/L = 200/0.5um")
print(f" gm = {gm_2:.2e} S")
print(f" ゲイン = {gain_2:.2f} 倍 = {gain_2_dB:.2f} dB")
import numpy as np
import matplotlib.pyplot as plt
from sympy import symbols, Eq, solve
# シンボリック変数の定義
mu_Cox, W, L, Veff, Vds, VA = symbols('mu_Cox W L Veff Vds VA')
# Ids の式
Ids_expr = (mu_Cox / 2) * (W / L) * Veff**2 * (1 + Vds / VA)
# 数値計算用パラメータ
Vth = 0.6 # 閾値電圧 [V]
k_prime = 160e-6 # k' = μCox [A/V^2]
Vdd = 3.3 # 電源電圧 [V]
W_L_1 = 100 / 0.5 # 初期の W/L
W_L_2 = 200 / 0.5 # 変更後の W/L
Id_1 = 1e-3 # 初期のドレイン電流 [A]
Id_2 = 2e-3 # 変更後のドレイン電流 [A]
VA_value = 10 # チャネル長変調係数 (仮の値)
# Vds の範囲を設定 (-10V から 10V)
Vds_values = np.linspace(-10, 10, 100)
Id_values = []
Veff_fixed = 2.0 # 固定した Veff の値
# Ids を計算
for Vds in Vds_values:
Id = (k_prime * W_L_1 / 2) * Veff_fixed**2 * (1 + Vds / VA_value)
Id_values.append(Id)
# Vds における Ids = 0 の値を求める
Vds_zero = None
for i in range(len(Id_values)):
if Id_values[i] <= 0:
Vds_zero = Vds_values[i]
break
if Vds_zero is not None:
print(f"Ids = 0 となる Vds: {Vds_zero:.2f} V")
else:
print("Ids = 0 となる Vds は見つかりませんでした。")
# 縦軸の最小値を求める
Id_min = min(Id_values)
# プロット
plt.figure(figsize=(8, 5))
plt.plot(Vds_values, Id_values, label="Id vs Vds", color='b')
plt.xlabel("Vds [V]")
plt.ylabel("Ids [A]")
plt.title("NMOS Saturation Region: Id vs Vds with Channel Length Modulation")
plt.ylim(0, max(Id_values) * 1.1) # 縦軸を0から最大値の1.1倍まで設定
plt.legend()
plt.grid()
plt.show()
# (VGS - VTH) を求める
VGS_minus_VTH_1 = np.sqrt((2 * Id_1) / (k_prime * W_L_1))
VGS_1 = VGS_minus_VTH_1 + Vth
# gm を求める
gm_1 = (2 * Id_1) / VGS_minus_VTH_1
# Rd を求める (ゲイン 20dB の条件より)
gain_1 = 10 # 20dB = 10倍
Rd = gain_1 / gm_1
# W/L を変更した場合
gm_2 = (2 * Id_2) / VGS_minus_VTH_1
gain_2 = gm_2 * Rd
gain_2_dB = 20 * np.log10(gain_2)
# 結果を表示
print(f"初期状態: W/L = 100/0.5um")
print(f" VGS = {VGS_1:.2f} V")
print(f" gm = {gm_1:.2e} S")
print(f" Rd = {Rd:.2f} Ω")
print(f" ゲイン = {gain_1:.2f} 倍 = {20 * np.log10(gain_1):.2f} dB")
print("\n")
print(f"変更後: W/L = 200/0.5um")
print(f" gm = {gm_2:.2e} S")
print(f" ゲイン = {gain_2:.2f} 倍 = {gain_2_dB:.2f} dB")
import numpy as np
import matplotlib.pyplot as plt
# パラメータ設定 (適切な値に変更)
W = 10e-6 # チャンネル幅 (m)
L = 1e-6 # チャンネル長 (m)
mu_Cox = 100e-6 # 移動度×酸化膜容量 (A/V^2)
VT = 0.7 # しきい値電圧 (V)
# VG の範囲を設定
VG = np.linspace(VT, 2.0, 100) # VT 以上でプロット
# 計算式
factor = ((W / (2 * L)) * mu_Cox) ** 0.5
ID_mod = factor * (VG - VT)
# プロット
plt.figure(figsize=(8, 5))
plt.plot(VG, ID_mod, label=r'$\left( \frac{W}{2L} \mu_{Cox} \right)^{0.5} (V_G - V_T)$')
plt.xlabel(r'$V_G$ (V)') # 横軸ラベル
plt.ylabel(r'$I_{D,mod}$') # 縦軸ラベル
plt.title('Modified Drain Current vs Gate Voltage')
plt.legend()
plt.grid()
plt.show()
カレントミラー負荷を用いた増幅器
import numpy as np
import matplotlib.pyplot as plt
# パラメータ設定
A_in = 10e-3 # 入力信号の振幅 (20mV_pp のため、10mV_peak)
G = -45 # 増幅率 (Gain)
f = 1e6 # 周波数 (1MHz, 適宜調整)
T = 1 / f # 周期
t = np.linspace(0, 2*T, 1000) # 2周期分の時間
# 入力信号 V_in
V_in = A_in * np.sin(2 * np.pi * f * t)
# 出力信号 V_out (増幅後)
V_out = G * V_in
# プロット
plt.figure(figsize=(8, 5))
plt.plot(t * 1e6, V_in, color='red', label=r'$V_{in} = 10mV \cdot \sin(2\pi f t)$')
plt.plot(t * 1e6, V_out, color='blue', label=r'$V_{out} = G \cdot V_{in}$')
# 軸ラベルとタイトル
plt.xlabel("Time (µs)") # 時間軸 (マイクロ秒)
plt.ylabel("Voltage (V)") # 電圧軸
plt.title("Input and Amplified Sine Waves")
plt.legend()
plt.grid()
plt.show()
import numpy as np
import matplotlib.pyplot as plt
import scipy.signal as signal
# パラメータ設定
gm1 = 1e-3 # S
gm6 = 5e-3 # S
ro2 = 100e3 # Ω
ro4 = 100e3 # Ω
ro6 = 50e3 # Ω
ro7 = 50e3 # Ω
Cc = 1e-12 # F
Cgs6 = 2e-12 # F
CL = 5e-12 # F
# ゲイン K の計算
K = gm1 * ((ro2 * ro4) / (ro2 + ro4)) * gm6 * ((ro6 * ro7) / (ro6 + ro7))
K_dB = 20 * np.log10(K) # デシベル表記
# 極 (ポール) の計算
wp1 = 1 / (((ro2 * ro4) / (ro2 + ro4)) * gm6 * ((ro6 * ro7) / (ro6 + ro7)) * Cc)
wp2 = (gm6 * Cc) / (Cgs6 * CL + Cc * (Cgs6 + CL))
# ゼロの計算 (RHPゼロ)
wz = -gm6 / Cc
# 伝達関数の作成
num = [K, K * wz] # 分子
den = [1, wp1 + wp2, wp1 * wp2] # 分母
sys = signal.TransferFunction(num, den)
# 周波数応答プロット
w, mag, phase = signal.bode(sys)
plt.figure(figsize=(10, 6))
# ゲインプロット
plt.subplot(2, 1, 1)
plt.semilogx(w, mag, label="Magnitude")
plt.xlabel("Frequency (rad/s)")
plt.ylabel("Magnitude (dB)")
plt.title("Bode Plot of the Transfer Function")
plt.grid(True)
plt.legend()
# 位相プロット
plt.subplot(2, 1, 2)
plt.semilogx(w, phase, label="Phase", color='r')
plt.xlabel("Frequency (rad/s)")
plt.ylabel("Phase (degrees)")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
# 計算結果出力
print("\n### 計算結果 ###")
print(f"K = {K:.2e} (linear), {K_dB:.2f} dB")
print(f"wp1 = {wp1:.2e} rad/s")
print(f"wp2 = {wp2:.2e} rad/s")
print(f"wz = {wz:.2e} rad/s (RHP Zero)")
import numpy as np
import matplotlib.pyplot as plt
import scipy.signal as signal
# パラメータ設定
gm1 = 1e-3 # S
gm6 = 5e-3 # S
ro2 = 100e3 # Ω
ro4 = 100e3 # Ω
ro6 = 50e3 # Ω
ro7 = 50e3 # Ω
Cc = 1e-12 # F
Cgs6 = 2e-12 # F
CL = 5e-12 # F
Rc = 1 / gm6 # RHPゼロを補償する抵抗
# Rc の値が 1/gm6 と等しい場合の回避策
denom = 1 - gm6 * Rc
if np.isclose(denom, 0):
denom = 1e-9 # 非ゼロの小さい値に置き換える
# ゲイン K の計算
K = gm1 * ((ro2 * ro4) / (ro2 + ro4)) * gm6 * ((ro6 * ro7) / (ro6 + ro7))
K_dB = 20 * np.log10(K) # デシベル表記
# 極 (ポール) の計算
wp1 = 1 / (((ro2 * ro4) / (ro2 + ro4)) * gm6 * ((ro6 * ro7) / (ro6 + ro7)) * Cc)
wp2 = (gm6 * Cc) / (Cgs6 * CL + Cc * (Cgs6 + CL))
# 修正されたゼロの計算 (RHPゼロの補償)
wz = - (gm6 / Cc) * (1 / denom)
# 伝達関数の作成
num = [K, K * wz] # 分子
den = [1, wp1 + wp2, wp1 * wp2] # 分母
sys = signal.TransferFunction(num, den)
# 周波数応答プロット
w, mag, phase = signal.bode(sys)
plt.figure(figsize=(10, 6))
# ゲインプロット
plt.subplot(2, 1, 1)
plt.semilogx(w, mag, label="Magnitude")
plt.xlabel("Frequency (rad/s)")
plt.ylabel("Magnitude (dB)")
plt.title("Bode Plot of the Transfer Function with Compensation")
plt.grid(True)
plt.legend()
# 位相プロット
plt.subplot(2, 1, 2)
plt.semilogx(w, phase, label="Phase", color='r')
plt.xlabel("Frequency (rad/s)")
plt.ylabel("Phase (degrees)")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
# 計算結果出力
print("\n### 計算結果 ###")
print(f"K = {K:.2e} (linear), {K_dB:.2f} dB")
print(f"wp1 = {wp1:.2e} rad/s")
print(f"wp2 = {wp2:.2e} rad/s")
print(f"wz = {wz:.2e} rad/s (Compensated Zero)")
print(f"Rc = {Rc:.2e} Ω (Compensation Resistor)")
# 必要なライブラリのインポート
import numpy as np
import pandas as pd
# パラメータ設定
I_SS = 100e-6 # 差動対バイアス電流 (A)
I_6 = 200e-6 # トランジスタ6の電流 (A)
beta_1_2 = 100e-6 # 差動対のトランジスタの電流増幅係数
beta_6 = 150e-6 # トランジスタ6の電流増幅係数
C_L = 2e-12 # 負荷容量 (F)
C_C = 0.22 * C_L # 補償容量 (F)
r_o4 = 100e3 # 出力抵抗 (Ω)
r_o2 = 80e3 # 出力抵抗 (Ω)
r_o5 = 50e3 # 出力抵抗 (Ω)
r_o6 = 90e3 # 出力抵抗 (Ω)
r_o7 = 70e3 # 出力抵抗 (Ω)
g_m3_4 = 1e-3 # 差動ペアのトランスコンダクタンス (S)
# トランスコンダクタンス計算
g_md = np.sqrt(beta_1_2 * I_SS) # 差動対のトランスコンダクタンス (S)
g_m6 = np.sqrt(2 * beta_6 * I_6) # トランジスタ6のトランスコンダクタンス (S)
# 抵抗計算
R_O1 = 1 / (1 / r_o4 + 1 / r_o2) # 並列合成
R_O2 = 1 / (1 / r_o6 + 1 / r_o7) # 並列合成
# 電圧利得計算
A_V = g_md * R_O1 * g_m6 * R_O2
# 利得帯域幅積 (GBW) 計算
GBW = g_md / (2 * np.pi * C_C)
# 同相除去比 (CMRR) 計算
CMRR = 2 * r_o5 * g_m3_4 * g_md * R_O1
# 出力抵抗
R_O = R_O2
# デシベル換算
A_V_dB = 20 * np.log10(A_V) # 電圧利得のデシベル値
CMRR_dB = 20 * np.log10(CMRR) # 同相成分除去比のデシベル値
# 計算結果をプリント関数で表示(デシベル値を含む)
print("=== Amplifier Calculations ===")
print(f"g_md (S): {g_md:.6f}")
print(f"g_m6 (S): {g_m6:.6f}")
print(f"R_O1 (Ω): {R_O1:.2f}")
print(f"R_O2 (Ω): {R_O2:.2f}")
print(f"A_V : {A_V:.6f} (linear), {A_V_dB:.2f} dB")
print(f"GBW (Hz): {GBW:.2f}")
print(f"CMRR : {CMRR:.2f} (linear), {CMRR_dB:.2f} dB")
print(f"R_O (Ω): {R_O:.2f}")
# 設定パラメータ
beta_6 = 100e-6 # μnCox for transistor M6 (A/V^2)
I_6 = 10e-6 # Bias current for M6 (A)
beta_1_2 = 200e-6 # μnCox for transistors M1, M2 (A/V^2)
I_SS = 20e-6 # Tail current source (A)
C_L = 4e-12 # Load capacitance (F)
# トランスコンダクタンス計算
g_m6 = np.sqrt(2 * beta_6 * I_6)
g_md = np.sqrt(beta_1_2 * I_SS)
# コンペンセーション・コンデンサ計算
C_C_min = 0.22 * C_L
# 抵抗の設定
r_o4_prime = 100e3 # ohm
r_2 = 50e3 # ohm
r_o6_prime = 80e3 # ohm
r_7 = 40e3 # ohm
# 出力インピーダンス
R_O1 = 1 / (1/r_o4_prime + 1/r_2) # 並列抵抗
R_O2 = 1 / (1/r_o6_prime + 1/r_7) # 並列抵抗
# 電圧利得
A_V = g_md * R_O1 * g_m6 * R_O2
A_V_dB = 20 * np.log10(A_V) # 電圧利得 (dB)
# 利得帯域幅積 (GBW)
GBW = g_md / (2 * np.pi * C_C_min)
# CMRR
r_o5 = 120e3 # ohm
g_m3_4 = 5e-6 # A/V (for transistors M3 and M4)
CMRR = 2 * r_o5 * g_m3_4 * g_md * R_O1
# 出力インピーダンス
R_O = R_O2
# 計算結果をプリント
print("=== オペアンプ設計パラメータ ===")
print(f"トランスコンダクタンス g_m6: {g_m6:.6e} S")
print(f"トランスコンダクタンス g_md: {g_md:.6e} S")
print(f"最小コンペンセーション・コンデンサ C_C_min: {C_C_min:.6e} F")
print(f"出力インピーダンス R_O1: {R_O1:.2f} Ω")
print(f"出力インピーダンス R_O2: {R_O2:.2f} Ω")
print(f"電圧利得 A_V: {A_V:.2e}")
print(f"電圧利得 A_V (dB): {A_V_dB:.2f} dB")
print(f"利得帯域幅積 GBW: {GBW:.2e} Hz")
print(f"同相分除去比 CMRR: {CMRR:.2e}")
print(f"出力インピーダンス R_O: {R_O:.2f} Ω")