125 lines
4.2 KiB
Matlab
125 lines
4.2 KiB
Matlab
%% ============================================================
|
|
% SNR vs Optical Input Power (dBm) — Shot vs Thermal vs Combined
|
|
% - Generate optical field as sine with target RMS power (verified)
|
|
% - Magnitude-square detection -> optical power
|
|
% - Photocurrent = Rd * P
|
|
% - Add shot noise + thermal noise (white, PSD-based)
|
|
% - Compute SNR for: shot-only, thermal-only, combined
|
|
% ============================================================
|
|
|
|
|
|
% Constants
|
|
k = Constant.Boltzmann;
|
|
q = Constant.ElementaryCharge;
|
|
|
|
% Receiver / PD parameters
|
|
T = 20 + 273.15; % K
|
|
R = 50; % Ohm (front-end/load)
|
|
Rd = 0.7; % A/W (responsivity)
|
|
Be = 100e9; % Hz (electrical noise bandwidth)
|
|
Id = 0; % A (dark current, optional)
|
|
|
|
% Sampling for time-domain demo (needs to be >> Be)
|
|
fs = 1e12; % Hz
|
|
N = 2^14; % samples
|
|
t = (0:N-1).'/fs;
|
|
|
|
% Choose an electrical tone within bandwidth (arbitrary for demo)
|
|
f0 = 10e9; % Hz
|
|
|
|
% Thermal current PSD (two-sided) and variance in Be
|
|
Si_th = 4*k*T/R; % A^2/Hz (two-sided)
|
|
sigma2_th = Si_th * Be; % A^2
|
|
sigma_th = sqrt(sigma2_th); % A_rms
|
|
|
|
% Optical input power sweep (in dBm)
|
|
P_dBm = linspace(-40, 10, 300);
|
|
P_W = 10.^((P_dBm - 30)/10); % W
|
|
|
|
% Pre-allocate results
|
|
SNR_shot_dB = zeros(size(P_dBm));
|
|
SNR_th_dB = zeros(size(P_dBm));
|
|
SNR_tot_dB = zeros(size(P_dBm));
|
|
|
|
% --- Main loop over optical input power
|
|
for ii = 1:numel(P_W)
|
|
Pavg = P_W(ii);
|
|
|
|
% Optical field with RMS power = Pavg:
|
|
% Let x(t) be the optical field amplitude such that |x|^2 has mean Pavg.
|
|
% Use a sinusoid: x(t) = A*sin(2*pi*f0*t), then mean(|x|^2)=A^2/2.
|
|
A = sqrt(2*Pavg); % -> mean(|x|^2) = Pavg
|
|
|
|
x = A * sin(2*pi*f0*t); % "optical field" (real for simplicity)
|
|
|
|
% Verify RMS/mean power numerically (optional)
|
|
P_meas = mean(abs(x).^2); % should be ~ Pavg
|
|
|
|
a = P_meas - Pavg;
|
|
assert(a<1);
|
|
|
|
% Magnitude-square detection -> optical power waveform
|
|
Popt = abs(x).^2; % W (instantaneous)
|
|
|
|
% Photocurrent waveform (includes DC + 2f0 component for this demo)
|
|
I_sig = Rd * Popt; % A
|
|
|
|
% Define "signal power" as the mean-squared photocurrent due to signal
|
|
% (for this sine-squared waveform, it's OK for a demo SNR definition)
|
|
P_sig = mean(I_sig.^2);
|
|
|
|
% -------- Shot noise (white) --------
|
|
% Two-sided PSD: Si_shot = 2*q*(I_photo + I_dark)
|
|
% For this demo, use average current to set the white-noise level:
|
|
Ibar = mean(I_sig) + Id;
|
|
Si_shot = 2*q*Ibar; % A^2/Hz
|
|
sigma2_sh = Si_shot * Be; % A^2
|
|
sigma_sh = sqrt(sigma2_sh); % A_rms
|
|
|
|
n_sh = sigma_sh * randn(N,1); % time-domain shot noise
|
|
|
|
% -------- Thermal noise (white Gaussian) --------
|
|
n_th = sigma_th * randn(N,1); % time-domain thermal noise
|
|
|
|
% Noise powers (mean-square) in time domain
|
|
Pn_sh = mean(n_sh.^2);
|
|
Pn_th = mean(n_th.^2);
|
|
Pn_tot = mean((n_sh + n_th).^2); % ~ Pn_sh + Pn_th (independent)
|
|
|
|
% SNRs
|
|
SNR_shot = P_sig / Pn_sh;
|
|
SNR_th = P_sig / Pn_th;
|
|
SNR_tot = P_sig / Pn_tot;
|
|
|
|
SNR_shot_dB(ii) = 10*log10(SNR_shot);
|
|
SNR_th_dB(ii) = 10*log10(SNR_th);
|
|
SNR_tot_dB(ii) = 10*log10(SNR_tot);
|
|
|
|
% Optional sanity check (can comment out)
|
|
% if ii == 1
|
|
% fprintf('Check Pavg target/meas: %.3g W / %.3g W\n', Pavg, P_meas);
|
|
% end
|
|
end
|
|
|
|
% Plot comparison
|
|
figure(1); clf; hold on;
|
|
plot(P_dBm, SNR_shot_dB, 'LineWidth', 1.5);
|
|
plot(P_dBm, SNR_th_dB, 'LineWidth', 1.5);
|
|
plot(P_dBm, SNR_tot_dB, 'LineWidth', 1.5);
|
|
grid on;
|
|
xlabel('Optical input power [dBm]');
|
|
ylabel('SNR [dB]');
|
|
title('SNR vs Optical Input Power: Shot vs Thermal vs Combined');
|
|
legend('Shot-noise only','Thermal-noise only','Shot + Thermal','Location','best');
|
|
|
|
% Print example at 0 dBm
|
|
[~,idx0] = min(abs(P_dBm - 0));
|
|
fprintf('At 0 dBm:\n');
|
|
fprintf(' SNR (shot only) = %.2f dB\n', SNR_shot_dB(idx0));
|
|
fprintf(' SNR (thermal only) = %.2f dB\n', SNR_th_dB(idx0));
|
|
fprintf(' SNR (combined) = %.2f dB\n', SNR_tot_dB(idx0));
|
|
|
|
% Also print NEP based on thermal PSD (constant NEP_th)
|
|
NEP_th = sqrt(Si_th)/Rd; % W/sqrt(Hz)
|
|
fprintf('Thermal NEP = %.3g W/sqrt(Hz)\n', NEP_th);
|