# BITSLIP in practice: word alignment with 7-series ISERDESE2

BITSLIP has one job: align the ISERDESE2 word to a word boundary. One CLKDIV-wide pulse rotates it 1 bit, up to DATA_WIDTH phases. It reports no phase, so the wire needs a known word to lock on.

## What it does and does not do


|                                                       | BITSLIP can                | Needs another mechanism                                   |
| ----------------------------------------------------- | -------------------------- | --------------------------------------------------------- |
| Word boundary (which bit the parallel word starts at) | ✔ rotates 1 bit per pulse |                                                           |
| Whether the sampling point sits in the eye centre     |                            | IDELAYE2 tap adjustment (or MMCM phase)                   |
| Bit skew between lanes                                |                            | independent IDELAY per lane, or length matching           |
| Which lane carries which bit                          |                            | fixed wiring plus a board-level check (not BITSLIP's job) |
| Reading the current phase back                        |                            | impossible; infer it from the data                        |
| Whole-word jumps (a word lost or gained)              |                            | frame sync code plus word-level alignment logic           |

One precondition to keep in mind: **BITSLIP only exists with `INTERFACE_TYPE="NETWORKING"`**; MEMORY mode does not have it. In DDR mode the legal `DATA_WIDTH` values are 4/6/8/10/14, in SDR 3/4/5/6/7/8.

## Using it correctly

1. **The pulse must be exactly one CLKDIV cycle wide**, generated in the CLKDIV domain. A longer pulse becomes several rotations (how many depends on internal logic — do not gamble).
2. **One pulse equals a 1-bit rotation**, so covering every phase takes up to `DATA_WIDTH` pulses; 8 bits means 8 phases.
3. **Give each lane its own slip controller.** Phase is per lane; a shared counter is wrong.
4. **Only pulse while data is flowing.** When the source is idle there is no word boundary to align to, so you cannot judge the result.
5. **There must be a known word on the wire** (comma, training word, line sync code). Without a reference you cannot tell whether you are aligned; you are guessing.

## Writing the phase search

The pattern is pulse, wait a few words, compare — not pulse and compare immediately:

```
for phase in 0 .. DATA_WIDTH-1:
    pulse_bitslip()                 # one CLKDIV cycle
    wait(5 words)                   # key: the stream is discontinuous right after the pulse
    good = compare(known_word)      # bit-exact against a local known word
    if good: lock(phase); break
```

Discarding a few words after the pulse is mandatory: a slip inserts or drops one bit, so the immediately following word is half old and half new and will always mismatch. Measured: after discarding 5 words the correct phase matches whole words exactly.

## How to judge it in simulation

Never pin the compare window to the first word after the pulse; **slide the window**: shift and compare, and only accept a phase that gives N consecutive whole words equal. Sweep every phase in SDR and judge each lane separately, and you can see whether a single correct phase exists. If two phases both pass, either your training word is periodic or the data itself is insensitive to phase — see the pitfalls below.

## When not to use BITSLIP

If the link has **no per-lane training word** (a video stream, for example: only de/hs/vs and pixel data, where flat colour fields are completely phase-insensitive), BITSLIP leads to two failures:

- **False lock**: on a solid-colour screen any phase passes, and the error only shows up once a checkerboard or a gradient arrives.
- **No recovery**: after a link disturbance you no longer know where you are, so the whole sweep must be rerun, and rerunning requires the source to provide a structured test pattern first.

In that situation a more robust approach is to **drop BITSLIP and do word-level alignment**: use a line sync code to locate each line's data window, barrel-shift whole words, and use the inter-line idle gap to tell a new line or field. It is deterministic, independent of image content, and self-correcting every line; the cost is a shift register that holds a whole word instead of an eight-phase search state machine.

## Common pitfalls

- Pulsing before `CLKDIV` is stable gives Q stuck at X; release reset first for the clock, then for the IO.
- Comparing only the first two words after the pulse inverts the conclusion (a good phase gets reported as bad).
- Testing the training word on one lane only leaves the other lanes misaligned.
- Expecting slip to fix a whole-word offset; that needs frame/line sync — slip only searches within a word.
- Expecting slip to buy timing margin; it does not move the sampling point, so a poor eye still needs IDELAY taps or better routing.

## Measured record

8-bit DDR, `INTERFACE_TYPE="NETWORKING"`, three lanes in parallel: at slip phase 2 all three lanes matched 8/8 whole words; stepping phase by phase, the Q numbering cycles 2→3→…→8→2, confirming the one-pulse-one-bit behaviour. The same PHY was once misjudged as "slip does not work" before the pulse verification was changed to a sliding-window comparison.

## In one sentence

BITSLIP is a narrow word-boundary tool: excellent when bit phases can be searched and a training word exists; when there is no training word, or the alignment must be deterministic and content-independent, a line sync code plus a whole-word barrel shift is the more reliable choice.

