From a55e55f04f42b1ce5754cb0242048f4cfec1495f Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 27 Jan 2021 15:04:23 -0800 Subject: [PATCH] Update process script to generate TeX. --- Lab2/lab2.tex | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ Lab2/process.py | 42 +++++++++++++++++++++++++------ 2 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 Lab2/lab2.tex diff --git a/Lab2/lab2.tex b/Lab2/lab2.tex new file mode 100644 index 0000000..2664f7c --- /dev/null +++ b/Lab2/lab2.tex @@ -0,0 +1,66 @@ +\documentclass{article} +\usepackage[margin=1in]{geometry} +\usepackage{amsmath} +\usepackage{graphicx} +\begin{document} +\section*{Lab 2} + +The data gathered in this lab is listed in tables +1 and 2. + +\begin{figure}[h] + \centering + \begin{tabular}{lcccccc} + Node & $g_m$ (S) & $r_o$ ($\Omega$) & Gain & $I_\text{off} (A)$ & $I_\text{on} (A)$ & $I_\text{on}/I_\text{off}$ \\ + \hline + longchannel pmos & 4.01E-04 & 1.36E+04 & 5.457 & 1.02E-11 & 1.36E-03 & 1.34E+08 \\ + longchannel nmos & 9.13E-04 & 1.31E+04 & 11.95 & 1.12E-11 & 3.22E-03 & 2.87E+08 \\ + 50nm pmos & 2.11E-04 & 1.55E+04 & 3.259 & 8.84E-09 & 1.48E-04 & 1.68E+04 \\ + 50nm nmos & 4.44E-04 & 1.31E+04 & 5.793 & 3.64E-09 & 3.12E-04 & 8.55E+04 \\ + 16nmlp pmos & 1.62E-04 & 1.68E+04 & 2.72 & 2.30E-11 & 5.54E-05 & 2.40E+06 \\ + 16nmlp nmos & 2.88E-04 & 1.33E+04 & 3.83 & 8.87E-12 & 9.13E-05 & 1.03E+07 \\ + 16nmhp pmos & 3.33E-04 & 5.37E+03 & 1.787 & 9.22E-08 & 1.51E-04 & 1.64E+03 \\ + 16nmhp nmos & 4.95E-04 & 5.56E+03 & 2.755 & 7.41E-08 & 2.17E-04 & 2.93E+03 \\ + \end{tabular} + \label{fig:dc} + \caption{Properties of various transistor sizes and types} +\end{figure} + +\begin{figure}[h] + \centering + \begin{tabular}{lcccccc} + Node & Oscillation Period (ps) & Oscillation Frequency (GHz) \\ + \hline + longchannel & 1020 & 0.980 \\ + 50nm & 222 & 4.49 \\ + 16nmlp & 140 & 7.11 \\ + 16nmhp & 32.2 & 31.0 \\ + \end{tabular} + \label{fig:t} + \caption{Switching frequency of 5-long inverter loop.} +\end{figure} + +From these tables, we can see that smaller transistors have progressively smaller +gain, and progressively smaller ratios of on current $I_\text{on}$ and off current +$I_\text{off}$. We can explain the drop in gain with velocity saturation. At smaller +scales, short-channel effects make the relationship between current and gate voltage no longer +quadratic, but linear (and thus smaller in magnitude). This means that the transconductance +of a transistor decreases as it gets smaller, leading to lower gain. Furthermore, +due to short-channel effects such as impact ionization, current doesn't stop increasing +past the theoretical saturation point. This makes the transistor behave less like +a current source past saturation, and decreases gain. + +Decreasing the size of the transistor does, however, significantly improve its timing characteristics. +While at 1$\mu m$ the 5-transistor loop we simulated has an oscillation frequency of 0.98GHz, the 16nm +high power loop can go as fast as 31GHz. This is likely due to the decreased capacitances at +this scale: it takes less time to charge up any part of the CMOS logic, including the outputs, +which makes it possible for subsequent transistors to respond faster, and so on. + +For analog circuits, we care about gain, since we want to ensure that our signal is transmitted +properly through our circuit. Thus, bigger transistors are probably better suited for this application, +since they have higher (sometimes much higher) gains than smaller transistors. On the other hand, +from the digital side, the gain doesn't matter as much as the performance characteristics of the transistor, +which makes the smaller nodes (ones that we measured to have higher oscillation frequency) preferable. + +\end{document} + diff --git a/Lab2/process.py b/Lab2/process.py index aa003dd..23511b8 100644 --- a/Lab2/process.py +++ b/Lab2/process.py @@ -27,8 +27,8 @@ simulations = { } moss = { - "nmos": "M1 2 1 0 0 nmos W={10*ll} L= ll", - "pmos": "M1 2 1 vdd vdd pmos W={10*ll} L={ll}" + "pmos": "M1 2 1 vdd vdd pmos W={10*ll} L={ll}", + "nmos": "M1 2 1 0 0 nmos W={10*ll} L= ll" } script_dc = """ @@ -96,16 +96,40 @@ def find_period(ident, script, model, mos, l): group2.append((dp, time[i])) peak1 = max(group1)[1] * 1000000000000 peak2 = max(group2)[1] * 1000000000000 - print(ident, peak2-peak1) + print(ident, peak2-peak1, 1/(peak2-peak1) * 1000) + + +def find_table(ident, script, model, mos, l): + vds = l.get_data('vds') + current_lo = l.get_data('I(vds)', 0) + current_hi = l.get_data('I(vds)', l.case_count - 1) + if mos == "nmos": + vgs1 = l.get_data('I(vds)', l.case_count - 2) + vgs2 = l.get_data('I(vds)', l.case_count - 1) + gm = (vgs2[-1]-vgs1[-1])/(simulations[model][0]/12) + vds = l.get_data('vds', l.case_count - 1) + ids = l.get_data('I(vds)', l.case_count - 1) + ro = (vds[-5] - vds[-1])/(ids[-5] - ids[-1]) + print("{} & {:.2E} & {:.2E} & {:.4} & {:.2E} & {:.2E} & {:.2E} \\\\".format( + ident[3:].replace("_", " "), -gm, -ro, gm * ro, -current_lo[-1], -current_hi[-1], current_hi[-1]/current_lo[-1])) + if mos == "pmos": + vgs1 = l.get_data('I(vds)', 0) + vgs2 = l.get_data('I(vds)', 1) + gm = (vgs2[0]-vgs1[0])/(simulations[model][0]/12) + vds = l.get_data('vds', 0) + ids = l.get_data('I(vds)', 0) + ro = (vds[50] - vds[0])/(ids[50] - ids[0]) + print("{} & {:.2E} & {:.2E} & {:.4} & {:.2E} & {:.2E} & {:.2E} \\\\".format( + ident[3:].replace("_", " "), -gm, -ro, gm * ro, current_hi[0], current_lo[0], current_lo[0]/current_hi[0])) def find_onoff(ident, script, model, mos, l): vds = l.get_data('vds') current_lo = l.get_data('I(vds)', 0) current_hi = l.get_data('I(vds)', l.case_count - 1) if mos == "nmos": - print(ident, -current_lo[-1] * 1000, -current_hi[-1] * 1000, current_hi[-1]/current_lo[-1]) + print("node: {}\toff: {:.2E}\ton: {:.2E}\tratio: {:.2E}".format(ident, -current_lo[-1], -current_hi[-1], current_hi[-1]/current_lo[-1])) if mos == "pmos": - print(ident, current_lo[0] * 1000, current_hi[0] * 1000, current_lo[0]/current_hi[0]) + print("node: {}\toff: {:.2E}\ton: {:.2E}\tratio: {:.2E}".format(ident, current_hi[0], current_lo[0], current_lo[0]/current_hi[0])) def find_gm(ident, script, model, mos, l): vds = l.get_data('vds') @@ -154,6 +178,10 @@ def run_sim(script, model, mos, callback, file_type = "dc"): callback(scriptname, script, model, mos, l) +print(" --- LaTeX --- ") +for node in simulations.keys(): + for mos in moss.keys(): + run_sim(script_dc, node, mos, find_table) print(" --- gm, ro --- ") for mos in moss.keys(): @@ -161,8 +189,8 @@ for mos in moss.keys(): run_sim(script_dc, node, mos, find_gm) print(" --- onoff --- ") -for mos in moss.keys(): - for node in simulations.keys(): +for node in simulations.keys(): + for mos in moss.keys(): run_sim(script_dc, node, mos, find_onoff) print(" --- period --- ")