基于FPGA的CDR时钟恢复设计

慈云数据 2024-03-27 技术支持 128 0

文章目录

  • 前言
  • 一、CDR原理
  • 二、CDR实现电路
  • 三、仿真波形
  • 总结

    [参考文献]

    [1] https://blog.csdn.net/yijingjijng/article/details/48024059

    前言

      CDR全称为Clock and Data Recovery,即时钟数据恢复。顾名思义,CDR就是接收端根据接收到的数据信号恢复出时钟,以便于接收端对数据信号进行恢复和处理。

    那为什么需要CDR呢?CDR一般应用于串行数据的恢复,那为什么不像SPI一样多传输一条数据线呢?我们知道SPI的最大传输速度也就几Mbps,这对图像等实时传输是不可能的。而如果速度传输加快,信道对传输信号的影响变大,会导致时钟和数据信号产生不同程度的影响,导致误码。因此后面演变出了SerDes这类高速传输方式,其采用LVDS差分信号进行数据传输,同时省去了时钟线,接收端再根据接收到的差分数据信号进行CDR处理,恢复出时钟和数据。

      本文是基于FPGA全数字电路实现的,重在实现的逻辑,没有物理层的优化,也就意味着无法对太高速的数据进行恢复,仅供参考。

    一、CDR原理

      目前基于FPGA的全数字CDR设计基本上都是采取了过采样的方式实现,具体可以使用同频多相时钟采样和数据延迟链采样两种方式实现。核心都是采用Nxf的高速时钟,对信号进行N倍的过采样,通过对采样后数据进行判断分析,得到数据跳变沿的位置,再用最佳的采样点进行恢复数据。但是对于A7系列FPGA来说,PLL最大只能生成600MHz左右的时钟,因此对于高速信号直接使用Nxf的高频时钟采样是很困难的。

      本文采用同频多相时钟采样的方式实现CDR,利用PLL产生0°和90°相位差的采样时钟,两时钟利用双沿采样,如此起到了4倍上采样的效果。最后通过一个判决器对四个采样点进行判决,得到信号跳变沿的位置,再选取最佳的采样点恢复出数据。

      如下图所示,数据信号发生跳变时存在四种情况,跳变沿前后两个采样点采样得到的值不一样,如此便能通过四个采样数值得到跳变沿所在的位置,再选取合适的采样点进行数据的恢复,比如说情况1,信号的上升沿在第一个和第二个采样点之间,可选择相对稳定的第三个采样点作为数据恢复点,以此类推。

    在这里插入图片描述

    二、CDR实现电路

    在这里插入图片描述

    代码实现

     module CDR(
        input clk_0,
        input clk_90,
        input rst_n,
        input ser_in,
        
        output ser_clk,
        output ser_out,
        output [3:0] debug
        );
        reg data00,data01,data02,data03;
        reg data10,data11,data12,data13;
        reg data20,data21,data22,data23;
        reg data30,data31,data32,data33;
        reg data04,data14,data24,data34;
        wire cdr_en ;
        reg [3:0] pos_neg;
        assign debug = {data34,data24,data14,data04};
        assign ser_out = (pos_neg[0])?data23:
                         (pos_neg[1])?data33:
                         (pos_neg[2])?data03:
                         (pos_neg[3])?data13:0 ;
                                      
        assign ser_clk = (pos_neg[0])?~clk_0 :
                         (pos_neg[1])?~clk_90:
                         (pos_neg[2])? clk_0 :
                         (pos_neg[3])? clk_90:0 ;
        //Determine which position is the edge
        always @(posedge clk_0  or negedge rst_n)begin
            if(!rst_n) pos_neg 
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon