Menu Close

Verilog自适应位同步信号提取

在异步通信中数据位的提取至关重要,如果能够准确的把数据位提取出来,在后面的字同步,帧同步以及数据包同步都会迎刃而解。如果熟悉计算机异步串行口通信的原理,我们就知道要想准确的接受串行口的数据帧(基本数据帧如图1),首先要准确识别start位,这就对start位准确采样提出要求。关于UART的详细内容请参照本教材的相关章节。

图1 UART 基本数据帧

在对异步串行数据采样中,由于采用本地时钟,因此对接受的串行数据流是异步采样,对于异步采样及同步处理可以按照如下步骤进行。

  1. 首先要时钟同步化处理,消除亚稳态的影响,
  2. 提取串行数据流中的边沿脉冲(上升沿,下降沿,双边沿),
  3. 数据采样定位,
  4. 同步数据为输出。

在上几节内容中介绍了时钟同步化原理及处理办法,以及串行数据流边沿提取的方法,本节内容着重介绍数据采样定位以及数据位同步输出。

1.采样定位原理

采样定位的原理,如图2所示,利用本地时钟获取数据流的边沿后,通过延迟将对数据流(bit流)中的某个bit进行中心定位并采样。由于延迟的原因,因此采样对应的原数据也要对应的延迟。在高速串行通信中最理想的就是能做到对每个数据位(bit)进行相位矫正,但由于原始数据传输时不可能每个bit都含有时钟信息,因此在对没有边沿变化的数据位采样时,按照过采样时钟的倍数进行延迟。如图2中成功得到上升沿后,延迟3个时钟对RX_rrr进行采样,但相邻的下一个bit的采样(采样点2)就只能依赖本地时钟的计数器实现,如4倍过采样就需要延迟4个过采样时钟进行采样。

图2       4倍过采样时序图

图2中 RX为原始接收数据,RX_r,RX_rr,RX_rrr分别经过过采样时钟锁存的三个信号,双边沿脉冲为RX_r与RX_rr异或产生。采样点分布在RX_rrr上。图2中的时序图显示的各个信号之间的关系可以由如下Verilog代码实现。

module recv_bit
(
    input rst,
    input clk_400M ,   //400Hz
    input rx,
    output reg rx_bit,
    output reg rx_bit_vld,


    output reg rx_r,     //r---register
    output reg rx_rr,     //rr--- rx_r registered
    output reg rx_dg  //dg----double (dual) edge, 上升沿或下降沿
);



////=========rx_r^rx_rr==1,dual edge


wire rx_out;
reg rx_rrr;
reg [ 1: 0 ] sample_count = 0;


always@( posedge clk_400M or posedge rst )

    if ( rst )
    begin
        rx_r <= 0;
        rx_rr <= 0;
        rx_rrr <= 0;
        rx_dg <= 0;

    end
    else
    begin
        rx_r <= rx_out;
        rx_rr <= rx_r;
        rx_rrr <= rx_rr;
        rx_dg <= rx_r ^ rx_rr;    //dual edge
    end




always@( posedge clk_400M or posedge rst )

    if ( rst )
    begin
        rx_bit_vld <= 0;
        rx_bit <= 0;
        sample_count <= 0;
    end
    else
    begin
        rx_bit_vld <= 0;

        if ( sample_count == 2 )    //0,1,2,3,0,1,2,3...
        begin
            rx_bit <= rx_rrr; //
            rx_bit_vld <= 1'b1;
        end


        if ( rx_dg )                  // 2 3 0  0
            sample_count <= 0;
        else
            sample_count <= sample_count + 1'b1;
    end

IO_RX IO_RX_inst
(
    .rx_in ( rx ),
    .rx_out ( rx_out )
);



endmodule

 

仿真程序:

`timescale 10 ps / 1 ps
module tb_recv_bit
       (
       );


parameter PERIOD_ORG = 1000 ;         
parameter PERIOD_OVER = 250;
reg org_clk = 0;
reg over_sample_clk = 0;

always # ( PERIOD_ORG / 2 ) org_clk = ~org_clk;
always # ( PERIOD_OVER / 2 ) over_sample_clk = ~over_sample_clk;

wire rx_bit;
wire rx_bit_vld;
wire rx_dg;

reg rst;
reg rx;

initial
begin
    rst = 1;
    rx  = 0;

    #1000
    rst = 0;

    #1000
    rx = 0;

    #2000
    rx = 1;

    #4000
    rx = 0;

    #8000
    rx = 1;

    #8000
    rx = 0;

    #8000
    rx = 1;

    #1000
    rx = 0;

    #4000
    rx = 1;

    #2000
    $stop;


end

recv_bit recv_bit_inst
(
    .rst        ( rst ),
    .clk_400M   ( over_sample_clk ),
    .rx         ( rx ),
    .rx_bit     ( rx_bit ),
    .rx_bit_vld ( rx_bit_vld ),
    .rx_r       (),
    .rx_rr      (),
    .rx_dg      ( rx_dg )

);

endmodule

 

仿真波形:

图3

2. 采样相位校准

从图3的仿真波形可以看出,在采样点S1之前由于没有边沿矫正,采样完全按照本地过采样时钟进行,因此S1采样点距离rx_rrr的边沿比较近,而且这个距离是随机的,取决于本地时钟稳定的时刻,以及远程时钟与本地时钟频率的差异。S6是第二个边沿的校准采样点,由于收发时钟频率相同,因此经过S1校正后,后面都同步跟随,因此S6点实际上没有校准。以下情况会发生校准情况。

(1) 收发时钟频率不同

虽然目前无论晶振还是有源震荡器的精度都比较高(如 50ppm),但收发双方的时钟频率不可能完全相等,因此随着时间的累积,在捕获边沿后必然会发生调整。

(2)由于直流不平衡,PCB布线不等长等诸多因素眼图没有完全张开,使数据流中边沿的位置发生偏移,此时会出现采样点的调整。

不管是什么原因发生了边沿调整,都会将采样点调整到做合适的位置采样,而且采样点调整又是自动实现的,因此称为自适应位同步信号提取。

可以改变仿真程序测试采样点的调整过程,

`timescale 10 ps / 1 ps
module tb_recv_bit
       (
       );


parameter PERIOD_ORG = 1000 ;          
parameter PERIOD_OVER = 250;
reg org_clk = 0;
reg over_sample_clk = 0;

always # ( PERIOD_ORG / 2 ) org_clk = ~org_clk;
always # ( PERIOD_OVER / 2 ) over_sample_clk = ~over_sample_clk;

wire rx_bit;
wire rx_bit_vld;
wire rx_dg;

reg rst;
reg rx;

initial
begin
    rst = 1;
    rx = 0;

    #1000
    rst = 0;
    
    #1000
    rx = 0;
    
    #2000
    rx = 1;
    
    #3800      //缩短2ns,
    rx = 0;

    #8200
    rx = 1;
    
    #8000
    rx = 0;
    
    #8000
    rx = 1;
    
    #1000
    rx = 0;
    
    #4000
    rx = 1;
    
    #2000
    $stop;


end

recv_bit recv_bit_inst
(
    .rst        ( rst ),
    .clk_400M   ( over_sample_clk ),
    .rx         ( rx ),
    .rx_bit     ( rx_bit ),
    .rx_bit_vld ( rx_bit_vld ),
    .rx_r       (),
    .rx_rr      (),
    .rx_dg      ( rx_dg )

);

endmodule

 

图4

图4中可以看出有两处调整,一处是在初始化阶段rx输入都是0,一直没有边沿,因此在第一个边沿处发生调整,可以看到正常sample_count的计数都是0,1,2,3,0而在调整的地方变成0,1,2,0,因此直接影响下一次的采样间隔。

3. 位采样输出

由于使用过采样的方法,每个位的输出宽度是过采样时钟的过采样倍数。如4倍过采样的位输出宽度基本上为4个时钟周期, 同时伴随着的有rx_bit_vld信号指示采样时刻,该信号的宽度为一个时钟周期,如图4所示,实现代码如下,

rx_bit_vld<=0;

if(sample_count==2) //0,1,2,3,0,1,2,3…

begin

rx_bit<=rx_rrr; //

rx_bit_vld<=1’b1;

end

 

关于收发时钟频率差异的处理,将在介绍帧同步的文章中详细探讨。

Posted in FPGA, FPGA 教材教案, Verilog, 开发语言, 教材与教案, 文章

3 Comments

  1. 13545030837

    rx 和 rx_r的信号为什么没有延后一个完整的时钟周期?延后的时钟周期不应该最少是1个时钟周期及以上吗?怎么看仿真波形,延后了半个时钟周期也行呢?

  2. 陈工

    采集异步串行信号:
    1.新手:通过边沿判断,获得到采样起始点之后,后面的信号都是在本地时钟下按照约定的时间间隔来采集信号;
    2.老手:通过边沿判断,获得到采样起始点之后,如果信号没有翻转,在本地时钟下按照约定的时间间隔来采集信号;如果信号有翻转,重新获得采样起始点,这样可以不断地校准和对齐异步串行信号。

发表回复

相关链接