做FPGA设计最头疼的就是时序收敛。代码写完了,功能仿真也过了,结果一布线时序不收敛,时序违例一大堆。分享一下我们团队的调试流程。

## 第一步:先看报告,找到关键路径

布线完成后,先打开时序报告,不要上来就改代码。重点看:
- WNS(Worst Negative Slack):最差的建立时间裕量
- TNS(Total Negative Slack):所有违例路径的总和
- 违例最多的是哪个时钟域

## 第二步:定位问题路径

时序报告里会列出违例路径的起点和终点。常见问题:
1. **跨时钟域**:两个不同时钟域之间没做同步
2. **组合逻辑太长**:一个周期里串了太多级组合逻辑
3. **数据路径太绕**:从一个BGA引脚进来,绕了大半个芯片才出去

## 第三步:对症下药

**情况1:跨时钟域违例**
- 加两级触发器同步器
- 或者用FIFO做跨时钟域数据传递

**情况2:组合逻辑太长**
- 加寄存器打拍,把长组合逻辑拆成两级
- 或者重新优化逻辑结构,减少级数

**情况3:布线绕路**
- 用Pblock约束把关键路径的逻辑放在一起
- 或者手动布局,把相关的引脚和逻辑靠近

## 一个实战案例

有个项目,DDR3接口的时序一直不收敛。查了半天发现是地址命令信号的布线绕远了,从FPGA的左边引脚进去,绕到右边的PHY,中间过了好几个时钟区域。

后来把DDR相关的逻辑全部约束在一个固定的区域里,时序一下就收敛了。

## 经验总结

1. 先写约束再写代码,不要等布线失败了才补约束
2. 跨时钟域一定要做同步,这是最常见的低级错误
3. 关键路径用Pblock约束,比让工具自己布靠谱多了
4. 时序问题80%是约束的问题,不是代码的问题

大家做FPGA时序收敛的时候,最常遇到什么问题?