Differential pair

Two nets carrying one signal, one rising as the other falls by the same amount. The receiver does not read either wire against ground. It reads the difference between them.

That is the whole trick. Interference picked up along the run hits both wires more or less equally, which moves both by the same amount and leaves the difference untouched.

flowchart TB
    D["driver"] -->|"CANH rises"| R["receiver<br/>reads CANH − CANL"]
    D -->|"CANL falls by<br/>the same amount"| R
    N["interference along the run<br/>hits both wires equally"] -.-> R
    R --> O["the difference is unchanged,<br/>so the interference cancels"]

The two halves are conventionally named as a pair, X_P and X_N, or for CAN _CANH and _CANL. A pair with only one half wired is not a pair at all, and the layout tool will route the survivor as an ordinary signal. diff-pair-naming exists to catch that. Some board tools also declare the pair outright. An Allegro board records it in its constraints, and agni reads that declaration (net.group) before it reads the names.

A pair almost always needs termination at each end, for a reason that has nothing to do with noise.

The course teaches it in chapter 1, which reads a resistor’s job from the nets it touches.