# BITSLIP 用法与边界：7 系列 ISERDESE2 字对齐实战

BITSLIP 只做一件事：把 ISERDESE2 的并行字对齐到正确的字边界 —— 每来一个 CLKDIV 周期宽的脉冲，整字旋转 1 bit，最多转 DATA_WIDTH 个相位。它管不了采样点位置（那是 IDELAY 的活），也读不回当前相位，所以必须靠线上的已知码字判定哪个相位是对的。

## 它做什么、不做什么


|                                | BITSLIP 能           | 需要别的手段                             |
| ------------------------------ | -------------------- | ---------------------------------------- |
| 字边界（并行字从哪一位开始算） | ✔ 旋转 1 bit / 脉冲 |                                          |
| 采样点是否落在眼图中心         |                      | IDELAYE2 tap 微调（或 MMCM 相位）        |
| lane 之间的位偏斜              |                      | 每 lane 独立 IDELAY，或等长走线          |
| 哪个 lane 对应哪个 bit         |                      | 固定布线 + 板级核对（不是 BITSLIP 的事） |
| 读出当前相位                   |                      | 不可读。只能从数据反推                   |
| 整字跳变（丢/多一个整字）      |                      | 帧同步码 + 字级对齐逻辑                  |

一个必须记住的前提：**BITSLIP 只在 `INTERFACE_TYPE="NETWORKING"` 下存在**，MEMORY 模式下没有这个功能。DDR 模式下合法 `DATA_WIDTH` 为 4/6/8/10/14，SDR 为 3/4/5/6/7/8。

## 正确的用法

1. **脉冲宽度正好一个 CLKDIV 周期**，且只在 CLKDIV 域产生。多拍会变成多次旋转（转几下取决于内部逻辑，不要赌）。
2. **一个脉冲 = 1 bit 旋转**，所以要覆盖全部相位最多打 `DATA_WIDTH` 次；8 bit 就是 8 个相位。
3. **每 lane 独立一套 slip 控制器**。相位是每 lane 各自的事，不能共用计数。
4. **只在数据在流动的时候打脉冲**。源端停着的时候没有字边界可对齐，转了也判不出来。
5. **必须在线上有已知码字**（comma、训练字、行同步码）。没有参照就无法判定"现在对齐了没有"，只能靠猜。

## 相位搜索的写法

思路是"打一次、等几拍、比一次"，不是"打一次立刻比"：

```
for phase in 0 .. DATA_WIDTH-1:
    pulse_bitslip()                 # 一个 CLKDIV 周期
    wait(5 words)                   # 关键：脉冲后数据流是不连续的
    good = compare(known_word)      # 与本地已知码字逐位比
    if good: lock(phase); break
```

丢掉脉冲后的几个字是必须的：slip 会插入或丢弃一位，紧接着的字处于"半新半旧"的状态，直接比一定失败。实测中丢掉 5 个字后，正确的相位可以做到整字全对。

## 仿真的判定方法

不要把比较窗口钉死在脉冲之后的第一字，要**滑窗**：一边移位一边比，只认"连续 N 个整字全等"的那个相位。用 SDR 逐相位扫描 + 每 lane 单独判定，就能看出是否存在唯一正确相位（若出现两个相位都对，说明你的训练码有周期性问题，或者数据内容对相位不敏感 —— 见下一条坑）。

## 什么时候不要用 BITSLIP

如果链路上**没有每 lane 独有的训练码**（例如视频流：只有 de/hs/vs 和像素数据，且平坦色块对相位完全不敏感），用 BITSLIP 会掉进两个坑：

- **假锁定**：全屏单色时任意相位都能"通过"，等到出现棋盘/灰阶才发现错了；
- **不可恢复**：链路扰动后不知道自己转到哪了，必须整套重扫，而重扫要求源端先给出结构化的测试图案。

这种场合更稳的做法是**放弃 BITSLIP，改做字级对齐**：用行同步码定位每一行的数据窗口，把整字做桶形移位，用"行内空闲间隔"判断新行/新场。它是确定性的、与图像内容无关、每行都能自愈，代价是需要一个能记住整个字的移位寄存器，而不是 8 个相位的搜索状态机。

## 常见坑

- 脉冲打了但 `CLKDIV` 还没稳定 → Q 一直是 X，reset 释放顺序要先时钟后 IO。
- 只测了脉冲后的头两个字 → 结论恰好相反（把对的说成错的）。
- 训练码只在一个 lane 上试 → 其它 lane 其实没对齐。
- 认为 slip 能补偿整字级偏移 → 整字偏移要靠帧/行同步，slip 只能在小范围内找位。
- 认为 slip 能提高时序裕量 → 它不改变采样点，眼图差还得靠 IDELAY/tap 或走线。

## 实测记录

8 bit DDR、`INTERFACE_TYPE="NETWORKING"`、三 lane 并联：slip 相位 2 时三条 lane 都是 8/8 整字全对；逐相位推进时 Q 的编号按 2→3→…→8→2 循环，印证"一个脉冲一位"的行为。同一套 PHY 在把脉冲验证改成滑窗判定之前，曾被误判为"slip 无效"。

## 一句话总结

BITSLIP 是"字边界对齐"的窄工具：有位级相位可搜、有训练码可比的时候它很好用；没有训练码、或者需要与内容无关的确定性对齐时，行同步码 + 整字桶形移位更可靠。

