WIP - implementation and debugging of 224 Gbd PAM4 system

This commit is contained in:
Silas Oettinghaus
2023-05-17 14:47:56 +02:00
parent c8f1ee17e9
commit 8d098a6c80
12 changed files with 274 additions and 254 deletions

View File

@@ -18,7 +18,6 @@ classdef AWG
lpf_active = 0;
lpf_type ;
f_cutoff ;
lowpass ;
signal_length;
H_lpf;
@@ -32,7 +31,7 @@ classdef AWG
% Detailed explanation goes here
arguments
options.preset = [] ;
options.preset = [] ;
options.kover = 16;
options.repetitions = 1;
options.normalize = 1;
@@ -41,62 +40,57 @@ classdef AWG
options.dac_min = -0.5;
options.dac_max = 0.5;
options.skew_active = 0;
options.awg_skew = 0;
options.awg_skew = 0;
options.lpf_active = 0;
options.lpf_type = 0;
options.f_cutoff = 32e9;
options.lowpass = 1;
end
if isempty(options.preset)
obj.skew_active = 0;
obj.lpf_active = 0;
fn = fieldnames(options);
for n = 1:numel(fn)
try
obj.(fn{n}) = options.(fn{n});
end
end
elseif options.preset == "M8196A"
if options.preset == "M8196A"
% M8196A (92GBd) https://www.keysight.com/us/en/product/M8196A/92-gsa-s-arbitrary-waveform-generators.html
obj.dac_max = 0.5;
obj.dac_min = -.5;
obj.lowpass = 1; %LP
obj.f_cutoff = 50e9;
elseif options.preset == "M8199B"
%https://www.keysight.com/us/en/assets/3120-1465/data-sheets/M8199A-128-256-GSa-s-Arbitrary-Waveform-Generator.pdf
% obj.fdac = 256e9;
obj.dac_max = 0.5;
obj.dac_min = -.5;
obj.f_cutoff = 80e9;
end
obj.kover = options.kover; %oversampling factor e.g. 16
obj.repetitions = options.repetitions; %repeat the signal to generate a longer sequence?
obj.fdac = options.fdac;
obj.normalize = options.normalize;%want to normalize at first? either 0 or 1
obj.bit_resolution = options.bit_resolution;%bit res. of quantizer (e.g. 5 bit)
obj.dac_min = options.dac_min;
obj.dac_max = options.dac_max;
obj.lpf_active = options.lpf_active;
obj.skew_active = options.skew_active;
obj.awg_skew = options.awg_skew;
end
function signalclass_out = process(obj,signalclass_in)
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% 4. Apply LPF on the signal
if obj.lpf_active
lpf = Filter('filtdegree',4,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",filtertypes.bessel_inp);
lpf = Filter('filtdegree',5,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",obj.lpf_type);
signalclass_in = lpf.process(signalclass_in);
end
% cast the inform. signal to electrical signal
% cast the inform. signal to electrical signal
signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook);
% append to logbook
% append to logbook
signalclass_in = signalclass_in.logbookentry();
% write to output
% write to output
signalclass_out = signalclass_in;
end
@@ -106,25 +100,24 @@ classdef AWG
% Detailed explanation goes here
arguments(Input)
obj
data_in
data_in
end
arguments(Output)
elec_out
elec_out
end
obj.signal_length = length(data_in);
if obj.normalize
% 5.1. Normalize the signal to 1 Vpp and set the amplitude of the signal
% 0a Normalize the signal to 1 Vpp and set the amplitude of the signal
data_in = data_in/(max(data_in)-min(data_in));
else
% 5.1. Cut the Signal at -1 and 1 and scale to amplitude
% 0b Cut the Signal at -1 and 1 and scale to amplitude
data_in(data_in > 1) = 1;
data_in(data_in < -1) = -1;
end
% 1. Quantize the signal
if obj.bit_resolution>0
elec_out = obj.quantization(data_in) ;
@@ -139,9 +132,7 @@ classdef AWG
% 3. Add skew
if obj.skew_active
elec_out = obj.skew(elec_out);
end
end
end
@@ -194,92 +185,5 @@ classdef AWG
end
function lpf_out = lpf(obj,x_in)
lpf_out = ifft(obj.H_lpf.*fft(x_in));
end
function H = buildFilter(obj,filterType)
filtdegree = 3;
fsimu = obj.kover*obj.fdac;
rp = 0.5; %passband ripple
rs = 0.5; %stopband ripple
switch filterType
case 1
% Bessel filter, impulse invariant transformed
[B, A] = besself(filtdegree, 2*pi*obj.f_cutoff);
[B ,A] = impinvar(B,A,fsimu);
case 2
% Bessel filter, impulse bilinear transformed
[Z, P, K] = besself(filtdegree, 2*pi*obj.f_cutoff);
[Z ,P, K] = bilinear(Z,P,K,fsimu);
[B ,A] = zp2tf(Z ,P ,K);
case 3
% Butterworth filter
if obj.lowpass == 1 %lowpass
[B, A] = butter(filtdegree, obj.f_cutoff/(fsimu/2),'low');
else % highpass
[B, A] = butter(filtdegree, obj.f_cutoff/(fsimu/2),'high');
end
case 4
% Chebyshev 1 filter
[B, A] = cheby1(filtdegree,rp, obj.f_cutoff/(fsimu/2));
case 5
% Chebyshev 2 filter
[B, A] = cheby2(filtdegree,rs, obj.f_cutoff/(fsimu/2));
case 6
% Elliptic filter
[B, A] = ellip(filtdegree,rp,rs,obj.f_cutoff/(fsimu/2));
case 7
% Hamming filter
g=(filtdegree-1)/2;
wc=obj.f_cutoff/(fsimu/2);
B = wc*sinc(wc*(-g:g)).*hamming(filtdegree)';
A=1;
case 8
% Raised Cosine filter
B = firrcos(filtdegree,obj.f_cutoff,para.df,fsimu);
A=1;
case 9
% Sinc filter
g=(filtdegree-1)/2;
wc=obj.f_cutoff/(fsimu/2);
B = wc*sinc(wc*(-g:g));
A=1;
end
H = freqz(B, A, obj.repetitions*obj.kover*obj.signal_length,'whole');
end
end
end