IHP-GmbH / IHP-Open-PDK

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

MOSFET PSP model usage of NF parameter #164

Open hpretl opened 4 months ago

hpretl commented 4 months ago

When I do a simple testbench in ngspice simulating just a single LV-NMOS (I assume it is the same for PMOS and HV variants, but I have not checked it), I see that the model parameter rg is not reacting to the number of fingers I set. This is not ideal, as the PSP model can model extrinsic resistances.

From the PSP model doc:

image

The calculation of rg is:

image

In the model file of IHP's PDK, the PSP model is instantiated like that:

image

This means that essentially the nf (number of fingers, here called ng, which is not consistent) parameter is never passed on to the PSP model, instead only the width of a single finger is used in the model, and the multiplier parameter m is then increased by nf as passed on to the model as mult=ng*m. In this way, the intrinsic model does not know about the true nf and m parameters. This is also confirmed by looking at the model parameters in ngspice, which always shows nf=1.

Maybe this can be changed in a future release? It looks like some capabilities of the PSP model are bypassed in this way.

hpretl commented 4 months ago

@bmurmann what do you think? Maybe this also explains some other model things you identified?

bmurmann commented 4 months ago

Potentially, but the issues I wrote about where also present for ng=1.

KrzysztofHerman commented 3 months ago

@hpretl I have followed the $R_G$ implementation and I found the exact lines of code in the file PSP103_module.include, which define it:

1522:  RG_p =  RSHG_i * (`oneThird * W_f / NGCON_i + XGWE) / (NGCON_i * L_slif) + (RINT_i + RVPOLY_i) / (W_f * L_f) + NF_i * RGO;
1709:  RG_i   = `CLIP_LOW(RG_p, 0.0);
3065:  rg  =  RG_i / MULT_i;

Also I found this:

1721: MULT_i  = `CLIP_LOW(MULT * NF_i, 0.0); // Note: NF_i is set to 1 for local model

Assuming that $R_G$ scales with m its value should consider the $N_F$ parameter passed indirectly as mult Could @miesli or @metroid120 comment on that ?

miesli commented 3 months ago

Hi,

yes the "m" or "ng" or "nf" issue is already well known for the PSP model in this PDK. Check also #25 for this.

Basically, the PDK was extracted and scaled like this in the SG13G2 PDK and somehow they decided that this was the best way to do that. @hpretl you are definitely right, that this does not use the PSP model correctly but without a new extraction with new measurements it is not easy to change since this requires most likely to verify all characteristics again.

Best regards

dwarning commented 2 months ago

We are speaking about psp Version 103.6.0.

3065: rg = RG_i / MULT_i;


The RG_i scaling by MULT_i is used here for OP variable calculation - not for contribution.

For that we have around line 1826:

if (RG_i > 0.0) begin ggate = 1.0 / RG_i; This value is used for matrix entry and noise analysis. The scaling is done in macro CollapsableR by multiplying with MULT_i. So in the end - even with our confusing instantiation - RG should be correct scaled by NF because NF is part of the mult instance parameter. @hpretl : Could you provide an simple test case to check our assumptions.

hpretl commented 2 months ago

My not-very-sophisticated test is this (so maybe I am just interpreting things wrong):

I take a single MOSFET test bench, and look at the model parameters after op using show. Setting ng=1 or ng=2 reports the same Rg, which should not be the case, I think.

Here the netlist: mosfet_diode_sizing.spice.zip

dwarning commented 2 months ago

Thanks for the test case. I think the problem is the reporting of the OP variable rg. I put in few strobes into the va code. For ng=1: OSDI(debug) n.xm1.nsg13_lv_nmos: RG_p 100.192 OSDI(debug) n.xm1.nsg13_lv_nmos: RG_i 100.192 OSDI(debug) n.xm1.nsg13_lv_nmos: RG_i 100.192 MULT_i 1 rg 100.192 OSDI(debug) n.xm1.nsg13_lv_nmos: RG_i 100.192 lp_rg 100.192

For ng=2: OSDI(debug) n.xm1.nsg13_lv_nmos: RG_p 200.385 OSDI(debug) n.xm1.nsg13_lv_nmos: RG_i 200.385 OSDI(debug) n.xm1.nsg13_lv_nmos: RG_i 200.385 MULT_i 2 rg 100.192 OSDI(debug) n.xm1.nsg13_lv_nmos: RG_i 200.385 lp_rg 200.385

From code I see that RG_i goes into ggate. ggate will be then multiplied with MULT_i in CollapsableR and brings the correct current into branch.

rg seems buggy maybe it is repaired in newer versions.

dwarning commented 1 month ago

I made a double-check and must correct my self: The calculation of RG is not correct with our actual device instantiation in the Open-PDK lib (and in the spectre lib too). At the moment we have

Nsg13_lv_nmos d g s b sg13g2_lv_nmos_psp w='w/ng' l=l mult='ng*m'

In consequence the model internal NF parameter will any time 1. In the formulae above from the psp manual we see that we have an component in RG which is independent fro NF - the RGO part. After calculation of RG_p the value is divided by (MULT*NF) and in MULT we have NG per instantiation. And so for any NG >1 the RGO part is lowered by the finger count. For NG values > 4 the error can be more then 25% dependent from parameter constellation. I made an experiment with following instantiation

    Nsg13_lv_nmos d g s b sg13g2_lv_nmos_psp w='w' l=l nf='ng' mult='m'

and get correct RG values for different finger count and separate device multiplier. All values are double checked per excel, debugging printouts in psp model and S-parameter simulation with ngspice (Rg=re(Z11)-re(Z22)/3) to get an rough estimation. Additional checks are made for junction capacitances and currents which are affected by the different calculation scheme for AD, AS, PD and PS. An test case will be provided to the PDK authors.

dwarning commented 1 month ago

I made 2 simulations with qucs-s/ngspice (klu enabled) with the mentioned instantiation schemes. Shown is the RG approximation from s-parameter simulation (Rg=re(Z11)-re(Z22)/3) of a w=10um NG=1...8 lv_nmos device with VG=1.2V and VD=0V. The actual implementation shows RG 65 ... 10Ohm: old_instantiation

The proposed new instantiation shows RG 67 ... 45Ohm: new_instantiation

The values are similar then hand calculated values.

I think from view point of noise analysis the optimistic values of the actual implementation are critical. @hpretl @bmurmann - your opinions?

hpretl commented 1 month ago

@dwarning I think we should fix this so that we get most realistic behavior due to RG. A question that I have: Why is RF only going down from 67 to 45Ohm when NG is increased from 1 to 8? I would assume that RG goes down with NG^2 (W per finger = W/NG, so RG/finger = RG/NG), and then NG fingers in parallel, so $R_G(NG) = R_G(NG=1) / NG^2$?

dwarning commented 1 month ago

Don't really know. But if you look to the formulae you see an NF independent term (our problem we have). This is the resistance from contact to beginning of fingers I think.

dwarning commented 1 month ago

I want show here my testbench for RG from S-parameter:

Bildschirmfoto vom 2024-09-18 12-05-37

lv_nmos_spar_vgs.sch.txt

Would be nice if someone could make same in spectre.