Skip to content

Commit

Permalink
Working default-valued rail-to-rail Fcasc
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-fritchman committed Oct 24, 2023
1 parent b0e55eb commit b352e50
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 20 deletions.
18 changes: 9 additions & 9 deletions AutoCkt/Server/autockt_server/opamps/FoldedCascode.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ class FcascParams:

# Unit device sizes
nbias = h.Param(dtype=int, desc="Bias Nmos Unit Width", default=2)
pbias = h.Param(dtype=int, desc="Bias Pmos Unit Width", default=2)
pbias = h.Param(dtype=int, desc="Bias Pmos Unit Width", default=4)
ncasc = h.Param(dtype=int, desc="Cascode Nmos Unit Width", default=2)
pcasc = h.Param(dtype=int, desc="Cascode Pmos Unit Width", default=2)
pcasc = h.Param(dtype=int, desc="Cascode Pmos Unit Width", default=4)
ninp = h.Param(dtype=int, desc="Input Nmos Unit Width", default=2)
pinp = h.Param(dtype=int, desc="Input Pmos Unit Width", default=2)
pinp = h.Param(dtype=int, desc="Input Pmos Unit Width", default=4)

# Current Mirror Ratios
alpha = h.Param(dtype=int, desc="Alpha (Pmos Input) Current Ratio", default=2)
Expand All @@ -33,7 +33,7 @@ class FcascParams:

# Input Bias Current
# Applied on *both* bias inputs
ibias = h.Param(dtype=h.Prefixed, desc="Input Bias Current", default=100 * µ)
ibias = h.Param(dtype=h.Prefixed, desc="Input Bias Current", default=10 * µ)

# Cascode Bias Voltages
vcp = h.Param(dtype=h.Prefixed, desc="Cascode Pmos Bias Voltage", default=200 * m)
Expand Down Expand Up @@ -137,6 +137,8 @@ class Fcasc:
def FcascTb(params: TbParams) -> h.Module:
"""# FoldecCascode Op-Amp Testbench"""

vicm = params.vicm or params.VDD / 2

@h.module
class OpAmpTb:
VSS = h.Port() # The testbench interface: sole port VSS
Expand All @@ -145,8 +147,8 @@ class OpAmpTb:
vdc = h.Vdc(dc=params.VDD)(n=VSS)
inp = h.Diff()
sig_out = h.Signal()
sig_p = h.Vdc(dc=params.VDD / 2, ac=0.5)(p=inp.p, n=VSS)
sig_n = h.Vdc(dc=params.VDD / 2, ac=-0.5)(p=inp.n, n=VSS)
sig_p = h.Vdc(dc=vicm, ac=+0.5)(p=inp.p, n=VSS)
sig_n = h.Vdc(dc=vicm, ac=-0.5)(p=inp.n, n=VSS)

# Primary difference: the two bias current inputs
ibias1, ibias2 = 2 * h.Signal()
Expand All @@ -173,9 +175,7 @@ def endpoint(inp: FoldedCascodeInput) -> OpAmpOutput:
# Create a testbench, simulate it, and return the metrics!
opamp = FcascParams(**asdict(inp))
tbparams = TbParams(
dut=opamp,
VDD=VDD,
ibias=ibias,
dut=opamp, VDD=VDD, ibias=ibias, vicm=None # Use the default common mode
)
tbmodule = FcascTb(tbparams)
return simulate(tbmodule)
5 changes: 5 additions & 0 deletions AutoCkt/Server/autockt_server/opamps/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
class TbParams:
"""# Testbench Parameters"""

# Required
dut = h.Param(dtype=h.Instantiable, desc="Design Under Test")
VDD = h.Param(dtype=h.Scalar, desc="VDD voltage")
ibias = h.Param(dtype=h.Scalar, desc="ibias current")
# Optional
vicm = h.Param(
dtype=Optional[h.Scalar], desc="Input common-mode voltage", default=None
)
20 changes: 9 additions & 11 deletions AutoCkt/Server/autockt_server/opamps/tb.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
def OpAmpTb(params: TbParams) -> h.Module:
"""# Generic Op-Amp Testbench"""

vicm = params.vicm or params.VDD / 2

@h.module
class OpAmpTb:
VSS = h.Port() # The testbench interface: sole port VSS
Expand All @@ -27,8 +29,8 @@ class OpAmpTb:
inp = h.Diff()
sig_out = h.Signal()
ibias = h.Signal()
sig_p = h.Vdc(dc=params.VDD / 2, ac=0.5)(p=inp.p, n=VSS)
sig_n = h.Vdc(dc=params.VDD / 2, ac=-0.5)(p=inp.n, n=VSS)
sig_p = h.Vdc(dc=vicm, ac=+0.5)(p=inp.p, n=VSS)
sig_n = h.Vdc(dc=vicm, ac=-0.5)(p=inp.n, n=VSS)
Isource = h.Isrc(dc=params.ibias)(p=vdc.p, n=ibias)

# The Op-Amp DUT
Expand Down Expand Up @@ -81,10 +83,6 @@ def simulate(tbmodule: h.Instantiable) -> OpAmpOutput:
return extract_outputs(results)


def find_I_vdd(vout: numpy.array) -> float:
return numpy.abs(vout)[0]


def find_dc_gain(vout: numpy.array) -> float:
return numpy.abs(vout)[0]

Expand Down Expand Up @@ -127,20 +125,20 @@ def _get_best_crossing(yvec: numpy.array, val: float) -> tuple[int, bool]:
def extract_outputs(results: h.sim.SimResult) -> OpAmpOutput:
"""# Extract our metrics from `results`"""

print(results)

ac_result = results["ac"]
sig_out = ac_result.data["v(xtop.sig_out)"]
gain = find_dc_gain(2 * sig_out)
ugbw = find_ugbw(ac_result.freq, 2 * sig_out)
phm = find_phm(ac_result.freq, 2 * sig_out)
idd = ac_result.data["i(v.xtop.vvdc)"]
ibias = find_I_vdd(idd)

# Get the supply current from the DC operating point results
op_result = results["op"]
idd = numpy.abs(op_result.data["i(v.xtop.vvdc)"])

# And return them as an `OpAmpOutput`
return OpAmpOutput(
ugbw=ugbw,
gain=gain,
phm=phm,
ibias=ibias,
ibias=idd,
)

0 comments on commit b352e50

Please sign in to comment.