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?

概算用のCMOS

Last updated at Posted at 2025-02-08

image.png
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} Ω")

image.png

image.png

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?