%========================================================================== % High-Speed Link Modell (Dispersion + Reflexionen + Crosstalk) % Eigenständiges MATLAB-Skript mit Testsequenz (PRBS), Kanalmodell im f-Bereich % und Auswertung (Eye + Spektren). % % Idee: % - Hauptkanal: H11(f) = exp(-gamma(f)*l) % - Crosstalk: H21(f) = k_xt * j*(f/fc) / (1 + j*(f/fc)) * exp(-gamma_xt(f)*l) % (Highpass-artig: typisches FEXT-ähnliches Verhalten; simpel aber nützlich) % - Reflexionen: optionaler 2-Tap Echo-Term (vereinfachtes Stub/Mismatch-Modell) % % Keine Toolboxes zwingend nötig (außer eye diagram -> optional). %========================================================================== clear; close all; clc; %% ----------------------- Simulationseinstellungen ----------------------- Rb = 10e9; % Bitrate [b/s] UI = 1/Rb; % Unit Interval [s] os = 32; % Oversampling Fs = Rb*os; % Abtastrate [Hz] Ts = 1/Fs; Nbits = 4096; % Anzahl Bits pro Lane A = 1.0; % NRZ-Amplitude (0/1 -> +/-A) % PRBS-Seed rng(1); %% ----------------------- Testsequenzen (Aggressor + Victim) ------------- % Victim-Lane Daten b_v = randi([0 1], Nbits, 1); x_v = A*(2*b_v - 1); % NRZ: -A/+A % Aggressor-Lane Daten (unabhängig) b_a = randi([0 1], Nbits, 1); x_a = A*(2*b_a - 1); % Upsampling (NRZ-Rechteck) x_v_up = upsample(x_v, os); x_a_up = upsample(x_a, os); % Simple Zero-Order Hold (rechteckig halten) x_v_up = filter(ones(os,1), 1, x_v_up); x_a_up = filter(ones(os,1), 1, x_a_up); % Am Anfang Filter-Transient entfernen / zentrieren x_v_up = x_v_up(os:end); x_a_up = x_a_up(os:end); % Signal-Länge N = length(x_v_up); % Optional: leichte TX-RiseTime-Abbildung (1st order LP) % (hilft, unrealistische unendliche Bandbreite zu vermeiden) f_tx_3dB = 0.35/(35e-12); % grob: 35ps 10-90% -> f3dB ~ 0.35/tr [x_v_up, x_a_up] = apply_1pole_lp(x_v_up, x_a_up, Fs, f_tx_3dB); %% ----------------------- Frequenzachse (FFT) ---------------------------- % FFT-Länge als Power-of-two (schneller, weniger Circular-Artefakte) Nfft = 2^nextpow2(N*2); f = (0:Nfft-1).'*Fs/Nfft; % 0 ... Fs*(1-1/Nfft) % Für Transferfunktionen brauchen wir auch negative Frequenzen implizit: % MATLAB-FFT nutzt diese Darstellung automatisch, solange H hermitesch ist. % Wir definieren H für alle FFT-Bins konsistent mit reellen Signalen. %% ----------------------- RLGC-Modell (Dispersion & Loss) ----------------- % Leitungslänge l = 0.40; % [m] % Per-unit-length Parameter (Beispielwerte, grob PCB-ähnlich) L = 3.2e-7; % [H/m] C = 1.6e-10; % [F/m] G0 = 0; % [S/m] (DC) tanD = 0.012; % Verlustfaktor (vereinfachtes Dielektrikum-Modell) % G(f) ~ omega*C*tanD omega = 2*pi*f; G = G0 + omega.*C*tanD; % Skin-Effekt / Rauheit: R(f) ~ Rdc + k*sqrt(f) Rdc = 0.05; % [Ohm/m] kR = 0.20; % [Ohm/m/sqrt(Hz)] * sqrt(Hz) -> Ohm/m R = Rdc + kR*sqrt(max(f,1)); % max(..,1) vermeidet sqrt(0) % gamma(f) und Z0(f) gamma = sqrt( (R + 1j*omega*L) .* (G + 1j*omega*C) ); % [1/m] Z0 = sqrt( (R + 1j*omega*L) ./ (G + 1j*omega*C) ); % [Ohm] % Hauptpfad-Transferfunktion (perfekt terminiert) H11 = exp(-gamma*l); %% ----------------------- Crosstalk-Modell (Aggressor -> Victim) ---------- % Sehr vereinfachtes FEXT-ähnliches Modell: wächst mit f, sättigt k_xt = 0.04; % Crosstalk-Stärke (skalieren) fc = 8e9; % Eckfrequenz der Koppelcharakteristik % optional etwas andere Verluste auf dem Koppelpfad gamma_xt = gamma .* (1.05 + 0.00j); Hxt_shape = (1j*(f/fc)) ./ (1 + 1j*(f/fc)); % ~ Highpass H21 = k_xt .* Hxt_shape .* exp(-gamma_xt*l); %% ----------------------- Reflexions/Echo-Modell (optional) --------------- % Einfache 2-Tap-Approximation: Hecho = 1 + a*exp(-j*2*pi*f*tau) % (z.B. Stub/Via-Resonanz als Echo) useEcho = true; a_echo = 0.18; % Echo-Amplitude (|a|<1) tau = 120e-12; % Echo-Delay [s] if useEcho Hecho = 1 + a_echo*exp(-1j*2*pi*f*tau); H11 = H11 .* Hecho; end %% ----------------------- Kanal-Anwendung per FFT ------------------------- % Zero-padding auf Nfft Xv = fft(x_v_up, Nfft); Xa = fft(x_a_up, Nfft); % Victim-Ausgang = Hauptpfad * Victim + Crosstalkpfad * Aggressor Yv = H11 .* Xv + H21 .* Xa; y_v = real(ifft(Yv, Nfft)); y_v = y_v(1:N); % zurück auf Originallänge %% ----------------------- Auswertung: Eye Diagramm ------------------------ % Eye über viele UIs (ohne Toolbox: eigene Darstellung) plot_eye(y_v, os, 2); % 2 UI Breite %% ----------------------- Auswertung: Frequenzgänge ----------------------- figure('Name','Transferfunktionen'); subplot(2,1,1); plot(f/1e9, 20*log10(abs(H11)+1e-15)); grid on; xlabel('f [GHz]'); ylabel('|H_{11}| [dB]'); title('Hauptkanal (inkl. Dispersion/Loss + optional Echo)'); subplot(2,1,2); plot(f/1e9, 20*log10(abs(H21)+1e-15)); grid on; xlabel('f [GHz]'); ylabel('|H_{21}| [dB]'); title('Crosstalk-Pfad (Aggressor -> Victim)'); %% ----------------------- Optional: Bitfehlersicht / Sampling ------------- % Einfaches Sampling in der UI-Mitte (ohne Taktwiedergewinnung) % (nur grobe Demo, kein echter CDR) sampleOffset = round(os/2); idx = sampleOffset:os:(sampleOffset + (Nbits-2)*os); samples = y_v(idx); % Hard Decision bh = samples > 0; ber = mean(bh(:) ~= b_v(1:length(bh))); fprintf('--- Ergebnis ---\n'); fprintf('Bitrate: %.2f Gb/s, Oversampling: %d, Fs: %.2f GHz\n', Rb/1e9, os, Fs/1e9); fprintf('Echo: %d (a=%.3f, tau=%.1f ps)\n', useEcho, a_echo, tau*1e12); fprintf('Crosstalk k_xt=%.3f, fc=%.2f GHz\n', k_xt, fc/1e9); fprintf('Grobe BER (ohne CDR/EQ): %.3e\n', ber); %========================================================================== % Lokale Hilfsfunktionen %========================================================================== function [x1o, x2o] = apply_1pole_lp(x1, x2, Fs, f3dB) % 1. Ordnung Tiefpass als TX-Bandbegrenzung (optional) if isempty(f3dB) || f3dB<=0 x1o = x1; x2o = x2; return; end w = 2*pi*f3dB; a = exp(-w/Fs); b = 1-a; x1o = filter(b, [1 -a], x1); x2o = filter(b, [1 -a], x2); end function plot_eye(y, os, nUI) % Eye-Diagramm ohne Toolbox: Segmente von nUI*os sampeln und überlagern Lseg = nUI*os; nSeg = floor(length(y)/os) - nUI - 2; if nSeg < 10 warning('Zu wenig Daten für Eye.'); return; end figure('Name','Eye Diagramm'); hold on; grid on; t = (0:Lseg-1)/os; % in UI for k = 1:nSeg i0 = (k-1)*os + 1; seg = y(i0:i0+Lseg-1); plot(t, seg); end xlabel('Zeit [UI]'); ylabel('Amplitude [V (rel.)]'); title(sprintf('Eye Diagramm (Breite = %d UI, Oversampling = %d)', nUI, os)); end