IHP-GmbH / IHP-Open-PDK

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

MOSFET PSP model usage of NF parameter #164

Open hpretl opened 1 month ago

hpretl commented 1 month 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 1 month ago

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

bmurmann commented 1 month ago

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

KrzysztofHerman commented 1 month 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 1 month 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 3 days 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 3 days 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 3 days 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.