LTspiceで解析 CMOS回路入門【理解度チェック演習問題付き】 (TOOL活用シリーズ)

https://www.amazon.co.jp/LTspice%E3%81%A7%E8%A7%A3%E6%9E%90-CMOS%E5%9B%9E%E8%B7%AF%E5%85%A5%E9%96%80%E3%80%90%E7%90%86%E8%A7%A3%E5%BA%A6%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E6%BC%94%E7%BF%92%E5%95%8F%E9%A1%8C%E4%BB%98%E3%81%8D%E3%80%91-TOOL%E6%B4%BB%E7%94%A8%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E9%95%B7%E9%87%8E-%E8%8B%B1%E7%94%9F/dp/4789849562



p92
```
import sympy as sp

# シンボリック変数の定義
gm, gmb, ro, R = sp.symbols('gm gmb ro R')

# 各回路の特性を定義
# 1. ソース接地回路
Av_source = -gm * (ro * R) / (ro + R)  # 電圧利得
Zin_source = sp.oo  # ソース接地回路の入力インピーダンスは無限大
Zout_source = (ro * R) / (ro + R)  # 出力インピーダンス

# 2. ドレイン接地回路
Av_drain = 1 / (1 + gm * (ro * R) / (ro + R) + gmb / gm)  # 電圧利得
Zin_drain = R + ro  # 入力インピーダンス
Zout_drain = 1 / (gm + gmb)  # 出力インピーダンス

# 3. ゲート接地回路
Av_gate = (gm + gmb + 1 / ro) * (ro * R) / (ro + R)  # 電圧利得
Zin_gate = R + ro  # 入力インピーダンス
Zout_gate = ro * R / (ro + R)  # 出力インピーダンス

# 結果を表示
print("ソース接地回路:")
print(f"電圧利得 Av_source = {Av_source}")
print(f"入力インピーダンス Zin_source = {Zin_source}")
print(f"出力インピーダンス Zout_source = {Zout_source}")

print("\nドレイン接地回路:")
print(f"電圧利得 Av_drain = {Av_drain}")
print(f"入力インピーダンス Zin_drain = {Zin_drain}")
print(f"出力インピーダンス Zout_drain = {Zout_drain}")

print("\nゲート接地回路:")
print(f"電圧利得 Av_gate = {Av_gate}")
print(f"入力インピーダンス Zin_gate = {Zin_gate}")
print(f"出力インピーダンス Zout_gate = {Zout_gate}")

# 数値例を使って計算する場合（例: gm = 1e-3, gmb = 1e-4, ro = 10e3, R = 5e3）
values = {gm: 1e-3, gmb: 1e-4, ro: 10e3, R: 5e3}

# 各回路の特性値を数値で表示
Av_source_value = Av_source.evalf(subs=values)
Zout_source_value = Zout_source.evalf(subs=values)

Av_drain_value = Av_drain.evalf(subs=values)
Zin_drain_value = Zin_drain.evalf(subs=values)
Zout_drain_value = Zout_drain.evalf(subs=values)

Av_gate_value = Av_gate.evalf(subs=values)
Zin_gate_value = Zin_gate.evalf(subs=values)
Zout_gate_value = Zout_gate.evalf(subs=values)

print("\n数値結果:")
print(f"ソース接地回路 - 電圧利得: {Av_source_value}, 出力インピーダンス: {Zout_source_value}")
print(f"ドレイン接地回路 - 電圧利得: {Av_drain_value}, 入力インピーダンス: {Zin_drain_value}, 出力インピーダンス: {Zout_drain_value}")
print(f"ゲート接地回路 - 電圧利得: {Av_gate_value}, 入力インピーダンス: {Zin_gate_value}, 出力インピーダンス: {Zout_gate_value}")
```
p182
```
# ライブラリのインポート
import sympy as sp

# 変数の定義
gm1, gm5, gm7 = sp.symbols('gm1 gm5 gm7')  # トランスコンダクタンス
r1, r3, r5, r7, r9 = sp.symbols('r1 r3 r5 r7 r9')  # 抵抗
parallel_r1_r3 = sp.Symbol('parallel_r1_r3')  # r1 || r3

# 並列抵抗 r1 || r3 の定義
parallel_r1_r3_expr = 1 / (1/r1 + 1/r3)

# 分子の定義
numerator = -gm1 * r5 * parallel_r1_r3 * (gm5 * r5 + 1)

# 分母の各項の定義
denominator_part1 = parallel_r1_r3 * (gm5 * r5 + 1) + r5
denominator_part2 = r9 * (gm7 * r7 + 1) + r7

# 全体の分母
denominator = denominator_part1 * (1 / r7) * denominator_part2

# 式 (7.55) の定義
transfer_function = numerator / denominator

# 伝達関数を表示
sp.pprint(transfer_function)

# 各定数を設定して数値計算 (任意の値を使用)
values = {gm1: 1e-3, gm5: 1e-3, gm7: 1e-3, r1: 10e3, r3: 10e3, r5: 5e3, r7: 10e3, r9: 10e3}
parallel_r1_r3_value = parallel_r1_r3_expr.subs(values)
values[parallel_r1_r3] = parallel_r1_r3_value

# 伝達関数の数値評価
numerical_result = transfer_function.subs(values)
print(f"伝達関数の数値評価: {numerical_result}")
```
p213
```
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# 定数の設定
gm1 = 1e-3  # トランスコンダクタンス g_m1 (S)
r2 = 10e3   # 抵抗 r2 (Ω)
r4 = 10e3   # 抵抗 r4 (Ω)
C1 = 1e-12  # キャパシタンス C1 (F)
C2 = 1e-12  # キャパシタンス C2 (F)

# 並列接続の抵抗 r2 || r4 の計算
r_parallel = 1 / (1 / r2 + 1 / r4)

# 伝達関数の分子と分母の係数を設定
# 分子: (r2 || r4) * gm1 * (1 + jω C1 / (2 * gm1))
num = [r_parallel * gm1, r_parallel * gm1 * C1 / (2 * gm1)]

# 分母: (1 + jω C2 (r2 || r4))(1 + jω C1 / gm1)
den = [1, (C2 * r_parallel) + (C1 / gm1), (C2 * r_parallel * C1 / gm1)]

# 伝達関数の作成
system = signal.TransferFunction(num, den)

# 周波数範囲の設定
w, mag, phase = signal.bode(system)

# ゲインプロット
plt.figure()
plt.semilogx(w, mag)
plt.title('Bode Diagram - Magnitude')
plt.xlabel('Frequency [rad/s]')
plt.ylabel('Magnitude [dB]')
plt.grid(True)

# 位相プロット
plt.figure()
plt.semilogx(w, phase)
plt.title('Bode Diagram - Phase')
plt.xlabel('Frequency [rad/s]')
plt.ylabel('Phase [degrees]')
plt.grid(True)

# プロット表示
plt.show()
```
p232
```
# 与えられた定数
beta = 11e-3  # β (mA/V^2) → A/V^2 に変換
Vgs = 0.7  # Vgs (V)
Vth = 0.335  # 閾値電圧 Vth (V)
lambda_val = 0.06  # λ (1/V)
R1 = 1e3  # 抵抗 R1 (Ω)
Vin_delta = 704.8e-3 - 695.2e-3  # ΔVin (V)
Vout_delta = 481.7e-3 - 444.5e-3  # ΔVout (V)

# 1. 式(9.6) IDSの計算
Ids = (beta / 2) * (Vgs - Vth) ** 2
print(f"IDS (飽和電流) = {Ids:.6f} A")

# 2. 式(9.7) gmの計算
gm = (2 * beta * Ids) ** 0.5
print(f"gm (トランスコンダクタンス) = {gm:.6f} S")

# 3. 式(9.8) roの計算
ro = 1 / (lambda_val * Ids)
print(f"ro (出力抵抗) = {ro:.2f} Ω")

# 4. 式(9.9) 増幅率AVの計算 (並列接続の抵抗を計算)
parallel_resistance = 1 / (1 / R1 + 1 / ro)
Av = gm * parallel_resistance
print(f"電圧利得 (Av) = {Av:.2f} 倍")

# 5. 式(9.10)および(9.12) 実測の電圧利得の計算
Av_measured = Vout_delta / Vin_delta
print(f"実測の電圧利得 (Av_measured) = {Av_measured:.2f} 倍")
```
p235
```
import math

# 定数の設定
beta = 11e-3  # β (mA/V^2) → A/V^2 に変換
Vgs = 0.7  # Vgs (V)
Vth = 0.335  # 閾値電圧 Vth (V)
lambda_val = 0.06  # λ (1/V)
Rd = 5e3  # 抵抗 Rd (Ω)
Vin_delta = 20e-3  # ΔVin (V)
Vout_high = 725.36e-3  # シミュレーションで得られたVoutの最高値
Vout_low = 582.59e-3  # シミュレーションで得られたVoutの最低値

# 1. 式(9.78)を用いてIDSを計算
Ids = (beta / 2) * ((Vgs - 0.22) - Vth) ** 2  # 画像ではVgs - 0.22とされているのでこれを使用

# 2. 式(9.79) gmの計算
gm = math.sqrt(2 * beta * Ids)

# 3. 式(9.80) roの計算
ro = 1 / (lambda_val * Ids)

# 4. 式(9.81) 差動電圧利得ADの計算 (並列接続の抵抗を計算)
parallel_resistance = 1 / (1 / ro + 1 / Rd)
Ad = gm * parallel_resistance

# 5. シミュレーション結果を用いた差動電圧利得ADの計算
Vout_delta = Vout_high - Vout_low  # ΔVout (V)
Ad_simulation = Vout_delta / Vin_delta

# 結果の表示
print(f"IDS (飽和電流) = {Ids:.6f} A")
print(f"gm (トランスコンダクタンス) = {gm:.6f} S")
print(f"ro (ドレイン抵抗) = {ro:.2f} Ω")
print(f"差動電圧利得 (AD) = {Ad:.2f} 倍")
print(f"シミュレーション結果の差動電圧利得 (AD) = {Ad_simulation:.2f} 倍")
```
p260
```
import math

# 与えられた定数
beta = 11e-3  # β (mA/V^2) を A/V^2 に変換
I_ds = 70e-6  # 飽和電流 I_ds (A)
Vth = 335e-3  # 閾値電圧 Vth (V)

# 1. 式(9.56)を用いてV_GS - V_th を計算
V_gs_minus_Vth = math.sqrt(2 * I_ds / beta)
print(f"V_GS - V_th = {V_gs_minus_Vth:.6f} V")

# 2. 飽和電圧 V_OD の計算 (V_OD = V_GS - V_th)
V_od = V_gs_minus_Vth
print(f"飽和電圧 V_OD = {V_od:.6f} V")

# 3. 各ノードの電圧を計算
V1 = V_od + Vth
V2 = 2 * (V_od + Vth)
V01 = V_od + Vth
V02_min = 2 * V_od + Vth

print(f"V1 = {V1:.6f} V")
print(f"V2 = {V2:.6f} V")
print(f"V01 = {V01:.6f} V")
print(f"V02_min = {V02_min:.6f} V")

# 4. 与えられた定数と条件を用いて電圧を計算
Vdd = 1.2  # 電源電圧 Vdd (V)
R2 = 5e3  # 抵抗 R2 (Ω)
Iref = 70e-6  # リファレンス電流 Iref (A)

# 電圧 V_02 の計算
V02 = Vdd - Iref * R2
print(f"V02 = {V02:.6f} V")
```
p269
```
import math

# 定数の設定
beta = 11e-3  # β (mA/V^2) → A/V^2 に変換
Vgs = 0.7  # Vgs (V)
Vth = 0.335  # 閾値電圧 Vth (V)
lambda_val = 0.06  # λ (1/V)
Rd = 5e3  # 抵抗 Rd (Ω)
Vin_delta = 20e-3  # ΔVin (V)
Vout_high = 725.36e-3  # シミュレーションで得られたVoutの最高値
Vout_low = 582.59e-3  # シミュレーションで得られたVoutの最低値

# 1. 式(9.78)を用いてIDSを計算
Ids = (beta / 2) * ((Vgs - 0.22) - Vth) ** 2  # 画像ではVgs - 0.22とされているのでこれを使用
print(f"IDS (飽和電流) = {Ids:.6f} A")

# 2. 式(9.79) gmの計算
gm = math.sqrt(2 * beta * Ids)
print(f"gm (トランスコンダクタンス) = {gm:.6f} S")

# 3. 式(9.80) roの計算
ro = 1 / (lambda_val * Ids)
print(f"ro (ドレイン抵抗) = {ro:.2f} Ω")

# 4. 式(9.81) 差動電圧利得ADの計算 (並列接続の抵抗を計算)
parallel_resistance = 1 / (1 / ro + 1 / Rd)
Ad = gm * parallel_resistance
print(f"差動電圧利得 (AD) = {Ad:.2f} 倍")

# 5. シミュレーション結果を用いた差動電圧利得ADの計算
Vout_delta = Vout_high - Vout_low  # ΔVout (V)
Ad_simulation = Vout_delta / Vin_delta
print(f"シミュレーション結果の差動電圧利得 (AD) = {Ad_simulation:.2f} 倍")
```

p62
```
# Defining all the necessary equations in a single function block

def Q_S(C_ox, V_GS, V_DS, V_th):
    return C_ox * (V_GS - V_DS / 2 - V_th)

def Q_total(C_ox, W, L, V_GS, V_DS, V_th):
    return C_ox * W * L * (V_GS - V_DS / 2 - V_th)

def v_q(E, mu):
    return E * mu

def t_1(L, mu, V_DS):
    return L**2 / (mu * V_DS)

def I_DS(C_ox, W, L, V_GS, V_DS, V_th, mu):
    return C_ox * (V_GS - V_DS / 2 - V_th) * W * L * (mu * V_DS / L**2)

def I_DS_beta(beta, V_GS, V_th, V_DS):
    return beta * ((V_GS - V_th) * V_DS - 0.5 * V_DS**2)

def beta(mu, C_ox, W, L):
    return mu * C_ox * W / L

# Sample values
C_ox = 1e-8   # Oxide capacitance per unit area in F/m^2
V_GS = 2.5    # Gate-source voltage in V
V_DS = 1.0    # Drain-source voltage in V
V_th = 1.0    # Threshold voltage in V
W = 1e-4      # Width of the channel in m
L = 1e-6      # Length of the channel in m
mu = 0.05     # Mobility in m^2/V·s

# Calculations
Q_s_value = Q_S(C_ox, V_GS, V_DS, V_th)
Q_total_value = Q_total(C_ox, W, L, V_GS, V_DS, V_th)
t_1_value = t_1(L, mu, V_DS)
I_DS_value = I_DS(C_ox, W, L, V_GS, V_DS, V_th, mu)
beta_value = beta(mu, C_ox, W, L)
I_DS_beta_value = I_DS_beta(beta_value, V_GS, V_th, V_DS)

# Results
print("Q_S (Surface charge density):", Q_s_value)
print("Q_total (Total channel charge):", Q_total_value)
print("t_1 (Transit time):", t_1_value)
print("I_DS (Drain-source current):", I_DS_value)
print("Beta (Device parameter constant):", beta_value)
print("I_DS using Beta method:", I_DS_beta_value)


```


```



```
ｐ９２
```
import sympy as sp

# Define constants (example values)
g_m_val = 5e-3      # Transconductance (S)
g_mb_val = 1e-3     # Backgate transconductance (S)
r_o_val = 10e3      # Output resistance (Ω)
R_val = 1e3         # Load resistance (Ω)

# Define the symbols
g_m, g_mb, r_o, R = sp.symbols('g_m g_mb r_o R')

# Helper function for parallel resistance
def parallel(R1, R2):
    return (R1 * R2) / (R1 + R2)

# Source Grounded Circuit
A_v_source_grounded = -g_m * parallel(r_o, R)
Z_out_source_grounded = parallel(R, r_o)

# Drain Grounded Circuit
A_v_drain_grounded = 1 / (1 + (1 / (g_m * parallel(r_o, R))) + (g_mb / g_m))
Z_out_drain_grounded = 1 / (g_m + g_mb)

# Gate Grounded Circuit
A_v_gate_grounded = (g_m + g_mb + 1 / r_o) * parallel(R, r_o)
Z_in_gate_grounded = (R + r_o) / (1 + g_m * r_o + g_mb * r_o)
Z_out_gate_grounded = parallel(R, r_o)

# Substitute the actual values
subs = {g_m: g_m_val, g_mb: g_mb_val, r_o: r_o_val, R: R_val}

# Calculate and print results
print("Source Grounded Circuit:")
print("Voltage Gain (A_v):", A_v_source_grounded.subs(subs))
print("Output Impedance (Z_out):", Z_out_source_grounded.subs(subs))

print("\nDrain Grounded Circuit:")
print("Voltage Gain (A_v):", A_v_drain_grounded.subs(subs))
print("Output Impedance (Z_out):", Z_out_drain_grounded.subs(subs))

print("\nGate Grounded Circuit:")
print("Voltage Gain (A_v):", A_v_gate_grounded.subs(subs))
print("Input Impedance (Z_in):", Z_in_gate_grounded.subs(subs))
print("Output Impedance (Z_out):", Z_out_gate_grounded.subs(subs))
```

ｐ１６４
```
import sympy as sp

# Define the symbols
g_m, r_o, R_D, R_S, v_in1, v_in2 = sp.symbols('g_m r_o R_D R_S v_in1 v_in2')

# Helper function for parallel resistance
def parallel(R1, R2):
    return (R1 * R2) / (R1 + R2)

# Expression for the equation
v_out2 = -g_m * parallel(R_D, r_o) * (
    (g_m * r_o * R_S + r_o + 2 * R_S) / (2 * g_m * r_o * R_S + r_o + 2 * R_S) * v_in2
    - (g_m * r_o * R_S) / (2 * g_m * r_o * R_S + r_o + 2 * R_S) * v_in1
)

# Display the symbolic equation
print("The symbolic equation for v_out2 is:")
sp.pprint(v_out2)

# Substitute with example values
values = {
    g_m: 5e-3,  # Transconductance (S)
    r_o: 10e3,  # Output resistance (Ω)
    R_D: 1e3,   # Load resistance (Ω)
    R_S: 1e3,   # Source resistance (Ω)
    v_in1: 1.0,  # Input voltage 1 (V)
    v_in2: 0.5   # Input voltage 2 (V)
}

# Calculate the numeric result
v_out2_value = v_out2.subs(values)

print("\nThe calculated value of v_out2 is:")
print(v_out2_value)

```
ｐ１８２


```
import sympy as sp

# Define the symbols
g_m1, g_m5, g_m7 = sp.symbols('g_m1 g_m5 g_m7')
r_1, r_3, r_5, r_7, r_9 = sp.symbols('r_1 r_3 r_5 r_7 r_9')
v_in, v_out = sp.symbols('v_in v_out')

# Helper function for parallel resistance
def parallel(R1, R2):
    return (R1 * R2) / (R1 + R2)

# Define the equation step by step
# Parallel resistances
r1_r3_parallel = parallel(r_1, r_3)

# First term in the equation for v_out / v_in
numerator = -g_m1 * r_5 * r1_r3_parallel * (g_m5 * r_5 + 1)
denominator = g_m5 * r_5 * r1_r3_parallel + r_5 + r1_r3_parallel

# Second term in the equation
r7_r9_parallel = r_9 / (g_m7 * r_7 * r_9 + r_7 + r_9)
term2 = (1 / r_7) * (r_7 / (g_m7 * r_7 * r_9 + r_7 + r_9))

# Final equation for v_out / v_in
v_out_over_v_in = numerator / denominator + term2

# Display the symbolic equation
print("The symbolic equation for v_out / v_in is:")
sp.pprint(v_out_over_v_in)

# Substitute example values
values = {
    g_m1: 2e-3,  # Example value for g_m1 (S)
    g_m5: 3e-3,  # Example value for g_m5 (S)
    g_m7: 4e-3,  # Example value for g_m7 (S)
    r_1: 10e3,   # Example value for r_1 (Ω)
    r_3: 5e3,    # Example value for r_3 (Ω)
    r_5: 2e3,    # Example value for r_5 (Ω)
    r_7: 1e3,    # Example value for r_7 (Ω)
    r_9: 8e3     # Example value for r_9 (Ω)
}

# Calculate the numeric result
v_out_over_v_in_value = v_out_over_v_in.subs(values)

print("\nThe calculated value of v_out / v_in is:")
print(v_out_over_v_in_value)


```
p183

```



import numpy as np

def parallel_resistance(r1, r3):
    """Calculate parallel resistance of r1 and r3."""
    return (r1 * r3) / (r1 + r3)

def calculate_gain(gm1, gm5, gm7, r1, r3, r5, r7, r9):
    """Calculate the voltage gain based on the given parameters."""
    r_parallel1 = parallel_resistance(r1, r3)
    term1 = (gm5 * r5 + 1)
    term2 = (gm7 * r7 + 1)
    
    # Calculate the full expression for gain
    gain = -gm1 * (r_parallel1 * term1 + r5) * r9 * term2 / (r9 * term2 + r7)
    return gain

def calculate_output_impedance(gm5, gm7, r1, r3, r5, r7, r9):
    """Calculate the output impedance based on the given parameters."""
    r_parallel1 = parallel_resistance(r1, r3)
    term1 = (gm5 * r5 + 1)
    term2 = (gm7 * r7 + 1)
    
    # Calculate the full expression for output impedance
    zout = (r_parallel1 * term1 + r5) * r9 * term2 / (r9 * term2 + r7)
    return zout

# Example values for gm1, gm5, gm7, r1, r3, r5, r7, r9
gm1 = 1e-3  # Transconductance gm1 (Siemens)
gm5 = 1e-3  # Transconductance gm5 (Siemens)
gm7 = 1e-3  # Transconductance gm7 (Siemens)
r1 = 1e3    # Resistance r1 (Ohms)
r3 = 1e3    # Resistance r3 (Ohms)
r5 = 1e3    # Resistance r5 (Ohms)
r7 = 1e3    # Resistance r7 (Ohms)
r9 = 1e3    # Resistance r9 (Ohms)

# Calculate gain and output impedance
gain = calculate_gain(gm1, gm5, gm7, r1, r3, r5, r7, r9)
zout = calculate_output_impedance(gm5, gm7, r1, r3, r5, r7, r9)

print(f"Voltage Gain (vout/vin): {gain:.4f}")
print(f"Output Impedance (Zout): {zout:.4f} Ohms")

```


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

# Define component values (these need to be adjusted based on your specific circuit)
r2 = 1e3  # Resistor value (Ohms)
r4 = 1e3  # Resistor value (Ohms)
C1 = 1e-9  # Capacitance (Farads)
C2 = 1e-9  # Capacitance (Farads)
gmp = 1e-3  # Transconductance (Siemens)
gmn = 1e-3  # Transconductance (Siemens)

# Define the parallel resistance (r2 || r4)
r_parallel = (r2 * r4) / (r2 + r4)

# Transfer function numerator and denominator coefficients
num = [r_parallel * gmn, 0, C1 / (2 * gmp)]
den = [r_parallel * C2, (C1 / gmp) + r_parallel, 1]

# Create the transfer function
sys = signal.TransferFunction(num, den)

# Generate Bode plot data
frequencies = np.logspace(1, 7, 1000)  # Frequency range (10^1 to 10^7 rad/s)
w, mag, phase = signal.bode(sys, frequencies)

# Plot the Bode magnitude plot
plt.figure()
plt.semilogx(w, mag)  # Bode magnitude plot
plt.title('Bode Plot - Magnitude')
plt.xlabel('Frequency [rad/s]')
plt.ylabel('Magnitude [dB]')
plt.grid(True)

# Plot the Bode phase plot
plt.figure()
plt.semilogx(w, phase)  # Bode phase plot
plt.title('Bode Plot - Phase')
plt.xlabel('Frequency [rad/s]')
plt.ylabel('Phase [degrees]')
plt.grid(True)

# Show both plots
plt.show()


```