Skip to content

Add NMOS PMOS Transistors #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/src/API/electrical.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ IdealOpAmp
Diode
HeatingDiode
VariableResistor
NMOS
PMOS
PNP
NPN
```
Expand Down
74 changes: 74 additions & 0 deletions docs/src/tutorials/MOSFET_calibration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# MOSFET I-V Curves
In this example, first we'll demonstrate the I-V curves of the NMOS transistor model.
First of all, we construct a circuit using the NMOS transistor. We'll need to import ModelingToolkit and the Electrical standard library that holds the transistor models.

```@example NMOS
using ModelingToolkit
using ModelingToolkit: t_nounits as t
using ModelingToolkitStandardLibrary.Electrical
using ModelingToolkitStandardLibrary.Blocks: Constant
using OrdinaryDiffEq
using Plots
```

Here we just connect the source pin to ground, the drain pin to a voltage source named `Vcc`, and the gate pin to a voltage source named `Vb`.
```@example NMOS
@mtkmodel SimpleNMOSCircuit begin
@components begin
Q1 = NMOS()
Vcc = Voltage()
Vb = Voltage()
ground = Ground()

Vcc_const = Constant(k=V_cc)
Vb_const = Constant(k=V_b)
end

@parameters begin
V_cc = 5.0
V_b = 3.5
end
@equations begin
#voltage sources
connect(Vcc_const.output, Vcc.V)
connect(Vb_const.output, Vb.V)

#ground connections
connect(Vcc.n, Vb.n, ground.g, Q1.s)

#other stuff
connect(Vcc.p, Q1.d)
connect(Vb.p, Q1.g)
end
end

@mtkbuild sys = SimpleNMOSCircuit(V_cc = 5.0, V_b = 3.5)

prob = ODEProblem(sys, Pair[], (0.0, 10.0))
sol = solve(prob)
```

Now to make sure that the transistor model is working like it's supposed to, we can examine the plots of the drain-source voltage vs. the drain current, otherwise knowns as the I-V curve of the transistor.
```@example NMOS
v_cc_list = collect(0.05:0.1:10.0)

I_D_list = []
I_D_lists = []

for V_b in [1.0, 1.4, 1.8, 2.2, 2.6]
I_D_list = []
for V_cc in v_cc_list
@mtkbuild sys = SimpleNMOSCircuit(V_cc=V_cc, V_b=V_b)
prob = ODEProblem(sys, Pair[], (0.0, 10.0))
sol = solve(prob)
push!(I_D_list, sol[sys.Q1.d.i][1])
end
push!(I_D_lists, I_D_list)
end

reduce(hcat, I_D_lists)
plot(v_cc_list, I_D_lists, title="NMOS IV Curves", label=["V_GS: 1.0 V" "V_GS: 1.4 V" "V_GS: 1.8 V" "V_GS: 2.2 V" "V_GS: 2.6 V"], xlabel = "Drain-Source Voltage (V)", ylabel = "Drain Current (A)")
```

We can see that we get exactly what we would expect: as the drain-source voltage increases, the drain current increases, until the the transistor gets in to the saturation region of operation.
Then the only increase in drain current is due to the channel-length modulation effect. Additionally, we can see that the maximum current reached increases as the gate voltage increases.
180 changes: 180 additions & 0 deletions src/Electrical/Analog/mosfets.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
"""
NMOS(;name, V_tn, R_DS, lambda)

Creates an N-type MOSFET transistor

# Structural Parameters
- `use_transconductance`: If `true` the parameter `k_n` needs to be provided, and is used in the calculation of the current
through the transistor. Otherwise, `mu_n`, `C_ox`, `W`, and `L` need to be provided and are used to calculate the transconductance.

- `use_channel_length_modulation`: If `true` the channel length modulation effect is taken in to account. In essence this gives
the drain-source current has a small dependency on the drains-source voltage in the saturation region of operation.

# Connectors
- `d` Drain Pin
- `g` Gate Pin
- `s` Source Pin

# Parameters
- `mu_n`: Electron mobility
- `C_ox`: Oxide capacitance (F/m^2)
- `W`: Channel width (m)
- `L`: Channel length
- `k_n`: MOSFET transconductance parameter

Based on the MOSFET models in (Sedra, A. S., Smith, K. C., Carusone, T. C., & Gaudet, V. C. (2021). Microelectronic circuits (8th ed.). Oxford University Press.)
"""
@mtkmodel NMOS begin
@variables begin
V_GS(t)
V_DS(t)
V_OV(t)
end

@components begin
d = Pin()
g = Pin()
s = Pin()
end

@parameters begin
V_tn = 0.8, [description = "Threshold voltage (V)"]
R_DS = 1e7, [description = "Drain to source resistance (Ω)"]

if use_channel_length_modulation
lambda = 1 / 25, [description = "Channel length modulation coefficient (V^(-1))"]
end

if !use_transconductance
mu_n, [description = "Electron mobility"]
C_ox, [description = "Oxide capacitance (F/m^2)"]
W, [description = "Channel width (m)"]
L, [description = "Channel length (m)"]
else
k_n = 20e-3, [description = "MOSFET transconductance parameter"]
end
end

@structural_parameters begin
use_transconductance = true
use_channel_length_modulation = true
end

begin
if !use_transconductance
k_n = mu_n * C_ox * (W / L)
end
end

@equations begin
V_DS ~ ifelse(d.v < s.v, s.v - d.v, d.v - s.v)
V_GS ~ g.v - ifelse(d.v < s.v, d.v, s.v)
V_OV ~ V_GS - V_tn

d.i ~ ifelse(d.v < s.v, -1, 1) * ifelse(V_GS < V_tn,
0 + V_DS / R_DS,
ifelse(V_DS < V_OV,
ifelse(use_channel_length_modulation,
k_n * (1 + lambda * V_DS) * (V_OV - V_DS / 2) * V_DS + V_DS / R_DS,
k_n * (V_OV - V_DS / 2) * V_DS + V_DS / R_DS),
ifelse(use_channel_length_modulation,
((k_n * V_OV^2) / 2) * (1 + lambda * V_DS) + V_DS / R_DS,
(k_n * V_OV^2) / 2 + V_DS / R_DS)
)
)

g.i ~ 0
s.i ~ -d.i
end
end



"""
PMOS(;name, V_tp, R_DS, lambda)

Creates an N-type MOSFET transistor

# Structural Parameters
- `use_transconductance`: If `true` the parameter `k_p` needs to be provided, and is used in the calculation of the current
through the transistor. Otherwise, `mu_n`, `C_ox`, `W`, and `L` need to be provided and are used to calculate the transconductance.

- `use_channel_length_modulation`: If `true` the channel length modulation effect is taken in to account. In essence this gives
the drain-source current has a small dependency on the drains-source voltage in the saturation region of operation.

# Connectors
- `d` Drain Pin
- `g` Gate Pin
- `s` Source Pin

# Parameters
- `mu_p`: Electron mobility
- `C_ox`: Oxide capacitance (F/m^2)
- `W`: Channel width (m)
- `L`: Channel length
- `k_p`: MOSFET transconductance parameter

Based on the MOSFET models in (Sedra, A. S., Smith, K. C., Carusone, T. C., & Gaudet, V. C. (2021). Microelectronic circuits (8th ed.). Oxford University Press.)
"""
@mtkmodel PMOS begin
@variables begin
V_GS(t)
V_DS(t)
end

@components begin
d = Pin()
g = Pin()
s = Pin()
end

@parameters begin
V_tp = -1.5, [description = "Threshold voltage (V)"]
R_DS = 1e7, [description = "Drain-source resistance (Ω)"]

if use_channel_length_modulation
lambda = 1 / 25, [description = "Channel length modulation coefficient (V^(-1))"]
end

if !use_transconductance
mu_p, [description = "Hole mobility"]
C_ox, [description = "Oxide capacitance (F/m^2)"]
W, [description = "Channel width (m)"]
L, [description = "Channel length (m)"]
else
k_p = 20e-3
end
end

@structural_parameters begin
use_transconductance = true
use_channel_length_modulation = true
end

begin
if !use_transconductance
k_p = mu_p * C_ox * (W / L)
end
end

@equations begin
V_DS ~ ifelse(d.v > s.v, s.v - d.v, d.v - s.v)
V_GS ~ g.v - ifelse(d.v > s.v, d.v, s.v)

d.i ~ -ifelse(d.v > s.v, -1.0, 1.0) * ifelse(V_GS > V_tp,
0.0 + V_DS / R_DS,
ifelse(V_DS > (V_GS - V_tp),
ifelse(use_channel_length_modulation,
k_p * (1 + lambda * V_DS) * ((V_GS - V_tp) - V_DS / 2) * V_DS +
V_DS / R_DS,
k_p * ((V_GS - V_tp) - V_DS / 2) * V_DS + V_DS / R_DS),
ifelse(use_channel_length_modulation,
((k_p * (V_GS - V_tp)^2) / 2) * (1 + lambda * V_DS) + V_DS / R_DS,
(k_p * (V_GS - V_tp)^2) / 2 + V_DS / R_DS)
)
)

g.i ~ 0
s.i ~ -d.i
end
end
3 changes: 3 additions & 0 deletions src/Electrical/Electrical.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ include("Analog/sensors.jl")
export Voltage, Current
include("Analog/sources.jl")

export NMOS, PMOS
include("Analog/mosfets.jl")

export NPN, PNP
include("Analog/transistors.jl")

Expand Down
Loading
Loading