---
title: |
  Fundamentals of Analog VLSI Design \
  Exercise 6 - Problem
subtitle: The Fully Differential G~m~-R Gain Stage
author: Christian Enz (christian.enz@epfl.ch)
affiliation: EPFL
date: 10-29-2025
date-format: "DD.MM.YYYY"
execute:
  echo: false
  warning: false
toc: true
number-sections: true
number-depth: 3
highlight-style: pygments
bibliography: references.bib
csl: ieee.csl
format: 
  html:
    include-in-header: mathjax.html
    code-fold: true
    html-math-method: mathjax
    css: styles.css
  pdf:
    keep-tex: true
    pdf-engine: pdflatex
    documentclass: scrreprt
    papersize: a4
    geometry:
      - top=20mm
      - bottom=20mm
      - left=20mm
      - right=20mm
    include-in-header:
      text: |
        \usepackage{scrlayer-scrpage}
        \rohead[\thepage]{\thepage}
        \cohead[Exercise 6]{Exercise 6}
        \lofoot[$\copyright$ C. Enz]{$\copyright$ C. Enz}
        \cofoot[Fundamentals of Analog VLSI Design]{Fundamentals of Analog VLSI Design}
        \rofoot[29.10.2025]{29.10.2025}
---

```{python}
# Initialization

from ekv_functions import *

import pandas as pd
import matplotlib.pyplot as plt
import subprocess
import shutil
import os
import os.path as op
import sys
sys.path.append(".")
import re

from IPython.display import Markdown
from tabulate import tabulate

plt.rcParams['svg.fonttype'] = 'none'
plt.rcParams['pdf.fonttype'] = 42
plt.rcParams['font.family'] = 'Arial'
plt.rcParams['mathtext.fontset'] = 'custom'
plt.rcParams['mathtext.rm'] = 'Arial'
plt.rcParams['mathtext.it'] = 'Arial:italic'
plt.rcParams['mathtext.bf'] = 'Arial:bold'

inkscapePath = r"C:\\Program Files\\Inkscape\bin\\inkscape.exe"
savePlotPath = "./Plots/"
#savePlots=True
savePlots=False

if savePlots:
  lw=1
  curvelw=2
  msize=6
  textFontSize=12
  BodePlotParams = {'figure.figsize': (6,6)}
  pltStyle='plt_style_medium.mplstyle'
else:
  lw=1
  curvelw=1
  msize=5
  textFontSize=9
  BodePlotParams = {'figure.figsize': (5,5)}
  pltStyle='plt_style_small.mplstyle'

plt.style.use(pltStyle)

circuitName="diff_pair"
version = "_v1" # Allows you to save different versions
newSim=True
#newSim=False
refloat=r'.*?([+-]?\d+([.]\d*)?([eE][+-]?\d+)?|[.]\d+([eE][+-]?\d+)?)'

def saveFigures(savePath, plotName):
#  print("Patience, saving plot!")
  figFolder = savePath + r"\\{}.{}"
  pngFile = figFolder.format(plotName,"png")
  pdfFile = figFolder.format(plotName,"pdf")
  svgFile = figFolder.format(plotName,"svg")
  plt.savefig(pngFile, format="png", dpi=1200, bbox_inches="tight", transparent=True)
  plt.savefig(pdfFile, format="pdf", dpi=1200, bbox_inches="tight", transparent=True)
  plt.savefig(svgFile, format="svg", dpi=1200, bbox_inches="tight", transparent=True)
  cmd_emf = '"{}" "{}\\{}.svg" --export-filename="{}\\{}.emf" --export-overwrite'.format(inkscapePath, savePath, plotName, savePath, plotName)
#    cmd_emf = '"{}" "{}\{}.pdf" --export-filename="{}\{}.emf" --export-overwrite'.format(inkscapePath, savePath, plotName, savePath, plotName)
#    cmd_pdf = '"{}" "{}\{}.svg" --export-filename="{}\{}.pdf" --export-overwrite'.format(inkscapePath, savePath, plotName, savePath, plotName)
  subprocess.call(cmd_emf, shell=True)
#    subprocess.call(cmd_pdf, shell=True)
```

# Introduction

![Schematic of the differential pair with resistive load.](Figures/Diff_Pair_with_Rload.png){#fig-Diff_Pair_with_Rload}

@fig-Diff_Pair_with_Rload shows a differential pair composed of two NMOS transistors $M_1$ and $M_2$, loaded with resistors $R_1$ and $R_2$, respectively. Since there are two input terminals, the output current or voltage depends on both the input voltages $V_{i1}$ and $V_{i2}$. It is usually more interesting to express the output current or voltage in terms of the differential and common mode input voltages $V_{id}$ and $V_{ic}$ defined as
\begin{align*}
  V_{id} &\triangleq V_{i1} - V_{i2}\\
  V_{ic} &\triangleq \frac{V_{i1}+V_{i2}}{2}.
\end{align*}
The differential mode and common mode operations are defined for $V_{ic} = const.$ and for $V_{id} = 0$, respectively. The input terminals are set to an appropriate common mode voltage $V_{ic}$, to which a differential voltage $V_{id}$ is superimposed according to
\begin{align*}
  V_{i1} &= V_{ic} + \frac{V_{id}}{2}\\
  V_{i2} &= V_{ic} - \frac{V_{id}}{2}.
\end{align*}

# Small-signal analysis
* Draw the small-signal equivalent schematic of the circuit assuming the transistors are biased in saturation.
* Calculate the small-signal differential voltage gain $A_{vd} \triangleq V_{od}/V_{id}$.
* Calculate the small-signal common-mode input voltage to differential output voltage gain $A_{vc} \triangleq V_{od}/V_{ic}$.

# Noise analysis
* Draw the small-signal equivalent schematic of the circuit assuming the transistors are biased in saturation and including all the noise sources.
* Calculate the output noise power spectral density (PSD) or output noise resistance assuming that the transistors and resistors are perfectly matched.
* Calculate the input-referred thermal noise PSD and the equivalent thermal noise resistance $R_{nin,th}$.
* Calculate the input-referred flicker noise PSD and the equivalent flicker noise resistance $R_{nin,fl}$.
* Calculate the total output thermal noise power assuming that there is an output capacitance $C$ in parallel with each of the load resistance $R_1$ and $R_2$ (assume that transistors, resistors and capacitors are perfectly matched).

# Offset analysis
Mismatch between the two transistors of the differential pair $M_1$-$M_2$ and of the resistors $R_1$-$R_2$ cause some non-zero differential output voltage even for a zero differential input voltage $V_{id} = 0$.

* Calculate the differential mode output mismatch voltage in terms of drain current mismatch $\Delta I_D$ and resistance mismatch $\Delta R$. Hint: use the above noise analysis where the noise currents are replaced by current mismatch.
* Calculate the input-referred offset voltage in terms of resistor mismatch $\Delta R$ and MOS transistor mismatch ($\beta$- and $V_{T0}$-mismatch).
* Determine the variance of the input referred offset voltage. How can it be minimized?

# Common-mode input range analysis (CMIR) and differential-mode output range analysis (DMOR)
* Calculate the minimum and maximum common-mode input voltages $V_{ic,min}$ and $V_{ic,max}$. For this analysis, $V_{id}$ is set to 0 and the ideal current source is replaced by a transistor ($M_2$).
* Calculate the minimum and maximum output voltages $V_{o,min}$ and $V_{o,max}$; deduce the differential output voltage swing $\Delta V_{od,max}$.

# Example
## Design
* Design the amplifier, i.e. size the transistors, determine the values of the resistors and the bias current, to meet the specifications given in @tbl-specs. For the design we will use a generic 180nm bulk CMOS process. The physical parameters are given in @tbl-physics_param, the global process parameters in @tbl-process_param and finally the MOSFET parameters in @tbl-mos_param. 

```{python}
#| label: tbl-specs
#| tbl-cap: Specifications for the differential pair with resistive loads.

from specs import *

table = [["Input common mode voltage","$V_{{ic}}$",f'{Vic:.1f}',"$V$"],
         ["DC gain","$A_{{dc}}$",f'{AdcdBspec:.0f}',"$dB$"],
         ["DC gain","$A_{{dc}}$",f'{Adcspec:.0f}',"-"],
         ["Bandwidth","$B$",f'{Bspec/1e6:.0f}',"$MHz$"],
         ["Input-referred thermal noise resistance","$R_{{nin,th}}$",f'{Rninthspec/1e3:.0f}',"$k \Omega$"],
         ["Maximum input-referred offset voltage","$V_{{os}}$",f'{Vosmaxspec/1e-3:.0f}',"$mV$"]
         ]

Markdown(tabulate(
  table,
  headers=["Specification","Symbol","Value","Unit"],
  numalign="center",
  stralign="center",
  colalign=("left","center","center","center")
))
```

```{python}
#| label: tbl-physics_param
#| tbl-cap: Physical parameters

from tsmc018_sekv_ekv2p6 import *

table = [["$T$",f'{T:.0f}',"$K$"],
         ["$U_T$",f'{UT/1e-3:.3f}',"$mV$"]
         ]

Markdown(tabulate(
  table,
  headers=["Parameter","Value","Unit"],
  numalign="center",
  stralign="center",
  colalign=("center", "center", "center")
))
```

```{python}
#| label: tbl-process_param
#| tbl-cap: Global process parameters

table = [["$V_{DD}$",f'{VDD:.1f}',"$V$"],
         ["$C_{ox}$",f'{Cox*1e3:.3f}',"$\\frac{fF}{\\mu m^2}$"],
         ["$W_{min}$",f'{Wmin/1e-9:.0f}',"$nm$"],
         ["$L_{min}$",f'{Lmin/1e-9:.0f}',"$nm$"]
         ]

Markdown(tabulate(
  table,
  headers=["Parameter","Value","Unit"],
  numalign="center",
  stralign="center",
  colalign=("center", "center", "center")
))
```

```{python}
#| label: tbl-mos_param
#| tbl-cap: Transistor process parameters

table = [["sEKV parameters"],
         ["$n$",f'{n0n:.2f}',f'{n0p:.2f}',"-"],
         ["$I_{{spec\\Box}}$",f'{Ispecsqn/1e-9:.0f}',f'{Ispecsqp/1e-9:.0f}',"$nA$"],
         ["$V_{{T0}}$",f'{VT0n:.3f}',f'{VT0p:.3f}',"$V$"],
         ["$L_{{sat}}$",f'{Lsatn/1e-9:.0f}',f'{Lsatp/1e-9:.0f}',"$nm$"],
         ["$\\lambda$",f'{lambdan*1e-6:.0f}',f'{lambdap*1e-6:.0f}',"$\\frac{{V}}{{\\mu m}}$"],
         ["Overlap capacitances parameters"],
         ["$C_{{GDo}}$",f'{CGDOn*1e9:.3f}',f'{CGDOp*1e9:.3f}','$\\frac{{fF}}{{\\mu m}}$'],
         ["$C_{{GSo}}$",f'{CGSOn*1e9:.3f}',f'{CGSOp*1e9:.3f}','$\\frac{{fF}}{{\\mu m}}$'],
         ["$C_{{GBo}}$",f'{CGBOn*1e9:.3f}',f'{CGBOp*1e9:.3f}','$\\frac{{fF}}{{\\mu m}}$'],
         ["Junction capacitances parameters"],
         ["$C_J$",f'{CJn*1e3:.3f}',f'{CJp*1e3:.3f}','$\\frac{{fF}}{{\\mu m^2}}$'],
         ["$C_{{JSW}}$",f'{CJSWn*1e9:.3f}',f'{CJSWp*1e9:.3f}','$\\frac{{fF}}{{\\mu m}}$'],
         ["Flicker noise parameters"],
         ["$K_F$",f'{KFn:.1e}',f'{KFp:.1e}',"$J$"],
         ["$AF$",f'{AFn:.1f}',f'{AFp:.1f}',"-"],
         ["$\\rho$",f'{rhon:.3e}',f'{rhop:.3e}','$\\frac{{V \\cdot m^2}}{{A \\cdot s}}$'],
         ["Matching parameters"],
         ["$A_{{VT}}$",f'{AVTn*1e9:.0f}',f'{AVTp*1e9:.0f}',"$mV \\cdot \\mu m$"],
         ["$A_{{\\beta}}$",f'{Abetan*1e8:.0f}',f'{Abetap*1e8:.0f}',"$\\% \\cdot \\mu m$"],
         ["Source and drain sheet resistance parameter"],
         ["$R_{{sh}}$",f'{RSHn:.0f}',f'{RSHp:.0f}',"$\\frac{{\\Omega}}{{\\mu m}}$"],
         ["Width and length parameters"],
         ["$\\Delta W$",f'{DWn/1e-9:.0f}',f'{DWp/1e-9:.0f}',"$\\,nm$"],
         ["$\\Delta L$",f'{DLn/1e-9:.0f}',f'{DLp/1e-9:.0f}',"$\\,nm$"]
         ]

Markdown(tabulate(
  table,
  headers=["Parameter","NMOS","PMOS","Unit"],
  numalign="center",
  stralign="center",
  colalign=("center", "center", "center")
))
```

## Simulation
* Simulate your design using the available qucs-s schematic.

## Reducing the supply voltage
* What happens if $V_{DD}=1\,V$? Can you use the same design as before and fulfill all the specifications? Using the same $V_{ic}$, get the new $\Delta V_{od,max}$ and propose an alternative design relaxing one of the specifications.
