当前位置:   article > 正文

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

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端,输入
   );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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)            // 复位信号,输入
   );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

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

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

数据整型

在实际传输中,由于存在抖动毛刺的现象,很难避免对数据采集错误的发生,毛刺分为数据中间与边沿两种情况,采用整型滤波的方式可去除数据的突变,使数据平滑。
整型滤波原理如下图所示,缓存一拍采样数据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])};
  • 1

边沿检测

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

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

鉴相编码

缓存一拍数据,对比上位数据,若这一位边沿检测数据为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);//对比上一位数据
  • 1
  • 2

对鉴相编码进行采集位置判定,为采集到数据中段,选择编码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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  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的设计及验证》 姚飞.西安电子科技大学
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/643571
推荐阅读
相关标签
  

闽ICP备14008679号