1. 程式人生 > 其它 >FPGA之邊沿檢測同步訊號和非同步訊號

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章節部分

  因此,在非同步訊號邊沿檢測電路中,至少需要採用三級暫存器來實現,在對系統穩定性要求較高的數字系統中,可以採用更多級的暫存器來減小亞穩態發生概率,提高系統穩定性