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?

Verilog-AMSの勉強とPython実装(日記)

Last updated at Posted at 2025-05-02

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

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?