Skip to content

Instantly share code, notes, and snippets.

@mithro
Created August 24, 2022 16:27
Show Gist options
  • Save mithro/f00b3f5effe576a0493e2e221420df18 to your computer and use it in GitHub Desktop.
Save mithro/f00b3f5effe576a0493e2e221420df18 to your computer and use it in GitHub Desktop.
VerilogA model for varactor on SkyWater 130nm (SKY130)
// VerilogA model for varactor
`include "discipline.h"
`include "constants.h"
module xcnwvc_va(poly, nwell, sub);
inout nwell;
electrical nwell;
inout poly;
electrical poly;
inout sub;
electrical sub;
parameter real w = 1;
parameter real l = 1;
parameter real vm = 1; //vm passed from subckt, if higher level subckt used will not receive this mult factor.
parameter real cnwvc_tox = 41.6503;
parameter real cnwvc_cdepmult=1;
parameter real cnwvc_cintmult=1;
parameter real cnwvc_vt1=0.3333;
parameter real cnwvc_vt2=0.2380952;
parameter real cnwvc_vtr=0.16;
parameter real cnwvc_dwc=0.0;
parameter real cnwvc_dlc=0.0;
parameter real cnwvc_dld=0.0;
parameter real rp1 = 48.2;
parameter real rcp1 = 150;
parameter real rnw = 1800;
parameter real rcn = 182;
parameter real cm0=5.571e-16*cnwvc_cintmult;
parameter real cm1=4.775e-16;
parameter real cm2=2.019e-16;
parameter real cm3=6.529e-16*cnwvc_cdepmult;
parameter real cx0=6.261e-16;
parameter real cx1=5.75e-16;
parameter real cx2=1.712e-16;
parameter real cx3=8.854e-14*3.9/cnwvc_tox;
real cnwvc_ldiff;
real wc,lc,wd,ld,ldd,dwr,dwp,dlr,wl,wlwdiff;
real cnwvc_slope1,cnwvc_slope2;
real cmin,cmax,cval1,cval2;
real con_sp;
real n_pocon,n_con;
real cnwvc_n1,cnwvc_n2;
real cPolySub,cNwellSub;
real cnwvc_k;
real cnwvc_a,cnwvc_b1,cnwvc_c;
real acon,apoly,apolyc;
real anwell,bnwell,cnwell;
real c0,c1,q;
real tc1,tc2;
real rgvalue,rg_nominal;
real v;
real treference;
real temp_celcius;
// Internal nodes
electrical v1 ;
analog begin
treference=30.0;
cnwvc_ldiff=0.15;
wc=1*w;
lc=1*l;
wd=wc+2*cnwvc_dwc;
ld=lc+2*cnwvc_dlc;
ldd=0.018+2*cnwvc_dld;
dwr=-0.02;
dwp=-0.5;
dlr=0.02;
wl=(wd-2*dwr)/(ld-2*dlr);
wlwdiff=((0.5*(ld-2*dlr))+cnwvc_ldiff)/(2*(wd-2*dwr));
cnwvc_slope1=0.21875;
cnwvc_slope2=0.125;
cmin=cm0+cm1*ld+cm2*wd+cm3*wd*(ld-ldd)+cx3*wd*ldd;
cmax=cx0+cx1*ld+cx2*wd+cx3*wd*ld;
cval1=0.5*(cmax+cmin);
cval2=0.5*(cmax-cmin);
con_sp=0.17;
cnwvc_k=12;
cnwvc_n1=0.1;
cnwvc_n2=0.28;
apoly=1.15;
apolyc=1;
acon=1;
anwell=1;
bnwell=0.6;
cnwell=2;
n_pocon=max((l-0.14)/(2*con_sp),1); //numbers of poly contact
n_con=(w-2*0.06+con_sp)/(2*con_sp);
cPolySub=0.15e-15;
cNwellSub=0.15e-15;
cnwvc_a=apoly*rp1*wl/cnwvc_k+apolyc*rcp1/n_pocon+acon*rcn/n_con+anwell*rnw*wlwdiff;
cnwvc_b1=bnwell*rnw*wlwdiff;
cnwvc_c=cnwell*rnw*((0.5*(ld-2*dlr))+cnwvc_ldiff)/(2*(wd-2*dwp));
v=V(v1,nwell);
tc1=3e-3;
tc2=0;
temp_celcius= $temperature-273.15; //$temperature is in Kelvin
rg_nominal =(cnwvc_a+cnwvc_b1*(0.5*tanh((v-cnwvc_vtr)/cnwvc_n1)+0.5)+20*cnwvc_c*(0.5*tanh((v-cnwvc_vtr)/cnwvc_n1)+0.5)*exp(-abs((v-cnwvc_vtr)/cnwvc_n2)));
rgvalue = rg_nominal*(1+tc1*(temp_celcius-treference)+tc2*(temp_celcius-treference)*(temp_celcius-treference));
q = cval1*v + (cval2/1.9) * (cnwvc_slope1*ln(0.5*((limexp((v-cnwvc_vt1)/cnwvc_slope1))+limexp(-(v-cnwvc_vt1)/cnwvc_slope1))) + 0.9*cnwvc_slope2*ln(0.5*((limexp((v-cnwvc_vt2)/cnwvc_slope2))+limexp(-(v-cnwvc_vt2)/cnwvc_slope2))));
I(v1,nwell) <+ vm*ddt(q);
V(poly,v1) <+ I(poly,v1)*rgvalue/vm;
V(poly,v1) <+ white_noise( 4*1.38e-23*$temperature*rgvalue/vm, "rg_noise");
//c1 and c2 are the tuning capacitors
I(poly,sub)<+ vm*cPolySub*ddt(V(poly,sub)); // c1 poly sub c=0.15e-15
I(nwell,sub)<+ vm*cNwellSub*ddt(V(nwell,sub)); // c2 nwell sub c=0.15e-15
end
endmodule
// VerilogA model for varactor
`include "discipline.h"
`include "constants.h"
module xcnwvc2_va(poly, nwell, sub);
inout nwell;
electrical nwell;
inout poly;
electrical poly;
inout sub;
electrical sub;
parameter real w = 1;
parameter real l = 1;
parameter real vm = 1; //vm passed from subckt, if higher level subckt used will not receive this mult factor.
parameter real cnwvc2_tox = 41.7642;
parameter real cnwvc2_cdepmult=1;
parameter real cnwvc2_cintmult=1;
parameter real cnwvc2_vt1=0.2;
parameter real cnwvc2_vt2=0.33;
parameter real cnwvc2_vtr=0.14;
parameter real cnwvc2_dwc=0.0;
parameter real cnwvc2_dlc=0.0;
parameter real cnwvc2_dld=0.0;
parameter real rp1 = 48.2;
parameter real rcp1 = 150;
parameter real rnw = 1800;
parameter real rcn = 182;
parameter real cm0=5.828e-16*cnwvc2_cintmult;
parameter real cm1=4.596e-16;
parameter real cm2=1.614e-16;
parameter real cm3=1.541e-15*cnwvc2_cdepmult;
parameter real cx0=6.778e-16;
parameter real cx1=6.461e-16;
parameter real cx2=1.517e-16;
parameter real cx3=8.854e-14*3.9/cnwvc2_tox;
parameter real slope_0=1.808e-17;
parameter real slope_0_tc1=7.2181e-20;
parameter real slope_0_tc2=-1.9745e-21;
parameter real slope_w=-3.169e-17;
parameter real slope_w_tc1=-1.4465e-19;
parameter real slope_w_tc2=3.5187e-21;
parameter real slope_l=-7.435e-17;
parameter real slope_l_tc1=-4.4474e-19;
parameter real slope_l_tc2=7.3824e-21;
parameter real slope_wl=2.509e-16;
parameter real slope_wl_tc1=-1.0793e-18;
parameter real slope_wl_tc2=-2.2625e-20;
real cnwvc_ldiff;
real wc,lc,wd,ld,ldd,dwr,dwp,dlr,wl,wlwdiff;
real cnwvc_slope1,cnwvc_slope2;
real cmin,cmax,cval1,cval2;
real con_sp;
real n_pocon,n_con;
real cnwvc_n1,cnwvc_n2;
real cPolySub,cNwellSub;
real cnwvc_k;
real cnwvc_a,cnwvc_b1,cnwvc_c;
real acon,apoly,apolyc;
real anwell,bnwell,cnwell;
real c0,c1,q;
real tc1,tc2;
real rgvalue,rg_nominal;
real v;
real treference;
real temp_celcius;
real cmin_slope_0;
real cmin_slope_w;
real cmin_slope_l;
real cmin_slope_wl;
real cmin_slope;
// Internal nodes
electrical v1 ;
analog begin
treference=30.0;
cnwvc_ldiff=0.15;
wc=1*w;
lc=1*l;
wd=wc+2*cnwvc2_dwc;
ld=lc+2*cnwvc2_dlc;
ldd=0.015+2*cnwvc2_dld;
dwr=0.0;
dwp=0.0;
dlr=0.03;
wl=(wd-2*dwr)/(ld-2*dlr);
wlwdiff=((0.5*(ld-2*dlr))+cnwvc_ldiff)/(2*(wd-2*dwr));
cnwvc_slope1=0.15;
cnwvc_slope2=0.35;
cmin=cm0+cm1*ld+cm2*wd+cm3*wd*(ld-ldd)+cx3*wd*ldd;
cmax=cx0+cx1*ld+cx2*wd+cx3*wd*ld;
cval1=0.5*(cmax+cmin);
cval2=0.5*(cmax-cmin);
con_sp=0.17;
cnwvc_k=12;
cnwvc_n1=0.2;
cnwvc_n2=0.35;
apoly=1.1;
apolyc=1.1;
acon=1;
anwell=1;
bnwell=0.5;
cnwell=0.3;
n_pocon=max((l-0.14)/(2*con_sp),1); //numbers of poly contact
n_con=(w-2*0.06+con_sp)/(2*con_sp);
cPolySub=0.15e-15;
cNwellSub=0.15e-15;
cnwvc_a=apoly*rp1*wl/cnwvc_k+apolyc*rcp1/n_pocon+acon*rcn/n_con+anwell*rnw*wlwdiff;
cnwvc_b1=bnwell*rnw*cnwvc_ldiff/(2*(wd-2*dwr));
cnwvc_c=cnwell*rnw*cnwvc_ldiff/(2*(wd-2*dwp));
v=V(v1,nwell);
tc1=9.611e-4;
tc2=5.523e-6;
temp_celcius= $temperature-273.15; //$temperature is in Kelvin
cmin_slope_0 = slope_0+(temp_celcius-treference)*slope_0_tc1+(temp_celcius-treference)*(temp_celcius-treference)*slope_0_tc2;
cmin_slope_w = slope_w+(temp_celcius-treference)*slope_w_tc1+(temp_celcius-treference)*(temp_celcius-treference)*slope_w_tc2;
cmin_slope_l = slope_l+(temp_celcius-treference)*slope_l_tc1+(temp_celcius-treference)*(temp_celcius-treference)*slope_l_tc2;
cmin_slope_wl = slope_wl+(temp_celcius-treference)*slope_wl_tc1+(temp_celcius-treference)*(temp_celcius-treference)*slope_wl_tc2;
cmin_slope = cmin_slope_0+cmin_slope_w*wd+cmin_slope_l*ld+cmin_slope_wl*wd*ld;
rg_nominal =(cnwvc_a+cnwvc_b1*(0.5*tanh((v-cnwvc2_vtr)/cnwvc_n1)+0.5)+20*cnwvc_c*(0.5*tanh((v-cnwvc2_vtr)/cnwvc_n1)+0.5)*exp(-abs((v-cnwvc2_vtr)/cnwvc_n2)));
rgvalue = rg_nominal*(1+tc1*(temp_celcius-treference)+tc2*(temp_celcius-treference)*(temp_celcius-treference));
q = cmin_slope*min(v+0.8,0)*min(v+0.8,0)+cval1*v + (cval2/1.9) * (cnwvc_slope1*ln(0.5*((limexp((v-cnwvc2_vt1)/cnwvc_slope1))+limexp(-(v-cnwvc2_vt1)/cnwvc_slope1))) + 0.9*cnwvc_slope2*ln(0.5*((limexp((v-cnwvc2_vt2)/cnwvc_slope2))+limexp(-(v-cnwvc2_vt2)/cnwvc_slope2))));
I(v1,nwell) <+ vm*ddt(q);
V(poly,v1) <+ I(poly,v1)*rgvalue/vm;
V(poly,v1) <+ white_noise( 4*1.38e-23*$temperature*rgvalue/vm, "rg_noise");
//c1 and c2 are the tuning capacitors
I(poly,sub)<+ vm*cPolySub*ddt(V(poly,sub)); // c1 poly sub c=0.15e-15
I(nwell,sub)<+ vm*cNwellSub*ddt(V(nwell,sub)); // c2 nwell sub c=0.15e-15
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment