Charts/Science charts
Eye Diagram
<EyeDiagram /> · 10 examples
A bit stream folded onto itself so thousands of transitions can be judged at once by how open the gap in the middle is.
Overview
A serial link sends ones and zeros as voltage, and the receiver has to decide, in a window a fraction of a nanosecond wide, which one it just saw. Whether it gets it right depends on three things: how high the high is, how low the low is, and how consistently each transition happens at the same time. A plain waveform shows one of those at a time and a million of them as a green smear.
The eye diagram is the smear, made useful on purpose. You cut the signal into pieces one or two bit periods long and draw them all on top of each other. Wherever bits behave the same way, the traces pile up into thick lines. Wherever they differ, the traces spread out. In the middle is a gap where no trace passes, and that gap is shaped like an eye. Wide and open: good link. Squinting and half closed: go find the cable.
Oscilloscopes have drawn these since the days of cathode-ray tubes, which is where the persistence phosphor did the stacking for free. You can build the same picture from any sampled signal in software, and that is what this chart does. It also counts where the signal crosses the middle level and shows those crossings underneath, because the width of that crowd is the timing jitter, and jitter is what actually kills links.
Props
API
<EyeDiagram data={samples} x={|s: &Sample| s.time} value={|s: &Sample| s.volts} period={1.} offset={0.5} />| Prop | Type | Default |
|---|---|---|
data | samples in time order | required |
x | Fn(&T) -> f64: time | required |
value | Fn(&T) -> f64 | required |
period | f64: one unit interval, in the units of x | required |
offset | f64: time that lands on the left edge | 0. |
spans | usize: unit intervals shown | 2 |
threshold | f64: the level crossings are counted at | halfway between the lowest and highest value |
jitter | bool: show the crossing histogram below | true |
bins | usize: histogram bins across the window | 60 |
trace_opacity | f32 | 0.25 |
color | colour of the traces | the first series colour |
x_axis, y_axis | AxisConfig; x is always the window | |
class |
The signal is cut every spans × period and the pieces are drawn on top of each other, joined across each cut so traces stay continuous. Faint traces build up into a density picture. The strip below counts where the signal crosses threshold inside the window: its width is the timing jitter. Built on <XYChart> and <Trend>, so Ctrl+scroll zooms both.
Run them
10 examples
Press Run to load an example into the live render at the top of the page. Open one to read its code.
How to read it
- 01Look at the opening in the middle. Height is voltage margin, and width is timing margin. Together they are the room the receiver has to decide.
- 02Look at how thick the two rails are. A fuzzy top and bottom are amplitude noise, and a clean eye with ragged crossings is a timing problem.
- 03Look at the crossing strip underneath. A narrow spike is good. A wide, lumpy hill means jitter, and two humps mean the edges depend on the data pattern.
- 04Ctrl+scroll zooms the eye and the strip together, so you can inspect the crossing without losing the window.
When to use it, and when not to
Reach for it when
- You are judging signal integrity on a serial link, a memory bus, a clock or any NRZ-like signal.
- You want a single picture of thousands of bit transitions, so one rogue edge does not hide among a million normal ones.
- You want to see timing jitter and voltage noise separately: horizontal spread at the crossing and vertical thickness of the rails.
- You are comparing two cables, two fixtures or two equalizer settings on the same data pattern.
Skip it when
- The signal is not periodic in a known interval. Without a correct
periodthe traces fold at the wrong width and the eye smears. - You need to see a specific rare event, such as a single glitch at 3.2 ms. A folded plot erases when things happened.
- You have only a few hundred samples. An eye is a statistical picture, and a few traces draw a few lines, not an eye.
- You want a pass or fail result with a mask. This chart shows the picture. It does not test it against a standard mask.
The math behind it
Folding time into a window
Each sample is a pair . Choose a unit interval (the period), a number of unit intervals to display (spans, 2 by default) and an offset that lands on the left edge. The window is . A sample is drawn at its phase inside that window, and every trace that started in a different window lands on the same axis.
Keeping each trace continuous
If you just plotted in order, the line would draw a horizontal streak from the right edge back to the left every time the phase wrapped. The chart instead detects the wrap (the phase drops by more than half a window), finds the value where the signal would have crossed the window edge by linear interpolation, ends the trace at the right edge, and starts the next one at the left edge from the same value. The traces are drawn at a low opacity (0.25 unless you change trace_opacity) so overlaps add up into brightness.
The crossing histogram
The strip underneath counts threshold crossings. The threshold defaults to halfway between the lowest and highest value in the data. A crossing happens between samples and whenever the two sit on opposite sides of , and its time is found by interpolation. Its phase is binned into bins equal slots (60 by default) across the window.
Real life usage
The cable that only failed on Tuesdays
Amara ran the test lab at a company that made industrial cameras, and the company's difficulty was a cable. The camera sat on a robot arm and sent images to a controller 15 metres away over a cable that met every datasheet and still dropped frames, but only on Tuesdays, which seemed implausible even for hardware.
The first theory was software. The second was the robot's motor. The third, advanced by a salesman, was that Tuesday was the day the factory ran the large press on the next floor. None of these was wrong, and none of them was a measurement.
She captured four million samples of the link at the controller input during a bad stretch, which is a great way to produce a file that no one can read. A plain waveform at that length is a thick bar of colour. She needed a way to ask a single question of the file: is the receiver being given enough room to decide?
She loaded the samples into a zopra-charts <EyeDiagram>, with the bit period of 400 picoseconds as period and the default two-bit window. On a good day the eye was a tidy diamond about 0.55 of a bit wide. On the bad capture it had closed to a slit, and the crossing strip below was no longer a spike but a broad double hill about 120 ps wide.
Two humps meant the edge timing depended on the data. That is the signature of inter-symbol interference, which means the cable was low-passing the bit stream, with long runs of identical bits ending up with different amplitudes than short ones. The press upstairs had nothing to do with it. A flexed connector on the robot arm had changed the cable's loss, and Tuesday was when the arm ran its full-reach routine.
She swapped the connector for a better one and added a 3 dB boost to the transmitter. The eye reopened to 0.62 and the dropped frames went from about 40 a day to none in the following month. The press was officially cleared of all charges.
Every link has a bad day. The eye diagram is the only chart that lets you see exactly how much room it left you.
Pitfalls
- Wrong
period. If it is off by even a percent, the traces slowly slide across the window and the eye blurs into a band. Take the period from the data rate, not from eyeballing the waveform. - Offset not at the bit centre. Choose
offsetso the eye is in the middle of the window, otherwise the crossings sit on the edge and the picture is hard to read. - Sampling too coarse. With fewer than about 8 samples per period the interpolation of edges is crude, and the crossing histogram gets lumpy.
- Threshold at the wrong level. The default is halfway between the extremes. A signal with overshoot or a DC offset can shift the true decision level, so set
thresholdyourself in those cases.
From around the web