//VerilogA for ring,nefffilter,veriloga //Xuanqi Chen, Zhifei Wang, Yi-Shing Chang, Jiang Xu, Jun Feng, Peng Yang, Zhehui Wang, Luan H. K. Duong, ”Modeling and Analysis of Optical Modulators Based on Free-Carrier Plasma Dispersion Effect,” IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems (TCAD), vol. 39, no. 5, pp. 977-990, May 2020. `include "constants.vams" `include "disciplines.vams" `define MAX_TABLE_SIZE 300000 `define MAX_X_NUM 1000 //500*500=250000 module nefffilter(Ipow1,Iphase1,Ilam1,Opow1,Ophase1,Olam1,Ipow2,Iphase2,Ilam2,Opow2,Ophase2,Olam2,Vbias,Gnd); //Parameters parameter real r = 10u from (0:inf); parameter real phaseshift_ratio = 0.8407 from (0:1); parameter real nref_coupler = 3.02 from (0:inf); parameter real kappa_coupler = 2.15e6 from (0:inf); parameter real l_coupler = 0.1u from (0:inf); parameter real alpha_phaseshift_ref = 80 from (0:inf); parameter real alpha_absorp = 1 from (0:inf); parameter real alpha_wd = 1 from (0:inf); parameter real rib_width = 0.4u from (0:inf); parameter real pn_offset = 0 from [0:inf); parameter real ni = 1e16 from (0:inf); parameter real N_A = 5e23 from (0:inf); parameter real N_D = 1e24 from (0:inf); parameter real Lp = 2u from (0:inf); parameter real Ln = 1u from (0:inf); parameter real epsr_Si = 11.7; parameter real Is = 1e-14 from (0:inf); parameter real IBV = 1000u from (0:inf); parameter real BV = 40 from (0:inf); parameter real V0 = 1 from [0:inf); parameter real Cj0 = 1.5p from [0:inf); parameter real tau = 0.5n from (0:inf); parameter real Rs = 55 from (0:inf); parameter real emi = 1 from (0:inf); parameter real Vt = 0.0259 from (0:inf); parameter string neff_ps_filename = "../../../data/EIM/outputPN1.54-1.56-500.txt"; parameter string neff_wg_filename = "../../../data/EIM/output-wg1.54-1.56-500.txt"; input Ipow1,Iphase1,Ilam1,Ipow2,Iphase2,Ilam2,Vbias; output Opow1,Ophase1,Olam1,Opow2,Ophase2,Olam2; inout Gnd; electrical Ipow1,Iphase1,Ilam1,Ipow2,Iphase2,Ilam2,Vbias,Opow1,Ophase1,Olam1,Opow2,Ophase2,Olam2,Gnd; electrical Nint; branch (Gnd,Nint) Iint; branch (Nint,Gnd) CCj,CCd,Idd,RRs; //internal variables real beta_cp; real k_cp_r,k_cp_i; real t_cp_r,t_cp_i; real beta_wg; real k_wg_r,k_wg_i; real beta_ps; real k_ps_r,k_ps_i; real er,ei; real p_mr_r,p_mr_i; real E_in1_R,E_in1_I,E_in2_R,E_in2_I; real E_out1_R,E_out1_I,E_out2_R,E_out2_I; real t2r,t2i,p2r,p2i,k2r,k2i; real c0r,c0i,c11r,c11i,c1r,c1i,c2r,c2i; real cpr,cpi,cdr,cdi; real alpha_phaseshift; real W,Wdp,Wdn; real eps,phi_bi,phi; real N_avr; real gd,Id,Cj,Cd; real pn00,np00; real lam; real neff_waveguide,neff_phaseshift_ref,neff_phaseshift; //1550nm real sigma_ne=-8.8E-22; real sigma_nh=-8.5E-18; real sigma_ae=8.5E-18; real sigma_ah=6.0E-18; real xlength;//=0.6u; integer xnum=`MAX_X_NUM+1; integer xnum2=2*`MAX_X_NUM+1; real x[0:`MAX_X_NUM]; real np[0:`MAX_X_NUM]; real pp[0:`MAX_X_NUM]; real pn[0:`MAX_X_NUM]; real nn[0:`MAX_X_NUM]; real xx[0:2*`MAX_X_NUM+1]; real n[0:2*`MAX_X_NUM+1]; real p[0:2*`MAX_X_NUM+1]; integer wi,wf; real dalpha_e[0:2*`MAX_X_NUM+1]; real dalpha_h[0:2*`MAX_X_NUM+1]; real dalpha[0:2*`MAX_X_NUM+1]; real sum_dalpha,dalpha_avr; integer ps_file, wg_file; real width_start, width_end, width_step; integer width_num; real lam_start, lam_end, lam_step; integer lam_num; integer lam_near, width_near; real tmp; real lam_old=0; real width_old=0; real neff_table_ps[0:`MAX_TABLE_SIZE] = {0}; real neff_lamtable_ps[0:`MAX_TABLE_SIZE] = {0}; real neff_widthtable_ps[0:`MAX_TABLE_SIZE] = {0}; real neff_table_wg[0:`MAX_TABLE_SIZE] = {0}; real neff_lamtable_wg[0:`MAX_TABLE_SIZE] = {0}; integer read_table_ps=1; integer read_table_wg=1; integer i, j; analog initial begin pn00=pow(ni,2)/N_D; np00=pow(ni,2)/N_A; eps=epsr_Si*`P_EPS0; phi_bi=`P_K*$temperature/`P_Q*ln(N_A*N_D/pow(ni,2)); N_avr=N_A*N_D/(N_A+N_D); end analog begin lam=V(Ilam1); gd=(-Is*(exp(5)-1)+IBV)/(-5*emi*Vt + BV); Id=Is*(limexp(V(Nint)/(emi*Vt))-1)+V(Nint)*gd; if (V(Nint) >= V0) Cj=0; else Cj=Cj0/sqrt(1-V(Nint)/V0); //Cd=Id*tau/(emi*Vt); Cd=Is*(exp(V(Nint)/(emi*Vt))-1)*tau/(emi*Vt); I(Iint) <+ V(Vbias)/Rs; I(CCj) <+ Cj*ddt(V(CCj)); I(CCd) <+ Cd*ddt(V(CCd)); I(Idd) <+ Id; V(RRs) <+ I(RRs)*Rs; E_in1_R=sqrt(V(Ipow1))*cos(V(Iphase1)/360.0*2*`M_PI); E_in1_I=sqrt(V(Ipow1))*sin(V(Iphase1)/360.0*2*`M_PI); E_in2_R=sqrt(V(Ipow2))*cos(V(Iphase2)/360.0*2*`M_PI); E_in2_I=sqrt(V(Ipow2))*sin(V(Iphase2)/360.0*2*`M_PI); beta_cp = 2.0*`M_PI*nref_coupler/lam; k_cp_r=-sin(kappa_coupler*l_coupler) * sin(l_coupler*beta_cp); k_cp_i=sin(kappa_coupler*l_coupler) * cos(l_coupler*beta_cp); t_cp_r=cos(kappa_coupler*l_coupler) * cos(l_coupler*beta_cp); t_cp_i=cos(kappa_coupler*l_coupler) * sin(l_coupler*beta_cp); phi=phi_bi-V(Nint); if (phi<0) phi=0; W=alpha_wd * sqrt(2.0*eps*phi/(`P_Q*N_avr)); Wdp=N_D * W/(N_A+N_D); Wdn=N_A * W/(N_A+N_D); xlength=rib_width/2; for (i=0; iWdp) begin pp[i]=N_A; end else begin pp[i]=0; end pn[i]=pn00*(exp(`P_Q*V(Nint)/(`P_K*$temperature))-1)*exp(-(x[i]-Wdn)/Lp)+pn00; if (x[i]>Wdn) begin nn[i]=N_D; end else begin nn[i]=0; end if (np[i]<0) np[i]=0; if (pn[i]<0) pn[i]=0; end for (i=0; i<2*xnum; i=i+1) begin if (ilam_end) begin $display("Warning: lam=%f is out of range [%f,%f]",lam*1e6,lam_start,lam_end); end if (Wdp*1e6width_end) begin $display("Warning: Wdp=%f is out of range [%f,%f]",Wdp*1e6,width_start,width_end); end neff_phaseshift = $table_model(Wdp*1e6, lam*1e6, neff_widthtable_ps, neff_lamtable_ps, neff_table_ps, "3L,3L"); end if (read_table_wg == 0|| lam_old==0 ) begin read_table_wg=1; end if (read_table_wg == 1) begin wg_file=$fopen(neff_wg_filename,"r"); if (wg_file==0) begin $display("Error: cannot open wg_file %s",neff_wg_filename); $finish; end $fscanf(wg_file,"%f",lam_start); $fscanf(wg_file,"%f",lam_end); $fscanf(wg_file,"%d",lam_num); for (i=0; ilam_end) begin $display("Warning: lam=%f is out of range [%f,%f]",lam*1e6,lam_start,lam_end); end neff_waveguide = $table_model(lam*1e6, neff_lamtable_wg, neff_table_wg, "3E"); end beta_wg = 2.0*`M_PI*neff_waveguide/lam; beta_ps = 2.0*`M_PI*neff_phaseshift/lam; k_wg_r=-alpha_phaseshift_ref; k_wg_i=beta_wg; k_ps_r=-alpha_phaseshift*alpha_absorp; k_ps_i=beta_ps; er = phaseshift_ratio*`M_PI*r*k_ps_r+(1.0-phaseshift_ratio)*`M_PI*r*k_wg_r; ei = phaseshift_ratio*`M_PI*r*k_ps_i+(1.0-phaseshift_ratio)*`M_PI*r*k_wg_i; p_mr_r = limexp(er)*cos(ei); p_mr_i = limexp(er)*sin(ei); t2r=t_cp_r*t_cp_r-t_cp_i*t_cp_i; t2i=2*t_cp_r*t_cp_i; p2r=p_mr_r*p_mr_r-p_mr_i*p_mr_i; p2i=2*p_mr_r*p_mr_i; k2r=k_cp_r*k_cp_r-k_cp_i*k_cp_i; k2i=2*k_cp_r*k_cp_i; c0r=1-t2r*p2r+t2i*p2i; c0i=-t2r*p2i-t2i*p2r; c11r=1+(k2r-t2r)*p2r-(k2i-t2i)*p2i; c11i=(k2r-t2r)*p2i+(k2i-t2i)*p2r; c1r=t_cp_r*c11r-t_cp_i*c11i; c1i=t_cp_r*c11i+t_cp_i*c11r; c2r=k2r*p_mr_r-k2i*p_mr_i; c2i=k2r*p_mr_i+k2i*p_mr_r; cpr=(c0r*c1r+c0i*c1i)/(c0r*c0r+c0i*c0i); cpi=(c0r*c1i-c0i*c1r)/(c0r*c0r+c0i*c0i); cdr=(c0r*c2r+c0i*c2i)/(c0r*c0r+c0i*c0i); cdi=(c0r*c2i-c0i*c2r)/(c0r*c0r+c0i*c0i); E_out1_R=cpr*E_in1_R-cpi*E_in1_I+cdr*E_in2_R-cdi*E_in2_I; E_out1_I=cpi*E_in1_R+cpr*E_in1_I+cdi*E_in2_R+cdr*E_in2_I; E_out2_R=cdr*E_in1_R-cdi*E_in1_I+cpr*E_in2_R-cpi*E_in2_I; E_out2_I=cdi*E_in1_R+cdr*E_in1_I+cpi*E_in2_R+cpr*E_in2_I; V(Opow1) <+ E_out1_R*E_out1_R+E_out1_I*E_out1_I; V(Ophase1) <+ atan2(E_out1_I,E_out1_R)*360.0/(2*`M_PI); V(Olam1) <+ V(Ilam1); V(Opow2) <+ E_out2_R*E_out2_R+E_out2_I*E_out2_I; V(Ophase2) <+ atan2(E_out2_I,E_out2_R)*360.0/(2*`M_PI); V(Olam2) <+ V(Ilam2); lam_old=lam; width_old=Wdp; end endmodule