Skip to content

Commit

Permalink
Theory finished, next is actual design
Browse files Browse the repository at this point in the history
  • Loading branch information
hpretl committed Jan 7, 2025
1 parent 5a11c57 commit 3ac46ee
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 15 deletions.
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
{
"cSpell.words": [
"Banba",
"cmim",
"CMRR",
"CTAT",
"gmgds",
"loopgain",
"openloop",
"OSIC",
"PSRR",
"PTAT",
"quasistatic",
"Razavi",
"rhigh",
"rppd",
"rsil",
"stronginversion",
"techsweep",
"vdsat",
"weakinversion"
"weakinversion",
"Widlar"
]
}
2 changes: 1 addition & 1 deletion content/_sec_biasing.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ plt.grid(True)
A well described design of a Banba bandgap reference (including a two-stage OTA and a regulated cascode for the output current mirror), covering much more details than discussed here, can be found in [Razavi_2021_bandgap].
::: {.callout-tip title="Exercise: Improved Low-Voltage Bandagap"}
::: {.callout-tip title="Exercise: Improved Low-Voltage Bandgap"}
As an *optional* exercise for advanced users: Design a bandgap circuit following [Razavi_2021_bandgap]. Implement the shown two-stage OTA and the regulated cascode.
As a starting point, the design of @sec-banba-bandgap can be used. As this design will contain more blocks, please build up a hierarchical design, with the OTAs designed in separate subcircuits.
Expand Down
10 changes: 10 additions & 0 deletions content/_sec_differential_ota.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,13 @@ In summary, stability investigations are critically important for differential c
Instead of a common-mode regulation loop (and all its complications regarding stability) often a common-mode setting is sufficient (after all, a somewhat imprecise setting of the dc points is good enough). A common-mode setting has the advantage that no error amplifier is required. We will also use this approach of a common-mode loop setting in the adapted differential OTA shown in @fig-diff-ota-resload-miller-cm.
{{< include ./figures/_fig_ota_diff_twostage_miller_cm.qmd >}}
Resistors $R_{3,4}$ sense the output voltages and create a replica of the common-mode point (assuming $R_3 = R_4$). This common-mode point is connected to the gates of $M_{7,8}$ to essentially connect $M_{7,8}$ like a diode (only for common-mode operation); in differential mode, $M_7$ and $M_8$ act as current source, like the load of the differential pair $M_{3,5}$. However, since we want to set the common-mode voltage at the output independently from $\VGS[7,8]$ we also pull a current through $R_{3,4}$ to cause $\VDS[7,8] \neq \VGS[7,8]$; essentially, this is a diode connection including a voltage shift! The output common-mode voltage is then given by
$$
V_\mathrm{out,cm} = \VGS[7,8] + \frac{R_{3,4} \ID[11]}{2}.
$$
::: {.callout-warning title="Modify Bias Points with Currents"}
Keep the technique shown in @fig-diff-ota-resload-miller-cm (using $R_{3,4}$ and $M_{11}$) in mind: You can always modify a bias point by injecting a dc current into a node, or by pulling a dc current out of a node (or do both to increase or lower the quiescent current through a resistor or transistor)! Since we likely have already current mirrors in the circuit it is usually a minor effort adding MOSFETs to create these bias currents.
:::
39 changes: 26 additions & 13 deletions figures/_fig_ota_diff_twostage_miller_cm.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,29 @@ with sd.Drawing(canvas='svg') as d:
M1 = elm.AnalogNFet(offset_gate=False).drop('source').theta(0).label('$M_1$', ofst=-1.5).reverse()
elm.Line().down().length(0.5)
elm.Line().right().length(2).dot()
elm.Line().right().length(0.5).dot()
d.push()
elm.Line().down().length(1.5)
elm.Line().down().length(4.5)
M10 = elm.AnalogNFet(offset_gate=False).anchor('drain').theta(0).label('$M_{10}$', ofst=-1.5).reverse()
elm.Ground()
elm.Line().left().length(0.5).at(M10.gate)
elm.Line().up().length(1).dot()
elm.Line().up().length(1)
pos3 = d.here
elm.Line().left().length(7.5)
d.push()
elm.Line().down().length(1)
elm.Line().left().length(0.5)
M9 = elm.AnalogNFet(offset_gate=False).anchor('gate').theta(0).label('$M_9$')
elm.Ground()
elm.Line().up().length(6).at(M9.drain)
elm.Line().up().length(8.5).at(M9.drain)
Ibias = elm.SourceI().up().label(r'$I_\mathrm{bias}$').reverse()
elm.Vdd()
d.pop()
elm.Line().left().tox(M9.drain).idot().dot()
d.pop()
elm.Line().right().length(2)
elm.Line().right().length(3.5)
elm.Line().up().length(0.5)
M2 = elm.AnalogNFet(offset_gate=False).anchor('source').theta(0).label('$M_2$')
Expand Down Expand Up @@ -90,14 +90,11 @@ with sd.Drawing(canvas='svg') as d:
elm.Capacitor().right().label(r'$C_\mathrm{m1}$')
elm.Resistor().right().label(r'$R_\mathrm{m1}$').tox(M3.drain).dot()
d.pop()
elm.Line().down().toy(M10.drain)
M7 = elm.AnalogNFet(offset_gate=False).anchor('drain').theta(0).label('$M_7$', ofst=-1.5).reverse()
elm.Line().down().length(4.5)
M7 = elm.AnalogNFet(offset_gate=False).anchor('drain').theta(0).label('$M_7$')
elm.Ground().at(M7.source)
elm.Line().at(M7.gate).left().length(0.5)
elm.Line().up().length(1).dot()
elm.Line().at(M6.drain).down().length(0.5)
#elm.Dot().label("$B'$", 'left')
elm.Dot()
d.push()
d.push()
Expand All @@ -109,9 +106,10 @@ with sd.Drawing(canvas='svg') as d:
elm.Line().down().toy(M7.drain)
M8 = elm.AnalogNFet(offset_gate=False).anchor('drain').theta(0).label('$M_8$', ofst=-1.5).reverse()
elm.Ground().at(M8.source)
elm.Line().at(M8.gate).left().length(0.5)
elm.Line().up().length(1)
elm.Line().left().length(6.5)
elm.Line().at(M8.gate).left().tox(M2.source)
elm.Line().left().length(0.5).dot()
pos4 = d.here
elm.Line().at(M8.gate).left().tox(M7.gate)
d.here = pos1
R1 = elm.Resistor().right().label('$R_1$').dot()
Expand All @@ -124,4 +122,19 @@ with sd.Drawing(canvas='svg') as d:
elm.Line().left().to(M3.gate)
d.pop()
elm.Line().right().to(M5.gate)
elm.Line().up().length(0.5).at(M7.drain)
elm.Resistor().right().tox(pos4).idot().dot().label('$R_3$')
d.push()
elm.Line().down().toy(M7.gate)
pos5 = d.here
d.pop()
elm.Resistor().right().tox(M8.drain).dot().label('$R_4$')
elm.Line().down().at(pos5).toy(M10.drain)
M11 = elm.AnalogNFet(offset_gate=False).anchor('drain').theta(0).label('$M_{11}$', ofst=-1.5).reverse()
elm.Ground()
elm.Line().left().length(0.5).at(M11.gate)
elm.Line().up().length(1)
elm.Line().left().length(3).dot()
```

0 comments on commit 3ac46ee

Please sign in to comment.