Verilog-A-like circuit components
I recently found examples how to use ModelingToolkit.jl to model electrical circuit components in a Verilog-A-esque fashion. Pretty neat!:
→ ModelingToolkit.jl/electrical_components.jl at master · SciML/ModelingToolkit.jl · GitHub
Using a similar methodology, I got a Shockley (exponential) diode model working. I’m having a bit of trouble converging on more complex circuits, but I got it to work - which is good!
Ideal diode (with discontinuities)
I then tried creating an “ideal” diode model using this same methodology, but it won’t simulate very well. I am aware that there are convergence issues when models have discontinuities like this, but Verilog-A seems to be able to manage quite well despite these issues.
Here is my model:
function Diode(::Ideal; name)
@named(p = Pin()); @named(n = Pin())
@variables v(t) i(t)
eqs = [
v ~ p.v - n.v #Convenience
0 ~ p.i + n.i #in = -out
i ~ p.i #Positive current flows *into* p terminal
0 ~ IfElse.ifelse(v<0, i, v)
]
ODESystem(eqs, t, [v, i], [], systems=[p, n], defaults=Dict(), name=name)
end
VerilogA events
I suspect one thing helping out in VerilogA is the fact that you can use events to trigger a timepoint at the discontinuity (If I remember correctly).
Here is an example of using events from the VerilogAMS Reference manual (v2.4):
module comparator(cout, inp, inm);
output cout;
input inp, inm;
electrical cout, inp, inm;
parameter real td = 1n, tr = 1n, tf = 1n;
real vcout;
analog begin
@(cross(V(inp) - V(inm), 0))
vcout = ((V(inp) > V(inm)) ? 1 : 0);
V(cout) <+ transition(vcout, td, tr, tf);
end
endmodule
Apparently, the VerilogA @cross
event is critical to help the simulator produce accurately-timed results with this device. In my experience, this sort of code deals fairly well with discontinuities - as long as the output transitions with finite rise/fall times (tr, tf)
- which it does thanks to the transition()
“filter”.
VerilogA events == MTK+callbacks?
I sort of stumbled on a few videos and docs regarding continuous callbacks that appear to do something similar to VerilogA’s @cross
events:
→ Event Handling and Callback Functions · DifferentialEquations.jl
MTK+callbacks only on solve()
?
One thing I noticed, though is that it only seems to be possible to add callbacks “globally” when you call solve()
. I find the way you add VerilogA’s @cross
events to be much more elegant/practical - given that it is specified/registered within the “device” model itself.
Adding callbacks to the solve()
command feels sort of inelegant/error-prone, etc when compared to the VerilogA events solution.
Attempt at creating diode “callback”
I tried to build my own callback to trigger a timepoint in my simulation using the docs I found:
(Event Handling and Callback Functions · DifferentialEquations.jl)
function condition(sys,t,integrator) # Event @ v = 0
sys.v ~ 0
end
function affect!(integrator)
nothing
end
cb = ContinuousCallback(condition,affect!)
But I don’t think this is correct. My model is using what I believe is called the “domain-specific language” layer from ModelingToolkit: “@variables v(t) i(t)
”, etc.
All examples I found in the DifferentialEquations.jl documentation expect you to use the u
and du
vectors instead of the more (subjectively) readable sys
variables.
Additional/Overall questions
- Am I possibly interpreting things incorrectly?