Gilbert cell

load "psp103v4.osdi"
load "spice/resistor.osdi"
load "capacitor.osdi"

include "models.inc"

model vcvs vcvs
model v vsource
model i isource
model r sp_resistor
model c capacitor

subckt gilbert(rfp rfn lop lon ifp ifn vdd vss)
  rd1 (vdd ifp) r r=10k 
  rd2 (vdd ifn) r r=10k 
  m1 (ifp rfp dg1 vss) nmos w=2u l=0.2u
  m2 (ifn rfn dg1 vss) nmos w=2u l=0.2u
  m3 (ifn rfp dg2 vss) nmos w=2u l=0.2u
  m4 (ifp rfn dg2 vss) nmos w=2u l=0.2u
  m5 (dg1 lop s  vss) nmos w=2u l=0.2u
  m6 (dg2 lon s  vss) nmos w=2u l=0.2u
  i0 (s 0) i dc=40u
  r0 (s 0) r r=1G
ends

vdd (vdd 0) v dc=1.2

x1 (rfp rfn lop lon ifp ifn vdd 0) gilbert
vrfb (rfb 0) v dc=0.5
vlob (lob 0) v dc=0.3

subckt dctest()
  vrf (rfp rfb) v dc=0
  erf (rfn rfb rfp rfb) vcvs gain=-1
  vlo (lop lob) v dc=0
  elo (lon lob lop lob) vcvs gain=-1
ends

subckt sintest()
  vrf (rfp rfb) v type="sine" sinedc=0 ampl=2m freq=50k
  erf (rfn rfb rfp rfb) vcvs gain=-1
  vlo (lop lob) v type="sine" sinedc=0 ampl=50m freq=1M
  elo (lon lob lop lob) vcvs gain=-1
ends


control
  elaborate circuit("dctest")

  save p('x1:rd1',i) p('x1:rd2',i) v(ifp) v(ifn)
  analysis op1 op

  clear saves
  sweep vlo instance="vlo" parameter="dc" from=-100m to=100m mode="lin" points=6
  sweep vrf instance="vrf" parameter="dc" from=-100m to=100m mode="lin" points=50
    analysis op2 op

  
  elaborate circuit("sintest")
  
  analysis tran1 tran step=1n stop=40u maxstep=2n 
  analysis hb1 hb freq=[50k, 1M] truncate="box" nharm=[3, 5]

  postprocess(PYTHON, "runme.py")
endc

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

raw = rawread('op1.raw')
plot = raw.get()
for name in plot.names:
  print(name, plot[name])

fig1 = plt.figure(figsize=(9,7), dpi=100)
fig1.suptitle('Gilbert cell')
ax_dict = fig1.subplot_mosaic("""
AB
AC
ED
""")

ax_dict["A"].set_title('DC response')
ax_dict["A"].set_ylabel('vout [V]')
ax_dict["A"].set_xlabel('vin [V]')

ax_dict["B"].set_title('Transient response for 1MHz + 50kHz')
ax_dict["D"].set_xlabel('time [us]')
ax_dict["B"].set_ylabel('vlo [V]')
ax_dict["C"].set_ylabel('vin [V]')
ax_dict["D"].set_ylabel('vout [V]')

ax_dict["E"].set_title('Spectrum of vout (HB)')
ax_dict["E"].set_xlabel('f [MHz]')
ax_dict["E"].set_ylabel('mag [V]')

raw = rawread('op2.raw')
plot = raw.get(sweeps=1)

for ii in range(plot.sweepGroups):
    sdata = plot.sweepData(ii)
    vlo = sdata['vlo']*2
    vrf = plot[ii, 'rfp']-plot[ii, 'rfn']
    vif = plot[ii, 'ifp']-plot[ii, 'ifn']
    ax_dict["A"].plot(vrf, vif, label='vlo={:.2e}'.format(vlo))
ax_dict["A"].legend(loc="lower right")

raw = rawread('tran1.raw')
plot = raw.get()
t = plot["time"]*1e6
vlo = plot['lop']-plot['lon']
vrf = plot['rfp']-plot['rfn']
vif = plot['ifp']-plot['ifn']
ax_dict["B"].plot(t, vlo)
ax_dict["C"].plot(t, vrf)
ax_dict["D"].plot(t, vif)


hb1 = rawread('hb1.raw').get()
f = np.real(hb1['frequency'])
S = hb1['ifp']-hb1['ifn']
Smag = np.abs(S)

# fig1, ax1 = plt.subplots(1, 1, figsize=(5,3), dpi=100, constrained_layout=True)
# fig1.suptitle('HB analysis of Gilbert cell')

ax_dict["E"].stem(f/1e6, Smag, markerfmt='.')
ax_dict["E"].set_yscale('log')

fig1.tight_layout()


plt.show()
>>>FILE


