計算環境
使用する言語: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で考える。
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()
出力結果
今回用いた公式
今回用いた公式は以下である。
しきい値電圧の計算(基盤バイアス効果)
トランジスタが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})
}