Verilog-AMS 発振器モジュール(リスト2.1 統合版)
`timescale 100ps / 10ps // 時間単位:100ps、時間精度:10ps
`include "disciplines.h" // 電気的特性(discipline)定義ファイルの取り込み
`include "connect.h" // モジュール間接続ルールの定義
// --- トップモジュール:発振器の基本構成 ---
module top;
wire a, b; // デジタル信号配線
not #1 g1 (b, a); // NOTゲート(1単位遅延)
assign #1 out = b; // bを1単位遅延でoutに出力
res (.val(5e3)) r1(b, a); // 抵抗インスタンス(5kΩ)をbとaの間に接続
cap (.val(1e-9)) cl(out, a); // コンデンサインスタンス(1nF)をoutとaの間に接続
endmodule
// --- 抵抗モデルモジュール ---
module res(a, b);
inout a, b; // 双方向ポート定義
electrical a, b; // electrical discipline(アナログ信号)定義
parameter real val = 1e3; // 抵抗値(デフォルト:1kΩ)
analog
V(a, b) <+ val * I(a, b); // アナログ記述:V = R * I(オームの法則)
endmodule
// --- キャパシタ(コンデンサ)モデルモジュール ---
module cap(a, b);
inout a, b;
electrical a, b;
branch (a, b) cap; // 電流の流れる経路(ブランチ)定義
parameter real val = 1e3; // 容量値(デフォルト:1k、使用時に1nFに上書き)
analog
I(cap) <+ val * ddt(V(cap)); // アナログ記述:I = C * dV/dt(キャパシタの基本式)
endmodule
import numpy as np
import matplotlib.pyplot as plt
# --- パラメータ設定 / Parameters ---
R = 5e3 # 抵抗値 [Ohm]
C = 1e-9 # キャパシタ [F]
Vdd = 1.0 # 電源電圧(HIGHレベル)
Vth = 0.5 # NOTゲートの閾値電圧
dt = 1e-11 # 時間刻み [s]
T = 2e-6 # 総時間 [s]
steps = int(T / dt)
# --- 初期化 / Initialization ---
t = np.linspace(0, T, steps)
a = np.zeros(steps) # ノードa(入力)
b = np.zeros(steps) # ノードb(出力)
a[0] = 0.0 # 初期値:LOW
# --- シミュレーションループ / Simulation loop ---
for i in range(1, steps):
# デジタルNOTゲート:aに対する反転出力がb
b[i-1] = 0.0 if a[i-1] > Vth else Vdd
# RC回路によるaの更新(アナログ)
dV = (b[i-1] - a[i-1]) / (R * C) * dt
a[i] = a[i-1] + dV
# --- プロット / Plotting ---
plt.figure(figsize=(10, 4))
plt.plot(t * 1e6, a, label='Node a (analog)', linewidth=1.5)
plt.plot(t * 1e6, b, label='Node b (digital)', linewidth=1.0, linestyle='--')
plt.xlabel("Time [µs]")
plt.ylabel("Voltage [V]")
plt.title("Oscillator Simulation: NOT + RC Feedback")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
Verilog-AMSによるVCO記述(パルス発生型、リスト4.9)
`include "disciplines.h" // アナログ信号のディシプリン定義
module vco(vctrl, vout, vdd, vss);
inout vctrl, vout, vdd, vss; // 入出力ポート宣言
electrical vctrl, vout, vdd, vss; // 電気信号として定義
// --- パラメータ宣言 ---
parameter real f0 = 100e6; // 基本周波数 100 MHz
parameter real fgain = 100e6; // ゲイン(Hz/V)
parameter real vdead = 1.0; // 発振が開始する電圧しきい値 [V]
parameter real tr = 0.1e-9; // 出力立ち上がり時間 [s]
parameter real tf = 0.1e-9; // 出力立ち下がり時間 [s]
real period; // 周期(内部変数)
integer state; // 出力状態(0 or 1)
analog begin
// --- 発振周期の計算 ---
if (V(vctrl) > vdead)
period = 1.0 / (f0 + (V(vctrl) - vdead) * fgain);
else
period = 1.0 / f0;
// --- タイマーでトグル動作(パルス出力) ---
@(timer(period/2, period/2)) // ON時間・OFF時間を同周期で繰り返す
state = !state; // 出力トグル(0→1→0...)
// --- パルス波形生成(0↔Vddの矩形波) ---
V(vout) <+ V(vdd, vss) * transition(state, 0.0, tr, tf);
// 出力電圧 = 状態に応じてVdd/vssを切替(transitionで滑らかに)
end
endmodule
import numpy as np
import matplotlib.pyplot as plt
# --- パラメータ設定 / VCO Parameters ---
f0 = 100e6 # 基本周波数 [Hz]
fgain = 100e6 # ゲイン [Hz/V]
vdead = 1.0 # 発振開始しきい値 [V]
vctrl = 2.0 # 制御電圧 [V]
vdd = 1.0 # 出力電圧(High)
vss = 0.0 # 出力電圧(Low)
tr = 0.1e-9 # 立ち上がり時間 [s](未使用、波形理想)
tf = 0.1e-9 # 立ち下がり時間 [s](未使用、波形理想)
# --- 時間軸の設定 / Time Axis ---
dt = 1e-10 # タイムステップ [s]
Tmax = 1e-6 # 総シミュレーション時間 [s]
steps = int(Tmax / dt)
time = np.arange(steps) * dt
# --- 初期化 / Initialization ---
vout = np.zeros(steps) # 出力波形
state = 0 # 初期状態(0 or 1)
t_next_toggle = 0.0 # 次の反転タイミング [s]
# --- 周期の計算 / Period Calculation ---
if vctrl > vdead:
period = 1.0 / (f0 + (vctrl - vdead) * fgain)
else:
period = 1.0 / f0
half_period = period / 2.0 # 半周期(トグル間隔)
# --- シミュレーションループ / Main Simulation Loop ---
for i in range(steps):
t = i * dt
if t >= t_next_toggle:
state = 1 - state # トグル(0→1→0…)
t_next_toggle += half_period # 次の反転時間更新
vout[i] = vdd if state == 1 else vss # 出力電圧の決定
# --- 結果の表示 / Plotting ---
plt.figure(figsize=(10, 4))
plt.plot(time * 1e6, vout, label='VCO Output (vout)', color='blue')
plt.xlabel("Time [µs]")
plt.ylabel("Voltage [V]")
plt.title("Voltage-Controlled Oscillator Output")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
[リスト 5.4] Verilog-AMS: ローパス&ハイパスフィルタ定義例(laplace_nd使用)
// --- ローパス・フィルタ(Low-pass Filters) ---
V(low1) <+ laplace_nd(V(in), (1), (1, 1)); // 1次ローパス
V(low2) <+ laplace_nd(V(in), (1), (1, 1.4142, 1)); // 2次ローパス(バターワース)
V(low3) <+ laplace_nd(V(in), (1), (1, 2, 2, 1)); // 3次ローパス
V(low4) <+ laplace_nd(V(in), (1), (1, 2.6131, 3.4142, 2.6131, 1)); // 4次ローパス(バターワース)
// --- ハイパス・フィルタ(High-pass Filters) ---
V(high1) <+ laplace_nd(V(in), (0, 1), (1, 1)); // 1次ハイパス
V(high2) <+ laplace_nd(V(in), (0, 0, 1), (1, 1.4142, 1)); // 2次ハイパス(バターワース)
V(high3) <+ laplace_nd(V(in), (0, 0, 0, 1), (1, 2, 2, 1)); // 3次ハイパス
V(high4) <+ laplace_nd(V(in), (0, 0, 0, 0, 1), (1, 2.6131, 3.4142, 2.6131, 1)); // 4次ハイパス(バターワース)
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# --- 周波数軸設定 / Frequency range ---
w = np.logspace(0, 6, 1000) # [rad/s]:1〜1Mの対数スケール
# --- フィルタ定義(laplace_ndと一致) ---
filters = {
'low1': ([1], [1, 1]),
'low2': ([1], [1, 1.4142, 1]),
'low3': ([1], [1, 2, 2, 1]),
'low4': ([1], [1, 2.6131, 3.4142, 2.6131, 1]),
'high1': ([0, 1], [1, 1]),
'high2': ([0, 0, 1], [1, 1.4142, 1]),
'high3': ([0, 0, 0, 1], [1, 2, 2, 1]),
'high4': ([0, 0, 0, 0, 1], [1, 2.6131, 3.4142, 2.6131, 1])
}
# --- プロット設定 / Plot configuration ---
fig_mag, ax_mag = plt.subplots(figsize=(10, 5))
fig_phase, ax_phase = plt.subplots(figsize=(10, 5))
# --- フィルタごとにプロット / Plot each filter ---
for name, (num, den) in filters.items():
system = signal.TransferFunction(num, den)
w_, mag, phase = signal.bode(system, w)
ax_mag.semilogx(w_, mag, label=name)
ax_phase.semilogx(w_, phase, label=name)
# --- 振幅プロット / Magnitude ---
ax_mag.set_title("Bode Magnitude Plot (Low-pass & High-pass Filters)")
ax_mag.set_xlabel("Frequency [rad/s]")
ax_mag.set_ylabel("Magnitude [dB]")
ax_mag.grid(True, which="both", ls='--')
ax_mag.legend()
# --- 位相プロット / Phase ---
ax_phase.set_title("Bode Phase Plot (Low-pass & High-pass Filters)")
ax_phase.set_xlabel("Frequency [rad/s]")
ax_phase.set_ylabel("Phase [deg]")
ax_phase.grid(True, which="both", ls='--')
ax_phase.legend()
plt.tight_layout()
plt.show()
基本素子モデル統合コード(Verilog-AMS)
`include "disciplines.h" // electricalディシプリンの定義
// ------------------------------
// 抵抗モデル / Resistor
// ------------------------------
module resistor(p, n);
inout p, n;
electrical p, n;
parameter real r = 100 from [0:inf); // 抵抗値 [Ω]
analog
V(p, n) <+ r * I(p, n); // V = R × I
endmodule
// ------------------------------
// キャパシタモデル / Capacitor
// ------------------------------
module capacitor(p, n);
inout p, n;
electrical p, n;
parameter real c = 1e-9 from (0:inf); // 容量 [F]
parameter real ic = 0 from [0:inf); // 初期電荷による電圧
analog
I(p, n) <+ c * ddt(V(p, n), ic); // I = C × dV/dt
endmodule
// ------------------------------
// インダクタモデル / Inductor
// ------------------------------
module inductor(p, n);
inout p, n;
electrical p, n;
parameter real l = 10e-6 from [0:inf); // インダクタンス [H]
parameter real ic = 0 from [0:inf); // 初期電流
analog
V(p, n) <+ l * idt(I(p, n), ic); // V = L × dI/dt
endmodule
// ------------------------------
// ダイオードモデル / Diode
// ------------------------------
module diode(a, c);
inout a, c;
electrical a, c;
parameter real is = 1e-14; // 逆方向飽和電流 [A]
analog
I(a, c) <+ is * (limexp(V(a, c)/$vt) - 1); // 指数関数特性
endmodule
import numpy as np
import matplotlib.pyplot as plt
# --- パラメータ設定 / Parameters ---
R = 100 # 抵抗 [Ω]
C = 1e-9 # 容量 [F]
L = 10e-6 # インダクタンス [H]
Is = 1e-14 # ダイオード飽和電流 [A]
Vt = 0.025 # 熱電圧 [V]
# --- シミュレーション設定 / Simulation parameters ---
dt = 1e-9 # タイムステップ [s]
Tmax = 2e-6 # 総時間 [s]
time = np.arange(0, Tmax, dt) # 時間軸
vin = np.ones_like(time) # 入力電圧:1Vステップ
# --- RC回路(直列) / RC circuit ---
vc = np.zeros_like(time)
for i in range(1, len(time)):
dV = (vin[i-1] - vc[i-1]) / (R * C) * dt
vc[i] = vc[i-1] + dV
# --- RL回路(直列) / RL circuit ---
il = np.zeros_like(time)
vl = np.zeros_like(time)
for i in range(1, len(time)):
dI = (vin[i-1] - R * il[i-1]) / L * dt
il[i] = il[i-1] + dI
vl[i] = L * (dI / dt) # V = L dI/dt(理論値)
# --- ダイオードモデル / Diode I-V curve ---
vd_range = np.linspace(-0.1, 0.8, 500)
id_diode = Is * (np.exp(vd_range / Vt) - 1)
# --- プロット / Plotting ---
fig, axs = plt.subplots(3, 1, figsize=(10, 10))
# RC回路電圧
axs[0].plot(time * 1e6, vc, label='V_C (RC circuit)', color='blue')
axs[0].set_title("RC Circuit: Capacitor Voltage")
axs[0].set_xlabel("Time [µs]")
axs[0].set_ylabel("Voltage [V]")
axs[0].grid(True)
axs[0].legend()
# RL回路電流
axs[1].plot(time * 1e6, il, label='I_L (RL circuit)', color='green')
axs[1].set_title("RL Circuit: Inductor Current")
axs[1].set_xlabel("Time [µs]")
axs[1].set_ylabel("Current [A]")
axs[1].grid(True)
axs[1].legend()
# ダイオード I-V 曲線
axs[2].semilogy(vd_range, np.abs(id_diode), label='I-V (Diode)', color='red')
axs[2].set_title("Diode I-V Characteristic")
axs[2].set_xlabel("Voltage [V]")
axs[2].set_ylabel("Current [A] (log scale)")
axs[2].grid(True, which='both')
axs[2].legend()
plt.tight_layout()
plt.show()
合体版:4ビット逐次比較A-Dコンバータ(SAR ADC)
include "disciplines.h"
module ad4 (ain, clk, convert, done, dval);
// --- ポート定義 ---
inout ain; // アナログ入力
input clk, convert; // クロック、変換トリガ
output done; // 変換完了フラグ
output [3:0] dval; // 4ビットディジタル出力
// --- 信号宣言 ---
electrical ain; // アナログ入力として宣言
reg [3:0] dval, bit, result, dac; // SARレジスタと出力
reg done; // 変換完了信号
reg track_hold; // サンプル&ホールド制御信号
wire [3:0] dacin = dac; // DAC制御入力(ビットごと)
wire comp; // コンパレータ出力
// --- 初期化 ---
initial begin
track_hold = 1; // 初期状態:サンプリング中
done = 0;
end
// --- SAR制御:クロックに同期して変換ステップを進める ---
always @(posedge clk) begin
if (convert == 1) begin
done <= 0;
bit <= 4'b1000; // 最上位ビットから順に評価
result <= 4'b0000;
track_hold <= 0; // サンプル開始(ホールド解除)
dac <= result | bit; // 試験ビットONしてDAC出力
end
else if (!done) begin
if (comp) begin
result <= result | bit; // sample > DAC → ビットを1に確定
end
bit <= bit >> 1; // 次のビットへ
if (bit == 0) begin
dval <= result; // 完了 → 結果格納
done <= 1;
track_hold <= 1; // サンプル保持(ホールドON)
end
else begin
dac <= result | bit; // 次ビット試験用値
end
end
end
// --- アナログモジュール呼び出し ---
ad4_amod amod (ain, track_hold, dacin[3], dacin[2], dacin[1], dacin[0], comp);
endmodule
// --- アナログモジュール:S/H + DAC + コンパレータ ---
module ad4_amod(ain, thold, d3, d2, d1, d0, comp);
input ain, thold, d3, d2, d1, d0;
output comp;
electrical ain, thold, d3, d2, d1, d0, comp;
// --- パラメータ定義 ---
parameter real vth = 2.5; // トラック→ホールド切替しきい値 [V]
parameter real logic1 = 5.0; // デジタルHIGHの電圧
parameter real logic0 = 0.0; // デジタルLOWの電圧
parameter real fullscale = 5.0; // DACフルスケール電圧
real sample; // サンプル保持用
real dac_out; // DAC出力電圧
analog begin
// --- サンプル&ホールド動作 ---
if (V(thold) > vth)
sample = V(ain); // トラック→ホールド時に保持
// --- 4ビットDAC:加重和で出力電圧を生成 ---
dac_out = (fullscale / logic1) * (
(V(d3) * 0.5) +
(V(d2) * 0.25) +
(V(d1) * 0.125) +
(V(d0) * 0.0625)
);
// --- コンパレータ動作 ---
if (sample > dac_out)
V(comp) <+ logic1; // sample > DAC → HIGH
else
V(comp) <+ logic0; // sample ≤ DAC → LOW
end
endmodule
import numpy as np
import numpy as np
import matplotlib.pyplot as plt
# --- パラメータ設定 / Parameters ---
V_ref = 5.0 # DACフルスケール電圧 [V]
bits = 4 # 4ビットADC
V_in = 2.7 # 入力アナログ電圧 [V]
# --- SAR ADC 変換関数 / SAR conversion logic ---
def sar_adc(V_in, V_ref, bits):
dval = 0 # 最終的な出力値(4ビット)
result_trace = [] # 各ステップのDAC出力を記録
compare_trace = [] # 各ビットの比較結果
step_labels = [] # ステップごとのラベル
for i in range(bits):
bit_pos = bits - 1 - i
test_val = dval | (1 << bit_pos) # そのビットを仮に1とする
V_dac = V_ref * test_val / (2 ** bits)
result_trace.append(V_dac)
compare_trace.append(V_in > V_dac)
step_labels.append(f"Bit {bit_pos}")
if V_in > V_dac:
dval = test_val # ビットを1に確定
return dval, result_trace, compare_trace, step_labels
# --- 実行 / Run ADC ---
dval, dac_trace, comp_result, labels = sar_adc(V_in, V_ref, bits)
# --- 結果表示 / Print Result ---
print(f"Input Voltage: {V_in:.2f} V")
print(f"Digital Output: {dval:04b} (Decimal: {dval})")
# --- 可視化 / Plot the DAC steps ---
plt.figure(figsize=(10, 4))
plt.plot(range(bits), dac_trace, marker='o', label='DAC Output (V)')
plt.axhline(V_in, color='red', linestyle='--', label='Input Voltage')
for i, c in enumerate(comp_result):
color = 'green' if c else 'gray'
plt.text(i, dac_trace[i] + 0.1, '1' if c else '0', color=color, ha='center')
plt.xticks(range(bits), labels)
plt.xlabel("SAR Step")
plt.ylabel("Voltage [V]")
plt.title("SAR ADC Bitwise Comparison Trace")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()