#!/usr/bin/env python # coding: utf-8 # \title{Diode Connected MOSFET Tobology} # \author{Steven K Armour} # \maketitle #

Table of Contents

#
# # Background # The Diode connected Mosfet is one of the four single Mosfet topologies (the others being CS, CD, CG) where the Mosfets gate is connected to its drain (for both NMOS and PMOS) thereby forcing it to behave much like a Diode till certain compliance voltage is reached. This compliance voltage is similar to the Diodes threshold voltage and where beyond this point the MOSFET will no longer conduct current at meaningful amounts. # # The usage of diode-connected MOSFETs is important not only in creating a pseudo Diode to then recreate notable diode topologies such as Half and Full wave rectifiers. But are also used like diodes in waveform shaping and biasing to eliminate resistors where possible at the ASIC level. The two most common first exposure to diode-connected MOSFETs come by way of the Saturated Enhancement loaded inverters in Digital MOSFETs topologies and in biasing and the current reference of current mirrors in Analog Mosfet topologies. # # (insert images) # # References (Need to Finish) # # Imports # In[1]: from sympy import * init_printing() import numpy as np import pandas as pd from itertools import product as IProd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm from matplotlib.ticker import LinearLocator, FormatStrFormatter get_ipython().run_line_magic('matplotlib', 'inline') # In[2]: import nbimporter nbimporter.options['only_defs'] = False from SympyMOSModels import * # In[3]: from PySpice.Probe.Plot import plot from PySpice.Spice.Library import SpiceLibrary from PySpice.Spice.Netlist import Circuit from PySpice.Unit import * libraries_path = 'SpiceLib/' spice_library = SpiceLibrary(libraries_path) # # Diode Connected NMOS # (Insert Image) # ## Square Law Theory # The Diode Connected NMOS is defined as the $V_{GS}=V_{DS}$ made possible by the connection of the gate to the drain. And in this analysis we will assume that the body voltage is not in play. # In[4]: VD, VS=symbols('V_D, V_S') # ### Simplified Analysis # In the simplified analysis, we forgo the channel length modulation effect. And we proceed with the analysis of the NMOS via expanding $V_{DS}=V_D-V_S$ where we affix the $V_D$. # In the simplified analysis, we forgo the channel length modulation effect. And we proceed with the analysis of the NMOS via expanding $V_{DS}=V_D-V_S$ where we affix the $V_D$. # In[5]: NIdSimpDiodConected=simplify(NMOS.IdSimp(subs={VGS:VDS})) NIdSimpDiodConected # In[6]: NIdSimpDiodConected=NIdSimpDiodConected.subs(VDS, VD-VS) NIdSimpDiodConected # The following example values for a greater than $1\mu m$ device are based on example 19.1 load NMOS from chapter 19 of reference DeMassa # In[7]: subsN={W:5e6,L:15e6, nTechConst:20e-6, Vnth:1.1, VnA:1/.02, VD:5} # In[8]: NIdSimpDiodConectedN=lambdify(VS, NIdSimpDiodConected.subs(subsN), dummify=False) NIdSimpDiodConectedN(3.3) # In[9]: VSN=np.linspace(0, 5) # In[10]: VSN=np.linspace(0, 5) NIdSimpDiodData=pd.DataFrame() NIdSimpDiodData['Vs[V]']=VSN NIdSimpDiodData['Id[A]']=NIdSimpDiodConectedN(VSN) NIdSimpDiodData['DIdDVs[OhmInv]']=np.gradient(NIdSimpDiodData['Id[A]'], NIdSimpDiodData['Vs[V]']) NIdSimpDiodData['DDIdDDVs']=np.gradient(NIdSimpDiodData['DIdDVs[OhmInv]'], NIdSimpDiodData['Vs[V]']) NIdSimpDiodData['DDDIdDDDVs']=np.gradient(NIdSimpDiodData['DDIdDDVs'], NIdSimpDiodData['Vs[V]']) NIdSimpDiodData.describe() # In[11]: NVCompSimpLoc=np.where(NIdSimpDiodData['DDDIdDDDVs']==NIdSimpDiodData['DDDIdDDDVs'].min())[0][0] NVCompSimp=NIdSimpDiodData['Vs[V]'][NVCompSimpLoc] print(f'NMOS Simp Square Law Complince Voltage ={NVCompSimp:.3f}[V]') # In[12]: fig, [axId, axDId, axDDId, axDDDId]=plt.subplots(ncols=1, nrows=4, sharex=True) NIdSimpDiodData.plot(ax=axId, x='Vs[V]', y='Id[A]', legend=False) axId.axvline(x=NVCompSimp, linestyle='--', color='y', label=f'VComp={NVCompSimp:.3f}[V]') axId.set_ylabel('$I_d[A]$') axId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axId.grid() box = axId.get_position() axId.set_position([box.x0, box.y0, box.width * 0.8, box.height]) axId.legend(loc='center left', bbox_to_anchor=(1, 0.5)) NIdSimpDiodData.plot(ax=axDId, x='Vs[V]', y='DIdDVs[OhmInv]', legend=False) axDId.axvline(x=NVCompSimp, linestyle='--', color='y') axDId.set_ylabel(r'$g_m[\Omega^{-1}]$') axDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDId.grid() NIdSimpDiodData.plot(ax=axDDId, x='Vs[V]', y='DDIdDDVs', legend=False) axDDId.axvline(x=NVCompSimp, linestyle='--', color='y') axDDId.set_ylabel('$\dfrac{\partial^2 I_d}{\partial V_{S}^2}$') axDDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDDId.grid() NIdSimpDiodData.plot(ax=axDDDId, x='Vs[V]', y='DDDIdDDDVs', legend=False) axDDDId.axvline(x=NVCompSimp, linestyle='--', color='y') axDDDId.set_ylabel('$\dfrac{\partial^3 I_d}{\partial V_{S}^3}$') axDDDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDDDId.set_xlabel('$V_s[V]$') axDDDId.grid() fig.subplots_adjust(hspace=.5) plt.suptitle('NMOS Diode $I_d$ Simplifed '); # In the above graph, the substitutions were made to our simple model and `lambdify` was utilized to create a numerical version of the symbolic model of a greater than $1\mu m$ Diode connected NMOS device. As well be seen later the transconductance ($g_m$) dictates the behavior of the Diode Connected NMOS. And as the differential voltage $V_{DS}$ becomes less, remember $V_D$ is fixed the conductance of the Diode Connect NMOS drops before shutting off much like that of an ordinary rectifying diode as the voltage differential between its terminals approaches the Diodes threshold voltage. Unlike the Diode, this voltage is typically referred to as the compliance voltage. Where we by examining up to the third derivative of the $I_d$ we respect to the changing $V_s$ we can ascertain the compliance voltage exactly (within the scope of the model) # ### Full Analysis # In this full analysis, the Channel Length Modulation effect $\dfrac{V_{DS}}{V_A}$ is not ignored and proceed through the analysis as was done in the Simplified Analysis # In[13]: NIdFullDiodConected=simplify(NMOS.IdFull(subs={VGS:VDS})) NIdFullDiodConected # In[14]: NIdFullDiodConected=NIdFullDiodConected.subs(VDS, VD-VS) NIdFullDiodConected # In[15]: NIdFullDiodConectedN=lambdify(VS, NIdFullDiodConected.subs(subsN), dummify=False) NIdFullDiodConectedN(3.3) # In[16]: VSN=np.linspace(0, 5) NIdFullDiodData=pd.DataFrame() NIdFullDiodData['Vs[V]']=VSN NIdFullDiodData['Id[A]']=NIdFullDiodConectedN(VSN) NIdFullDiodData['DIdDVs[OhmInv]']=np.gradient(NIdFullDiodData['Id[A]'], NIdFullDiodData['Vs[V]']) NIdFullDiodData['DDIdDDVs']=np.gradient(NIdFullDiodData['DIdDVs[OhmInv]'], NIdFullDiodData['Vs[V]']) NIdFullDiodData['DDDIdDDDVs']=np.gradient(NIdFullDiodData['DDIdDDVs'], NIdFullDiodData['Vs[V]']) NIdFullDiodData.describe() # In[17]: NVCompFullLoc=np.where(NIdFullDiodData['DDDIdDDDVs']==NIdFullDiodData['DDDIdDDDVs'].min())[0][0] NVCompFull=NIdFullDiodData['Vs[V]'][NVCompFullLoc] print(f'NMOS Full Square Law Complince Voltage ={NVCompFull:.3f}[V]') # In[18]: fig, [axId, axDId, axDDId, axDDDId]=plt.subplots(ncols=1, nrows=4, sharex=True) NIdFullDiodData.plot(ax=axId, x='Vs[V]', y='Id[A]', legend=False) axId.axvline(x=NVCompFull, linestyle='--', color='y', label=f'VComp={NVCompFull:.3f}[V]') axId.set_ylabel('$I_d[A]$') axId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axId.grid() box = axId.get_position() axId.set_position([box.x0, box.y0, box.width * 0.8, box.height]) axId.legend(loc='center left', bbox_to_anchor=(1, 0.5)) NIdFullDiodData.plot(ax=axDId, x='Vs[V]', y='DIdDVs[OhmInv]', legend=False) axDId.axvline(x=NVCompFull, linestyle='--', color='y') axDId.set_ylabel(r'$g_m[\Omega^{-1}]$') axDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDId.grid() NIdFullDiodData.plot(ax=axDDId, x='Vs[V]', y='DDIdDDVs', legend=False) axDDId.axvline(x=NVCompFull, linestyle='--', color='y') axDDId.set_ylabel('$\dfrac{\partial^2 I_d}{\partial V_{S}^2}$') axDDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDDId.grid() NIdFullDiodData.plot(ax=axDDDId, x='Vs[V]', y='DDDIdDDDVs', legend=False) axDDDId.axvline(x=NVCompFull, linestyle='--', color='y') axDDDId.set_ylabel('$\dfrac{\partial^3 I_d}{\partial V_{S}^3}$') axDDDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDDDId.set_xlabel('$V_s[V]$') axDDDId.grid() fig.subplots_adjust(hspace=.5) plt.suptitle('NMOS Diode $I_d$ Full '); # ### Difference Between Simplified and Full analysis # We can compare not only the $I_d vs. V_S$ graphs for the two analysis but also the difference in the found Compliance Voltage to see if there are any difference in ignoring the Channel Length Modulation effect in a greater then $1\mu m$ Diode connected NMOS. # In[19]: NVCompFull-NVCompSimp # In[20]: fig, ax=plt.subplots(nrows=1, ncols=1) ax.plot(VSN, NIdSimpDiodConectedN(VSN), label='Simp Model') ax.plot(VSN, NIdFullDiodConectedN(VSN), label='Full Model') ax.set_xlabel('$V_S[V]$'); ax.set_ylabel('$I_d[A]$') ax.grid() ax.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) fig.subplots_adjust(hspace=.5) plt.suptitle('NMOS Diode Id Compersion between Simp and Full'); # As is shown the differences between the Simplified and the Full analysis are minute for a diode connected NMOS ( be in mind a large channel NMOS). # ### Diode Connected as a Topology Slice # In the following, we will examine the what a Diode Connected Transistor means in terms of the global view of $I_d$. This is maybe not a new viewpoint but a less common than the declaration that a Diode Connected MOSFET is always in the saturated state (This is true-ish up to the compliance voltage). But given the ease of data collection and analyses with `PySpice` and *Python* we can do better in predicting the Diode-Connected MOSFET from the transistors $I_d$ surface that shows the MOSFETS behaver for all combinations of $V_{GS}, V_{DS}$ # In[21]: NIdFullN=lambdify((VGS, VDS), NMOS.IdFull(subs=subsN), dummify=False) VGSN, VDSN=np.meshgrid(np.linspace(0, 5), np.linspace(0, 5)) NIdFullNDate=NIdFullN(VGSN, VDSN) NIdFullNDateDiag=NIdFullNDate.diagonal() VdiagN=VGSN.diagonal() # In[22]: get_ipython().run_line_magic('matplotlib', 'notebook') get_ipython().run_line_magic('matplotlib', 'notebook') from mpl_toolkits.mplot3d import axes3d fig = plt.figure() axId = fig.gca(projection='3d') axId.set_xlabel('$V_{gs}$'); axId.set_ylabel('$V_{ds}$'); axId.set_zlabel('$I_d[mA]$') surf = axId.plot_surface(VGSN, VDSN, NIdFullNDate*1000, cmap=cm.coolwarm, linewidth=0, antialiased=True) axId.plot(VdiagN, VdiagN, NIdFullNDateDiag*1000, label='$V_{GS}=V_{DS}$') box = ax.get_position() axId.set_position([box.x0, box.y0, box.width * 0.8, box.height]) axId.legend(loc='center left', bbox_to_anchor=(1, 0.5)) plt.suptitle('NMOS $I_d$ Full Surface') plt.show() # (if the 3D Graph is not showing up try rerunning the cell twice, at the time of this writing the nbmagic `notebook` is still a bit temperamental) # The above surface plot of the current for (this cant be stressed enough) large channel Full modeled NMOS shows every combination of $V_{GS}$ and $V_{DS}$ that effects the NMOS's $I_d$. Since we are interested in the Diode-Connected NMOS in this analysis we know that the regions of interest will be where $$V_{GS}=V_{DS}$$. # Thus we can find this ROI and overlay it on the $I_D$ surface and plot it individually below. The result is identical to what we predicted from modify the governing equations to the Diode-Connected topology. Save for the vertical mirroring that arises from the choice of fixing the $V_D$ and not the $V_S$. # In[23]: get_ipython().run_line_magic('matplotlib', 'inline') Xdiag=VDSN.diagonal(); Zdiag=NIdFullNDate.diagonal() fig, ax=plt.subplots(ncols=1, nrows=1) ax.plot(Xdiag, Zdiag*1000) ax.set_xlabel('$V_{DS}[V]$'); ax.set_ylabel('$I_d[mA]$') plt.suptitle('NMOS $I_d$ Full Surface Cut along $V_{DS}=V_{GS}$'); # ## SPICE Diode Connected NMOS # Here we proceed with the same analysis but instead utilizing an older submicron NMOS technology. The technology that was chosen was the readily available Taiwan Semiconductor Manufacturing Company (TSMC) $180nm$ NMOS with a channel width and length set in the next cell. While the $180nm$ is not even close to there current cutting-edge $7nm$ process it does display non-square law effects without getting too much deviation from greater $1\mu m$ technology where the Square Law holds better. # In[24]: NMOSR_W=200; NMOSR_L=200 #nm # ### SPICE analysis of TSMC 180nm Diode Connected NMOS # setup the "NetList" # In[25]: TestCirN=Circuit('DCBench') Vbs=TestCirN.V('bs', 'base', TestCirN.gnd, 0@u_V) #VDD Vds=TestCirN.V('ds', 'drain', TestCirN.gnd, 1.8@u_V) #Vload Vsgnd=TestCirN.V('sgnd', 'source', TestCirN.gnd, 0@u_V) TestCirN.include(spice_library['TSMC180nmN']) M0=TestCirN.MOSFET('0', 'drain', 'drain', 'source', 'base', model='TSMC180nmN', length=NMOSR_L@u_nm, width=NMOSR_W@u_nm) print(TestCirN) # setup and run the Simulation # In[26]: TempC=27 TestCirNSim=TestCirN.simulator(temperature=TempC, nominal_temperature=TempC) TestCirNSimData=TestCirNSim.dc(Vsgnd=slice(0, 1.8, .01)) # In[27]: NDiodeConctedData=pd.DataFrame() NDiodeConctedData['Vsgnd[V]']=pd.Series(TestCirNSimData.sweep) NDiodeConctedData['Id[A]']=-TestCirNSimData.Vds NDiodeConctedData.count() # In[28]: NDiodeConctedData['DIdDVs[OhmInv]']=np.gradient(NDiodeConctedData['Id[A]'], NDiodeConctedData['Vsgnd[V]']) NDiodeConctedData['DDIdDDVs']=np.gradient(NDiodeConctedData['DIdDVs[OhmInv]'], NDiodeConctedData['Vsgnd[V]']) NDiodeConctedData['DDDIdDDDVs']=np.gradient(NDiodeConctedData['DDIdDDVs'], NDiodeConctedData['Vsgnd[V]']) NDiodeConctedData.describe() # In[29]: NVCompReal=NDiodeConctedData['Vsgnd[V]'][np.where(NDiodeConctedData['DDDIdDDDVs']==NDiodeConctedData['DDDIdDDDVs'].max())[0]] NVCompReal=np.around(float(NVCompReal), 4); NVCompReal # In[30]: NVbiasTarget=NVCompReal/2; NVbiasTarget # In[31]: get_ipython().run_line_magic('matplotlib', 'inline') fig, [axId, axDId, axDDId, axDDDId]=plt.subplots(ncols=1, nrows=4, sharex=True) NDiodeConctedData.plot(ax=axId, x='Vsgnd[V]', y='Id[A]', legend=False) axId.axvline(x=NVCompReal, linestyle='--', color='y', label=f'VComp={NVCompReal:.3f}[V]') axId.axvline(x=NVbiasTarget, linestyle='--', color='g', label=f'VBiasTar={NVbiasTarget:.3f}[V]') axId.set_ylabel('$I_d[A]$') axId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axId.grid() box = axId.get_position() axId.set_position([box.x0, box.y0, box.width * 0.8, box.height]) axId.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ############### NDiodeConctedData.plot(ax=axDId, x='Vsgnd[V]', y='DIdDVs[OhmInv]', legend=False) axDId.axvline(x=NVCompReal, linestyle='--', color='y') axDId.axvline(x=NVbiasTarget, linestyle='--', color='g') axDId.set_ylabel(r'$g_m[\Omega^{-1}]$') axDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDId.grid() ####################################### NDiodeConctedData.plot(ax=axDDId, x='Vsgnd[V]', y='DDIdDDVs', legend=False) axDDId.axvline(x=NVCompReal, linestyle='--', color='y') axDDId.axvline(x=NVbiasTarget, linestyle='--', color='g') axDDId.set_ylabel('$\dfrac{\partial^2 I_d}{\partial V_{S}^2}$') axDDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDDId.grid() ############################################# NDiodeConctedData.plot(ax=axDDDId, x='Vsgnd[V]', y='DDDIdDDDVs', legend=False) axDDDId.axvline(x=NVCompReal, linestyle='--', color='y') axDDDId.axvline(x=NVbiasTarget, linestyle='--', color='g') axDDDId.set_ylabel('$\dfrac{\partial^3 I_d}{\partial V_{S}^3}$') axDDDId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) axDDDId.set_xlabel('$V_s[V]$') axDDDId.grid() fig.subplots_adjust(hspace=.5) plt.suptitle(f'TSMC180nm NMOS $I_d$ Diode Connnected W={NMOSR_W}[nm], L={NMOSR_L}[nm]'); # (Finish later) # ### SPICE Confirmation of Topology Interpretation # Test Circuit for extracting NMOS characteristics curves # In[32]: TestCir=Circuit('DCBench') Vgs=TestCir.V('gs', 'gate', TestCir.gnd, 1.8@u_V) Vbs=TestCir.V('bs', 'base', TestCir.gnd, 0@u_V) Vds=TestCir.V('ds', 'drain', TestCir.gnd, 1.8@u_V) TestCir.include(spice_library['TSMC180nmN']) M0=TestCir.MOSFET('0', 'drain', 'gate', TestCir.gnd, 'base', model='TSMC180nmN', length=200@u_nm, width=200@u_nm) print(TestCir) # Create simulation object # In[33]: TempC=27 TestCirSim=TestCir.simulator(temperature=TempC, nominal_temperature=TempC) # In[34]: x=np.linspace(0, 1.8) y=np.linspace(0, 1.8) X, Y=np.meshgrid(x, y) len(x),len(y), np.prod([*X.shape]) # perform a DC operating point analyses at every combination of $V_{GS}$ and $V_{DS}$ specified and bind the results to a 2D array for use in plotting a 3D surface of $I_D$ # In[35]: Z=np.zeros(X.shape) M0.length=200@u_nm for i in IProd(x, y): Vgs.dc_value=i[0]@u_V; Vds.dc_value=i[1]@u_V TestCirSimData=TestCirSim.operating_point() Z[np.where(x==i[0])[0], np.where(y==i[1])[0]]=np.array(-TestCirSimData.Vds) # In[36]: DIdDVgs, DIdDVds=np.gradient(Z, x, y) Av0=DIdDVgs/DIdDVds DIdDVgsDiag=DIdDVgs.diagonal() DIdDVdsDiag=DIdDVds.diagonal() Av0Diag=Av0.diagonal() # In[37]: Xdiag=X.diagonal(); ZDiag=1000*Z.diagonal() # In[38]: get_ipython().run_line_magic('matplotlib', 'notebook') get_ipython().run_line_magic('matplotlib', 'notebook') from mpl_toolkits.mplot3d import axes3d fig = plt.figure() ############### axId = fig.add_subplot(3, 1, 1, projection='3d') axId.set_xlabel('$V_{gs}[V]$'); ax.set_ylabel('$V_{ds}[V]$'); axId.set_zlabel('$I_d[mA]$') axId.plot_surface(X, Y, Z*1000, cmap=cm.coolwarm, linewidth=0, antialiased=True) axId.ticklabel_format(axis='z', style='sci', scilimits=(-1,1)) axId.plot(Xdiag, Xdiag, ZDiag, label='Diode Line') axId.legend() ################## axDIdDVgs = fig.add_subplot(3, 2, 3, projection='3d') axDIdDVgs.set_xlabel('$V_{gs}[V]$'); axDIdDVgs.set_ylabel('$V_{ds}[V]$'); axDIdDVgs.set_zlabel('$\dfrac{\partial I_d}{\partial V_{gs}}$') axDIdDVgs.plot_surface(X, Y, DIdDVgs, cmap=cm.coolwarm, linewidth=0, antialiased=True) axDIdDVgs.ticklabel_format(axis='z', style='sci', scilimits=(-1,1)) axDIdDVgs.plot(Xdiag, Xdiag, DIdDVgsDiag) ############################## axDIdDVds = fig.add_subplot(3, 2, 4, projection='3d') axDIdDVds.set_xlabel('$V_{gs}[V]$'); axDIdDVds.set_ylabel('$V_{ds}[V]$'); axDIdDVds.set_zlabel('$\dfrac{\partial I_d}{\partial V_{ds}}$') axDIdDVds.plot_surface(X, Y, DIdDVds, cmap=cm.coolwarm, linewidth=0, antialiased=True) axDIdDVds.plot(Xdiag, Xdiag, DIdDVdsDiag) axDIdDVds.ticklabel_format(axis='z', style='sci', scilimits=(-1,1)) ############################ axAv0 = fig.add_subplot(3, 2, 5, projection='3d') axAv0.set_xlabel('$V_{gs}[V]$'); axAv0.set_ylabel('$V_{ds}[V]$'); axAv0.set_zlabel('$A_{V0}$') axAv0.plot_surface(X, Y, Av0, cmap=cm.coolwarm, linewidth=0, antialiased=True) axAv0.plot(Xdiag, Xdiag, Av0Diag) axAv0.ticklabel_format(axis='z', style='sci', scilimits=(-1,1)) plt.suptitle(f'TSMC180nm NMOS $I_d$ Surface W={NMOSR_W}[nm], L={NMOSR_L}[nm]') fig.subplots_adjust(hspace=.5, wspace=0.5); plt.show() # (Need to Get a hold of the subplot numbering arghh) # In[39]: get_ipython().run_line_magic('matplotlib', 'inline') fig, [axId, axDIdDVgs, axDIdDVds, axAv0]=plt.subplots(nrows=4, ncols=1, sharex=True) axId.plot(Xdiag, ZDiag) axId.set_ylabel('$I_d[mA]$') axId.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) ######################### axDIdDVgs.plot(Xdiag, DIdDVgsDiag) axDIdDVgs.set_ylabel('$\dfrac{\partial I_d}{\partial V_{gs}}$') axDIdDVgs.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) ######################## axDIdDVds.plot(Xdiag, DIdDVdsDiag) axDIdDVds.set_ylabel('$\dfrac{\partial I_d}{\partial V_{ds}}$') axDIdDVds.ticklabel_format(axis='y', style='sci', scilimits=(-1,1)) ####################### axAv0.plot(Xdiag, Av0Diag) axAv0.set_ylabel('$A_{V0}$') axAv0.set_xlabel('$V_{ds}[V]$') fig.subplots_adjust(hspace=.5) plt.suptitle(f'TSMC180nm NMOS $I_d$ Diode Connnected Counters W={NMOSR_W}[nm], L={NMOSR_L}[nm]'); # In the above graph there is a $A_{vo}$ where # $$A_{vo}=g_m r_{DS}=\dfrac{\partial I_d}{\partial V_{gs}}/\dfrac{\partial I_d}{\partial V_{ds}}$$ # this is not a true intrensit gain. It is however a meassure of the influsince between $\dfrac{\partial I_d}{\partial V_{gs}}$ and $\dfrac{\partial I_d}{\partial V_{ds}}$ that shows that the transcondutance domonated the output resistince for a Diode connected NMOS # ### Testing the frequency dependence of the Bias point # In[43]: TestCirSinN=Circuit('DCBench') Vbs=TestCirSinN.V('bs', 'base', TestCirSinN.gnd, 0@u_V) #VDD Vds=TestCirSinN.V('ds', 'drain', TestCirSinN.gnd, 1.8@u_V) #Vload Vsgnd=TestCirSinN.SinusoidalVoltageSource('sgnd', 'source', TestCirSinN.gnd, dc_offset=NVbiasTarget@u_V, amplitude=.1@u_V, frequency=1@u_kHz) TestCirSinN.include(spice_library['TSMC180nmN']) M0=TestCirSinN.MOSFET('0', 'drain', 'drain', 'source', 'base', model='TSMC180nmN', length=200@u_nm, width=200@u_nm) print(TestCirSinN) # In[44]: TempC=27 TestCirSinNSim=TestCirSinN.simulator(temperature=TempC, nominal_temperature=TempC) TestCirSinNData=TestCirSinNSim.ac(start_frequency=1@u_Hz, stop_frequency=100@u_MHz, number_of_points=100, variation='dec') # In[45]: from PySpice.Plot.BodeDiagram import bode_diagram # In[46]: Id_Freq=pd.Series(-TestCirSinNData.Vds) figure = plt.figure(1, (20, 10)) axes = (plt.subplot(211), plt.subplot(212)) bode_diagram(axes=axes, frequency=TestCirSinNData.frequency, gain=20*np.log10(np.absolute(Id_Freq)), phase=np.angle(Id_Freq, deg=True), marker='.', linestyle='-', ) # # Diode Connected PMOS # ## Square Law Theory # ### Simplifed # In[47]: PIdSimpDiodConected=simplify(PMOS.IdSimp(subs={VSG:VSD})) PIdSimpDiodConected # In[48]: PIdSimpDiodConected=PIdSimpDiodConected.subs(VSD, VS-VD) PIdSimpDiodConected # In[49]: subsP={W:8e6,L:2e6, nTechConst:2e-6, Vnth:1.1, VnA:1/.02, VD:5} # # I will finish this later # In[ ]: # In[ ]: