Skip to content

Commit

Permalink
Add first figures for sizing
Browse files Browse the repository at this point in the history
  • Loading branch information
hpretl committed Jul 27, 2024
1 parent 671fb12 commit 5ec23ba
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 1 deletion.
4 changes: 4 additions & 0 deletions _sec_sizing.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This section needs to be written, but we have a first figure for the NMOS and for the PMOS.

{{< include figures/_fig_nmos_gmid_vs_ft.qmd >}}
{{< include figures/_fig_pmos_gmid_vs_ft.qmd >}}
54 changes: 54 additions & 0 deletions figures/_fig_nmos_gmid_vs_ft.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
```{python}
#| label: fig-nmos-gmid-vs-ft
#| echo: false
#| fig-cap: "LV NMOS gm/ID vs. transit frequency."
devices = ['sg13_lv_nmos', 'sg13_lv_pmos']
choice = 0 # select which device to plot, start from 0
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# widths used for characterization
w = np.array([5, 5])
# read ngspice data
df_raw = pd.read_csv('./sizing/techsweep_'+devices[choice]+'.txt', sep=r'\s+')
par_names = df_raw.columns.to_list()
par_prefix = par_names[1].split('[')[0]
# remove extra headers in file body and unwanted columns
df_raw = df_raw[~df_raw['v-sweep'].str.contains('v-sweep')]
df = df_raw.drop(['v-sweep', 'v-sweep.1'], axis=1)
df = df.apply(pd.to_numeric)
# rename columns for readability
df.columns = df.columns.str.removeprefix(par_prefix+'[')
df.columns = df.columns.str.removesuffix(']')
# sweep variable vectors
l = (np.unique(abs(df['l']))*1e6).round(3)
vgs = np.unique(abs(df['g']))
vds = np.unique(abs(df['d']))
vsb = np.unique(abs(df['b']))
# plot gm/ID and fT versus gate bias
L1 = min(l); VDS1=0.75; VSB1=0
df1 = df.loc[(df['l'] == L1*1e-6) & (abs(df['d']) == VDS1) & (abs(df['b']) == VSB1)]
gm_id1 = df1['gm'].values/df1['ids'].values
cgg1 = df1['cgg'].values + df1['cgdol'].values+df1['cgsol'].values
ft1 = df1['gm'].values/cgg1/2/np.pi
ft2 = df1['fug'].values
fig, ax1 = plt.subplots()
ax1.grid(axis='x')
ax1.set_xlabel(r'$V_\mathrm{GS}$ (V)')
color = 'tab:blue'
ax1.set_ylabel(r'$g_\mathrm{m}/I_\mathrm{D}$ (S/A)', color=color)
ax1.plot(vgs, gm_id1, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx()
color = 'tab:red'
ax2.set_ylabel(r'$f_\mathrm{T}$ (GHz)', color=color)
ax2.plot(vgs, ft1/1e9, color=color)
ax2.plot(vgs, ft2/1e9, color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout()
plt.title(devices[choice]+', $L$='+str(L1)+r'µm, $V_\mathrm{DS}$='+str(VDS1)+r'V, $V_\mathrm{SB}$='+str(VSB1)+'V')
plt.xlim(0, 1.5)
plt.axvline(x = df1['vth'].values[0], color='k', linestyle='--')
plt.show()
```
54 changes: 54 additions & 0 deletions figures/_fig_pmos_gmid_vs_ft.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
```{python}
#| label: fig-pmos-gmid-vs-ft
#| echo: false
#| fig-cap: "LV PMOS gm/ID vs. transit frequency."
devices = ['sg13_lv_nmos', 'sg13_lv_pmos']
choice = 1 # select which device to plot, start from 0
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# widths used for characterization
w = np.array([5, 5])
# read ngspice data
df_raw = pd.read_csv('./sizing/techsweep_'+devices[choice]+'.txt', sep=r'\s+')
par_names = df_raw.columns.to_list()
par_prefix = par_names[1].split('[')[0]
# remove extra headers in file body and unwanted columns
df_raw = df_raw[~df_raw['v-sweep'].str.contains('v-sweep')]
df = df_raw.drop(['v-sweep', 'v-sweep.1'], axis=1)
df = df.apply(pd.to_numeric)
# rename columns for readability
df.columns = df.columns.str.removeprefix(par_prefix+'[')
df.columns = df.columns.str.removesuffix(']')
# sweep variable vectors
l = (np.unique(abs(df['l']))*1e6).round(3)
vgs = np.unique(abs(df['g']))
vds = np.unique(abs(df['d']))
vsb = np.unique(abs(df['b']))
# plot gm/ID and fT versus gate bias
L1 = min(l); VDS1=0.75; VSB1=0
df1 = df.loc[(df['l'] == L1*1e-6) & (abs(df['d']) == VDS1) & (abs(df['b']) == VSB1)]
gm_id1 = df1['gm'].values/df1['ids'].values
cgg1 = df1['cgg'].values + df1['cgdol'].values+df1['cgsol'].values
ft1 = df1['gm'].values/cgg1/2/np.pi
ft2 = df1['fug'].values
fig, ax1 = plt.subplots()
ax1.grid(axis='x')
ax1.set_xlabel(r'$V_\mathrm{GS}$ (V)')
color = 'tab:blue'
ax1.set_ylabel(r'$g_\mathrm{m}/I_\mathrm{D}$ (S/A)', color=color)
ax1.plot(vgs, gm_id1, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx()
color = 'tab:red'
ax2.set_ylabel(r'$f_\mathrm{T}$ (GHz)', color=color)
ax2.plot(vgs, ft1/1e9, color=color)
ax2.plot(vgs, ft2/1e9, color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout()
plt.title(devices[choice]+', $L$='+str(L1)+r'µm, $V_\mathrm{DS}$='+str(VDS1)+r'V, $V_\mathrm{SB}$='+str(VSB1)+'V')
plt.xlim(0, 1.5)
plt.axvline(x = df1['vth'].values[0], color='k', linestyle='--')
plt.show()
```
4 changes: 3 additions & 1 deletion index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ date: last-modified

{{< include _sec_mosfet_diode.qmd >}}

## Transistor Sizing Using Inversion Coefficient
## Transistor Sizing Using gm/ID Methodoloy

{{< include _sec_sizing.qmd >}}

## Current Mirror

Expand Down

0 comments on commit 5ec23ba

Please sign in to comment.