IHP-GmbH / IHP-Open-PDK

130nm BiCMOS Open Source PDK, dedicated for Analog, Mixed Signal and RF Design
Apache License 2.0
295 stars 39 forks source link

Glitch in capacitance evaluation #64

Closed dwarning closed 3 weeks ago

dwarning commented 1 month ago

The attached ngspice script cg_glitch.txt shows Cgb, Cg_ds and Cg_dsb capacitances over Vg of a 400/0.5 lv_nmos transistor. The strong glitch around -0.9V is in my opinion fatal and follows in time step problems for transient simulation.

The observed behaviour is for psp103 version 6.0 and actual version 8.2 va-models and can also be seen for the hv-nmos device.

Would be fine to see same curves from same va-code with other simulators.

cg_glitch

Additional open question is the y-axis scale of the documented curves in report_nmos_lv page 401. Are this 400 pF? Because e-12 is shown.

sergeiandreyev commented 1 month ago

Hi @dwarning, we still have to reproduce the testcase in Xyce, as well as run/recheck this for commercial (internal) PDK models on your second question - yes, these are 400pF

dwarning commented 1 month ago

I see no problem with adms/Xyce:

Xyce

KrzysztofHerman commented 1 month ago

Hello, @dwarning could you please share the testcase for Xyce as well, there is an inconsistency with the values on Y-axis. As for the plots of Cgdsb I attach simulation results where ng parameter is used

image

the orange curve corresponds to the device with ng=1 X1 _net2 _net0 _net2 _net2 sg13_lv_nmos w=400u l=0.5u and the blue one corresponds to the device with ng=40 what limits W to 10u X1 _net2 _net0 _net2 _net2 sg13_lv_nmos w=400u l=0.5u ng=40

dwarning commented 1 month ago

OK, scripts attached. ( spend not the time to adapt Xyce library syntax ) cg_glitch.plt.txt cg_glitch.cir.txt cg_glitch.sp.txt

Even I assume that original problem has nothing to do with geometry control I used your recommended size: X1 _net2 _net0 _net2 _net2 sg13_lv_nmos w=400u l=0.5u ng=40

adms - Xyce: adms_Xyce

openvaf - ngspice: openvaf_ngspice

Because the glitch is at VFB I am sure there is a bug in the openvaf compilation. Not easy to find, but possible.

sergeiandreyev commented 1 month ago

@metroid120, could you please take a look?..

metroid120 commented 1 month ago

I agree that this is a serious bug. I was not able to track the issue down exactly, but I found that it is related to the PSP current calculation in "PSP103_SPCalculation.incldue"

// Core PSP current calculation
    Vdsat_lim    =  3.912023005 * phit1;
    if (xg <= 0.0) begin
        qis          =  0.0;
        xgm          =  xg - x_s;
        Voxm         =  xgm * phit1;
        qeff1        =  Voxm;
        Vdsat        =  Vdsat_lim;
        Vdse         =  Vds;
    end else begin // (xg > 0)
        ...

For the xg>0 branch, the variable "Voxm" should be continued smoothly, but is not. I do not know exactly how those model functions should work together, so it is difficult to find the root cause. Maybe somebody else has more insight...

edit: A minimum example that can be used to reproduce the glitch:

* Qucs 24.2.1 cov_lv_nmos.sch
.model sg13g2_lv_nmos_psp pspnqs103va type  =  +1

V1 _net0 _net1 DC 0 SIN(0 1 1K 0 0 0) AC 1 ACPHASE 0
Vg _net1 0 DC 1
Vg_dsb _net2 0 DC 0

N1 _net2  _net0  _net2  _net2 sg13g2_lv_nmos_psp

.control
pre_osdi './va_code_psp103p6/psp103_nqs.osdi'
let points = 300
set vgsp = "$&points"
let Cgdsb = vector($vgsp)
let Cgb = vector($vgsp)
let Cgds = vector($vgsp)
let Vg = vector($vgsp)
let ind = 0
while ind < $vgsp
  let v1_act = -1.5+ind*0.01
  alter Vg = $&v1_act
  ac lin 1 1meg 1meg 
  let Cgdsb[ind] = imag(Vg_dsb#branch)/(2*pi*1e6)
  let Vg[ind] = $&v1_act
  let ind = ind + 1
  destroy ac1
end
plot Cgdsb vs Vg
destroy all
reset
.endc
.END
metroid120 commented 1 month ago

I think this is issue can be closed here, since it is an OpenVAF issue, where I have re-opened it. https://github.com/pascalkuthe/OpenVAF/issues/120 Even if we manage to detect the erroneous derivative, nobody currently has control over the repo since the original developer left. At some point we must make a new repo, but I lack the time at the moment...

Sad story.

sergeiandreyev commented 1 month ago

It's good that this will be tracked on OpenVAF repo, but still I propose to have this issue open here until the fix in OpenVAF will be made available.

metroid120 commented 3 weeks ago

Thanks to the bad weather I spend some time on this. Folks, can you please confirm.

If one replaces the following three code blocks in the Verilog-A

            SP_S_delta0 = exp(SP_S_x0); \
            SP_S_delta1 = 1.0 / SP_S_delta0; \

(above block occurs 2 times in the code)

            delta_1s     =  exp(x_s); \
            Es           =  1.0 / delta_1s; \

with

            SP_S_delta0 = exp(SP_S_x0); \
            SP_S_delta1 = exp(-SP_S_x0); \
            delta_1s     =  exp(x_s); \
            Es           =  exp(-x_s); \

(so in total 3 occurrences), the problem is gone.

dwarning commented 3 weeks ago

I can agree - this 3 modifications let the glitch disappear. Seems openvaf makes a kind of over-optimization.

metroid120 commented 3 weeks ago

Ok @sergeiandreyev , then I guess we have a fix/workaround. Replace the blocks of code as described above and the Glitch is gone.

I think OpenVAF generates the derivative of $y2$ in the following structure $y1=exp(a)$ $y2=1/exp(a)$

as

$\frac{dy2}{dx}=-(exp(a))^{-2}exp(a)\frac{da}{dx}$

which causes numerical problems in contrast to the mathematically equivalent

$\frac{dy2}{dx}=-exp(-a)\frac{da}{dx}$

but this is just my guess.

Anyhow I doubt that the fundamental OpenVAF issue will be fixed soon, since the project is not active.

sergeiandreyev commented 3 weeks ago

@metroid120 , thank you for taking the time to thoroughly investigate this issue over the weekend and finding a solution!

dwarning commented 3 weeks ago

A note that the modified PSP model from this distribution is to use would be preferable.