You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
584 lines
24 KiB
584 lines
24 KiB
//VerilogA for modulator,neffmz,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_MODES 200
|
|
`define MAX_ITER 10000
|
|
`define IDX_NUM 10000
|
|
`define TOLERANCE 0.0000000001
|
|
`define MAX_TABLE_SIZE 300000
|
|
|
|
module neffmz(Ipow,Iphase,Ilam,Opow,Ophase,Olam,Vbias,Gnd);
|
|
parameter real design_lam = 1.55e-6 from (0:inf);
|
|
parameter real n_ps = 3.45 from (0:inf);
|
|
parameter real n_sub = 1.45 from (0:inf);
|
|
parameter real width_MMI = 3e-6 from (0:inf);
|
|
parameter real width_port = 0.45e-6 from (0:inf);
|
|
parameter real port_offset = 0.75e-6 from (0:inf);
|
|
parameter real thickness = 0.22e-6 from (0:inf);
|
|
parameter real alpha_mmi = 80 from (0:inf);
|
|
parameter real l_ps = 0.1e-6 from (0:inf);
|
|
parameter real l_arm = 40e-6 from (0:inf);
|
|
parameter real alpha_phaseshift_ref = 80 from [0:inf);
|
|
parameter real alpha_waveguide = 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.4e-6 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 = 2e-6 from (0:inf);
|
|
parameter real Ln = 1e-6 from (0:inf);
|
|
parameter real epsr_Si = 11.7 from (0:inf);
|
|
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";
|
|
|
|
input Ipow,Iphase,Ilam,Vbias;
|
|
output Opow,Ophase,Olam;
|
|
inout Gnd;
|
|
electrical Ipow,Iphase,Ilam,Vbias,Opow,Ophase,Olam,Nint,Gnd;
|
|
|
|
branch (Gnd,Nint) Iint;
|
|
branch (Nint,Gnd) CCj,CCd,Idd,RRs;
|
|
|
|
real ulam, ulam0, uwidth_in, uwidth_MMI, uoffset, uthickness, alpha0;
|
|
real k1_ref, kc_ref;
|
|
integer mode_num, mode_num_ref;
|
|
real beta_x_MMI, beta_in, beta_x_in;
|
|
real neff_MMI[0:`MAX_MODES];
|
|
real beta_MMI[0:`MAX_MODES];
|
|
real length_MMI;
|
|
real ky_in, gamma_in;
|
|
real ky_MMI[0:`MAX_MODES];
|
|
real gamma_MMI[0:`MAX_MODES];
|
|
real c0;
|
|
real c0_dis[0:`MAX_MODES];
|
|
real icoff[0:`MAX_MODES];
|
|
real delta_beta;
|
|
real ocoff_r[0:`MAX_MODES];
|
|
real ocoff_i[0:`MAX_MODES];
|
|
real c1r, c1i, c2r, c2i;
|
|
real inr, ini, out1r, out1i, out2r, out2i;
|
|
real sum_outfield1, sum_outfield2, sum_outfield3, sum_outfield4;
|
|
real sum_singlemode1,sum_singlemode2,sum_singlemode3,sum_singlemode4;
|
|
real border;
|
|
integer i, j;
|
|
real p0=1;
|
|
real h;
|
|
|
|
real beta_ps;
|
|
real k_ps_r,k_ps_i;
|
|
real p_ps_r,p_ps_i,p_wg_r,p_wg_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 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_phaseshift_ref,neff_phaseshift;
|
|
|
|
real cp_tr11_r,cp_tr11_i,cp_tr12_r,cp_tr12_i,cp_tr21_r,cp_tr21_i,cp_tr22_r,cp_tr22_i;
|
|
real ar_tr11_r,ar_tr11_i,ar_tr12_r,ar_tr12_i,ar_tr21_r,ar_tr21_i,ar_tr22_r,ar_tr22_i;
|
|
real t1_11_r,t1_11_i,t1_12_r,t1_12_i,t1_21_r,t1_21_i,t1_22_r,t1_22_i;
|
|
real t2_11_r,t2_11_i,t2_12_r,t2_12_i,t2_21_r,t2_21_i,t2_22_r,t2_22_i;
|
|
|
|
//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=10001;
|
|
real x[0:10000];
|
|
real np[0:10000];
|
|
real pp[0:10000];
|
|
real pn[0:10000];
|
|
real nn[0:10000];
|
|
real xx[0:20001];
|
|
real n[0:20001];
|
|
real p[0:20001];
|
|
real wi,wf;
|
|
real dalpha_e[0:20001];
|
|
real dalpha_h[0:20001];
|
|
real dalpha[0:20001];
|
|
real sum_dalpha;
|
|
real dalpha_avr;
|
|
|
|
integer ps_file;
|
|
real width_start, width_end, width_step;
|
|
real lam_start, lam_end, lam_step;
|
|
integer width_num, lam_num;
|
|
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};
|
|
integer read_table_ps=1;
|
|
|
|
analog function real findzeropoint_rect_x;
|
|
input x_lower_input, x_upper_input, Vx;
|
|
real x_lower_input, x_upper_input, Vx;
|
|
real iter_count;
|
|
real x_lower, x_upper;
|
|
real y_mid;
|
|
|
|
real y_lower, x_mid;
|
|
|
|
begin
|
|
findzeropoint_rect_x = -1;
|
|
x_lower = x_lower_input;
|
|
x_upper = x_upper_input;
|
|
iter_count = 0;
|
|
y_mid = 1;
|
|
while (iter_count<`MAX_ITER && abs(y_mid) > `TOLERANCE) begin
|
|
x_mid = (x_lower + x_upper) / 2;
|
|
y_lower = tan(x_lower / 2) - sqrt(pow(Vx,2) - pow(x_lower,2)) / x_lower;
|
|
y_mid = tan(x_mid / 2) - sqrt(pow(Vx,2) - pow(x_mid,2)) / x_mid;
|
|
|
|
if (abs(y_mid) < `TOLERANCE) begin
|
|
findzeropoint_rect_x = x_mid;
|
|
end
|
|
|
|
if (y_mid * y_lower < 0)
|
|
x_upper = x_mid;
|
|
else
|
|
x_lower = x_mid;
|
|
|
|
iter_count = iter_count + 1;
|
|
end
|
|
if (findzeropoint_rect_x == -1)
|
|
$display("No zero point found in the given range. Please try again with different range.");
|
|
end
|
|
endfunction
|
|
|
|
analog function real findzeropoint_rect_y;
|
|
input x_lower_input, x_upper_input, Vy, m;
|
|
real x_lower_input, x_upper_input, Vy, m;
|
|
real iter_count;
|
|
real x_lower, x_upper;
|
|
real y_mid;
|
|
|
|
real y_lower, x_mid;
|
|
|
|
begin
|
|
x_lower = x_lower_input;
|
|
x_upper = x_upper_input;
|
|
iter_count = 0;
|
|
y_mid = 1;
|
|
findzeropoint_rect_y = -1;
|
|
while (iter_count<`MAX_ITER && abs(y_mid) > `TOLERANCE) begin
|
|
x_mid = (x_lower + x_upper) / 2;
|
|
y_lower = tan(x_lower / 2 - m * `M_PI / 2) - sqrt((pow(Vy,2) - pow(x_lower,2))) / x_lower;
|
|
y_mid = tan(x_mid / 2 - m * `M_PI / 2) - sqrt((pow(Vy,2) - pow(x_mid,2))) / x_mid;
|
|
|
|
if (abs(y_mid) < `TOLERANCE)
|
|
findzeropoint_rect_y = x_mid;
|
|
|
|
if (y_mid * y_lower < 0)
|
|
x_upper = x_mid;
|
|
else
|
|
x_lower = x_mid;
|
|
iter_count = iter_count + 1;
|
|
end
|
|
if (findzeropoint_rect_y == -1)
|
|
$display("No zero point found in the given range. Please try again with different range.");
|
|
end
|
|
endfunction
|
|
|
|
analog function real eim_rect;
|
|
input lam, width, thickness, n_ps, n_sub, numflag, mode_index;
|
|
real lam, width, thickness, n_ps, n_sub;
|
|
integer numflag, mode_index;
|
|
real k1, Vx, yx, hx, beta_x, neff_x_MMI, Vy, yy, hxy;
|
|
real beta_xy[0:`MAX_MODES];
|
|
real neff_xy[0:`MAX_MODES];
|
|
real beta_xy_out[0:`MAX_MODES];
|
|
real neff_xy_out[0:`MAX_MODES];
|
|
integer i, m, mode_num;
|
|
|
|
begin
|
|
k1=2*`M_PI*n_ps/lam;
|
|
Vx=2*`M_PI/lam*thickness*sqrt((pow(n_ps,2)-pow(n_sub,2)));
|
|
yx=findzeropoint_rect_x(1e-6,min(`M_PI,Vx),Vx);
|
|
hx=yx/thickness;
|
|
beta_x=sqrt(pow(k1,2)-pow(hx,2));
|
|
neff_x_MMI=lam*beta_x/(2*`M_PI);
|
|
Vy=2*`M_PI/lam*width*sqrt((pow(neff_x_MMI,2)-pow(n_sub,2)));
|
|
i=0;
|
|
m=0;
|
|
while (m*`M_PI<Vy) begin
|
|
yy=findzeropoint_rect_y(m*`M_PI+1e-6,min((m+1)*`M_PI-1e-6,Vy),Vy,m);
|
|
m=m+1;
|
|
// if m*`M_PI>=Vy
|
|
// break
|
|
hxy=yy/width;
|
|
beta_xy[i]=sqrt(pow(beta_x,2)-pow(hxy,2));
|
|
neff_xy[i]=lam*beta_xy[i]/(2*`M_PI);
|
|
i=i+1;
|
|
end
|
|
mode_num=m-1;
|
|
if (numflag==1 || numflag==2) begin
|
|
for (i=0;i<mode_num;i=i+1) begin
|
|
beta_xy_out[i]=beta_xy[i];
|
|
neff_xy_out[i]=neff_xy[i];
|
|
end
|
|
if (numflag==1)
|
|
eim_rect=neff_xy_out[mode_index];
|
|
else
|
|
eim_rect=beta_xy_out[mode_index];
|
|
end
|
|
else if (numflag==3) begin
|
|
eim_rect=beta_x;
|
|
end
|
|
else if (numflag==4) begin
|
|
eim_rect=mode_num;
|
|
end
|
|
end
|
|
endfunction
|
|
|
|
analog function real fieldfunc;
|
|
input y,width,offset,ky,gamma,m,c0;
|
|
real y,width,offset,ky,gamma,m,c0;
|
|
real fai;
|
|
|
|
begin
|
|
fai = m * `M_PI / 2;
|
|
if (((y - offset) <= (width / 2)) && ((-width / 2) <= (y - offset)))
|
|
fieldfunc=c0 * cos(ky * (y - offset) - fai);
|
|
else if ((y - offset) > width / 2)
|
|
fieldfunc=c0 * cos(ky * width / 2 - fai) * exp(-gamma * ((y - offset) - width / 2));
|
|
else
|
|
fieldfunc=c0 * cos(ky * width / 2 + fai) * exp(gamma * ((y - offset) + width / 2));
|
|
end
|
|
endfunction
|
|
|
|
analog function real normpower_fieldfunc_quad;
|
|
input width,offset,ky,gamma,m,c0,width_MMI,border;
|
|
real width,offset,ky,gamma,m,c0,width_MMI,border;
|
|
real n,h;
|
|
// real border=width_MMI/2;
|
|
integer i;
|
|
real sum;
|
|
begin
|
|
n=`IDX_NUM;
|
|
h=border*2/n;
|
|
sum=0.5*(pow(abs(fieldfunc(-1*border,width,offset,ky,gamma,m,c0)),2)+pow(abs(fieldfunc(border,width,offset,ky,gamma,m,c0)),2));
|
|
for (i=1;i<n;i=i+1) begin
|
|
sum=sum+pow(abs(fieldfunc(-1*border+i*h,width,offset,ky,gamma,m,c0)),2);
|
|
end
|
|
normpower_fieldfunc_quad=1/sqrt(h*sum);
|
|
end
|
|
endfunction
|
|
|
|
analog function real infidx_modecoeffcient_quad;
|
|
input width1,offset1,ky1,gamma1,m1,c01,width2,offset2,ky2,gamma2,m2,c02,border;
|
|
real width1,offset1,ky1,gamma1,m1,c01,width2,offset2,ky2,gamma2,m2,c02,border;
|
|
real n,h;
|
|
// real border=20;
|
|
integer i;
|
|
real sum;
|
|
begin
|
|
n=`IDX_NUM;
|
|
h=border*2/n;
|
|
sum=0.5*(fieldfunc(-1*border,width1,offset1,ky1,gamma1,m1,c01)* fieldfunc(-1*border,width2,offset2,ky2,gamma2,m2,c02)+fieldfunc(border,width1,offset1,ky1,gamma1,m1,c01)* fieldfunc(border,width2,offset2,ky2,gamma2,m2,c02));
|
|
for (i=1;i<n;i=i+1) begin
|
|
sum=sum+fieldfunc(-1*border+i*h,width1,offset1,ky1,gamma1,m1,c01)* fieldfunc(-1*border+i*h,width2,offset2,ky2,gamma2,m2,c02);
|
|
end
|
|
infidx_modecoeffcient_quad=h*sum;
|
|
end
|
|
endfunction
|
|
|
|
analog initial begin
|
|
ulam0=design_lam*1e6;
|
|
uwidth_in=width_port*1e6;
|
|
uwidth_MMI=width_MMI*1e6;
|
|
uoffset=port_offset*1e6;
|
|
uthickness=thickness*1e6;
|
|
alpha0=alpha_mmi*1e-6;
|
|
k1_ref = 2 * `M_PI * n_ps / ulam0;
|
|
kc_ref = 2 * `M_PI * n_sub / ulam0;
|
|
|
|
mode_num_ref = eim_rect(ulam0, uwidth_MMI, uthickness, n_ps, n_sub, 4, 0);
|
|
for (i=0;i<mode_num_ref;i=i+1) begin
|
|
beta_MMI[i] = eim_rect(ulam0, uwidth_MMI, uthickness, n_ps, n_sub, 2, i);
|
|
end
|
|
length_MMI = p0*1.5*`M_PI/(beta_MMI[0]-beta_MMI[1]); //0.375Lpi?
|
|
// $display("length_MMI=%f",length_MMI);
|
|
border=20;
|
|
|
|
pn00=pow(ni,2)/N_D;
|
|
np00=pow(ni,2)/N_A;
|
|
|
|
eps=epsr_Si*`P_EPS0;
|
|
phi_bi=`P_K*$temperature/`P_Q*log(N_A*N_D/pow(ni,2));
|
|
|
|
N_avr=N_A*N_D/(N_A+N_D);
|
|
end
|
|
|
|
analog begin
|
|
ulam = V(Ilam) * 1e6;
|
|
beta_in=eim_rect(ulam, uwidth_in, uthickness, n_ps, n_sub, 2, 0);
|
|
// $display("beta_in=%f",beta_in);
|
|
beta_x_in=eim_rect(ulam, uwidth_in, uthickness, n_ps, n_sub, 3, 0);
|
|
// $display("beta_x_in=%f",beta_x_in);
|
|
beta_x_MMI=eim_rect(ulam, uwidth_MMI, uthickness, n_ps, n_sub, 3, 0);
|
|
// $display("beta_x_MMI=%f",beta_x_MMI);
|
|
mode_num = eim_rect(ulam, uwidth_MMI, uthickness, n_ps, n_sub, 4, 0);
|
|
// $display("mode_num=%d",mode_num);
|
|
ky_in = sqrt(pow(beta_x_in,2) - pow(beta_in,2));
|
|
// $display("ky_in=%f",ky_in);
|
|
gamma_in = sqrt(pow(beta_in,2) - pow(kc_ref,2));
|
|
// $display("gamma_in=%f",gamma_in);
|
|
for (i=0;i<mode_num;i=i+1) begin
|
|
neff_MMI[i] = eim_rect(ulam, uwidth_MMI, uthickness, n_ps, n_sub, 1, i);
|
|
beta_MMI[i] = eim_rect(ulam, uwidth_MMI, uthickness, n_ps, n_sub, 2, i);
|
|
ky_MMI[i] = sqrt(pow(beta_x_MMI,2) - pow(beta_MMI[i],2));
|
|
gamma_MMI[i] = sqrt(pow(beta_MMI[i],2) - pow(kc_ref,2));
|
|
// $display("neff_MMI[%d]=%f, beta_MMI[%d]=%f, ky_MMI[%d]=%f, gamma_MMI[%d]=%f",i,neff_MMI[i],i,beta_MMI[i],i,ky_MMI[i],i,gamma_MMI[i]);
|
|
end
|
|
|
|
c0=normpower_fieldfunc_quad(uwidth_in,0,ky_in,gamma_in,0,1,uwidth_MMI,border);
|
|
// $display("c0=%f",c0);
|
|
for (i=0;i<mode_num;i=i+1) begin
|
|
c0_dis[i]=normpower_fieldfunc_quad(uwidth_MMI,0,ky_MMI[i],gamma_MMI[i],i,1,uwidth_MMI,border);
|
|
// $display("c0_dis[%d]=%f",i,c0_dis[i]);
|
|
icoff[i]=infidx_modecoeffcient_quad(uwidth_in,uoffset,ky_in,gamma_in,0,c0,uwidth_MMI,0,ky_MMI[i],gamma_MMI[i],i,c0_dis[i],border);
|
|
// $display("icoff[%d]=%f",i,icoff[i]);
|
|
end
|
|
|
|
delta_beta = beta_MMI[0] - beta_MMI[1];
|
|
// $display("delta_beta=%f",delta_beta);
|
|
for (i=2;i<mode_num;i=i+1) begin
|
|
beta_MMI[i]=beta_MMI[0] - i* (i + 2) * delta_beta / 3;
|
|
// $display("beta_MMI[%d]=%f",i,beta_MMI[i]);
|
|
end
|
|
for (i=0;i<mode_num;i=i+1) begin
|
|
ocoff_r[i]=icoff[i]*cos(-beta_MMI[i]*length_MMI);
|
|
ocoff_i[i]=icoff[i]*sin(-beta_MMI[i]*length_MMI)*-1.0;
|
|
// $display("ocoff_r[%d]=%f, ocoff_i[%d]=%f",i,ocoff_r[i],i,ocoff_i[i]);
|
|
end
|
|
|
|
h=border*2.0/`IDX_NUM;
|
|
sum_outfield1=0;
|
|
sum_outfield2=0;
|
|
sum_outfield3=0;
|
|
sum_outfield4=0;
|
|
for (j=0;j<mode_num;j=j+1) begin
|
|
sum_singlemode1=0.5*(ocoff_r[j]*fieldfunc(-1*border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border,uwidth_in,uoffset,ky_in,gamma_in,0,c0)+ocoff_r[j]*fieldfunc(border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(border,uwidth_in,uoffset,ky_in,gamma_in,0,c0));
|
|
sum_singlemode2=0.5*(ocoff_i[j]*fieldfunc(-1*border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border,uwidth_in,uoffset,ky_in,gamma_in,0,c0)+ocoff_i[j]*fieldfunc(border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(border,uwidth_in,uoffset,ky_in,gamma_in,0,c0));
|
|
sum_singlemode3=0.5*(ocoff_r[j]*fieldfunc(-1*border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border,uwidth_in,-uoffset,ky_in,gamma_in,0,c0)+ocoff_r[j]*fieldfunc(border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(border,uwidth_in,-uoffset,ky_in,gamma_in,0,c0));
|
|
sum_singlemode4=0.5*(ocoff_i[j]*fieldfunc(-1*border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border,uwidth_in,-uoffset,ky_in,gamma_in,0,c0)+ocoff_i[j]*fieldfunc(border,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(border,uwidth_in,-uoffset,ky_in,gamma_in,0,c0));
|
|
for (i=1;i<`IDX_NUM;i=i+1) begin
|
|
sum_singlemode1=sum_singlemode1+ocoff_r[j]*fieldfunc(-1*border+i*h,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border+i*h,uwidth_in,uoffset,ky_in,gamma_in,0,c0);
|
|
sum_singlemode2=sum_singlemode2+ocoff_i[j]*fieldfunc(-1*border+i*h,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border+i*h,uwidth_in,uoffset,ky_in,gamma_in,0,c0);
|
|
sum_singlemode3=sum_singlemode3+ocoff_r[j]*fieldfunc(-1*border+i*h,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border+i*h,uwidth_in,-uoffset,ky_in,gamma_in,0,c0);
|
|
sum_singlemode4=sum_singlemode4+ocoff_i[j]*fieldfunc(-1*border+i*h,uwidth_MMI,0,ky_MMI[j],gamma_MMI[j],j,c0_dis[j])*fieldfunc(-1*border+i*h,uwidth_in,-uoffset,ky_in,gamma_in,0,c0);
|
|
end
|
|
sum_outfield1=sum_outfield1+h*sum_singlemode1;
|
|
sum_outfield2=sum_outfield2+h*sum_singlemode2;
|
|
sum_outfield3=sum_outfield3+h*sum_singlemode3;
|
|
sum_outfield4=sum_outfield4+h*sum_singlemode4;
|
|
end
|
|
c1r=sum_outfield1*exp(-alpha0*length_MMI);
|
|
c1i=sum_outfield2*exp(-alpha0*length_MMI);
|
|
c2r=sum_outfield3*exp(-alpha0*length_MMI);
|
|
c2i=sum_outfield4*exp(-alpha0*length_MMI);
|
|
|
|
// $display("c1r=%f, c1i=%f, c2r=%f, c2i=%f",c1r,c1i,c2r,c2i);
|
|
|
|
lam=V(Ilam);
|
|
gd=(-Is*(exp(5)-1)+IBV)/(-5*emi*Vt + BV);
|
|
Id=Is*(exp(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;
|
|
|
|
phi=phi_bi-V(Nint);
|
|
// $display("V(Nint)=%e",V(Nint));
|
|
if (phi<0)
|
|
phi=0;
|
|
|
|
// $display("phi=%e",phi);
|
|
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);
|
|
|
|
for (i=0; i<xnum; i=i+1) begin
|
|
x[i]=i*xlength/(xnum-1);
|
|
np[i]=np00*(exp(`P_Q*V(Nint)/(`P_K*$temperature))-1)*exp(-(x[i]-Wdp)/Ln)+np00;
|
|
if (x[i]>Wdp) 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 (i<xnum) begin
|
|
xx[i]=-x[xnum-1-i];
|
|
n[i]=np[xnum-1-i];
|
|
p[i]=pp[xnum-1-i];
|
|
end
|
|
else begin
|
|
xx[i]=x[i-xnum];
|
|
n[i]=nn[i-xnum];
|
|
p[i]=pn[i-xnum];
|
|
end
|
|
if (abs(xx[i]+rib_width/2) < 0.001u) begin
|
|
wi=i;
|
|
end
|
|
if (abs(xx[i]-rib_width/2) < 0.001u) begin
|
|
wf=i;
|
|
end
|
|
dalpha_e[i]=n[i]*sigma_ae*1e-4;
|
|
dalpha_h[i]=p[i]*sigma_ah*1e-4;
|
|
dalpha[i]=dalpha_e[i] + dalpha_h[i];
|
|
end
|
|
|
|
sum_dalpha=0;
|
|
for (i=wi; i<=wf; i=i+1) begin
|
|
sum_dalpha=sum_dalpha+dalpha[i];
|
|
end
|
|
dalpha_avr=sum_dalpha/(wf-wi+1.0);
|
|
alpha_phaseshift = alpha_phaseshift_ref + dalpha_avr;
|
|
|
|
if (read_table_ps==0 || lam_old==0 || width_old==0) begin
|
|
read_table_ps=1;
|
|
end
|
|
|
|
if (read_table_ps == 1) begin
|
|
ps_file=$fopen(neff_ps_filename,"r");
|
|
if (ps_file==0) begin
|
|
$display("Error: cannot open ps_file %s",neff_ps_filename);
|
|
$finish;
|
|
end
|
|
$fscanf(ps_file,"%f",width_start);
|
|
$fscanf(ps_file,"%f",width_end);
|
|
$fscanf(ps_file,"%d",width_num);
|
|
width_step = (width_end-width_start)/(width_num-1);
|
|
// $display("width_start=%f, width_end=%f, width_num=%f, width_step=%f",width_start,width_end,width_num,width_step);
|
|
$fscanf(ps_file,"%f",lam_start);
|
|
$fscanf(ps_file,"%f",lam_end);
|
|
$fscanf(ps_file,"%d",lam_num);
|
|
lam_step = (lam_end-lam_start)/(lam_num-1);
|
|
// for (i=0; i<width_num; i=i+1) begin
|
|
// $fscanf(ps_file,"%f",tmp);
|
|
// end
|
|
for (i=0; i<width_num; i=i+1) begin
|
|
for (j=0; j<lam_num; j=j+1) begin
|
|
$fscanf(ps_file,"%f",tmp);
|
|
// $display("%f",tmp);
|
|
neff_widthtable_ps[i*lam_num+j] = width_start+i*width_step;
|
|
neff_lamtable_ps[i*lam_num+j] = lam_start+j*lam_step;
|
|
neff_table_ps[i*lam_num+j] = tmp;
|
|
//$display("neff_widthtable_ps[%d]=%f, neff_lamtable_ps[%d]=%f, neff_table_ps[%d]=%f",i*lam_num+j,neff_widthtable_ps[i*lam_num+j],i*lam_num+j,neff_lamtable_ps[i*lam_num+j],i*lam_num+j,neff_table_ps[i*lam_num+j]);
|
|
end
|
|
end
|
|
$fclose(ps_file);
|
|
neff_widthtable_ps[width_num*lam_num+1] = 0;
|
|
neff_lamtable_ps[width_num*lam_num+1] = 0;
|
|
neff_table_ps[width_num*lam_num+1] = 0;
|
|
neff_widthtable_ps[width_num*lam_num+2] = 0;
|
|
neff_lamtable_ps[width_num*lam_num+2] = -1;
|
|
neff_table_ps[width_num*lam_num+2] = 0;
|
|
read_table_ps=2;
|
|
end
|
|
|
|
if (read_table_ps == 2) begin
|
|
if (lam*1e6<lam_start || lam*1e6>lam_end) begin
|
|
$display("Warning: lam=%f is out of range [%f,%f]",lam*1e6,lam_start,lam_end);
|
|
end
|
|
if (Wdp*1e6<width_start || Wdp*1e6>width_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);
|
|
// $display("neff=%f",neff_phaseshift);
|
|
end
|
|
|
|
beta_ps = 2.0*`M_PI*neff_phaseshift/lam;
|
|
|
|
k_ps_r=-alpha_phaseshift*alpha_absorp;
|
|
k_ps_i=beta_ps;
|
|
|
|
p_ps_r=exp(k_ps_r*l_ps)*cos(k_ps_i*l_ps);
|
|
p_ps_i=exp(k_ps_r*l_ps)*sin(k_ps_i*l_ps);
|
|
|
|
p_wg_r=exp((k_ps_r+alpha_waveguide-alpha_phaseshift_ref)*(l_ps+l_arm))*cos((k_ps_i)*(l_ps+l_arm));
|
|
p_wg_i=exp((k_ps_r+alpha_waveguide-alpha_phaseshift_ref)*(l_ps+l_arm))*sin((k_ps_i)*(l_ps+l_arm));
|
|
// $display("p_ps_r=%g, p_ps_i=%g, p_wg_r=%g, p_wg_i=%g",p_ps_r,p_ps_i,p_wg_r,p_wg_i);
|
|
ar_tr11_r=p_ps_r;
|
|
ar_tr11_i=p_ps_i;
|
|
ar_tr12_r=0;
|
|
ar_tr12_i=0;
|
|
ar_tr21_r=0;
|
|
ar_tr21_i=0;
|
|
ar_tr22_r=p_wg_r;
|
|
ar_tr22_i=p_wg_i;
|
|
// $display("p_ps_r=%f, p_ps_i=%f, p_wg_r=%f, p_wg_i=%f",p_ps_r,p_ps_i,p_wg_r,p_wg_i);
|
|
|
|
t1_11_r=c1r*ar_tr11_r-c1i*ar_tr11_i+c2r*ar_tr21_r-c2i*ar_tr21_i;
|
|
t1_11_i=c1r*ar_tr11_i+c1i*ar_tr11_r+c2r*ar_tr21_i+c2i*ar_tr21_r;
|
|
t1_12_r=c1r*ar_tr12_r-c1i*ar_tr12_i+c2r*ar_tr22_r-c2i*ar_tr22_i;
|
|
t1_12_i=c1r*ar_tr12_i+c1i*ar_tr12_r+c2r*ar_tr22_i+c2i*ar_tr22_r;
|
|
t1_21_r=c2r*ar_tr11_r-c2i*ar_tr11_i-c1r*ar_tr21_r+c1i*ar_tr21_i;
|
|
t1_21_i=c2r*ar_tr11_i+c2i*ar_tr11_r-c1r*ar_tr21_i-c1i*ar_tr21_r;
|
|
t1_22_r=c2r*ar_tr12_r-c2i*ar_tr12_i-c1r*ar_tr22_r+c1i*ar_tr22_i;
|
|
t1_22_i=c2r*ar_tr12_i+c2i*ar_tr12_r-c1r*ar_tr22_i-c1i*ar_tr22_r;
|
|
|
|
t2_11_r=t1_11_r*c1r-t1_11_i*c1i+t1_12_r*c2r-t1_12_i*c2i;
|
|
t2_11_i=t1_11_r*c1i+t1_11_i*c1r+t1_12_r*c2i+t1_12_i*c2r;
|
|
t2_12_r=t1_11_r*c2r-t1_11_i*c2i+t1_12_r*c1r-t1_12_i*c1i;
|
|
t2_12_i=t1_11_r*c2i+t1_11_i*c2r+t1_12_r*c1i+t1_12_i*c1r;
|
|
t2_21_r=t1_21_r*c1r-t1_21_i*c1i+t1_22_r*c2r-t1_22_i*c2i;
|
|
t2_21_i=t1_21_r*c1i+t1_21_i*c1r+t1_22_r*c2i+t1_22_i*c2r;
|
|
t2_22_r=t1_21_r*c2r-t1_21_i*c2i+t1_22_r*c1r-t1_22_i*c1i;
|
|
t2_22_i=t1_21_r*c2i+t1_21_i*c2r+t1_22_r*c1i+t1_22_i*c1r;
|
|
// $display("t2_11_r=%f, t2_11_i=%f, t2_12_r=%f, t2_12_i=%f, t2_21_r=%f, t2_21_i=%f, t2_22_r=%f, t2_22_i=%f",t2_11_r,t2_11_i,t2_12_r,t2_12_i,t2_21_r,t2_21_i,t2_22_r,t2_22_i);
|
|
|
|
inr=sqrt(V(Ipow))*cos(V(Iphase)/360.0*2*`M_PI);
|
|
ini=sqrt(V(Ipow))*sin(V(Iphase)/360.0*2*`M_PI);
|
|
out1r=t2_11_r*inr-t2_11_i*ini;
|
|
out1i=t2_11_r*ini+t2_11_i*inr;
|
|
out2r=t2_21_r*inr-t2_21_i*ini;
|
|
out2i=t2_21_r*ini+t2_21_i*inr;
|
|
|
|
V(Olam) <+ lam;
|
|
V(Opow) <+ pow(out1r,2)+pow(out1i,2);
|
|
V(Ophase) <+ atan2(out1i,out1r)*360.0/(2*`M_PI);
|
|
end
|
|
endmodule
|
|
|