pascalkuthe / OpenVAF

An innovative Verilog-A compiler
https://openvaf.semimod.de/
GNU General Public License v3.0
113 stars 15 forks source link

Wrong Derivative of Gate Charge in PSP Model #120

Open metroid120 opened 2 months ago

metroid120 commented 2 months ago

The IHP PDK showed that there is an erroneous calculation of the derivative of the gate charge against gate voltage for the PSP model. https://github.com/IHP-GmbH/IHP-Open-PDK/issues/64

An exemplary plot:

image

Exemplary ngspice netlist using IHP Open PDK

* 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

We must locate the erroneous derivative that causes the bug.

metroid120 commented 2 months ago

I did some investigations today. The line of code

SP_S_delta1 = 1.0 / SP_S_delta0; \ in the PSP model seems to be critical somehow for the observed behavior.

metroid120 commented 2 months ago

Ok I now know where this comes from. There is a code structure that is repeated three times in the PSP code:

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

If this is replace at all occurences with the mathematically equivalent

            SP_S_delta0 = exp(SP_S_x0); \
            SP_S_delta1 = exp(-SP_S_x0); \

the problem is gone. I will go into further detail tomorrow.

metroid120 commented 2 months ago

Ok I leave it here, since above mentioned solution is a feasible workaround. Fundamentally the issue must be related to the derivative generation algorithm in OpenVAF.

My guess is that 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}$

Just a guess.