赞
踩
一言蔽之,就是利用PLL产生多个不同相位的同频时钟,对数据进行多倍采样后判决最佳采样位,将接收数据恢复输出。
如图所示,过采样恢复数据基本流程如下:
不过在实际测试中(核心板为正点原子的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端,输入
);
对两路互补数据进行延迟,p端根据数据频率延迟1/8bit,n端延迟0bit。
由于经过idelay即使打0拍也有固定延迟,所以n端数据也需要经过idelay。
图中0°Data为延迟1/8bit的p端数据,45°Data为0延迟的n端数据。采样关系如下表。
时钟 | 0°Data | 45°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,如下图所示。
数据选择基本流程:
判断当前周期内需要恢复的数据位数。
当周期内需要恢复两个数据时,由于鉴相编码的方式,需要恢复的数据会分别出现在高位与低位。
//两个恢复数据
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;
将对应位置的数据缓存进data[cnt],并根据需要恢复的数据位数计数cnt+0/1/2。
cnt计数到7时置零,并将data[0:7]写入FIFO。
其中值得注意的情况有两种:
具体流程如下图。
整体框图如上图所示,差分信号缓冲后的互补信号进入过采样同步数据恢复模块,并输出恢复数据进行后续处理。
参考
《Efficient 8X Oversampling Asynchronous Serial Data Recovery Using IDELAY》
《基于过采样的数字CDR的设计及验证》 姚飞.西安电子科技大学
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。