我是靠谱客的博主 背后台灯,最近开发中收集的这篇文章主要介绍FPGA面试笔试专题——跨时钟域处理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

跨时钟域处理时需要考虑两个方面:

方面1:不同位宽,处理方式不同

  • 位宽为1,可以采用寄存器打两拍的方式;
  • 位宽为多位时,需要采用异步FIFO、转换为格雷码、握手等;

异步FIFO:通过异步读写,以及空满标志实现了跨时钟数据同步。

转换为格雷码:利用相邻格雷码仅一位改变的特性,实现跨时钟域数据同步。

握手:在具体实现中,假设 req、ack、data 总线在初始化时都处于无效状态,发送域先把数据放入总线,随后发送有效的 req 信号给接收域。接收域在检测到有效的 req 信号后锁存数据总线,然后回送一个有效的 ack 信号表示读取完成应答。发送域在检测到有效 ack 信号后撤销当前的 req 信号,接收域在检测到 req 撤销后也相应撤销 ack 信号,此时完成一次正常握手通信。此后,发送域可以继续开始下一次握手通信,依次循环。但是握手方式效率较低。

方面2:时钟域快慢不同,处理方式不同

时钟从慢到快时:数据一定会被快的时钟采到,信号先在慢时钟域抓一拍,然后打两拍传向快时钟域;

时钟从快到慢时,需要进行数据展宽:快时钟域变换的数据慢时钟域有可能采不到,因此需要先把数据在快时钟域下展宽,使其大于慢时钟域的一个时钟周期,再向慢时钟域传递,当慢时钟域的信号已经采样到信号时,再清理展宽的信号;

以数据上升沿展宽为例:

快时钟域检测到输入上升沿来临,就将展宽信号拉高,直至接收到慢时钟域的反馈信号才将展宽信号降低。

慢时钟域对展宽信号进行打拍同步,并反馈到慢时钟域将展宽信号降低。代码如下(直接粘贴了附录博客中的代码):

 module  Sync_Pulse(
                                         input              clk_a,
                                         input              clk_b,
                                         input              rst_n,
                                         input              pulse_a_in,
                                         output           pulse_b_out,
                                         output           b_out
                                          );
  /**************************************************************************************/
  reg                          signal_a;
  reg                          signal_b;
  reg                          signal_b_s;
  reg                          signal_b_ss;
  reg                          signal_b_a1;
  reg                          signal_b_a2;

//在时钟域clk_a下,生成展宽信号signal_a
    always @ (posedge clk_a or negedge rst_n)
        begin
            if (rst_n == 1'b0)
                signal_a <= 1'b0;
            else if (pulse_a_in)            //检测到到输入信号pulse_a_in被拉高,则拉高signal_a
                signal_a <= 1'b1;
            else if (signal_b_a2)           //检测到signal_b1_a2被拉高,则拉低signal_a
                signal_a <= 1'b0;
            else;
        end
//在时钟域clk_b下,采集signal_a生成signal_b

always@(posedge clk_b or negedge rst_n)begin
            if(rst_n == 1'b0)begin
                signal_b <= 0;
           end
           else begin
               signal_b <= signal_a;
           end
end
//多级触发器将clk_b抓到的signal_b信号打两拍输出
always@(posedge clk_b or negedge rst_n)begin
       if(rst_n == 1'b0)begin
       signal_b_s  <= 1'b1;
       signal_b_ss <= 1'b1;
       end
       else begin
       signal_b_s  <= signal_b;
       signal_b_ss <= signal_b_s;
       end
end
//在时钟域clk_a下,采集signal_b_s,用于反馈来拉低展宽信号signal_a
always@(posedge clk_a or negedge rst_n)begin
  if(rst_n == 1'b0)begin
      signal_b_a1 <= 1'b0;
      signal_b_a2 <= 1'b0;
  end
  else begin    //对signal_b_s打两拍,因此处涉及到跨时钟域
      signal_b_a1 <= signal_b_s;
      signal_b_a2 <= signal_b_a1;
  end
end
assign   pulse_b_out = signal_b_s & (~signal_b_ss);
assign   b_out            = signal_b_s;

endmodule

 

注意:

1、组合逻辑后需要加一级触发器

2、MTBF平均无故障时间

出现亚稳态的平均时间间隔常用“平均无故障时间” (MTBF, Mean Time Between Failure)来表示,MTBF时间越长,表示出现亚稳态的可能性越小。

可以看出,MTBF与触发器的时钟频率密切相关,甚至受到时钟频率的影响极大

一个计算例子:例如假设触发器的时钟频率为10MHZ,而输入数据频率为3KHZ,其MTBF如下图所计算的:

提高MTBF的方式:

1、提高工艺,使亚稳态信号更快的稳定下来。

2、提高电路的tr(无误条件下亚稳态能持续的最长时间),如打拍。

 

参考了以下博客(部分图片和描述直接复制于以下博客):

FPGA跨时钟域的处理方法

FPGA跨时钟域设计

FPGA的亚稳态跟MTBF

最后

以上就是背后台灯为你收集整理的FPGA面试笔试专题——跨时钟域处理的全部内容,希望文章能够帮你解决FPGA面试笔试专题——跨时钟域处理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部