FPGA基础知识14(跨时钟域处理--异步时钟)

需求说明:IC设计基础

内容       :第一部分 FPGA跨时钟域的处理方法

                  第二部分 基于FPGA的跨时钟域信号处理——专用握手信号

来自       :时间的诗


第一部分 FPGA跨时钟域的处理方法

原文:http://blog.csdn.net/verylogic/article/details/21410077


在一个fpga系统设计中,经常需要处理多个时钟来源,比如FPGA作为一个转发桥连接几个不同的IC。不同的时钟域有不同的时钟频率和时钟相位。如何处理好多个时钟信号在FPGA内部的关系,让数据以及相关的控制信号在不同的时钟域之间准确的传递就是一个比较困难的问题。在这种情况下,建立与保持时间就显得尤为重要。理论上完美的信号应该是矩形的,上升和下降时间为0,在低速率系统中,上升下降时间确实可以忽略不计,但在高速系统中,这个时间不能忽略。在数字系统中0和1的判决在于电压,高于一个电压值表示为1,低于一个电压值表示为0,在这两个电压之间存在一个中间不确定状态的值,当跨时钟域的时候,新的时钟域时钟采样时间恰好落在这个区间内,就可能发生错误,这就是数字系统中最需要避免的亚稳态。如何避免呢?

最好的办法是采用FIFO,读写时钟分别是两个时钟域的时钟,通过FIFO的满空状态,以及读写使能,控制好输入输出的流量。

还有一种办法就是使用双锁存器的办法,即一个信号从A时钟域进入另一个时钟域B的时候,先用B时钟对输入信号连续锁存2次,然后再在B时钟域中使用,可以有效消除亚稳态,不过需要注意的是假如A时钟频率低于B时钟频率的时候,出现数据被插值,即一组数据,本来是10个字节依次传递过来,但到达B时钟域后,因为B时钟较快,而数据变化速率依然是A时钟频率决定,于是数据可能会出现被多次采样,造成不被期望产生的插值,变成十几个乃至几十个数据。当A时钟频率高于B时钟频率的时候,可能会出现信号漏采的问题。所以采用FIFO是更稳妥的办法,当然FIFO也有一定的局限性,所以需要灵活的使用这两种办法,以达到最佳效果。


第二部分 基于FPGA的跨时钟域信号处理——专用握手信号

原文:http://www.eepw.com.cn/article/269611.htm


      在逻辑设计领域,只涉及单个时钟域的设计并不多。尤其对于一些复杂的应用,往往需要和多个时钟域的信号进行通信。异步时钟域所涉及的两个时钟之间可能存在相位差,也可能没有任何频率关系,即通常所说的不同频不同相。

      图1是一个跨时钟域的异步通信实例,发送域和接收域的时钟分别是clk_a和clk_b。这两个时钟频率不同,并且存在一定的相位差。对于接收时钟域而言,来自发送时钟域的信号data_a2b有可能在任何时刻变化。

  

点击看大图

 

  图1 跨时钟域通信

  对于上述的异步时钟域通信,设计者需要做特殊的处理以确保数据可靠的传输。由于两个异步时钟域的频率关系不确定,触发器之间的建立时间和保持时间要求也无法得到保证。如果出现建立时间或者保持时间违规,接收域将会采样到处于亚稳态数据,那么后果可想而知。

  如何有效的进行跨时钟域的信号传输呢?最基本的思想是同步,在这个基础上设计者可以利用各种协议约定进行通信。单向控制信号检测方式(前面提到过的脉冲信号检测方法,这里为了和握手方式相区别,所以如此称呼)、握手协议的方式或者借助存储器的方式都是比较常用的处理手段。

  本文将重点介绍握手方式进行异步时钟域的通信。

  图2是一个基本的握手通信方式。所谓握手,意即通信双方使用了专用控制信号进行状态指示。这个控制信号既有发送域给接收域的,也有接收域给发送域的,有别于前面的单向控制信号检测方式。

  

点击看大图

 

  图2 握手通信原理

  使用握手协议方式处理跨时钟域数据传输,只需要对双方的握手信号(req和ack)分别使用脉冲检测方法进行同步。在具体实现中,假设req、ack、data总线在初始化时都处于无效状态,发送域先把数据放入总线,随后发送有效的req信号给接收域。接收域在检测到有效的req信号后锁存数据总线,然后回送一个有效的ack信号表示读取完成应答。发送域在检测到有效ack信号后撤销当前的req信号,接收域在检测到req撤销后也相应撤销ack信号,此时完成一次正常握手通信。此后,发送域可以继续开始下一次握手通信,如此循环。该方式能够使接收到的数据稳定可靠,有效的避免了亚稳态的出现,但控制信号握手检测会消耗通信双方较多的时间。以上所述的通信流程如图3所示。

  

点击看大图

 

  图3 握手通信流程

  下面通过一个简单的工程代码及其仿真测试进一步加深大家对基本握手协议的认识。

  

module handshack(
  clk,rst_n,
  req,datain,ack,dataout
  );

  input clk; //50MHz系统时钟
  input rst_n; //低电平复位信号
  input req; //请求信号,高电平有效
  input[7:0] datain; //输入数据
  output ack; //应答信号,高电平有效
  output[7:0] dataout;//输出数据,主要用于观察是否和输入一致

  //--------------------------------------
  //req上升沿检测
  reg reqr1,reqr2,reqr3;
  always @(posedge clk or negedge rst_n)
  if(!rst_n) begin
  reqr1 <= 1'b1;
  reqr2 <= 1'b1;
  reqr3 <= 1'b1;
  end
  else begin
  reqr1 <= req;
  reqr2 <= reqr1;
  reqr3 <= reqr2;
  end

  //pos_req2比pos_req1延后一个时钟周期,确保数据被稳定锁存
  wire pos_req1 = reqr1 & ~reqr2; //req上升沿标志位,高有效一个时钟周期
  wire pos_req2 = reqr2 & ~reqr3; //req上升沿标志位,高有效一个时钟周期

  //--------------------------------------
  //数据锁存
  reg[7:0] dataoutr;
  always @(posedge clk or negedge rst_n)
  if(!rst_n) dataoutr <= 8'h00;
  else if(pos_req1) dataoutr <= datain; //检测到req有效后锁存输入数据
  assign dataout = dataoutr;

  //--------------------------------------
  //产生应答信号ack
  reg ackr;
  always @(posedge clk or negedge rst_n)
  if(!rst_n) ackr <= 1'b0;
  else if(pos_req2) ackr <= 1'b1;
  else if(!req) ackr <= 1'b0;
  assign ack = ackr;
  endmodule



  该实例的verilog代码模拟了握手通信的接收域,其仿真波形如图4所示。在发送域请求信号(req)有效的若干个时钟周期后,先是数据(datain)被有效锁存了(dataout),然后接收域的应答信号(ack)也处于有效状态,此后发送域撤销请求信号,接收域也跟着撤销了应答信号,由此完成一次通信。

  

点击看大图

 

  图4 握手通信仿真波形




  • 15
    点赞
  • 115
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值