help-gnucap
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-gnucap] Oscillator Simulation


From: al davis
Subject: Re: [Help-gnucap] Oscillator Simulation
Date: Wed, 21 Sep 2016 21:31:29 -0400

On Wed, 21 Sep 2016 23:46:15 +1000
Richard Gipps <address@hidden> wrote:

> On 15/09/16 1:57 AM, al davis wrote:
> > There is another hidden issue here, something I have been working on. 
> > As originally stated, rise=fall=delay=0, there is nothing in the 
> > circuit to hint at what time stepping to start with, so the automated 
> > step control would miss the oscillation. In the original, the 
> > requested step of 1ps was a hint, but otherwise with what Felix 
> > suggested, it would have skipped by the oscillation. You might call 
> > this a "bug" but most other simulators are worse. By giving a finite 
> > rise time, the simulator now has some basis to figure out time 
> > stepping and can go from there. You just need something, somewhere, 
> > that somehow requests a step size less then the expected period of the 
> > oscillator.  
> ngspice behaves differently with the statement VCC 10 0 PULSE(0 8), it 
> uses the step time by default when not explicitly specified.

There is a bug in the gnucap pulse, the ">=" relationship where it
should be ">", that shows only when delay, rise, and fall are all zero,
causing the zero time value to be the pulse value not the initial value
in this case.  It's fixed in the current "unstable" branch.

Using the step time by default is really an artifact of the algorithm.
The actual step size for the first step is not known until after the
initial DC has already been computed.  A user specified, on the tran
line, step size is usually not needed or desirable. 

By the algorithm, user specified "strobe" is optional in gnucap.  It has
been a syntax requirement, now being removed, because it was for
Spice.  It actually works best to specify it unreasonably big, and use
"trace all" to see all of the steps.  This syntax requirement is being
changed to allow (and encourage) just specifying start and stop, no
step or strobe, while maintaining compatibility.  It's in the
"transient-3" branch.

Looking again at what Felix suggested ...

>> maybe you want to try this instead 
>> .TRAN 0 {start_print} {start_print/10}  

This is a strobe at {start_print/10}.  That is, 10 steps on the whole
startup interval.  You wouldn't want this for the pulse rise time!
It's really to run with suppressed output, that may take a while, but
give you some hint that something is actually happening.

> 1ps is a very small time step for a 100MHz oscillator.  I am injecting a 
> current pulse into the oscillator and measuring the phase shift in the 
> signal. I need to measure down to 0.01 radians. I was experimenting with 
> ngspice with different step times but the phase shifts I was observing 
> were not sensible.

You need to look at the tolerance settings.

0.01 radians is .00159 cycles.  628.3 samples in a cycle.  You need a
little more than that, call it 1000 x oversampling, near the
measurement points, not necessarily everywhere else.  1ps is 10000 x
oversampled.  10x better than you need, but that in itself is not a
problem.

With default tolerances, accuracy will be nowhere near good enough,
even with the oversampling.

Default reltol is .001.  Strictly this should be good enough, but
practically it isn't.  You are measuring to .00159, so reltol alone
will use up most of your error tolerance, assuming that it works
perfectly.  Approximations are never perfect.  Try reltol=.0001, or
smaller.  Also look at vntol and abstol. This is for convergence
tolerance.  I haven't gotten to step control yet.

One way to check whether it is good enough is to tighten or loosen the
tolerance.  If the results change significantly, it's not good enough.
The definition of "significantly" depends on what you want.  Either you
need to tighten or you have gone too far and are seeing rounding
errors.  For rounding errors, look at floor, vfloor, and roundofftol.
It may have reached the hardware limit.

Now on to step control ...

By specifying strobe and dtmax of 1p, you are in effect disabling the
automatic step control.  One quick check of whether you are getting
good results is to change (half or double) the step size and see if the
results change.  Again, if results change significantly, it's wrong.

It is probably better to use the step control.  Then you need to look
at some other options, especially trtol.  The default value is 7, for
Spice compatibility, which is certainly wrong for this.  It says that
time control tolerances are this much worse than convergence
tolerances.  So, trtol=7 and reltol=.001 means step control is based
on .007.  This is, alone, worse than your accuracy requirement.  Try
trtol=1.  Also check chgtol.

Still,  step control is based on the "y" axis, mostly voltage and
charge,  If you want to measure phase errors, you also need to control
it the other way, the "x" axis, time.  This is why I suggested adding a
switch to your circuit, to sense the time of a crossing.  That way it
too will be accuracy controlled to the specified tolerances.

Now look at what steps you are getting.  Try half and double the
tolerances and see what changes.

With all this about tightening tolerances, you can use loose tolerances
to get by the start-up.  Then tighten and continue.

There is an oscillator example on the wiki ....
http://gnucap.org/dokuwiki/doku.php?id=gnucap:manual:examples:phase_shift_oscillator

Also .. more recent versions of gnucap ..
The current "unstable" branch has a fix for the "<=" bug, and lots of
other improvements.

You might want to try the experimental "transient-3" branch, which has
some changes that I hope are improvements in the transient analysis.
http://git.savannah.gnu.org/cgit/gnucap.git

This has been a good example for me to work on step control.  I have
made some refinements to how it handles the first few steps.

Here is what the oscillator has evolved to:
============================================
oscillator.cir
* 100MHz Oscillator
* This oscillator takes about 100us to reach steady state.
* The charge displacement through each capacitor is 170pC p-p
* 0.01radians = 0.16% = 16ps @ 100MHz

.param start_print = 100.u
.param stop_time = 100.15u

.MODEL q2SC3357_v13_M NPN
+(IS=684.2e-18 BF=161.1 NF=1.0 VAF=51
+ IKF=574.6e-3 BR=10.71 NR=1.0 VAR=2.1
+ IKR=28.05e-3 ISE=1.0e-18 NE=1.193 ISC=6.211e-18
+ NC=1.1 RB=3.0 IRB=75.9e-5 RBM=1.0
+ RE=2.67 RC=3.5 CJE=1.847e-12 VJE=1.014
+ MJE=464.8e-3 CJC=1.086e-12 VJC=617.4e-3 MJC=353.8e-3
+ XCJC=0.1 CJS=0 VJS=0.75 MJS=0
+ FC=0.50 TF=23e-12 XTF=0.39 VTF=0.668
+ ITF=0.06 TR=0 PTF=20 EG=1.11
+ XTI=3.0 XTB=0)

VCC 10 0 PULSE(0 8)
Vb 2 0 DC 4.78
Q1 1 2 3  q2SC3357_v13_M
IC 3 0 DC 10m

L1 10 1 120n
C1 1 3 21.14p
C2 3 0 15.48n

.model cross sw vt=7
S1 (0 0 1 0) cross

.store tran v(nodes)
.print tran v(nodes) charge(c?)

.opt reltol=.01

.TRAN start=0 stop={start_print} strobe={start_print/5}

.opt trtol=1 reltol=.000001 numdgt=9

.TRAN stop={stop_time} strobe=0

.measure t2=cross("v(1)", cross=7, rise, last)
.measure t1=cross("v(1)", cross=7, rise, last, before=t2)
.param period={t2-t1}
.eval period
.param frequency={1/(t2-t1)}
.eval frequency

.print fourier v(1)
.fourier 0 {frequency*10} {frequency/2}
.fourier 0 {frequency*10} {frequency}

.status
.END








reply via email to

[Prev in Thread] Current Thread [Next in Thread]