MATLAB Examples

Eye Diagram Measurements

This example shows how to use the comm.EyeDiagram System object to perform eye diagram measurements on simulated signals.

Contents

Using the comm.EyeDiagram System Object

The comm.EyeDiagram System object collects eye diagram data in the form of vertical and horizontal histograms. We can utilize these histograms to extract quantitative metrics on the system under test. These quantitative metrics are called eye diagram measurements. The following simulation parameters (sample rate, samples per symbol) are chosen to provide a high resolution for the analysis.

% Initialize system parameters
Fs = 10000;             % Sample rate
Rs = 100;               % Symbol rate (Sps)
sps = Fs/Rs;            % Number of samples per symbol
SNR = 30;               % Signal to noise ratio (dB)
Trise = 1/(5*Rs);       % Rise time of the NRZ signal
Tfall = 1/(5*Rs);       % Fall time of the NRZ signal
frameLen = 5000;        % Number of symbols in a frame

The following code generates a binary non-return-to-zero (NRZ) signal utilizing the pattern generator provided in the communication sources package. Then we add additive white Gaussian noise (AWGN) to this signal via an AWGNChannel System object. Next, the time domain signal is plotted. Another way to examine the signal characteristics is to generate the signal's eye diagram using the eye diagram System object. Note that the SymbolsPerTrace property, which represents the number of symbols in a trace of the eye diagram, should be set to two to perform the measurements. The figure on the right shows the eye diagram of the same signal. The specified SampleOffset value is set to ensure that the eye is centered in the figure. For more detail on using the eye diagram object, please refer to the documentation (comm.EyeDiagram) and the example Eye and Constellation Diagram.

% Set up the pattern generator
src = commsrc.pattern('SamplingFrequency', Fs, ...
                      'SamplesPerSymbol', sps, ...
                      'RiseTime', Trise, ...
                      'FallTime', Tfall) %#ok

% Generate NRZ signal
message = generate(src, frameLen);

% Create an comm.AWGNChannel System object.
% Set the NoiseMethod property of the channel to 'Signal to noise ratio
% (SNR)'. The commsrc.pattern object generates unit power signals; set the
% SignalPower property to 1 Watt.
channel = comm.AWGNChannel('NoiseMethod', 'Signal to noise ratio (SNR)',...
  'SNR', SNR, 'SignalPower', 1);

% Add AWGN
received = channel(message);

% Create an eye diagram and display properties
eyeObj = comm.EyeDiagram(...
    'YLimits', [-1.5 1.5], ...
    'SamplesPerSymbol', sps, ...
    'SampleRate', Fs, ...
    'SampleOffset', 0.004*Fs, ...
    'DisplayMode', '2D color histogram', ...
    'ColorScale', 'Logarithmic') %#ok

% Update the eye diagram object with the noisy NRZ signal
eyeObj(received);

% Plot the time domain signal
t = 0:1/Fs:15/Rs-1/Fs; idx = round(t*Fs+1);
hFig = figure('Position', [0 0 460 360]);
plot(t, received(idx));
title('Noisy NRZ signal');
xlabel('Time (sec)');
ylabel('Amplitude');
grid on;

% Manage the figures
hFig.Position = [10 10 hFig.Position(3:4)];
eyeObj.Position = [hFig.Position(1)+hFig.Position(3)+10 hFig.Position(2) ....
                   eyeObj.Position(3)*0.75 eyeObj.Position(4)*0.75];
src = 

                 Type: 'Pattern Generator'
    SamplingFrequency: 10000
     SamplesPerSymbol: 100
           SymbolRate: 100
            PulseType: 'NRZ'
         OutputLevels: [-1 1]
             RiseTime: 0.0020
             FallTime: 0.0020
          DataPattern: 'PRBS7'
               Jitter: [1x1 commsrc.combinedjitter]


eyeObj = 

  comm.EyeDiagram with properties:

                  Name: 'Eye Diagram'

   Trace configuration
            SampleRate: 10000
      SamplesPerSymbol: 100
          SampleOffset: 40
       SymbolsPerTrace: 2

   Display configuration
           DisplayMode: '2D color histogram'
    EnableMeasurements: 0
      ShowImaginaryEye: 0
               YLimits: [-1.5000 1.5000]
              ShowGrid: 1
              Position: [400 220 640 460]

  Use get to show all properties

An important characteristic of communication signals, especially in high speed applications such as backplane communications, is the timing jitter. Timing jitter is defined as the deviation of a signal's timing clock from the ideal clock. Timing jitter can be divided into two main subcategories: deterministic and random jitter [ 1 ]. Two examples of deterministic jitter are periodic jitter and inter-symbol interference (ISI).

Periodic jitter can be modeled as a sum of sinusoidals, while ISI can be modeled as a train of Dirac functions. Random jitter is modeled as Gaussian variation of the signal clock edges.

The jitter encountered in a communication system can be any combination of these components. A commonly used combination is the dual-Dirac model, where ISI and random jitter are combined [ 2 ]. ISI is modeled by two equal amplitude Dirac functions. The following figure shows the probability density functions of random jitter, periodic jitter, periodic and random jitter, and ISI and random jitter. We generated the jitter samples using the jitter generator provided in the communication sources package.

histEdges = -0.1/Rs:1/(10*Fs):0.1/Rs; hFigPdf = figure;

% Obtain PDF of random jitter generated by the combined jitter object
jitterSrc = commsrc.combinedjitter('RandomJitter', 'on', 'RandomStd', 0.01/Rs);
jitter = generate(jitterSrc, 1e6);
rjPdf = histc(jitter, histEdges);
rjPdf = rjPdf / sum(rjPdf);
subplot(221);
plot(histEdges*1e3,rjPdf);
grid on;
title('Random Jitter');
xlabel('Time (ms)');
ylabel('PDF');

% Obtain PDF of periodic jitter
set(jitterSrc, 'RandomJitter', 'off', 'PeriodicJitter', 'on', ...
    'PeriodicAmplitude', 0.05/Rs, 'PeriodicFrequency', 1/33);
jitter = generate(jitterSrc, 1e6);
rjPdf = histc(jitter, histEdges);
rjPdf = rjPdf / sum(rjPdf);
subplot(222);
plot(histEdges*1e3,rjPdf);
grid on;
title('Periodic Jitter');
xlabel('Time (ms)');
ylabel('PDF');

% Obtain PDF of random and periodic jitter
jitterSrc.RandomJitter = 'on';
jitter = generate(jitterSrc, 1e6);
rjPdf = histc(jitter, histEdges);
rjPdf = rjPdf / sum(rjPdf);
subplot(223);
plot(histEdges*1e3,rjPdf);
grid on;
title('Periodic and Random Jitter');
xlabel('Time (ms)');
ylabel('PDF');

% Obtain PDF of ISI and random jitter
jitterSrc.PeriodicJitter = 'off';
jitterSrc.DiracJitter = 'on';
jitterSrc.DiracDelta = 0.05/Rs*[-1 1];
jitter = generate(jitterSrc, 1e6);
rjPdf = histc(jitter, histEdges);
rjPdf = rjPdf / sum(rjPdf);
subplot(224);
plot(histEdges*1e3,rjPdf);
grid on;
title('ISI and Random Jitter');
xlabel('Time (ms)');
ylabel('PDF');

We can use the same jitter object in the pattern generator to inject jitter to the output signal. The following code generates a signal that is impaired not only by AWGN but also by random jitter. This example uses the same message data as in the previous case and compares the two signals. Note that the effect of jitter on the signal is not clear in this time domain figure.

close(hFigPdf);
hide(eyeObj);

% Attach the jitter object to the pattern generator
src.Jitter = jitterSrc;
% Generate only random jitter with standard deviation 0.3 ms.
src.Jitter.DiracJitter = 'off';
src.Jitter.RandomJitter = 'on';
src.Jitter.RandomStd = 0.3e-3;

% Generate NRZ signal with random jitter and add AWGN
reset(src);
release(channel);
message = generate(src, frameLen);
received = channel(message);

% Plot the jittered noisy NRZ signal with the noisy signal
t = 0:1/Fs:15/Rs-1/Fs;
idx = round(t*Fs+1);
figure(hFig);
hold on;
plot(t, received(idx), 'r');
title('Noisy and Jittered NRZ signal');
xlabel('Time (sec)');
ylabel('Amplitude');
grid on;

The effect of jitter is better illustrated by the eye diagram of the signal. The next two eye diagram figures illustrate the impact of jitter. The width of the jittered signal at the zero amplitude level is considerably larger than the width of the non-jittered signal as a result of the added random jitter. Note that even though this example focuses on real signals, the eye diagram object can also display complex signals if the ShowImaginaryEye property is set to true.

close(hFig)

% Make a copy of the eye diagram object and reset
eyeObjJitter = clone(eyeObj);
release(eyeObjJitter);
reset(eyeObjJitter);

% Update the eye diagram object with the noisy, jittered signal
eyeObjJitter(received);

% Bring up the previous eye diagram for comparison
show(eyeObj);
show(eyeObjJitter);
eyeObj.Name       = 'Eye Diagram without Jitter';
eyeObjJitter.Name = 'Eye Diagram with Jitter';
eyeObjJitter.Position = [eyeObj.Position(1)+eyeObj.Position(3) eyeObj.Position(2) ...
                         eyeObj.Position(3) eyeObj.Position(4)];

The horizontal histogram can be utilized to examine the jitter characteristics more closely. The horizontal histogram is calculated at the amplitude level specified via the DecisionBoundary property. The figure shows the horizontal histogram at 0 Amplitude Units (AU). Since the eye diagram traces two symbol durations, it crosses the reference amplitude level at two locations, 5 ms and 15 ms. Note that the symbol duration is 10 ms. Also, both crossings have Gaussian characteristics since the signal is impaired with random jitter.

% Enable vertical histogram overlay, and therefore measurements
eyeObjJitter.EnableMeasurements = true;
eyeObjJitter.Position = eyeObjJitter.Position + [0 0 0 eyeObjJitter.Position(4)*0.75];
eyeObjJitter.OverlayHistogram = 'Jitter';

% Need to step the input again for histograms to be collected:
eyeObjJitter(received);

% Also export the plotted horizontal histogram with the jitterHistogram
% method
horHist = jitterHistogram(eyeObjJitter);
hide(eyeObj);

The vertical histogram can be utilized to examine the noise characteristics of the channel. The vertical histogram is collected at the best sampling time, i.e., at the value of the Eye Delay measurement, which corresponds to the average of the two crossing times.

eyeObjJitter.OverlayHistogram = 'Noise';

% Also export the plotted vertical histogram, with the noiseHistogram
% method
verHist = noiseHistogram(eyeObjJitter);

The following code runs a simulation with random jitter, ISI, and AWGN. ISI is introduced by passing the signal through a raised cosine filter. The Hysteresis property is set to a value such that level crossings due to noise are suppressed. Note that changing most measurement settings may reset the Eye Diagram object. The MeasurementDelay is set to a value greater than the filter delay to eliminate the transient part of the signal. The simulation runs in a FOR loop so that the eye diagram object computes measurements in a streaming manner.

eyeObjJitter.OverlayHistogram = 'None';
reset(eyeObjJitter);
release(eyeObjJitter);

% Set the jitter parameters
src.Jitter.RandomStd = 0.1e-3;

% Set jitter hysteresis value, measurement delay, and color scale
eyeObjJitter.Hysteresis = 0.1;
eyeObjJitter.MeasurementDelay = 6/Rs;
eyeObjJitter.ColorScale = 'Linear';

% Set up the square root raised cosine filter.
b = rcosdesign(0.5, 6, sps);
b = b / sum(b);
transmitFilter = dsp.FIRFilter('Numerator', b);

% Run simulation
frameLen = 1000;
numFrames = 20;
lastSymbol = 0;
lastJitter = 0;

release(channel);
% Generate jittered signal
message = generate(src, frameLen*numFrames);
% Add ISI and noise
messageISI = transmitFilter(message);
received = channel(messageISI);

for k = 1:800
  % Update the eye diagram object with the signal
    eyeObjJitter( received( 1+(k-1)*10*2*sps : k*10*2*sps ) );
end

% Also export the displayed measurements with the measurements method:
meas = measurements(eyeObjJitter) %#ok<NOPTS>

% For a detailed explanation of the measurements, please refer to the
% documentation (type "doc comm.EyeDiagram" on the command line). Note that
% since the simulation was run using less than 20000 symbols, the results
% are not very accurate.
meas = 

  struct with fields:

              EyeLevels: [2x1 double]
           EyeAmplitude: 1.8519
              EyeHeight: 1.5124
        VerticalOpening: 1.0447
                 EyeSNR: 10.5280
          QualityFactor: 16.0473
         CrossingLevels: [2x1 double]
          CrossingTimes: [2x1 double]
               EyeDelay: 0.0104
               EyeWidth: 0.0077
      HorizontalOpening: 0.0048
               RiseTime: 0.0066
               FallTime: 0.0066
    DeterministicJitter: 6.5994e-04
           RandomJitter: 0.0045
            TotalJitter: 0.0052
              RMSJitter: 3.8680e-04
       PeakToPeakJitter: 0.0049

Comparing Measurements

We can use the measurement exporting capability of comm.EyeDiagram to compare measurements obtained under different configurations. The next example examines the effect of random jitter on an NRZ system with a 10 Gsps symbol rate. The deterministic jitter is set to 2 ns. The standard deviation of the random jitter is increased from 300 ps to 500 ps, in 100 ps steps. The NRZ signal is passed through an AWGN channel with 40 dB SNR. Note that AWGN will increase the random jitter since the rise and fall times are non-zero.

Fs = 10e9;
Rs = 100e6;
sps = Fs/Rs;
Trise = 2e-9;
Tfall = 2e-9;

% Create a pattern generator object
warning('off', 'comm:commsrc:randomjitter:StdTooLarge')
warning('off', 'comm:commsrc:combinedjitter:InvalidDelta')
srcObj = commsrc.pattern( ...
    'SamplingFrequency', Fs, ...
    'SamplesPerSymbol', sps, ...
    'DataPattern', 'PRBS31', ...
    'RiseTime', Trise, ...
    'FallTime', Tfall);
srcObj.Jitter.RandomJitter = 'on';
srcObj.Jitter.DiracJitter = 'on';
srcObj.Jitter.DiracDelta = [-1e-9 1e-9];
warning('on', 'comm:commsrc:randomjitter:StdTooLarge')
warning('on', 'comm:commsrc:combinedjitter:InvalidDelta')

% Create an eye diagram object
eyeObj = comm.EyeDiagram(...
    'SampleRate', Fs, ...
    'SamplesPerSymbol', sps, ...
    'YLimits', [-1.75 1.75], ...
    'EnableMeasurements', true, ...
    'MeasurementDelay', 6e-9);

% Set the range of standard deviation for the random jitter
stdVec = (300:50:500)*1e-12;

% Set simulation parameters
frameLen = 1000;
numFrames = 100;
cnt = 1;

% Main loop
for randStd = stdVec
    % Set the random jitter standard deviation and reset the eye diagram
    % object
    srcObj.Jitter.RandomStd = randStd;
    hide(eyeObj);
    reset(eyeObj);
    release(eyeObj);

    % Update the eye diagram object with the jittered and noisy source
    x = generate(srcObj, frameLen*numFrames);
    r = awgn(x, 40);
    eyeObj(r);

    meas(cnt) = measurements(eyeObj);

    % Adjust the eye center to the middle of the time axis
    timeOffsetSamps = 2*eyeObj.SamplesPerSymbol - Fs*meas(cnt).EyeDelay;
    eyeObj.SampleOffset = round(timeOffsetSamps);

    cnt = cnt+1;
end

hide(eyeObj);
hide(eyeObjJitter);

The following figure shows the measurement results for Horizontal Opening, Random Jitter, and Deterministic Jitter. Since Random Jitter is measured for a bit error rate of 1e-12 (see the BER Threshold property), the expected value of random jitter is about 14 times the standard deviation of the jitter samples. For example, for a standard deviation of 300 ps, the random jitter at BER = 1e-12 is 4.2 ns.

hFig = figure;
plot(300:50:500, [meas.HorizontalOpening], 'b-*');
hold on;
plot(300:50:500, [meas.RandomJitter], 'r-*');
hold on;
plot(300:50:500, [meas.DeterministicJitter], 'g-*');
legend('Horizontal opening', 'Random jitter', 'Deterministic jitter', 'Location', 'northwest');
title('Measurement comparison for noisy NRZ signal');
xlabel('Standard deviation of random jitter (ps)');
ylabel('Time (s)');
grid on;

The horizontal and vertical openings can also be compared for different BER Threshold values using the available bathtub curve displays.

eyeObj.ShowBathtub = 'Horizontal';
eyeObj.BathtubBER  = [0.5 10.^-(1:3:13)];
show(eyeObj);

References

  1. Ou N. et al., "Jitter Models for the Design and Test of Gbps-Speed Serial Interconnects," IEEE® Design & Test of Computers, Vol. 21, July-August 2004, pp. 302-313.
  2. Stephens R., "Jitter Analysis: The dual-Dirac Model, RJ/DJ, and Q-Scale," Agilent Technologies® Whitepaper, 2004. Available from www.Agilent.com.