Professional Documents
Culture Documents
PLL Design
PLL Design
PLL Design
clear
clc
close all
%% Settings for computation
fig_on = 1; % Set to 1 for plots
comp_variation = 0; % Set based on the following
% comp_variation = 0 : no variation
% comp_variation = 10 : all components variation
% comp_variation = 1 : R variation
% comp_variation = 11 : all except R variation
% comp_variation = 2 : kvco variation
% comp_variation = 12 : all except kvco variation
% comp_variation = 3 : C variation
% comp_variation = 13 : all except C variation
% comp_variation = 4 : Icp variation
% comp_variation = 14 : all except Icp variation
% comp_variation = 5 : alacarte
if(comp_variation == 0)
R_var_min = 3;
kvco_var_min = 3;
C_var_min = 3;
Icp_var_min = 3;
elseif(comp_variation == 10)
R_var_min = 1;
kvco_var_min = 1;
C_var_min = 1;
Icp_var_min = 1;
elseif(comp_variation == 1)
R_var_min = 1;
kvco_var_min = 3;
C_var_min = 3;
Icp_var_min = 3;
elseif(comp_variation == 11)
R_var_min = 3;
kvco_var_min = 1;
C_var_min = 1;
Icp_var_min = 1;
elseif(comp_variation == 2)
R_var_min = 3;
kvco_var_min = 1;
C_var_min = 3;
Icp_var_min = 3;
elseif(comp_variation == 12)
R_var_min = 1;
kvco_var_min = 3;
C_var_min = 1;
Icp_var_min = 1;
elseif(comp_variation == 3)
R_var_min = 3;
kvco_var_min = 3;
C_var_min = 1;
Icp_var_min = 3;
elseif(comp_variation == 13)
R_var_min = 1;
kvco_var_min = 1;
C_var_min = 3;
Icp_var_min = 1;
elseif(comp_variation == 4)
R_var_min = 3;
kvco_var_min = 3;
C_var_min = 3;
Icp_var_min = 1;
elseif(comp_variation == 14)
R_var_min = 1;
kvco_var_min = 1;
C_var_min = 1;
Icp_var_min = 3;
elseif(comp_variation == 5)
R_var_min = 1;
kvco_var_min = 3;
C_var_min = 1;
Icp_var_min = 1;
end
VCO_noise_sw = 1;
div_noise_sw = 1;
pfd_cp_noise_sw = 1;
ref_noise_sw = 0;
% VCO
VCO_noise_file = 'C:\Users\Bhavin\Desktop\share\vcodbc.csv';
VCO_noise_data = dlmread(VCO_noise_file,',');
% VCO_noise = VCO_noise_data(:,2)';
VCO_noise_freq = VCO_noise_data(:,1)';
% Crystal oscillator
crys_osc_noise_file = 'C:\Users\Bhavin\Desktop\share\null.csv';
crys_osc_noise_data = dlmread(crys_osc_noise_file,',');
crys_osc_noise_freq = crys_osc_noise_data(:,1)';
% Divider
div_pnoise_file = 'C:\Users\Bhavin\Desktop\share\null.csv';
div_pnoise_data = dlmread(div_pnoise_file,',');
div_noise_freq = div_pnoise_data(:,1)';
% PFD+CP noise
pfd_cp_noise_file = 'C:\Users\Bhavin\Desktop\share\cpnoise.csv';
pfd_cp_noise_data = dlmread(pfd_cp_noise_file,',');
max_div_noise_freq = max(div_noise_freq);
max_VCO_noise_freq = max(VCO_noise_freq);
max_crys_osc_noise_freq = max(crys_osc_noise_freq);
if((max_div_noise_freq>=max_VCO_noise_freq)&&(max_crys_osc_noise_freq>=max_VCO_nois
e_freq))
eval_freq = VCO_noise_freq;
elseif((max_div_noise_freq<=max_VCO_noise_freq)&&(max_crys_osc_noise_freq>=max_div_
noise_freq))
eval_freq = div_noise_freq;
else
eval_freq = crys_osc_noise_freq;
end
%pfd_cp_noise_data(end+1,1) = eval_freq(end);
%pfd_cp_noise_data(end,2) = pfd_cp_noise_data(end-1,2);
pfd_cp_noise_freq = pfd_cp_noise_data(:,1)';
VCO_noise = interp1(VCO_noise_freq,VCO_noise_data(:,2)',eval_freq);
div_noise = interp1(div_noise_freq,div_pnoise_data(:,2)',eval_freq);
pfd_cp_noise = interp1(pfd_cp_noise_freq,pfd_cp_noise_data(:,2)',eval_freq);
crys_osc_noise = interp1(crys_osc_noise_freq,crys_osc_noise_data(:,2)',eval_freq);
loop_count = 0;
no_of_comp = (length(R_var)-R_var_min+1)*(length(kvco_var)-kvco_var_min+1);
fig_legend = cell(no_of_comp,1);
%% Computations
for(var_R=R_var_min:length(R_var))
for(var_kvco=kvco_var_min:length(kvco_var))
for(var_C=C_var_min:length(C1_var))
for(var_Icp=Icp_var_min:length(Icp_var))
% Loop filter
Z = tf((1/(C1+C2))*[tau_z 1],[tau_p 1 0]);
R_noise = 2*kb*T*R;
vlpn_by_vn = tf([C1/(C1+C2)],[tau_p 1]);
NTF_lp = Closed_loop_gain*(2*pi/Icp)*(vlpn_by_vn/Z);
Out_noise_R_comp =
power(abs(freqresp(NTF_lp,2*pi*eval_freq)),2)*R_noise;
% figure(var_R*100+var_kvco*10+4)
% bode(NTF_lp)
% figure(var_R*100+var_kvco*10+3)
for i=1:length(Out_noise_R_comp)
Out_noise_R(1,i) = Out_noise_R_comp(:,:,i);
end
Out_noise_R = 10*log10(Out_noise_R);
if(fig_on == 1)
figure(3)
semilogx(eval_freq,Out_noise_R);
hold on
end
% VCO
NTF_VCO = 1/(1+Loop_gain);
NTF_VCO_amp_sq = power(abs(freqresp(NTF_VCO,2*pi*eval_freq)),2);
% figure(var_R*100+var_kvco*10+5)
% bode(NTF_VCO)
% figure(var_R*100+var_kvco*10+6)
for i=1:length(NTF_VCO_amp_sq)
Out_noise_VCO(1,i) = 10*log10(NTF_VCO_amp_sq(:,:,i))
+VCO_noise(1,i);
end
if(VCO_noise_sw<1)
Out_noise_VCO = ones(1,length(Out_noise_VCO))*(-200);
end
if(fig_on == 1)
figure(6)
semilogx(eval_freq,Out_noise_VCO);
hold on
end
% Divider
NTF_div = Closed_loop_gain;
NTF_div_amp_sq = power(abs(freqresp(NTF_div,2*pi*eval_freq)),2);
for i=1:length(NTF_div_amp_sq)
Out_noise_div(1,i) = 10*log10(NTF_div_amp_sq(:,:,i))
+div_noise(1,i);
end
if(div_noise_sw<1)
Out_noise_div = ones(1,length(Out_noise_div))*(-200);
end
if(fig_on == 1)
figure(7)
semilogx(eval_freq,Out_noise_div);
hold on
end
% Reference clock
NTF_ref = Closed_loop_gain;
NTF_ref_amp_sq = power(abs(freqresp(NTF_ref,2*pi*eval_freq)),2);
for i=1:length(NTF_ref_amp_sq)
Out_noise_ref(1,i) = 10*log10(NTF_ref_amp_sq(:,:,i))
+crys_osc_noise(1,i);
end
if(ref_noise_sw<1)
Out_noise_ref = ones(1,length(Out_noise_ref))*(-200);
end
if(fig_on == 1)
figure(10)
semilogx(eval_freq,Out_noise_ref);
hold on
end
% PFD+CP
NTF_pfd_cp = Closed_loop_gain*(2*pi/Icp);
NTF_pfd_cp_amp_sq =
power(abs(freqresp(NTF_pfd_cp,2*pi*eval_freq)),2);
for i=1:length(NTF_pfd_cp_amp_sq)
Out_noise_pfd_cp(1,i) =
10*log10(NTF_pfd_cp_amp_sq(:,:,i)*pfd_cp_noise(1,i));
end
if(pfd_cp_noise_sw<1)
Out_noise_pfd_cp = ones(1,length(Out_noise_pfd_cp))*(-200);
end
if(fig_on == 1)
figure(8)
semilogx(eval_freq,Out_noise_pfd_cp);
hold on
end
semilogx(eval_freq,10*log10(power(10,Out_noise_R./10)),'linewidth',2);
grid on
hold on
semilogx(eval_freq,10*log10(power(10,Out_noise_VCO./10)),'linewidth',2);
semilogx(eval_freq,10*log10(power(10,Out_noise_div./10)),'linewidth',2);
semilogx(eval_freq,10*log10(power(10,Out_noise_pfd_cp./10)),'linewidth',2);
semilogx(eval_freq,10*log10(power(10,Out_noise_ref./10)),'linewidth',2);
semilogx(eval_freq,total_noise,'linewidth',2);
end
end
end
end
end
if(fig_on == 1)
figure(3)
title('Loop filter noise');
hold off
legend(fig_legend);
figure(6)
title('VCO noise');
hold off
legend(fig_legend);
figure(7)
title('Divider noise');
hold off
legend(fig_legend);
figure(8)
title('PFD+CP noise');
hold off
legend(fig_legend);
figure(9)
title('VCO + Loop filter + Divider noise + PFD + CP');
hold off
figure(10)
title('Reference noise');
hold off
legend(fig_legend);
figure(20)
title('Phase noise at PLL output');
hold off
legend('Loop filter resistor noise','VCO noise','Divider noise','PFD + Charge
pump noise','Reference noise','Total noise');
end
%max_noise_at_2M = max(noise_at_2M);
%index_max_noise = find(noise_at_2M == max(noise_at_2M));
%str = sprintf('\n\nMax. noise at 2MHz : %f in run
%d',max_noise_at_2M,index_max_noise);
%disp(str);
%min_phase_margin = min(Phase_margin);
%index_min_pm = find(Phase_margin == min_phase_margin);
%str = sprintf('Min. phase margin : %f in run %d',min_phase_margin,index_min_pm);
%disp(str);
%min_Bandwidth = min(Bandwidth);
%index_min_bw = find(Bandwidth == min_Bandwidth);
%str = sprintf('Min. bandwidth(kHz) : %f in run %d',min_Bandwidth,index_min_bw);
%disp(str);
%max_Bandwidth = max(Bandwidth);
%index_max_bw = find(Bandwidth == max_Bandwidth);
%str = sprintf('Max. bandwidth(kHz) : %f in run %d',max_Bandwidth,index_max_bw);
%disp(str);
%max_ref_spur = max(spur);
%index_max_ref_spur = find(spur == max_ref_spur);
%str = sprintf('Max. ref spur : %f in run %d',max_ref_spur,index_max_ref_spur);
%disp(str);
str = sprintf('R = %.2fk, C1 = %.2fp, C2 = %.2fp, Icp = %.2fu',R_nom/1e3,C1_nom/1e-
12,C2_nom/1e-12,Icp_nom/1e-6);
disp(str);