不枉初心,砥砺前行

皮皮祥的博客

欢迎留言,评论

导航

FPGA之边沿检测同步信号和异步信号

文章目录


   边沿检测,就是 检测输入信号的上升沿和下降沿。在设计数字系统时,边沿检测是一种很重要的设计思想。
  通常情况下,always块的敏感信号列表中可以直接用posedge和negedge来提取上升沿和下降沿, 但是要在always程序块的内部检测上升沿或者下降沿使用posedge和negedge显然是不可以的,因为这样的语句不可综合
   要实现边沿检测,最直接的想法是用两级寄存器,第二级寄存器锁存住某个时钟上升沿到来时的输入电平,第一级寄存器锁存住下一个时钟沿到来时的输入电平,如果这两个寄存器锁存住的电平信号不同,就说明检测到了边沿,具体是上升沿还是下降沿可以通过组合逻辑来实现。

一、同步信号的边沿检测

  电路设计如下图所示:
  该电路很简单地实现了边沿检测的功能,但是该方法存在一个潜在的风险:当待测信号pulse是一个异步信号时,输出可能是亚稳态,如果pulse信号的变化刚好发生在clk时钟的变化边沿时(建立时间和保持时间存在违例),那么第一级寄存器的输出 pulse_r1 就会进入亚稳态,而pulse_r1的亚稳态会立即传递给pos_edge和neg_edge信号,从而使得整个电路的输出进入亚稳态,进而影响下一级电路的正常工作,甚至导致整个系统崩溃,因此下述边沿检测电路只适合同步输入信号的边沿检测,若要对异步信号进行边沿检测,还需要适当的改进,对一步输入信号进行同步处理(增加触发器)。在这里插入图片描述

  • 上升沿特征: 先进来的是低电平,后进来的是高电平;
  • 下降沿特征: 先进来的是高电平,后进来的是低电平;

上图的verilog代码如下:

//仅适用于同步信号的边沿检测电路,两级寄存器实现检测功能

module edge_capture(input     clk,rst_n,
                    input     pulse,             //待检测信号
                    output    pos_edge,          //输出为上边沿
                    output    neg_edge           //输出为下边沿
                    );
  
  reg  pulse_r1,  pulse_r2;     //中间信号
  
  always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
      pulse_r1 <= 0;
      pulse_r2 <= 0;
    else begin
      pulse_r1 <= pulse;
      pusle_r2 <= pulse_r1;
    end
  end

  assign pos_edge = (pulse_r1 && ~pulse_r2) ? 1 : 0;  //检测到上升沿时, pos_edge输出一个时钟周期的高电平
  assign neg_edge = (~pulse_r1 && pulse_r2) ? 1 : 0;  //检测到下降沿时,neg_edge输出一个时钟周期的高电平

endmodule

二、异步信号的边沿检测(适用同步)

  异步信号检测电路设计如下图所示(同样适用于同步信号检测):
  异步信号边沿提取时,不能直接使用上面的这种电路,而应该先将异步信号同步化,一般采用多加一级寄存器的方法来减小亚稳态的发生概率
在这里插入图片描述
上图的verilog代码如下:

//异步信号的边沿检测电路,同样适用于同步信号检测,第一/二级寄存器同步信号,第二/三级寄存器实现检测功能

module edge_capture(input   clk, rst_n,
                    input   pulse,            //待检测信号
                    output  pos_edge,         //输出上边沿
                    output  neg_edge          //输出下边沿
                   );

  reg   pulse_r1, pulse_r2, pulse_r3;    //中间信号

  always@(posedge clk or negedge rst_n)begin
    if(!rst_n) 
      pulse_r1 <= 0;
      pulse_r2 <= 0;
      pulse_r3 <= 0;
    esle begin
      pulse_r1 <= pulse;
      pulse_r2 <= pulse_r1;
      pulse_r3 <= pulse_r2;
    end
  end

  assign pos_edge = (pulse_r2 && ~pulse_r3) ? 1 : 0;
  assign neg_edge = (~pulse_r2 && pulse_r3) ? 1 : 0;

endmodule

  经过触发器同步处理后, 可以大大减小电路进入亚稳态的概率,如果第一级寄存器进入了亚稳态,一般也会在一个clk周期内稳定下来(可能稳定为0也可能稳定为1),如下图所示:pulse信号的改变刚好发生在 clk 的建立时间和保持时间之内,因而第一级寄存器的输出pulse_r1可能会进入亚稳态,图中Tco为第一级寄存器pulse_r1的状态建立时间(即clock to output),一般情况下,亚稳态的决断时间(即从进入亚稳态到稳定下来的时间)不会超过一个时钟周期,因此在下一个clk上升沿到来之前,pulse_r1已经稳定下来(可能稳定到0也可能稳定到1),这样第二级寄存器就会采集到一个稳定的状态,从而把亚稳态限制在第二级寄存器之前,保证了整个电路输出的稳定性。
  亚稳态部分详细参见CDC章节部分
在这里插入图片描述
  因此,在异步信号边沿检测电路中,至少需要采用三级寄存器来实现,在对系统稳定性要求较高的数字系统中,可以采用更多级的寄存器来减小亚稳态发生概率,提高系统稳定性

posted on 2022-06-01 21:35  皮皮祥  阅读(1105)  评论(0)    收藏  举报