# Ideal diode: MTK+callbacks to mimic Verilog-A events?

### 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.