<jupyter_start><jupyter_text>\title{Diode Connected MOSFET Tobology}\author{<NAME>}\maketitle Table of Contents1&nbsp;&nbsp;Background2&nbsp;&nbsp;References  (Need to Finish)3&nbsp;&nbsp;Imports4&nbsp;&nbsp;Diode Connected NMOS4.1&nbsp;&nbsp;Square Law Theory4.1.1&nbsp;&nbsp;Simplified Analysis4.1.2&nbsp;&nbsp;Full Analysis4.1.3&nbsp;&nbsp;Difference Between Simplified and Full analysis4.1.4&nbsp;&nbsp;Diode Connected as a Topology Slice4.2&nbsp;&nbsp;SPICE Diode Connected NMOS4.2.1&nbsp;&nbsp;SPICE analysis of TSMC 180nm Diode Connected NMOS4.2.2&nbsp;&nbsp;SPICE Confirmation of Topology Interpretation4.2.3&nbsp;&nbsp;Testing the frequency dependence of the Bias point5&nbsp;&nbsp;Diode Connected PMOS5.1&nbsp;&nbsp;Square Law Theory5.1.1&nbsp;&nbsp;Simplifed6&nbsp;&nbsp;I will finish this later  BackgroundThe 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<jupyter_code>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
%matplotlib inline
import nbimporter
nbimporter.options['only_defs'] = False
from SympyMOSModels import *
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)<jupyter_output><empty_output><jupyter_text>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.<jupyter_code>VD, VS=symbols('V_D, V_S')<jupyter_output><empty_output><jupyter_text>Simplified AnalysisIn 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$.<jupyter_code>NIdSimpDiodConected=simplify(NMOS.IdSimp(subs={VGS:VDS}))
NIdSimpDiodConected
NIdSimpDiodConected=NIdSimpDiodConected.subs(VDS, VD-VS)
NIdSimpDiodConected<jupyter_output><empty_output><jupyter_text>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<jupyter_code>subsN={W:5e6,L:15e6, nTechConst:20e-6, Vnth:1.1, VnA:1/.02, VD:5}
NIdSimpDiodConectedN=lambdify(VS, NIdSimpDiodConected.subs(subsN), dummify=False)
NIdSimpDiodConectedN(3.3)
VSN=np.linspace(0, 5)
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()
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]')

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 ');<jupyter_output><empty_output><jupyter_text>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 AnalysisIn 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<jupyter_code>NIdFullDiodConected=simplify(NMOS.IdFull(subs={VGS:VDS}))
NIdFullDiodConected
NIdFullDiodConected=NIdFullDiodConected.subs(VDS, VD-VS)
NIdFullDiodConected
NIdFullDiodConectedN=lambdify(VS, NIdFullDiodConected.subs(subsN), dummify=False)
NIdFullDiodConectedN(3.3)
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()
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]')

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 ');<jupyter_output><empty_output><jupyter_text>Difference Between Simplified and Full analysisWe 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.<jupyter_code>NVCompFull-NVCompSimp
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');<jupyter_output><empty_output><jupyter_text>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 SliceIn 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}$<jupyter_code>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()
%matplotlib notebook
%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()<jupyter_output><empty_output><jupyter_text>(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$.<jupyter_code>%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}$');<jupyter_output><empty_output><jupyter_text>SPICE Diode Connected NMOSHere 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.<jupyter_code>NMOSR_W=200; NMOSR_L=200 #nm<jupyter_output><empty_output><jupyter_text>SPICE analysis of TSMC 180nm Diode Connected NMOS setup the "NetList"<jupyter_code>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)<jupyter_output>.title DCBench
.include /home/iridium/Documents/ClonedGitReps/PySpiceExsamples/SpiceLib/TSMC180N.lib
Vbs base 0 0V
Vds drain 0 1.8V
Vsgnd source 0 0V
M0 drain drain source base TSMC180nmN l=200nm w=200nm<jupyter_text>setup and run the Simulation<jupyter_code>TempC=27
TestCirNSim=TestCirN.simulator(temperature=TempC, nominal_temperature=TempC)
TestCirNSimData=TestCirNSim.dc(Vsgnd=slice(0, 1.8, .01))
NDiodeConctedData=pd.DataFrame()
NDiodeConctedData['Vsgnd[V]']=pd.Series(TestCirNSimData.sweep)
NDiodeConctedData['Id[A]']=-TestCirNSimData.Vds
NDiodeConctedData.count()

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()
NVCompReal=NDiodeConctedData['Vsgnd[V]'][np.where(NDiodeConctedData['DDDIdDDDVs']==NDiodeConctedData['DDDIdDDDVs'].max())[0]]
NVCompReal=np.around(float(NVCompReal), 4); NVCompReal
NVbiasTarget=NVCompReal/2; NVbiasTarget
%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]');<jupyter_output><empty_output><jupyter_text>(Finish later)  SPICE Confirmation of Topology Interpretation Test Circuit for extracting NMOS characteristics curves<jupyter_code>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)<jupyter_output>.title DCBench
.include /home/iridium/Documents/ClonedGitReps/PySpiceExsamples/SpiceLib/TSMC180N.lib
Vgs gate 0 1.8V
Vbs base 0 0V
Vds drain 0 1.8V
M0 drain gate 0 base TSMC180nmN l=200nm w=200nm<jupyter_text>Create simulation object<jupyter_code>TempC=27
TestCirSim=TestCir.simulator(temperature=TempC, nominal_temperature=TempC)
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])<jupyter_output><empty_output><jupyter_text>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$<jupyter_code>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)
DIdDVgs, DIdDVds=np.gradient(Z, x, y)
Av0=DIdDVgs/DIdDVds
DIdDVgsDiag=DIdDVgs.diagonal()
DIdDVdsDiag=DIdDVds.diagonal()
Av0Diag=Av0.diagonal()
Xdiag=X.diagonal(); ZDiag=1000*Z.diagonal()
%matplotlib notebook
%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()<jupyter_output><empty_output><jupyter_text>(Need to Get a hold of the subplot numbering arghh)<jupyter_code>%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]');<jupyter_output><empty_output><jupyter_text>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<jupyter_code>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)
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')
from PySpice.Plot.BodeDiagram import bode_diagram
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='-',
            )<jupyter_output><empty_output><jupyter_text>Diode Connected PMOS  Square Law Theory  Simplifed<jupyter_code>PIdSimpDiodConected=simplify(PMOS.IdSimp(subs={VSG:VSD}))
PIdSimpDiodConected
PIdSimpDiodConected=PIdSimpDiodConected.subs(VSD, VS-VD)
PIdSimpDiodConected
subsP={W:8e6,L:2e6, nTechConst:2e-6, Vnth:1.1, VnA:1/.02, VD:5}<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15789917738873654, 'fraction_numerical': 0.01885678126977431, 'mean_word_length': 6.949698189134809, 'pattern_counts': {'":': 0, '<': 68, '<?xml version=': 0, '>': 68, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '17', 'dir': 'jupyter-structured-clean-dedup', 'id': '482733', 'license': 'MIT', 'n_tokens_mistral': 9882, 'n_tokens_neox': 9303, 'n_words': 1858, 'path': 'DiodeConnectedMOFET.ipynb', 'repo_name': 'PyLCARS/PySpiceExsamples', 'size': '23714'}