基于FPGA的LVDS过采样数据恢复设计

工作原理

一言蔽之,就是利用PLL产生多个不同相位的同频时钟,对数据进行多倍采样后判决最佳采样位,将接收数据恢复输出。

在这里插入图片描述
如图所示,过采样恢复数据基本流程如下:

  1. 8倍过采样:生成相位分别为0,45°,90°,135°的四个时钟通过双边沿对数据进行采样,以获得8倍过采样的效果。
  2. 边沿检测:对相邻采样信号进行异或,若异或结果为1,则表示相邻信号间存在边沿。
  3. 鉴相编码:8倍过采样采用3位编码,第一位编码为0,后续位置编码结果为上一个编码加1直到加到7,若遇到数据边沿,则编码又从0开始。
  4. 数据恢复:为采样到数据段中间位置,以编码为3或4时的数据作为最终恢复结果。

不过在实际测试中(核心板为正点原子的ZYNQ7020),仅采用上述逻辑实现的过采样数据恢复系统有两点无法忽视的现象会对造成严重的误码率:

  • 四个时钟的相位抖动较大,采样数据出错频率不可容忍。
    在这里插入图片描述
    如图所示,此处准确数据应为<0000_0000>,<1110_0000>(低位在前),而采样出现了3位突变,导致了后续数据恢复的出错。

  • 实际传输中由于边沿毛刺和频偏的存在,1和0的长度并不总是恰好相等,因此一个时钟周期内会出现0个或2个采样判决位。如下图所示。
    在这里插入图片描述

    因此,需要对原流程进行调整,最终方案如下:

在这里插入图片描述
对接收的差分数据进行缓冲互补输出,对p端数据打拍1/8bit,n端数据无延迟,利用0,90°两个相位的时钟对两路数据分别进行双边沿采样,极大地减小了时钟相位抖动的影响。
此外在数据恢复单元根据周期内采样判决位的数量(0/1/2),分别缓存相应数据后写入fifo,保证数据的完整性。

模块实现

差分信号处理

使用原语IBUFDS_DIFF_OUT,输出互补数据。

IBUFDS_DIFF_OUT #(
    .DIFF_TERM("TRUE"),   // 是否为差分终端(TRUE/FALSE)
    .IBUF_LOW_PWR("FALSE"), // 高性能:FALSE,低功耗:TRUE
    .IOSTANDARD("LVDS25") // IO电平标准
   ) IBUFDS_DIFF_OUT_inst (
    .O(datain_p),   // 缓冲信号p端,输出
    .OB(datain_n), // 缓冲信号n端,输出
    .I(data_p),   // 接收差分信号p端,输入
    .IB(data_n)  // 接收差分信号n端,输入
   );

8倍过采样同步

对两路互补数据进行延迟,p端根据数据频率延迟1/8bit,n端延迟0bit。

由于经过idelay即使打0拍也有固定延迟,所以n端数据也需要经过idelay。

在这里插入图片描述
图中0°Data为延迟1/8bit的p端数据,45°Data为0延迟的n端数据。采样关系如下表。

时钟0°Data45°Data
CLK0↑sample_0°~sample_45°
CLK90↑sample_90°~sample_135°
CLK0↓sample_180°~sample_225°
CLK90↓sample_270°~sample_315°

打拍使用原语idelay2。

IDELAYCTRL IDELAYCTRL_0 (
    .RDY(RDY),       // 准备信号,输出
    .REFCLK(clk_200), // 参考时钟,输入
    .RST(!rst_n)        //复位信号,输入
   );

//p端延迟 
IDELAYE2 #(
    .CINVCTRL_SEL("FALSE"),          // 动态转换时钟极性切换,未使用
    .DELAY_SRC("IDATAIN"),           //  IBUF输入选择IDATAIN
    .HIGH_PERFORMANCE_MODE("TRUE"), //是否减少时钟抖动(TRUE/FALSE)
    .IDELAY_TYPE("FIXED"),     // 固定延迟
    .IDELAY_VALUE(10),      // 延迟拍数(0-31)
    //参考时钟200MHz的场合1tap≈78ps(=(1/200M)/64)
    .PIPE_SEL("FALSE"),              // pipelined模式,未使用
    .REFCLK_FREQUENCY(200.0),        // 参考时钟
    .SIGNAL_PATTERN("DATA")          // 数据/时钟输入
   )IDELAYE2_0(
    .CNTVALUEOUT(cnt_delay_tap), //延迟拍数,输出
    .DATAOUT(data_0),         // 延迟后的数据,输出
    .C(clk_200),                //时钟,输入
    .CE(1'b0),                   //使能增加减少
    .CINVCTRL(1'b0),       // 动态转换时钟极性,未使用
    .CNTVALUEIN(0),   		//动态延迟拍数,输入,未使用
    .DATAIN(1'b0),           //来自FPGA逻辑的数据,输入,未使用
    .IDATAIN(datain_p),         //来自IBUF的数据,输入
    .INC(1'b0),                 //增减延迟拍数,输入,未使用
    .LD(1'b0),				//在VARIABLE模式使用加在delay2延时的值,输入,未使用
    .LDPIPEEN(1'b0),       //使能pipelined模式寄存器加载数据,输入,未使用
    .REGRST(!rst_n)            // 复位信号,输入
   );

延迟后的两路数据分别用CLK0,CLK90进行采样拼接,输出采样数据为:

//低位在前
sampleout < = {~sample_315,sample_270,~sample_225,sample_180,~sample_135,sample_90,~sample_45,sample_0};

数据整型

在实际传输中,由于存在抖动毛刺的现象,很难避免对数据采集错误的发生,毛刺分为数据中间与边沿两种情况,采用整型滤波的方式可去除数据的突变,使数据平滑。
整型滤波原理如下图所示,缓存一拍采样数据d0[0]d0[7],与当前采样数据d1[0]d1[7],连续5个型号相加得到d_add_0~d_add_7,与阈值3’b010进行比较,大于该阈值则判断该点采样信号为1’b1,否则为1’b0。放入d_real作为模块输出。

在这里插入图片描述
输出整型后的数据为:

fitter_data < = {(d_add_7[2]|d_add_7[1]&d_add_7[0]),(d_add_6[2]|d_add_6[1]&d_add_6[0]),(d_add_5[2]|d_add_5[1]&d_add_5[0]),(d_add_4[2]|d_add_4[1]&d_add_4[0]),(d_add_3[2]|d_add_3[1]&d_add_3[0]),(d_add_2[2]|d_add_2[1]&d_add_2[0]),(d_add_1[2]|d_add_1[1]&d_add_1[0]),(d_add_0[2]|d_add_0[1]&d_add_0[0])};

边沿检测

简单的异或处理,需要缓存一拍数据。

assign trans_data[0]=fitter_data[0]^q1[7]; 	//与上一个数据的最后一位进行异或
assign trans_data[1]=fitter_data[1]^fitter_data[0];	//与上一位数据进行异或

鉴相编码

缓存一拍数据,对比上位数据,若这一位边沿检测数据为1(即有边沿翻转)或上一位鉴相编码为7,则该位鉴相编码置零重新开始计数,否则+1。

assign samcode[0]=trans_data[0]?3'd0:(q2+3'd1);//对比上一个数据的最后一位
assign samcode[1]=trans_data[1]?3'd0:(samcode[0]+3'd1);//对比上一位数据

对鉴相编码进行采集位置判定,为采集到数据中段,选择编码3或4为最佳采集位。

例如该周期内鉴相编码为{4,5,6,7,0,1,2,3},则位置判定为<0000_0001>,周期内编码为{3,4,5,6,0,1,2,3}时,位置判定为<1000_0001>。

数据选择

在理想情况下,每个时钟周期都应有且只有一个需要恢复的数据,但由于存在边沿毛刺现象,在一个时钟周期内可能会存在0个或者2个数据需要恢复,通过周期内鉴相编码3出现的次数,判断周期内需要恢复的数据数量,写入fifo,如下图所示。

在这里插入图片描述
数据选择基本流程:

  1. 判断当前周期内需要恢复的数据位数。
    当周期内需要恢复两个数据时,由于鉴相编码的方式,需要恢复的数据会分别出现在高位与低位。

    //两个恢复数据
    assign two = ([0]|pos[1]|pos[2]) & (pos[5]|pos[6]|pos[7]);
    //一个恢复数据
    assign one = !two & (pos[0]|pos[1]|pos[2]|pos[3]|pos[4]|pos[5]|pos[6]|pos[7]);
    //零个恢复数据
    assign zero = !one&!two;
    
  2. 将对应位置的数据缓存进data[cnt],并根据需要恢复的数据位数计数cnt+0/1/2。

  3. cnt计数到7时置零,并将data[0:7]写入FIFO。

    • data位宽为9bit,只将低8位写入FIFO。
    • FIFO读出时先读高位,需要注意数据大小端。

其中值得注意的情况有两种:

  • 当计数到7,而此周期采集位置判决为2,则需要将高位缓存至data[8],在下个周期时data[8]数据写入data[0],并将下个周期的采集数据顺延。
  • 当计数为0,上个周期采集位置判决不为2,且这个周期采集位置判决为0时,该周期内不将data写入fifo。

具体流程如下图。

在这里插入图片描述

在这里插入图片描述
整体框图如上图所示,差分信号缓冲后的互补信号进入过采样同步数据恢复模块,并输出恢复数据进行后续处理。

参考
《Efficient 8X Oversampling Asynchronous Serial Data Recovery Using IDELAY》
《基于过采样的数字CDR的设计及验证》 姚飞.西安电子科技大学
  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
FPGA(现场可编程门阵列)是一种集成电路芯片,具有高度可编程性和灵活性。而LVDS(低压差分信号)是一种常用的差分信号传输标准,具有低功耗和高带宽的特点。 对于FPGA来说,采集LVDS信号数据对齐是一个重要的问题。数据对齐是指在将多个LVDS信号输入FPGA之前,将它们的时序做出调整,使得这些信号在FPGA内部可以同时进行数据处理。数据对齐的目的是确保FPGA能够准确记录和处理输入信号。 在实现LVDS信号数据对齐时,一种常见的做法是使用时钟对齐技术。该技术通过使用一个高频的时钟信号来采样LVDS信号,以确保采样的时机一致。 首先,需要在FPGA内部生成一个与输入LVDS信号相同频率的时钟信号。这个时钟信号作为采样时钟,用于控制时序的调整。其次,需要将LVDS信号输入到FPGA的输入引脚,同时使用时钟信号进行采样。采样完成后,可以得到与LVDS信号具有相同频率的数字信号。 然后,通过对FPGA内部的数字信号进行时序分析和处理,可以实现数据的对齐。通过对齐,输入的多个LVDS信号就可以在FPGA内部进行并行处理了。 总之,FPGA采集LVDS信号数据对齐是通过使用时钟对齐技术来实现的。通过生成相同频率的时钟信号对LVDS信号进行采样,然后在FPGA内部进行时序调整和处理,从而实现对数据的精确记录和处理。这种技术在许多应用中都具有重要的意义,如高速数据采集和图像处理等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值