idt implementation in Verilog-a

605 views
Skip to first unread message

Murat Eskiyerli

unread,
Jul 1, 2020, 6:48:49 AM7/1/20
to xyce-users
Hi,

Are there any plans to implement idt function in Verilog-A? What would be the blocking item for its implementation? It is difficult to create some models such as VCOs without it.

Regards,

Dr Murat Eskiyerli, DIC CEng MIET

xyce-users

unread,
Jul 1, 2020, 9:27:26 AM7/1/20
to xyce-users

There is no plan at this time to support idt in Xyce/ADMS.  There are some technical blockers, but the main blocker is limited team resources and higher priorities.

Murat Eskiyerli

unread,
Jul 1, 2020, 9:36:05 AM7/1/20
to xyce-users
Fair enough. 

Murat H. Eskiyerli

--
You received this message because you are subscribed to the Google Groups "xyce-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xyce-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/xyce-users/0301d90f-0c7d-412a-a6a0-79a851991385o%40googlegroups.com.

xyce-users

unread,
Jul 1, 2020, 10:02:29 AM7/1/20
to xyce-users

To be a little more explicit:  as a DAE solver, Xyce doesn't easily provide a mechanism for a compact model to integrate a quantity of interest, and the design of Xyce doesn't give devices direct access to the time integration package (there is no equivalent of the SPICE function "niintegrate").  Devices don't even have ready access to time derivatives, which is why you can only use ddt() in contributions in Xyce/ADMS: when ddt appears on the right-hand side of a contribution, the quantity is not differentiated at that time --- it is loaded into the Q vector of the DAE that Xyce solves,  F(x)+dQ(x)/dt -B(t) = 0 and is differentiated later as part of the solve.

Use of idt() is discouraged in compact modeling in several best-practices papers we've encountered.  A notable one can be found here:  https://www.researchgate.net/publication/281227678_Best_Practices_for_Compact_Modeling_in_Verilog-A .  Suggestions for how to replace use of idt() with alternatives that will certainly exist in any DAE solver are given there.  These alternatives generally require voltage branch contributions (which introduce additional solution variables for the associated branch current), and Xyce/ADMS does support such contributions.


On Wednesday, July 1, 2020 at 7:36:05 AM UTC-6, Murat Eskiyerli wrote:
Fair enough. 

Murat H. Eskiyerli

On Wed, 1 Jul 2020, 15:27 xyce-users, <xyce-...@googlegroups.com> wrote:

There is no plan at this time to support idt in Xyce/ADMS.  There are some technical blockers, but the main blocker is limited team resources and higher priorities.

On Wednesday, July 1, 2020 at 4:48:49 AM UTC-6, Murat Eskiyerli wrote:
Hi,

Are there any plans to implement idt function in Verilog-A? What would be the blocking item for its implementation? It is difficult to create some models such as VCOs without it.

Regards,

Dr Murat Eskiyerli, DIC CEng MIET

--
You received this message because you are subscribed to the Google Groups "xyce-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xyce-users+unsubscribe@googlegroups.com.

Murat Eskiyerli

unread,
Jul 1, 2020, 11:08:08 AM7/1/20
to xyce-users
I can understand your point of view.  I cannot really argue about the finer points of design of a circuit simulator. Ages ago, I was involved with the mathematical modelling of a convection-diffusion problem. I changed PhD subject after few months 😀.

I was trying to use a model for a VCO and I see that much higher frequency oscillations at the output of the VCO.

This is the verilog-a file for VCO. I must admit I haven't spent much time on this implementation just copied from somewhere and removed integration of the argument of sin function:
`include "disciplines.vams"
`include "constants.vams"
module vaVco(in, out) ;
parameter real amplitude = 1.0 (* type="instance" xyceAlsoModel="yes" *),
centre_frequency = 1000 (* type="instance" xyceAlsoModel="yes" *),
gain = 1000 (* type="instance" xyceAlsoModel="yes" *);
parameter integer steps_per_cycle=20 ;
parameter real omegac = 2.0 * `M_PI * centre_frequency,
omega_gain = 2.0 * `M_PI * gain ;
electrical in, out ;
analog
begin
real vin, instantaneousFreq ;
vin = V(in) ;
V(out) <+ amplitude*sin((vin*omega_gain+omegac)*$abstime) ;
// Use $bound_step system task to limit time step
// This is to ensure that sine wave is rendered with
// adequate detail.
//instantaneousFreq = centre_frequency + gain * vin ;
//$bound_step (1.0 / instantaneousFreq / steps_per_cycle) ;
end
endmodule

The original code was using:
V(out) <+ amplitude*sin(idt(vin*omega_gain+omegac,0.0)) ;

xyce-users

unread,
Jul 1, 2020, 12:13:37 PM7/1/20
to xyce-users
I'm not surprised this simple substitution of argument to sin doesn't work as you expect.

At the moment, Xyce/ADMS does not support $bound_step, though there are no fundamental technical impediments to doing so --- Xyce does have the means to allow a device to restrict the time step, we just haven't exposed that capability in Verilog.  It is just not something that should be used often, and very few of our existing compact devices do so (the independent voltage sources do, as does the lossless transmission line, but few others).

I was able to mock up a modified version of your verilog-a that does the integration of the sin argument as desired, but it is tough to get right and the adaptive time integrator just loves to skip over the interesting behaviors of the circuit.  By restricting the time step manually (on the tran line) I was able to get it to look reasonable, but to run for the extremely long times you show in your graphs was very slow with those restricted timesteps.  The output file is enormous, too.  If I run for 15ms rather than 15s and scale all the transition points in the input voltage source accordingly run time and output file size are more reasonable and you can see that the results look more like what may be expected.

I'm attaching my version of your vavco verilog-a model that performs the integration of vin*gain+omegac by effectively pumping that value as a "current" into a 1Farad capacitor, then using the voltage across the capacitor as the argument of the sine.  The attached .cir file is the one with the 15ms simulation time instead of 15s.

It works after a fashion, and the frequency of the output does indeed make sense.  If, and only if, you restrict the time step of the simulation by external means.  The PWL voltage source will gleefully allow simulation to take enormous time steps if no other device in the circuit is limiting that time step, and if the time integrator thinks it can get away with larger steps.  Few devices artificially impose time step limits, and time step selection is mostly driven by convergence.  A device like this one will be delighted to take any step asked of it without impacting convergence at all, and so all of its behaviors will be skipped over.

Supporting $bound_step is not unreasonable, but I wouldn't hold my breath waiting for it.
vavco.va
testvco.cir

xyce-users

unread,
Jul 1, 2020, 1:52:32 PM7/1/20
to xyce-users
I was unnecessarily pessimistic about $bound_step support.  Getting Xyce/ADMS to handle that was basically trivial, and support for this system task will be available in Xyce 7.2 (about 6 months from now), or if you can't wait that long for a formal release, in the master branch on github sometime next week.

Once I added that support to Xyce/ADMS, the verilog-a behavioral model I attach here, using the "capacitor" integration instead of idt and a $bound_step call, works without any netlisting limitation on the time step --- the module itself signals to the time integrator that it should not take steps longer than what can resolve the output sine wave.
vavco.va

Kevin Cameron

unread,
Jul 1, 2020, 8:50:04 PM7/1/20
to xyce-users
There's a lot of stuff in Verilog-AMS that looks like functions but  is really more like an in-lined module (because it has state). One could translate a lot Verilog-AMS like that into Xyce supported constructs in subcircuits - I started a thread on that because I have a Verilog-AMS parser.
  
BTW when you model VCOs for PLLs it's best to just calculate the delay to the next clock edge, the "V(out) <+ amplitude*sin(V(theta))" equation isn't particularly reliable

Kev.

xyce-users

unread,
Jul 4, 2020, 12:18:49 PM7/4/20
to xyce-users
We got the weekly github update done a little early this week, and the changes to Xyce/ADMS to support $bound_step are available on github in the master branch as of today.

Murat Eskiyerli

unread,
Jul 4, 2020, 12:38:03 PM7/4/20
to xyce-users
Hi,

This is the result I get for the output waveform using your va and test circuit:
Unless I am doing something wrong somewhere, there are few issues I can see:
  1. When Vin is negative, you would expect that the output frequency is lowest. In this case, the frequencies of the first and third output waveforms are almost the same while the frequency of the output when Vin=0 is the lowest.
  2. The output phase is discontinuous when the Vin changes.
Thanks for implementing the $bound_step by the way. I really appreciate the hard work of Xyce team.

Best,

xyce-users

unread,
Jul 4, 2020, 1:23:16 PM7/4/20
to xyce-users
The netlist I posted had 10V on the input, and when I work it through with the defaults, the solution should be 9KHz when Vin=-10, 1KHz at Vin=0, and 11KHz when Vin=10.  That kinda looks like what you have here.  I haven't worked through the phase question, but I think that's doing the right thing, too, because of the way that vin is slewing between values over .25ms and the fact that when vin=-10 the output is really sin(-9000*2*pi*t)=-sin(9000*2*p*t), and we transition somewhat abruptly to sin(2*pi*1000*t).  I'd expect a phase shift.  If I plot the actual value of V(theta) (the result of the integration of vin*omega_gain+omegac, which is available as N(yvavco!vco1_theta)) I see a smooth, basically piecewise linear function as one would expect (modulo the curving of the transitions due to the vin rise time) the slope of which is the instantaneous vin, and if I take its sin and plot that, I get exactly the v(out) results, complete with the odd-looking phase change.

If you change the netlist so that vin ranges from -1 to 1 (which is more like the range you've got your vin plot set to show), then you get 0, 1kHz and 2Khz signals, with no phase issues during the frequency changes.  I had only chosen -10/+10 based on your first post, which had that range in its vin plot.

I did not try to design a behavioral model of a VCO of any value.  All I did to get "my" vavco.va is to take the one you posted and replace the v(out) with what you said the original had (with idt in the argument), replacing the idt integration with the capacitor integration trick (which does indeed give V(theta) that is the integral from t=0 to t=now of the quantity vin*omega_gain+omegac).  Could it be that the original had a little more to it?

plusminus1.png

testvco.cir

camer...@gmail.com

unread,
Jul 4, 2020, 2:22:16 PM7/4/20
to xyce-users
Like I said earlier: if you use  "V(out) <+ amplitude*sin(V(theta))"   you'll get odd behavior - it works for loop analysis in (say) Matlab, but doesn't model hardware well so you get discontinuities (in Xyce). You are better off going for a sawtooth waveform on a capacitor which integrates Vin - that's less work for the simulator and a stable model.

Kev.

Murat Eskiyerli

unread,
Jul 5, 2020, 6:00:05 AM7/5/20
to xyce-users

My apologies about the first point. You are right, of course it is indeed -9kHz. My original netlist had actualy a centre  frequency of 10MHz.
.model vaVcoModel vaVco gain=1e6 centre_frequency=1e7
Thus, when Vin=-10V, I expected to see a DC output.
I think, it is fair to say that Verilog-a implementation in Xyce is really oriented towards device models.

Regards,
 
Dr Murat Eskiyerli, DIC CEng MIET
On Jul 4 2020, at 7:23 pm, xyce-users <xyce-...@googlegroups.com> wrote:
The netlist I posted had 10V on the input, and when I work it through with the defaults, the solution should be 9KHz when Vin=-10, 1KHz at Vin=0, and 11KHz when Vin=10.  That kinda looks like what you have here.  I haven't worked through the phase question, but I think that's doing the right thing, too, because of the way that vin is slewing between values over .25ms and the fact that when vin=-10 the output is really sin(-9000*2*pi*t)=-sin(9000*2*p*t), and we transition somewhat abruptly to sin(2*pi*1000*t).  I'd expect a phase shift.  If I plot the actual value of V(theta) (the result of the integration of vin*omega_gain+omegac, which is available as N(yvavco!vco1_theta)) I see a smooth, basically piecewise linear function as one would expect (modulo the curving of the transitions due to the vin rise time) the slope of which is the instantaneous vin, and if I take its sin and plot that, I get exactly the v(out) results, complete with the odd-looking phase change.

If you change the netlist so that vin ranges from -1 to 1 (which is more like the range you've got your vin plot set to show), then you get 0, 1kHz and 2Khz signals, with no phase issues during the frequency changes.  I had only chosen -10/+10 based on your first post, which had that range in its vin plot.

I did not try to design a behavioral model of a VCO of any value.  All I did to get "my" vavco.va is to take the one you posted and replace the v(out) with what you said the original had (with idt in the argument), replacing the idt integration with the capacitor integration trick (which does indeed give V(theta) that is the integral from t=0 to t=now of the quantity vin*omega_gain+omegac).  Could it be that the original had a little more to it?





On Saturday, July 4, 2020 at 10:38:03 AM UTC-6, Murat Eskiyerli wrote:
Hi,

This is the result I get for the output waveform using your va and test circuit:
Unless I am doing something wrong somewhere, there are few issues I can see:
  1. When Vin is negative, you would expect that the output frequency is lowest. In this case, the frequencies of the first and third output waveforms are almost the same while the frequency of the output when Vin=0 is the lowest.
  2. The output phase is discontinuous when the Vin changes.
Thanks for implementing the $bound_step by the way. I really appreciate the hard work of Xyce team.

Best,

Dr Murat Eskiyerli, DIC CEng MIET
--
You received this message because you are subscribed to the Google Groups "xyce-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xyce-users+...@googlegroups.com.

xyce-users

unread,
Jul 5, 2020, 2:08:41 PM7/5/20
to xyce-users


On Sunday, July 5, 2020 at 4:00:05 AM UTC-6, Murat Eskiyerli wrote:


I think, it is fair to say that Verilog-a implementation in Xyce is really oriented towards device models.


It would be fair to say that the Verilog-A implementation in Xyce is *strictly* oriented towards analog compact device models. It was never really intended as a tool for general behavioral modeling, though in many cases it is useful for that purpose --- that's just a bonus.  There are no features in Xyce/ADMS that are meant for mixed-signal use.

Xyce/ADMS (the XML files that do actual code generation for Xyce when run through ADMS) has been in development for quite some time ago, and for years was a strictly internal tool used by the Xyce team to add new industry standard models that were available only in Verilog-A form.  The first such model was VBIC 1.2, and the list has grown slowly and sporadically since then.  It's getting to be reasonably good for its intended purpose of getting compact device models into Xyce, but there are still huge gaps between what the LRM says should be supported and what we can actually do. 

Because ADMS is extremely difficult to work with, adding support for some Verilog-A constructs in the Xyce/ADMS back-end is slow and we typically don't add a feature unless some industry standard model actually uses it, and no best-practice article contains a diatribe against its use in compact modeling (or it turns out to be trivial *and* nobody rails against its use, such as $bound_step).  There are still some features that are used by standard models but that we don't support yet because they're really difficult to implement and we don't have a driving need for supporting the models that use them (yet).


camer...@gmail.com

unread,
Jul 5, 2020, 7:46:26 PM7/5/20
to xyce-users
Just FYI, I'm not a solver expert, but I worked with one at MetaSoftware back in the 90s and we threw together a Verilog-A interpreter/compiler in C with dynamic loading in about 6 months (as an add-on to HSPICE). It got lost in the Avant! takeover. It worked by just running the code repeatedly with minor perturbations to work out the partial derivavtives - i.e. you just call the Verilog-A analog process code in sequence more-or-less as written and you can get the partial derivatives.

If I was going to have another go at it I'd try doing that but just run the code once with GiNaC  https://ginac.de/  

ADMS was always just a hack to get CMC models into existing SPICE simulators, it should have died years ago (along with a bunch of other EDA bad practices).

Kev.

Dan FitzPatrick

unread,
Jul 6, 2020, 10:46:43 AM7/6/20
to camer...@gmail.com, xyce-users

I wouldn't advise getting caught up in the benefits of some computer algebra system (CAS) such as GiNaC.  Computing
partial derivatives in ASTs is relatively trivial.    The complications for implementing a Verilog-A compiler supporting symbolic
derivatives comes about in properly tracing system variables thru the behavioral code control flow, e.g. conditional blocks, 
or even thru external C-level Verilog PLI functions (as in the spec).   Within the generated evaluation context, additional 
code for initialization needs to be generated, as well as any peripheral code to support the solver method (typically newton-raphson).  

Support for idt() becomes easier in this context, as the Verilog-A compiler just implements the solver methods for 
generating a new equation (w/optional initialization), evaluation and loading during the simulation.   idt(idt(idt(...),...),...)
becomes trivial (not sure the value from a modeling context though).

There is no real difference between device or system-level Verilog-A behavioral modules.    But as has been said here, 
"Because ADMS is extremely difficult to work with...", and can't disagree with that.

Regards,

--Dan

--
You received this message because you are subscribed to the Google Groups "xyce-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xyce-users+...@googlegroups.com.

xyce-users

unread,
Jul 6, 2020, 3:06:35 PM7/6/20
to xyce-users
Interesting...  I hadn't spotted it before, but your verilog-a has a subtle issue in it that leads to the center frequency and gain being ignored for all practical purposes if specified on the instance line.

You're declaring omegac and omega_gain as parameters, and they're strictly model parameters.  But they are set from the centre_frequency and gain parameters, which are designated as instance and with "xyceAlsoModel".  A quirk of how this feature works means that your omegac and omega_gain variables are NEVER being set correctly if gain and centre_frequency are given on the instance.

"xyceAlsoModel" works by making *two* versions of the parameter, one belonging to the instance and one belonging to the model.  If any instance of the device has no explicit setting of the parameter, it gets its value from the model parameter.  The main block of code generated from your analog block is generated to access only the instance version when there are both.

However, if you set a model-only parameter to have a default value dependent on parameters, it can *ONLY* get at the model version, even if there exists an instance parameter of the same name --- models have no access to instance parameters (because they may be shared by multiple instances).  So making a model parameter have a parameter-dependent default value means that all the parameters used in the default expression must have the same scope as the one being declared.

The result here is that your model parameters omegac and omega_gain *always* get their values from the model version of centre_frequency and gain, and the latter variables are never used anywhere else --- so the instance versions are essentially useless.

It is better to make omegac and omega_gain local variables rather than parameters.  With this modification, the parameters function as intended.  Attaching the modified version.  This version will respect either the model or instance parameters correctly.  One could also keep them as parameters (allowing them to be specified directly in the netlist), but then one would have to make them *also* be dual model/instance parameters.

The whole instance/model parameter thing can get confusing, and it's unfortunate that some simulators blur the distinction.  Xyce, like SPICE before it, stores these different sets of parameters in completely separate structures, with consequent limitations on where they are accessible
To unsubscribe from this group and stop receiving emails from it, send an email to xyce-users+unsubscribe@googlegroups.com.
vavco.va

Murat Eskiyerli

unread,
Jul 8, 2020, 3:26:22 AM7/8/20
to xyce-users
Thanks a lot. I think it now works and I think I have now a better understanding of subtleties verilog-a parameter setting.
Reply all
Reply to author
Forward
0 new messages