%%% Run parameters % TX M = 4; fsym = 112e9; apply_pulsef = 1; fdac = 256e9; fadc = 256e9; random_key = 2; rcalpha = 0.05; kover = 16; vbias_rel = 0.5; u_pi = 2.9; vbias = -vbias_rel*u_pi; laser_wavelength = 1290; laser_linewidth = 0; % Channel link_length = 10000; vnle_order1 = 50; vnle_order2 = 3; vnle_order3 = 3; vnle_order=[vnle_order1,vnle_order2,vnle_order3]; dfe_order = [0 0 0]; alpha = 0; len_tr = 4096*2; mu_ffe1 = 0.0001; mu_ffe2 = 0.0008; mu_ffe3 = 0.001; mu_dc = 0.005; % mu_dc = 0; mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3]; mu_dfe = 0.0004; dfe_ = sum(dfe_order)>0; doub_mode = db_mode.no_db; rop = [-8]; bwl = [0.5:0.1:1.5]; fsym = [128:16:170].*1e9; ber_vnle = []; ber_mlse = []; ber_viterbi = []; ber_db = []; ber_db_diff_precoded = []; gmi_vnle = []; gmi_mlse = []; gmi_mlse_db = []; for r = 1:length(fsym) Pform = Pulseformer("fsym",fsym(r),"fdac",4*fsym(r),"pulse","rc","pulselength",16,"alpha",rcalpha); db_precode = 0; db_encode = 0; duob_mode = db_mode.no_db; apply_pulsef = 1; [Digi_sig,Symbols,Tx_bits] = PAMsource(... "fsym",fsym(r),"M",M,"order",18,"useprbs",0,... "fs_out",fdac,... "applyclipping",0,"clipfactor",1.5,... "applypulseform",apply_pulsef,"pulseformer",Pform,... "randkey",random_key,... "db_precode",db_precode,"db_encode",db_encode,... "mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process(); % Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',0); %%%%% AWG % El_sig = M8199A("kover",kover).process(Digi_sig); El_sig = AWG("fdac",fdac,"f_cutoff",fsym(r),"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig); % El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',0); % El_sig = El_sig.setPower(0,"dBm"); %%%%% Low-pass el. components %%%%%% % f_nyquist = fsym/2; % tx_bwl = tx_bw_nyquist.*f_nyquist; tx_bwl = 50e9; El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig); % El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',1); %%%%% Electrical Driver Amplifier %%%%%% El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig); El_sig = El_sig.normalize("mode","oneone"); %%%%% MODULATE E/O CONVERSION %%%%%% [Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",laser_wavelength,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",random_key+1).process(El_sig); Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",link_length/1000,"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig); %%%%%% ROP %%%%%% Rx_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop).process(Opt_sig); %%%%%% PD Square Law %%%%%% Rx_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11).process(Rx_sig); %%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%% % rx_bwl = rx_bw_nyquist.*f_nyquist; rx_bwl = 50e9; Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(Rx_sig); % %%%%%% Low-pass Scope %%%%%% Lp_scpe = Filter('filtdegree',4,"f_cutoff",110e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true); % Rx_sig.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1); % %%%%%% Scope %%%%%% Scpe_sig = Scope("fsimu",fdac*kover,"fadc",fadc,... "delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,... "samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,... "adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',0,'H_lpf',Lp_scpe).process(Rx_sig); Scpe_sig_resampled = Scpe_sig.resample("fs_out",2*fsym(r)); % Scpe_sig_resampled.signal = Scpe_sig_resampled.signal(1:2*length(Symbols)); [~, Scpe_cell, ~, found_sync] = Scpe_sig_resampled.tsynch("reference", Symbols, "fs_ref", fsym(r), "debug_plots", 1); % Scpe_cell = cell(1); % Scpe_cell{1} = Scpe_sig_resampled; Scpe_cell{1}.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1); eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"Nb",[dfe_order],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1); mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels); if 0 %Duobinary Targeting db_ref_sequence = Duobinary().encode(Symbols); db_ref_constellation = unique(db_ref_sequence.signal); [eq_signal, eq_noise] = eq_.process(Scpe_cell{1},db_ref_sequence); mlse_.DIR = [1,1]; [mlse_sig_sd,LLR,gmi_mlse_db(r)] = mlse_.process(eq_signal,Symbols); mlse_sig_hd = PAMmapper(M,0,"eth_style",0).quantize(mlse_sig_sd); mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M); mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M); tx_symbols_precoded = Duobinary().encode(Symbols); tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded); tx_bits_precoded = PAMmapper(M,0,"eth_style",0).demap(tx_symbols_precoded); rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_precoded); [~,errors_db_diff_precoded,ber_db_diff_precoded(r),~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); %B) Just determine BER rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd); [bits_mlse,errors_mlse,ber_db(r),~] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); end % FFE or VNLE eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"Nb",[dfe_order],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1); [eq_signal_sd, eq_noise] = eq_.process(Scpe_cell{1}, Symbols); [gmi_gomez(r)] = calc_air(eq_signal_sd, Symbols, "skip_front", 100, "skip_end", 100); [gmi_vnle(r)] = calc_ngmi(eq_signal_sd,Symbols); [gmi_bitwise(r)] = calc_gmi_bitwise(eq_signal_sd,Symbols); snr_vnle(r) = calc_snr(Symbols, eq_signal_sd-Symbols); eq_signal_sd.plot("displayname",'bla','fignum',118); % Hard decision on VNLE output eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd); rx_bits = PAMmapper(M,0,"eth_style",0).demap(eq_signal_hd); [~,~,ber_vnle(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); fprintf('BER VNLE: %.2e \n',ber_vnle(r)); fprintf('NGMI VNLE: %.2f \n',gmi_vnle(r)./log2(M)); if 1 % Process through postfilter and MLSE pf_ncoeffs = 1; pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); [mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise); mlse_.DIR = pf_.coefficients; alpha(r) = pf_.coefficients(2); [signalclass_hd,LLR,gmi_mlse(r)] = mlse_.process(mlse_sig_sd,Symbols); mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(signalclass_hd); rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd); [~,~,ber_mlse(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); fprintf('BER: %.2e \n',ber_mlse(r)); fprintf('GMI MLSE: %.5f \n',gmi_mlse(r)); % Process through postfilter and MLSE pf_ncoeffs = 1; pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); [mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise); mlse_.DIR = pf_.coefficients; mlse_sig_sd = mlse_.process(mlse_sig_sd); mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(mlse_sig_sd); rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd); [~,~,ber_viterbi(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); fprintf('Viterbi BER: %.2e \n',ber_viterbi(r)); end end cols = cbrewer2('Paired',8); d = 1; figure(11);hold on plot(fsym.*1e-9,alpha,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:)); xlabel('Baudrate in GBd'); ylabel('alpha'); figure(15);hold on plot(fsym.*1e-9,gmi_gomez,'DisplayName','gomez','Marker','x','LineStyle','-','Color',cols(1+d,:)); plot(fsym.*1e-9,gmi_vnle,'DisplayName','vnle other','Marker','x','LineStyle','-','Color',cols(3+d,:)); plot(fsym.*1e-9,gmi_bitwise,'DisplayName','bitwise','Marker','x','LineStyle','--','Color',cols(5+d,:)); plot(fsym.*1e-9,gmi_mlse,'DisplayName','MLSE','Marker','*'); ylim([0 2.6]); xlabel('Baudrate in GBd'); ylabel('GMI'); figure(13);hold on plot(fsym.*1e-9,ber_vnle,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:)); plot(fsym.*1e-9,ber_mlse,'DisplayName','MLSE','Marker','x','LineStyle','-','Color',cols(3+d,:)); plot(fsym.*1e-9,ber_viterbi,'DisplayName','Viterbi','Marker','x','LineStyle','--','Color',cols(5+d,:)); % plot(bwl,ber_db_diff_precoded,'DisplayName','MLSE db diff','Marker','.','MarkerSize',15,'LineStyle','-'); % plot(bwl,ber_db,'DisplayName','MLSE db','Marker','.','MarkerSize',15,'LineStyle','-'); xlabel('Baudrate in GBd'); ylabel('BER'); set(gca, 'yscale', 'log'); % ylim([1e-6 0.1]); legend % Auxiliary nested helper for numerically stable log-sum-exp function s = logsumexp(a) % LOGSUMEXP Compute log(sum(exp(a))) in a numerically stable way m = max(a); s = m + log(sum(exp(a - m))); end