高速串行通信经常需要用到 XILINX FPGA 内部专用的 SERDESE 模块来实现串并转换。 LVDS 配合 SERDESE可以充分发挥 FPGA 的高速接口优势。 SERDESE 分输入和输出,输入采用 ISERDESE, 输出采用 OSERDESE,OSERDESE 的使用要比 ISERDESE 简单。
本文涉及到一些重要原语概念,包括 idelay 延迟原语,IDELAYCTRL原语, ISERDESE 、OSERDESE。其中很关键一点时使用 idelay 延迟模块以及 ISERDESE 原语中 BITSLIP 功能,实现比特流的时钟对齐,以及数据流的位流顺序对齐。XILINX FPGA 高速通信中经常会用到 idelay模块对信号比特流做细微的时序调整。
参考文档包括:官方手册ug471,xapp585,第三方米联客教程。
1、IDELAYCTRL模块
2、IDELAY模块
3、IDELAY模块工作时序
4、OSERDES模块
OSERDES模块数据传输方式支持SDR,DDR两种,数据位宽支持级联以扩展到14比特。
由上图可知,OSERDES串行输出的数据流与原始并行数据比较,大小端是相反的。
5、ISERDES模块
ISERDESE2 在 SDR 模式下数据转换的位宽可以为 2、 3、 4、 5、 6、 7、 8bit,在 DDR 模式时,数据转换位宽为 4、 6、 8bit, 2 个 ISERDESE2 级联使用, DDR 模式可以支持 10、 14bit。 如下图所示通过 2 个 ISERDESE2 级联输出14bit 位宽数据接口。
6、Bitslip数据对齐功能
7、Serdes时钟源设计要求
二、源码解析
1、SDR ISERDESE 时钟恢复
ISERDESE 的作用是和 OSERDESE 相反的过程,但是比 OSERDESE 稍微复杂一些。 ISERDESE 代码需要实现自动找到最佳的数据采样点, 自动完成数据对其,其中的加入了 IDELAY 和 BITSLIP 功能的使用,以及一些状态机代码。笔者下面根据 XAPP585 中给出的 demo 源码分析。
1.1使用IDELAY之前,需配置IDELAYCTRL。
1.2 计算比特流最大速率参数
官方源码仿真使用的并行时钟为80M,SDR模块采用1_to_7串并转换,则Serdes工作速率为560Mbps,由此可以得到Idelay调节Tap最大的步数。
设置 bit_rate_value=0560,那么代表了 serdes 的速率是 560Mbps,根据下面代码得出 bt_val=5’h17(bt_val=5’d23)。由上文可知, idelay 的参考时钟是 200MHZ, 那么每个延迟节拍是 78ps,则23*78ps= 1,794 ps = 557 Mb/s.最接近 560Mbps。
1.3 如何实现时钟恢复时,差分时钟信号正负相位对齐
查看源码可知,SERDES工作速率为560Mbps参数,就可以选出 bit_rate_value 为 0557, 所以 bt_val 为 17h。先取出 bt_val 的中间值,即17h 的中间值是 0Bh。把差分时钟n 的延迟时间设定为0Bh,把差分时钟p的初始延迟设定为17h,然后保持差分时钟n 的延迟时间不变,每次调节1个Tape,用于差分时钟p和差分时钟n的反向 进行相位对比,直到二者相位差为零。这个细节就是实现差分时钟信号对齐的核心,看代码时很容易忽略。我在第一遍时就犯了这个错误,导致始终不明白所以然。
1.4 Bitslip进行比特流位顺序调节
这段代码不复杂,Bitslip的调节原理见上文,也容易理解。
1.5 差分时钟正负信号时序补偿
需要把上述代码段看明白就知道补偿原理了。
通过控制每次减 1 个 tap,减少 idelay 延迟,并且通过 ISERDESE 检测时钟的跳变。当第一次跳变发生的时候,代表检测到了时钟的跳变沿,假设这个时候 bt_val=05h,05h<0Bh 所以计算出时钟的 0BH+05H =10H。
如果恢复出的时钟信号不是目标Pattern值 1100001 或者 1100011,就需要用到 Bslip 调整,每次设置 Bslip 调整一次。
仿真结果如上图的箭头所示,接收的 clk_data 是 7bit 时钟数据,通过调整 c_delay_in 值调整 idelay每次减 1 个 tap,直到 clk_data 发生改变,可以看到这个值是 0b 整好是和中间值相等。这个时候状态机 state2 也会进入状态 1,这个时候计算出 c_delay_in_target=0,这个就是我们需要延迟的时间,可以看到需要延迟的时间为 0,这种情况非常理想,如果实际程序跑起来一般不会是 0,之后进入状态 2。在状态 2 中继续调整 c_delay_in 直到和 c_delay_in_target 相等,如下图,可以看到 clk_data=1100001b 是占比3:4 的时钟就恢复出来了。
总结:
本篇文档通过学习米联客的教程,并结合UG471的学习,XAPP585的源码学习,来不断加深SERDES的工作原理及实现细节,并记录一下自己学习过程,仿真有助于理解源码。
后续会移植源码进行项目开发即可达到应用的要求,有兴趣可以深入源码那更好。