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?

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

Last updated at Posted at 2024-08-20

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)





p92

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))

p164

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)

p182

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()


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?