SPICE VDMOS body-diode reverse recovery test

load "spice/vdmos.osdi"
load "resistor.osdi"

model v vsource
vgs (g 0) v dc=0
vds (d 0) v dc=-6 type="pulse" val0=-0.7 val1=0.1 delay=0.2u rise=1n

model nm sp_vdmos ( type=1
  vto=4 kp=5.9 lambda=0.001 theta=0.015 ksubthres=0.27
  rd=61m rs=18m rg=3 rds=1e7
  cgdmax=2.45n cgdmin=10p a=0.3 cgs=1.2n
  is=60p n=1.1 rb=14m xti=3
  cjo=1.5n vj=0.8 m=0.5
  tcvth=0.0065 mu=-1.27 texp0=1.5
  rthjc=0.4 cthj=5e-3
  mtriode=0.8 vq=100 rq=0.5
  kf=0.032f af=1
  tt=1e-6
)
m1 (d g 0) nm $mfactor=2

control
  print devices
  print device("sp_vdmos")
  print instance("m1")

  save p(m1,qdio) default

  analysis tran1 tran step=0.1u stop=0.5u

  // Soft reverse recovery: vp!=0 (with tt!=0, already set on the model)
  // is supposed to enable the body diode's excess-carrier relaxation
  // branch, slowing down the snap-off at the end of reverse recovery
  // instead of the abrupt current drop seen with the default vp=0 (hard
  // recovery). Currently broken: vp!=0 makes the DC operating point fail
  // with "Factorization failed, size=13, rank=2, zero pivot @ node
  // 'm1:qp_int'" in devices/spice/vdmos.va, independent of alter (fails
  // the same way with vp given directly in the model card). Uncomment
  // once that's fixed.
  alter model("nm") vp=0.1
  analysis tran2 tran step=0.1u stop=0.5u

  postprocess(PYTHON, "runme.py")
endc

embed "runme.py" <<<FILE
from rawfile import rawread
import numpy as np
import matplotlib.pyplot as plt

raw = rawread('tran1.raw')
tranHard = raw.get()

raw = rawread('tran2.raw')
tranSoft = raw.get()

fig1, ax1 = plt.subplots(1, 2, figsize=(10,4.5), dpi=100)
fig1.suptitle('VDMOS body diode reverse recovery')

fig1.axes[0].set_title('Body diode reverse recovery')
fig1.axes[0].plot(tranHard['time']*1e6, -tranHard['vds:flow(br)'], marker=".", label="hard (vp=0)")
fig1.axes[0].plot(tranSoft['time']*1e6, -tranSoft['vds:flow(br)'], marker=".", label="soft (vp=0.1)")
fig1.axes[0].set_ylabel('Id [A]')
fig1.axes[0].set_xlabel('time [us]')
fig1.axes[0].legend()

fig1.axes[1].set_title('Body diode charge')
fig1.axes[1].plot(tranHard['time']*1e6, tranHard['m1.qdio']*1e6, marker=".", label="hard (vp=0)")
fig1.axes[1].plot(tranSoft['time']*1e6, tranSoft['m1.qdio']*1e6, marker=".", label="soft (vp=0.1)")
fig1.axes[1].set_ylabel('Qdio [uAs]')
fig1.axes[1].set_xlabel('time [us]')
fig1.axes[1].legend()

fig1.tight_layout()

plt.show()
>>>FILE

