140 lines
5.7 KiB
Matlab
140 lines
5.7 KiB
Matlab
clear; clc;
|
|
|
|
M = 4;
|
|
randkey = 1;
|
|
duob_mode = db_mode.no_db;
|
|
|
|
mlse = 1;
|
|
dbtgt = 1;
|
|
|
|
baudrates = 180e9:2e9:220e9; % outer loop
|
|
rops = linspace(-10,0,12); % inner sweep
|
|
FEC_thr = 3.8e-3; % BER target
|
|
|
|
% --- allocate results
|
|
reqROP_FFE = nan(size(baudrates));
|
|
reqROP_MLSE = nan(size(baudrates));
|
|
reqROP_DBTGT = nan(size(baudrates));
|
|
reqROP_ML_MLSE2 = nan(size(baudrates));
|
|
reqROP_ML_MLSE3 = nan(size(baudrates));
|
|
|
|
%% ====================== OUTER LOOP ======================
|
|
for b = 1:numel(baudrates)
|
|
baudrate = baudrates(b);
|
|
fprintf('\n=== %.0f GBd ===\n', baudrate/1e9);
|
|
|
|
ber_ffe = nan(size(rops));
|
|
ber_mlse = nan(size(rops));
|
|
ber_dbtgt = nan(size(rops));
|
|
ber_ml2 = nan(size(rops));
|
|
ber_ml3 = nan(size(rops));
|
|
|
|
%% -------- inner ROP loop --------
|
|
for i = 1:length(rops)
|
|
rop = rops(i);
|
|
|
|
[Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1] = standard_link_model( ...
|
|
"M",M,"fsym",baudrate,"rop",rop,"laser_linewidth",1310, ...
|
|
"link_length_m",0,"random_key",1);
|
|
|
|
|
|
|
|
%% FFE + MLSE
|
|
if mlse
|
|
pf_ncoeffs = 1;
|
|
ffe_order = [50, 0, 0];
|
|
mu_ffe = [0.0001, 0.0008, 0.001];
|
|
mu_dfe = 0.0004;
|
|
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
|
|
"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005, ...
|
|
"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0, ...
|
|
"plotfinal",0,"ideal_dfe",1);
|
|
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
|
mlse_ = MLSE("duobinary_output",0,'M',M, ...
|
|
'trellis_states',PAMmapper(M,0).levels,'scale_mode',2, ...
|
|
'trellis_exclusion',0,'trellis_state_mode',2,'debug',0, ...
|
|
'DIR',pf_.coefficients);
|
|
|
|
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, ...
|
|
Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ...
|
|
"precode_mode", duob_mode,'showAnalysis', 0, "postFFE", [], ...
|
|
"eth_style_symbol_mapping", 0);
|
|
|
|
ber_ffe(i) = ffe_results.metrics.BER;
|
|
ber_mlse(i) = mlse_results.metrics.BER;
|
|
end
|
|
|
|
%% FFE + duobinary target MLSE
|
|
if dbtgt
|
|
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M, ...
|
|
"trellis_states",PAMmapper(M,0).levels,'scale_mode',2, ...
|
|
'trellis_exclusion',0,'trellis_state_mode',3);
|
|
ffe_order = [50, 0, 0];
|
|
mu_ffe = [0.0001, 0.0008, 0.001];
|
|
mu_dfe = 0.0004;
|
|
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
|
|
"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005, ...
|
|
"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0, ...
|
|
"plotfinal",0,"ideal_dfe",1);
|
|
|
|
dbt_results = duobinary_target(eq_, mlse_db_, M, Rx_sig_2sps_v1, ...
|
|
Symbols_v1, Tx_bits_v1, "precode_mode", duob_mode, ...
|
|
'showAnalysis', 0, "postFFE", []);
|
|
ber_dbtgt(i) = dbt_results.metrics.BER;
|
|
end
|
|
|
|
%% ML-based MLSE (L=2)
|
|
mu_ml = 0.1; training_epochs = 100;
|
|
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
|
|
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
|
|
"traceback_depth",128,"L",2,"delta",4,"adaptive_mu",0);
|
|
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
|
|
ref_bits = PAMmapper(M,0).demap(y_ref);
|
|
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
|
|
[~,~,ber_ml2(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
|
|
"skip_front",10,"skip_end",10);
|
|
|
|
%% ML-based MLSE (L=3)
|
|
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
|
|
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
|
|
"traceback_depth",128,"L",3,"delta",4,"adaptive_mu",0);
|
|
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
|
|
ref_bits = PAMmapper(M,0).demap(y_ref);
|
|
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
|
|
[~,~,ber_ml3(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
|
|
"skip_front",10,"skip_end",10);
|
|
end % ROP loop
|
|
|
|
%% --- find required ROP (FEC crossing)
|
|
reqROP_FFE(b) = interp_fec_cross(rops, ber_ffe, FEC_thr);
|
|
reqROP_MLSE(b) = interp_fec_cross(rops, ber_mlse, FEC_thr);
|
|
reqROP_DBTGT(b) = interp_fec_cross(rops, ber_dbtgt, FEC_thr);
|
|
reqROP_ML_MLSE2(b) = interp_fec_cross(rops, ber_ml2, FEC_thr);
|
|
reqROP_ML_MLSE3(b) = interp_fec_cross(rops, ber_ml3, FEC_thr);
|
|
|
|
% --- diagnostic
|
|
fprintf('Baud %.0f GBd: FFE %.1f, MLSE %.1f, DB %.1f, ML2 %.1f, ML3 %.1f\n', ...
|
|
baudrate/1e9, reqROP_FFE(b), reqROP_MLSE(b), reqROP_DBTGT(b), ...
|
|
reqROP_ML_MLSE2(b), reqROP_ML_MLSE3(b));
|
|
end
|
|
|
|
%% ====================== PLOT REQUIRED ROP ======================
|
|
cols = cbrewer2('Set1',8);
|
|
colFFE = cols(1,:);
|
|
colMLSE = cols(2,:);
|
|
colDBTGT = cols(4,:);
|
|
colML_MLSE = cols(3,:);
|
|
|
|
figure(); hold on
|
|
plot(baudrates/1e9, reqROP_FFE, '-o','Color',colFFE, 'DisplayName','FFE');
|
|
plot(baudrates/1e9, reqROP_MLSE, '-s','Color',colMLSE, 'DisplayName','FFE+PF+MLSE');
|
|
plot(baudrates/1e9, reqROP_DBTGT, '--^','Color',colDBTGT, 'DisplayName','DB tgt. MLSE');
|
|
plot(baudrates/1e9, reqROP_ML_MLSE2, '-v','Color',colML_MLSE, 'DisplayName','ML-based MLSE (L=2)');
|
|
plot(baudrates/1e9, reqROP_ML_MLSE3, '-d','Color',colML_MLSE*0.8,'DisplayName','ML-based MLSE (L=3)');
|
|
|
|
xlabel('Baud rate [GBd]');
|
|
ylabel('Required ROP [dBm]');
|
|
title('ROP required for FEC threshold');
|
|
grid on; legend('Location','northwest');
|
|
beautifyBERplot("logscale",0,"polyfit",1,"polyorder",4,"fitmethod",'polyfit');
|