FPGA跨时钟域的处理方法

本文深入探讨了时钟域的概念,分析了不同时钟域间信号传输时可能出现的亚稳态问题,并详细介绍了多种亚稳态处理方法,包括相位控制、多级寄存器和异步FIFO缓存,特别聚焦于多级触发寄存器的使用,为解决跨时钟域信号同步提供了实用指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、时钟域
如果一个设计全局只使用了一个时钟,那么此设计有一个时钟域。如果在一个设计中有两个时钟去控制不同的接口,那么就称这个设计中有两个时钟域。如下图所示双时钟域图
当时钟不匹配时,就要进行同步化,否则就可能出现亚稳态,从而造成整个设计不稳定。
二、亚稳态
亚稳态其实就是数据的转变没有符合时钟采样所需要的setup/hold时间,在时钟的上升沿或下降沿到来时正好采到数据的变化状态。此时,由于数据并没有稳定,所以会导致采到的数据不停变化,而不是逻辑0或逻辑1.此时采到的数据会一直抖动,直至隔一段时间稳定。产生亚稳态的时序图如下:亚稳态产生原理
处理亚稳态的方法:
1、相位控制
2、多级寄存器
3、异步FIFO缓存
多级触发寄存器处理
如果信号来自同一时钟域,则不需要多级触发器处理,如果来自两个时钟域,那么分为两种情况:
1、从快到慢
2、从慢到快
此处的快慢指时钟的频率,首先说从快到慢的处理方法:
其实此处也分信号所来的时间长短与慢的时钟的频率关系。
有以下两种可能这里写图片描述
从快到慢
右图中的pulse_a信号是不会被clk_b采集到的,因为pulse_a信号的保持时间小于clk_b的时钟周期,所以要从clk_a的时钟域下将此信号采集过来就必须对其进行展宽,否则极有可能采集不到。

 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

从慢到快
这里写图片描述
在clk_a时钟看来,pulse_b信号是一个非常宽的信号,那么在clk_b时钟域下的pulse_b必然能够被clk_a采到。如果pulse_b是clk_b时钟域下的组合逻辑所产生的信号,那么就得先用DFF在clk_b时钟抓一拍,之后再用DFF抓两次或者更高次向clk_a时钟域传递。

module  sys_clk(
                  input    clk_a,
                  input    clk_b,
                  input    pules_in,
                  input    rst_n,
                  output   pules_out 
                 );
reg         pules_b;
reg         pules_a1;
reg         pules_a2;
reg         pules_a3;
wire        pules_a_pos;
wire        pules_a_neg;
always@(posedge clk_b or negedge rst_n)begin
if(rst_n == 1'b0)begin
   pules_b <= 1'b0;
end
else  begin
   pules_b <= 1'b1;
end
end
always@(posedge clk_a or negedge rst_n)begin
if(rst_n == 1'b0)begin
  pules_a1 <= 1'b0;
  pules_a2 <= 1'b0;
  pules_a3 <= 1'b0;
end
else begin
  pules_a1 <= pules_b;
  pules_a2 <= pules_a1;
  pules_a3 <= pules_a2;
end
end
assign  pules_out = pules_a2;
assign pules_a_pos = pules_a2 & (~pules_a3); //输出信号的上升沿检测
assign pules_a_neg = pules_a3 & (~pules_a2); //下降沿检测

endmodule

需要强调的是,此时的pules_必须为clk_b时钟域下的信号**

在设计中可以简单的牢记以下五条原则:
1. 再全局时钟的跳变沿最可靠。
2. 来自异步时钟域的输入需要寄存一次以同步化,再寄存一次以减少亚稳态带来的影响。
3. 不需要用到跳变沿的来自同一时钟域的输入,没有必要对信号进行寄存。
4. 需要用到跳变沿的来自同一时钟域的输入,寄存一次即可。
5. 需要用到跳变沿的来自不同时钟域的输入,需要用到3个触发器,前两个用以同步,第3个触发器的输出和第2个的输出经过逻辑门来判断跳变沿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值