文章来源:FPGA技术实战
ADS4249是一款双通道、14位、250MSPS ADC,具有双总线、字节级数字接口。ADS4249接口示例适用于许多TI高速ADC,包括以下系列:ADS41xx、ADS42xx和ADS62Pxx。ADS4249对外接口如图1所示。
DAC3482是一个双通道、16位、1.25GSPS DAC,具有单总线采样数字接口。本文代码示例的设计数据速率为250MSPS,同样的概念扩展到涵盖大多数LVDS、不同数据速率的高速DAC。DAC3482对外接口如图2所示。
ADS4249及DAC3482硬件连接框图如图3所示。
以下部分将详细分解示例代码,示例代码的简化框图如下图4所示。
图4:FPGA架构和时钟域框图
2.1 输入时钟和时钟域
如图4示例代码中,有两个时钟发送到FPGA,在FPGA内形成两个时钟域(接收时钟域和发送时钟域)。ADS4249源同步数据时钟lvds_rx_clk_p为接收域提供250MHz的输入时钟。FPGA的发送侧从CDCE62005接收250MHz时钟lvds_tx_fpga_clk_p。
两个输入时钟都被引入FPGA内部锁相环(ALTPLL),锁相环产生内部时钟。
ADC输入接口由ALTDDIO_IN 函数创建。该块具有双倍数据速率(DDR)输入寄存器,可捕获输入时钟上升沿和下降沿的数据。单数据速率(SDR)数据在输入时钟的上升沿从块中时钟输出,其中dataout_l包含在前一个下降沿时钟输入的数据,dataout_h包含在当前上升沿时钟输出的数据。图6显示了ALTDDIO_IN函数的框图。
图6:ALTDDIO_IN的ALTDDIO_RX实例框图
ADS4249的奇数位和偶数位的ALTDDIO_IN函数的默认时序图如图7所示。该时序图假设ADS4249和ALTDDIO_IN函数之间的时钟没有相移。该时序图显示,在输入时钟的上升沿,输出dataout_l具有前一个样本(样本N-1)的奇数位,输出dataout_h具有当前样本(样本N)的偶数位。这意味着每个时钟周期函数输出端的奇数位和偶数位不是来自同一ADC样本。当试图将DDR数据编译成单个样本进行处理时,这会产生问题。问题如图7所示。
有两种方法可以解决这个问题:第一种方法是通过在PLL中应用180°相移来反转输入时钟。反相输入时钟的时序图如图8所示。新的图表显示,同一样本的偶数位和奇数位在输入时钟的上升沿上时钟输出,偶数位在dataout_l上,奇数位在dataout_h上。请注意,偶数位和奇数位交换了之前默认情况下的输出,这是示例代码中使用的方法。
图8:交换差分时钟对的ALTDDIO_IN时序图
第二种选择是将dataout_h上的偶数位从上一个采样延迟一个时钟周期。这可以通过创建一个寄存器来轻松实现,该寄存器在SDR时钟的上升沿上对偶数位进行计时。一旦偶数位延迟了一个时钟周期,匹配的奇数位将在SDR时钟的下一个上升沿从ALTDDIO_IN块中出来。然后,这些可以组合在一起形成一个ADC样本。
图9:ALTDDIO_IN函数外ADC位的排列和重新排序
对于DAC,使用了两个ALTDDIO_OUT 函数。其中一个实例简单地输出数据和同步信号,另一个实例创建DDR输出时钟。数据输出ALTDDIO_OUT函数的框图如图10所示。
图10:ALTDDIO_OUT的ALTDDIO_TX实例框图
datain_h端口接收DAC通道A的采样,datain_l接收通道B的采样,使得通道A在时钟的上升沿输出,通道B在下降沿输出。这些样本来自分隔RX和TX时钟域的FIFO。DAC同步信号有一个额外的输入,该信号是通过用去抖动码推送PUSHBUTTON1生成的,以防止多个同步实例。请注意,最后一个输入位是零,这是必要的,因为不允许使用17位ALTDDIO_OUT函数。因此,创建了一个18位函数,并使用虚拟位来允许代码编译。
还有一个ALTDDIO_OUT实例,它生成图11所示的输出时钟。ALTDDIO_CLK_OUT仅接收分别在tx_pll_output_CLK的上升沿和下降沿输出的1和0。该块的输出成为传输到DAC的数据的数据时钟。请注意,此块的时钟是与数据时钟相比具有90°相移的PLL时钟。这将根据DAC的要求创建一个中心对齐的源同步接口。
图11:ALTDDIO_OUT的ALTDDIO_CLK_OUT实例的框图
这两个块的时序图如图12所示,表明tx_pll_output_clk与tx_pll_data_clk相比有90°的相移。数据在tx_pll_data_clk上计时,输出时钟由tx_pll_output_clk创建。在图的底部,很明显,数据和输出时钟形成了一个中心对齐的源同步输出。输出时钟是使用ALTDDIO_OUT块创建的,而不是直接使用PLL时钟,因为DDR输出块与输出引脚的延迟比DDR输出块的全局时钟网络更匹配。这简化了定时关闭。
图12:ALTDDIO_TX和ALTDDIO_CLK_OUT的时序图
2.3 LVDS接口时钟约束设计
2.3.1 概述
create_clock -name ADC_DATA_CLK -period 4.00 [get_ports lvds_rx_clk_p]
接下来,创建一个虚拟时钟,为ADC输出的数据定义理想的启动时钟。由于ADC是一个中心对齐的接口,因此启动时钟需要提前90°,以获得正确的初始设置和保持时间。如下图所示,波形参数分别定义了上升沿和下降沿位置,其中250 MHz时钟的默认值为0 ns和2 ns。将时钟提前90°相当于使上升沿提前1ns出现,因此-1ns的值应该有效,但是波形参数不能为负值。由于波形参数理解时钟是周期性的,因此3ns和5ns的值将被理解为-1ns和1ns。
create_clock -name ADC_LAUNCH_CLK -period 4.00 -waveform {3 5}
接下来,ADC锁存时钟是从PLL输出手动创建的,如下图所示,而不是让工具自动创建。这样,名称ADC_LATCH_CLK可以在其他语句中使用,而不是使用较长的自动生成的PLL时钟名称。这些时钟定义必须位于下面提到的derive_pll_clocks语句之前。
create_generated_clock -name ADC_LATCH_CLK \ -source [get_pins {RX_PLL_inst|altpll_component|auto_generated|pll1|inclk[0]}] \ [get_pins {RX_PLL_inst|altpll_component|auto_generated|pll1|clk[0]}]
添加下面的两行会自动得出尚未定义的PLL时钟,并计算时钟不确定性。
derive_pll_clocks derive_clock_uncertainty
图13显示了上述时钟的默认设置和保持时间。TimeQuest分析了四种可能的默认设置和保持时间:
•上升沿到上升沿
•上升沿到下降沿
•下降沿到上升沿
图13:带有250 MHz时钟的ADS4249的默认设置和保持时间
所需的默认设置时间应基于上升沿到上升沿和下降沿到下降沿。所需的默认保持时间应基于上升沿到下降沿和下降沿到上升沿。尽管TimeQuest分析了设置和保持的所有四种情况,但只有两种最严格的情况用于限制时间。四种情况中的两种如图13所示。
使用图13中所示的较短的设置和保持时间是因为它们比较长的设置和保留时间更具限制性。示例代码中的SDC文件包含ADC锁存器和启动时钟之间的set_false_path语句,该语句告诉TimeQuest忽略这些额外的设置和保持时间,这简化了分析和定时报告,但它们不是正确分析所必需的。
对于TX侧,首先需要添加DAC3482的输入时钟,如下所示。该时钟应用于输入端口lvds_tx_fpga_clk_p,并用作tx_PLL块的输入时钟。
create_clock -name TX_FPGA_CLK -period 4.00 [get_ports lvds_tx_fpga_clk_p]
接下来,DAC启动时钟是手动创建的,而不是通过derive_pll_clocks语句,允许使用更方便的时钟名称,如下所示。这样,在其他语句中使用名称DAC_LAUNCH_CLK来定义PLL输出时钟,而不是使用较长的自动生成名称。这两个时钟定义必须位于前面提到的derive_pll_clocks语句之前。
create_generated_clock -name DAC_LAUNCH_CLK \ -source [get_pins {TX_PLL_inst|altpll_component|auto_generated|pll1|inclk[0]}] \ [get_pins {TX_PLL_inst|altpll_component|auto_generated|pll1|clk[0]}]
接下来,推导上述PLL时钟和时钟不确定性,然后定义DAC数据输出时钟,如下所示。以下语句定义了FPGA输出端口的DAC数据时钟。虽然该时钟是由ALTDDIO_clock_OUT函数生成的,但时钟的来源是90°相移PLL时钟输出。ALTDDIO_CLOCK_OUT输出应用于端口lvds_tx_data_clk_p。
create_generated_clock -name DAC_DATA_CLK \ -source [get_pins {TX_PLL_inst|altpll_component|auto_generated|pll1|clk[1]}] \ [get_ports lvds_tx_data_clk_p]
图14:ADS4249数据表中的时间要求
图15提供了ADC设置和保持时间以及必须定义的输入延迟的图形视图。在图中,绿色块表示FPGA允许在内部引入的总偏斜,红色块表示ADC可能在数据线上引入的最大和最小延迟。
图15:SDC输入时序约束图
由于ADC建立和保持时间定义了数据时钟周围的数据有效窗口,因此很直观的是,ADC以数据线上的延迟形式消耗了时钟周期的其余部分。然后,SDC文件中定义的输入定时延迟指定了ADC可能引入的数据延迟范围。因此,最小和最大延迟被定义为下面的方程。方程式中使用的变量如图15所示。
这些方程假设电路板上的数据和时钟走线匹配良好。如果数据走线比时钟走线长,则会减少设置时间并增加保持时间,因此最大延迟增加,最小延迟相应减少。如果时钟走线比数据走线长,则会减少保持时间并增加设置时间,因此最小延迟增加(变得更负),最大延迟相应减少。
图16:SDC输出时序约束图
同样,这些延迟只有在数据和时钟线精确匹配的情况下才有效。如果走线之间存在不匹配,则需要考虑延迟。如果数据走线比时钟走线长,则最大延迟增加,最小延迟相应减少。如果时钟走线比数据走线长,则最大延迟减小,最小延迟增大。
3. ADC接口设计不使用PLL情况
当与许多设备连接时,很容易消耗FPGA的所有PLL。在这种情况下,最好避免将PLL用于接收设备。可以将时钟引入FPGA,并直接在ALTDDIO_IN块中使用。需要注意的是,FPGA内不再像使用具有源同步补偿的PLL时那样保持时钟与数据的关系。因此,FPGA必须匹配时钟和数据线之间的延迟,以满足中心对齐接口的必要时序。这应该是可能的,因为FPGA I/O单元具有可调的数据延迟。如果时间约束设置正确,应该能够匹配时钟和数据走线之间的延迟。
如果无法满足时序要求或满足时序要求的结果很差,则可以使用ADS4249的时钟偏移功能来移动与数据相比的时钟沿,以放宽FPGA内部的匹配要求。如果这样做,则需要更新时序约束以匹配ADC接口的新时序。