I am trying to understand the concept of direct feedthrough in QSPICE, particularly when using a DLL block.
My understanding is that a direct feedthrough exists when the output at the current simulation time depends immediately on the current input, without any delay or state update. I would like to know:
How does QSPICE detect or handle direct feedthrough in DLL blocks?
Is there a way to explicitly specify whether a DLL has direct feedthrough or not?
What are the implications of enabling or avoiding direct feedthrough on convergence, timestep control, and simulation speed?
Any clarification or references would be greatly appreciated.
Just to clarify, the output of a DLL block is ALWAYS delayed by one simulation timestep relative to the input.
You can verify this with a simple DLL by setting the input port as IN and the output port as OUT, using the simple code OUT=IN. If you zoom in on it, the OUT signal is always delayed by one simulation step compared to the IN signal.
As you work with PLECS, I recently built a library for Qspice to create equivalent devices to PLECS to make setting up Qspice simulations easier for PLECS equivalent.
You can find this in my custom library. Of course, just a small parts of them.
Does it mean if larger time step simulations (lets say 1second ) will be inaccurate because of large delay and dependence on previous time step input in DLL block?
Well, it depends on what inaccuracy you are referring to. If you are looking for a function where the output must be updated at the same simulation time step, a DLL is not something you should consider (use a B-source instead).
A DLL block includes the Trunc() function. You can define a state change to dramatically reduce the time step at critical moments, such as a gate toggle. This allows the time step to temporarily decrease during transitions and return to a larger step afterward, balancing precision and total simulation time. This is also why Qspice can be so effective.
@physicboy, @RDunn, and I have had multiple discussions on this topic in this forum. @physicboy and I have different preferences regarding how to handle time step reduction. There is no right or wrong way to do things; it all depends on what you want to achieve. The best way to understand this topic is to build a simulation with your own DLL and post your work if you encounter challenges.
I have a SVPWM project implemented with both a B-source and a DLL, and they yield identical results. So, don’t worry too much, but of course, have to gain enough experience to master how to manage time steps in a DLL.
I wanna add a few points from @KSKelvin
(補充英文怎麼講?)
There are 2 methods to manipulate the timestep from Cblock: Trunc() and MaxExtStepSize()
The original example from Mike and what Kelvin also like to do is by using Trunc() to call the eval_func() under the “hypothetical timestep” to see if the discrete output state of eval_func() change. If none, do nothing to the timestep. If change detected, suggest the main solver a very small timestep.
Meanwhile, I have 2 different approach.
If I am emulating a fully digital PWM controller or if I am doing mixed mode simulation.
If it’s mixed mode, I actually cannot predict the exact discontinuity timing location. Here I will use Trunc() but I will use timestep halving logic instead of directly forcing a very small timestep.
If it is fully digital simulation, I will instead use MaxExtStepSize() only to guide the solver to directly hit the calculated discontinuity event.
I compared the simulation with halving and directly forcing TTOL, but at that time (maybe two years ago) directly forcing TTOL resulted in a more stable outcome (it was out of my expectation)… but maybe the situation has already changed after two years.
But as I didn’t see any simulation speed benefit from halving, I didn’t spend too much time investigating that.
I think, for example, the pulse source is a direct hit. The recent DelayedPulseTrain example in the demo \QSPICE\Examples\delayedpulsetrain.cpp also uses a direct hit for the delayed output. But Mike put it in Trunc() instead of maxstep().