1
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集積回路の設計」の問題をPythonで解いてみる[2-4]

Last updated at Posted at 2025-07-10

計算環境

使用する言語:Python
使用するライブラリ:Numpy Matplotlib.pyplot
使用するPC:HP 15-fc windows11

パラメータの定義

本書p.44の表2.1にすべてのパラメータが定義されており、それらはあらかじめコードの序盤に定義している。

大問2-4

MOSトランジスタの$ I_D $と$ V_{GS} $の関係を(a)$ V_{DS} $をパラメータ、(b)$ V_{BS} $をパラメータ、としてそれぞれ図示せよ。特性領域の境界を図に示せ。

解答コード

今回はNMOSで考える。

Q_2-4.py
import numpy as np
import matplotlib.pyplot as plt

# 定義済みのパラメータ
EPSILON_0 = 8.85 * 10**-12  # 真空の誘電率[F/m]
EPSILON_SIO2 = 3.9  # SI02の比誘電率[F/m]
TOX = 9.0 * 10**-9  # ゲート酸化膜厚[m]
COX = (EPSILON_0 * EPSILON_SIO2) / TOX  # 単位面積あたりのゲート容量[F/m**2]

#表2-1のモデルパラメータ
UO_N = 350 * 10**-4  # 電子の移動度[m^2/Vs]
LAMBDA_N = 0.1  # NMOSのチャネル長変調係数
GAMMA_N = 0.45  # NMOSの基板バイアス定数[V**(1/2)]
PHI_N = 0.9  # 2PHI[V]
VTH_N = 0.7  # NMOSのしきい値電圧[V]
LD_N = 0.08e-6  # ソース/ドレインの側壁拡散長[m]
PB_N = 0.9  # ソース/ドレイン接合のビルトインポテンシャル[V]
MJ_N = 0.45  # CJの解析式の指数[なし]
MJSW_N = 0.2  # CJSWの解析式の指数[なし]
CJ_N = 0.56E-3  # ソース/ドレイン底面の単位面積あたりの接合容量[F/m**2]
CJSW_N = 0.35e-11  # ソース/ドレイン側壁の単位長あたりの接合容量[F/m]
CGDO_N = 0.4E-9  # 単位長あたりのゲート-ドレインのオーバーラップ容量[F/m]
UO_P = 100 * 10**-4  # ホールの移動度[m^2/Vs]
LAMBDA_P = 0.2  # PMOSのチャネル長変調係数
GAMMA_P = 0.4  # PMOSの基板バイアス定数[V**(1/2)]
PHI_P = 0.8  # 2PHI[V]
VTH_P = -0.8  # PMOSのしきい値電圧[V]
LD_P = 0.09e-6  # ソース/ドレインの側壁拡散長[m]
PB_P = 0.9  # ソース/ドレイン接合のビルトインポテンシャル[V]
MJ_P = 0.5  # CJの解析式の指数[なし]
MJSW_P = 0.3  # CJSWの解析式の指数[なし]
CJ_P = 0.94E-3  # ソース/ドレイン底面の単位面積あたりの接合容量[F/m**2]
CJSW_P = 0.32e-11  # ソース/ドレイン側壁の単位長あたりの接合容量[F/m]
CGDO_P = 0.3E-9  # 単位長あたりのゲート-ドレインのオーバーラップ容量[F/m]

#大問2の定義
VDD = 3  # VDD[V]
W = 50 * 10**-6  # ゲート幅W[m]
L = 0.5 * 10**-6  # ゲート長L[m]
beta_N = UO_N * COX * (W / L)  # beta_N
beta_P = UO_P * COX * (W / L)  # beta_P
R1 = 1000  # 抵抗[Ω]
R2 = 2000  # 抵抗[Ω]

# NMOSのドレイン電流を計算する関数(修正版)
def calculate_id_nmos(vgs, vds, vbs):
    """
    NMOSのドレイン電流I_Dを計算します。
    vgsはNumpy配列、vdsとvbsはスカラーを想定しています。
    """
    # 基板バイアス効果によるしきい値電圧の変化
    vth = VTH_N + GAMMA_N * (np.sqrt(PHI_N - vbs) - np.sqrt(PHI_N))
    
    # 出力用の配列を0で初期化 (カットオフ領域)
    id_current = np.zeros_like(vgs, dtype=float)

    # 線形領域のマスク
    linear_mask = (vgs >= vth) & (vds < vgs - vth)
    # 飽和領域のマスク
    saturation_mask = (vgs >= vth) & (vds >= vgs - vth)
    
    # 線形領域の電流を計算
    if np.any(linear_mask):
        id_current[linear_mask] = beta_N * ((vgs[linear_mask] - vth) * vds - 0.5 * vds**2) * (1 + LAMBDA_N * vds)
    
    # 飽和領域の電流を計算
    if np.any(saturation_mask):
        id_current[saturation_mask] = 0.5 * beta_N * (vgs[saturation_mask] - vth)**2 * (1 + LAMBDA_N * vds)
        
    return id_current

# --- (a) V_DSをパラメータとしたI_D-V_GS特性 ---
plt.figure(figsize=(10, 6))
vgs_range = np.linspace(0, VDD, 500)
vds_params = [0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
vbs_a = 0  # V_BSを0Vに固定

for vds in vds_params:
    ids = calculate_id_nmos(vgs_range, vds, vbs_a)
    plt.plot(vgs_range, ids * 1000, label=f'$V_{{DS}} = {vds:.1f}$ V')

# 飽和領域と線形領域の境界線 (V_DS = V_GS - V_th)
vth_a = VTH_N + GAMMA_N * (np.sqrt(PHI_N - vbs_a) - np.sqrt(PHI_N))
vgs_boundary = np.linspace(vth_a, VDD, 100)
# 境界線上では V_ds = V_gs - V_th
ids_boundary = 0.5 * beta_N * (vgs_boundary - vth_a)**2 * (1 + LAMBDA_N * (vgs_boundary - vth_a))
plt.plot(vgs_boundary, ids_boundary * 1000, 'k--', label='Saturation Boundary ($V_{DS} = V_{GS} - V_{th}$)')

plt.title('(a) $I_D$ vs $V_{GS}$ with $V_{DS}$ as a parameter ($V_{BS}=0$ V)')
plt.xlabel('$V_{GS}$ [V]')
plt.ylabel('$I_D$ [mA]')
plt.legend()
plt.grid(True)
plt.xlim(0, VDD)
plt.ylim(0)
plt.show()


# --- (b) V_BSをパラメータとしたI_D-V_GS特性 ---
plt.figure(figsize=(10, 6))
vds_b = VDD  # V_DSを3Vに固定
vbs_params = [0, -0.5, -1.0, -1.5, -2.0]

boundary_vgs = []
boundary_ids = []

for vbs in vbs_params:
    ids = calculate_id_nmos(vgs_range, vds_b, vbs)
    plt.plot(vgs_range, ids * 1000, label=f'$V_{{BS}} = {vbs:.1f}$ V')
    
    # 各曲線の飽和開始点を計算 (V_GS - V_th = V_DS)
    vth_b = VTH_N + GAMMA_N * (np.sqrt(PHI_N - vbs) - np.sqrt(PHI_N))
    vgs_sat_point = vds_b + vth_b
    if vgs_sat_point <= VDD:
        # vgs_sat_pointが配列でないことを確認
        ids_sat_point_arr = calculate_id_nmos(np.array([vgs_sat_point]), vds_b, vbs)
        if ids_sat_point_arr.size > 0:
            ids_sat_point = ids_sat_point_arr[0]
            boundary_vgs.append(vgs_sat_point)
            boundary_ids.append(ids_sat_point)

# 飽和領域の境界線をプロット
if boundary_vgs:
    sorted_points = sorted(zip(boundary_vgs, boundary_ids))
    if sorted_points:
        sorted_vgs, sorted_ids = zip(*sorted_points)
        label_text = 'Saturation Boundary ($V_{GS} - V_{th} = V_{DS} = ' + str(vds_b) + '$ V)'
        plt.plot(sorted_vgs, [i * 1000 for i in sorted_ids], 'k--o', label=label_text)

title_text = '(b) $I_D$ vs $V_{GS}$ with $V_{BS}$ as a parameter ($V_{DS}=' + str(vds_b) + '$ V)'
plt.title(title_text)
plt.xlabel('$V_{GS}$ [V]')
plt.ylabel('$I_D$ [mA]')
plt.legend()
plt.grid(True)
plt.xlim(0, VDD)
plt.ylim(0)
plt.show()


出力結果

Q_2-4(a).png
Q_2-4(b).png

今回用いた公式

今回用いた公式は以下である。

しきい値電圧の計算(基盤バイアス効果)

トランジスタがONになるために必要なゲート電圧であるしきい値電圧 $ V_{TH} $ は、基板-ソース間電圧 $ V_{BS} $の影響を受けて変動する。これを基板バイアス効果と呼ぶ。

\displaylines{
V_{TH}=V_{TH0}+\gamma_N(\sqrt{2\phi_F-V_{BS}}-\sqrt{2\phi_F})
}

ここで、
$ \gamma_N $:基盤バイアス定数
$ 2\phi_F $:表面ポテンシャル
$ V_{BS} $:基盤-ソース間電圧

ドレイン電流の計算

ドレイン電流$ I_D $は、$ V_{GS} $と$ V_{DS} $の関係によって決まる3つの動作領域で、異なる式を用いて計算される。計算には、以下の利得係数 ($ \beta_N $) が共通して使われる。

\displaylines{
\beta_N=\mu_NC_{ox}\frac{W}{L}
}

ここで、
$ \mu_N $:電子の移動度
$ C_{ox} $:単位面積当たりのゲート容量
$ W,L $:ゲート幅とゲート長

①カットオフ領域

ゲート-ソース間電圧がしきい値電圧より低い($ V_{GS}<V_{TH} $)領域である。トランジスタはOFFになる。

\displaylines{
I_D=0
}

②線形領域(非飽和領域)

トランジスタはONの状態で、$ V_{DS} $が十分に低い$ (V_{GS}>V_{TH} $かつ$ V_{DS}<V_{GS}-V_{TH} )$領域である。

\displaylines{
I_D=\beta_N[(V_{GS}-V_{TH})V_{DS}-\frac{1}{2}V_{DS}^2](1+\lambda_NV_{DS})
}

$ \lambda_N $:チャネル長係数

③飽和領域

トランジスタはONの状態で、$ V_{DS} $が十分に高い$ (V_{GS}>V_{TH} $かつ$ V_{DS}>V_{GS}-V_{TH}) $領域である。ドレイン電流$ I_D $は$ V_{DS} $にあまり依存しなくなる。

\displaylines{
I_D=\frac{1}{2}\beta_N(V_{GS}-V_{TH})^2(1+\lambda_NV_{DS})
}
1
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
1
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?