xilinx FPGA觸發器和鎖存器

我們知道觸發器是邊沿敏感,鎖存器是電感敏感的存儲單元。那麼它們在FPGA內部究竟有什麼區別呢?本文通過幾個實際的案例來說明。

在xilinx 7系列的FPGA中,CLB(Configurable Logic Block)是邏輯實現的主要資源,在ug474中詳細介紹了CLB。每個CLB包含兩個slices,每個slices由4個(A,B,C,D)6輸入LUT和8個寄存器,1個CARRY4,3個MUX(多路選擇器)組成。同一CLB中的兩片slices沒有直接的線路連接,分屬於兩個不同的列,每列擁有獨立的快速進位鏈資源。slice分爲兩種類型 SLICEL,  SLICEM .  SLICEL可用於產生邏輯,算術,ROM。 SLICEM除以上作用外還可配置成分佈式RAM或32位的移位寄存器。每個CLB可包含兩個SLICEL或者一個SLICEL與一個SLICEM.(https://www.eefocus.com/b3574027/blog/15-05/312609_2e5ad.html

打開vivado的device就能看到每個藍色框內就是1個CLB,左起第三個slice就是slicem。

在ug953中介紹各種底層硬件資源,其中CLB中的寄存器可以配置爲D Flip-Flop (D觸發器)和Transparent Data Latch(鎖存器),在245頁上有描述,具體又可以分爲以下幾種:

觸發器:

異步復位 FDCE 復位後Q輸出0
FDPE 復位後Q輸出1
同步復位 FDRE 復位後Q輸出0
FDSE 復位後Q輸出1

鎖存器:

異步復位 LDCE 復位後Q輸出0
LDPE 復位後Q輸出1

觸發器的基本結構如下圖所示:

當復位端CLR拉高時Q輸出0,當CE等於0時,Q保持不變,當CLR = 0;CE = 1; 在C端邊沿觸發時將D的數據同步到Q端。

鎖存器的基本結構如下圖所示:

當復位端CLR拉高時Q輸出0,當GE G有一個拉低時,Q端保持不變,都爲高時,Q輸出D的值。可以看到鎖存器是沒有同步復位的。無論altera還是xilinx的ff都可以配置成fd或者ld。

1.異步復位時序電路

以4分頻器爲例。

module test(
    output c,
    input clk,
    input rst
    );
    
    
    reg clk2 = 1'd0;
    reg [1:0]cnt = 1'd0;
    always@(posedge clk or posedge rst)
    if(rst)
        begin
            clk2 <= 1'd0;   
            cnt  <= 1'd0;
        end
    else if(cnt == 1'd1)
        begin
            clk2 <= ~clk2;
            cnt  <= 1'd0;
        end
    else
        cnt <= cnt + 1'd1;
    
    assign    c = clk2;
   
endmodule

綜合後的RTL圖爲:

可以看到佔用了2個FF和2個LUT,而且FF都是FDCE,是異步復位,初始值爲0的觸發器,這和代碼是一致的。LUT1的作用就是一個反相器,當cnt = 1時,cnt = 0;cnt = 0時,cnt = 1;同理,可以分析LUT2的真值表,當I0 = 1時,O輸出的是I1的取反,這和代碼也是一致的。總之,我們可以看出異步復位電路,RST異步接入,高電平有效時,FF配置爲FDCE。

當代碼修改爲if(!rst)時,RTL如下圖所示:

編譯器會用一個lut對rst做反相,這將佔用更多的資源,所以一般來說用高電平復位,同時,復位時應將用到的寄存器都初始化。

2.同步復位時序電路

同步復位就是在always 敏感列表裏不添加rst,僅在clk邊沿變化時,D發生變化。代碼修改爲:

    always@(posedge clk)
    if(rst)
        begin
            clk2 <= 1'd0;   
            cnt  <= 1'd0;
        end
    else if(cnt == 1'd1)
        begin
            clk2 <= ~clk2;
            cnt  <= 1'd0;
        end
    else
        cnt <= cnt + 1'd1;

 綜合後的RTL圖爲:

可以看到rst信號接入到了lut,FF配置爲了FDRE。對於xilinx的LUT來說,觸發器支持高電平的異步和同步復位。

3.完整if else組合邏輯電路 

一般認爲組合邏輯是指輸出只與當前的輸入狀態有關電路,而時序邏輯是指輸出不僅與當前輸入有關,還跟歷史輸入有關,例如前面的電路。

例如,a = (b&c&d) + e; 這明顯是組合邏輯。組合邏輯裏沒有時鐘,輸入信號至LUT裏後,直接輸出Q,不經過觸發器,除非電路中生成了鎖存器,Q輸出後會接入一個由FF配置成的LD。鎖存器會在什麼地方產生呢?我們一般回答在組合邏輯裏分支沒有完全描述的情況下產生,例如if後沒有else,case沒有default。

下面是完整的if else例子。

module test(
    input a,b,
    output [1:0]c,
    input clk,
    input rst
);
    
    reg [1:0]reg_c = 1'd0;
    always @(rst or a or b)
    if(rst)
        reg_c  = 2'd0;
    else if(a)
        reg_c = 2'd1;
    else if(b)
        reg_c = 2'd2;
    else
        reg_c = 1'd0;
        
    assign c = reg_c;
endmodule

生成的RTL圖如下圖所示:

由於它是組合邏輯,敏感列表裏寫不寫都是一樣的(我猜的)。

4不完整if else if組合邏輯電路

如果少了else會是什麼情況呢?

module test(
    input a,b,
    output [1:0]c,
    input clk,
    input rst
);
    
    reg [1:0]reg_c = 1'd0;
    always @(*)
    if(rst)
        reg_c  = 2'd0;
    else if(a)
        reg_c = a - b;
    else if(b)
        reg_c = a + b;
        
    assign c = reg_c;
endmodule

注意代碼,沒有了else,同時else if裏的內容也有修改。RTL圖爲:

可以看到,在LUT輸出後,加入了一個LDCE,這便是鎖存器。因爲在兩個else if以外的情況下,編譯器會將邏輯定爲保持當前輸出不變,因此,觀察LDCE的端口,rst接到了異步復位的CLR,鎖存器只支持異步復位,當a b條件不滿足else if時,即在LUT2中描述情況下a b同時爲0時,數據將鎖存,因此LUT會輸出0到LDCE的G端,此時Q將保持當前值。可以看到當條件羅列完全時,僅需要LUT就可以完成組合邏輯的描述,未羅列完全時,還需要LUT用於描述LDCE的G端,因此會多佔用FF資源。同時,鎖存器也不利於靜態時序分析,所謂靜態時序分析,我們通常是以clk的週期爲參考,去分析DATA和CLK的路徑,計算是否滿足下一級FF的setup和hold時間,而latch的復位是異步的,G端的變化是異步的,latch和時鐘毫無關係,分析起來自然十分麻煩。因此我們應儘量避免產生latch

時序邏輯中if 或case不完整會不會產生latch呢?

答案是不一定產生,因爲時序邏輯是在clk的變化沿同步數據,它會用一個lut來描述沒有窮舉的情況,並輸出到FF的CE端,使FF在輸出時保持前一個值。如下圖所示。

反正最好是把else和default寫完整。也可以在組合邏輯always@(*)的首行,把信號先用阻塞方式(=)把信號先賦值,效果等同於else或default。

那麼如何檢查代碼中有latch呢?

最簡單的方法是在綜合後的message窗口,ctrl + f,搜索latch或者設置條件爲latch,點擊確定,即可看到有多少個latch。從資源佔用中看到只用了1個LUT 和1個FF就實現了,可是明明是2個LUT和1個FF?這時候要打開版圖來看。

如果在FLOP_LATCH下沒有LATCH選項,說明該設計中就沒有latch產生,同理,用Find命令可以查看其它資源。也可以在輸入腳本命令 all_latches。輸入all_ 會有命令提示,可以查看許多資源,請自行嘗試。

至此,本文介紹了latch和ff的區別,和latch產生的原因。實際上數字電路基礎中花了很多篇幅去講晶體三極管和MOS管組成TTL和CMOS電路,有或與非等基本電路,分析它們的電流和電壓特性,但FPGA裏負責大量邏輯運算是基於SRAM的LUT,是查找表,應該有一個區別的認識,不是FPGA裏有很多或與非門,是用LUT組成的或與非邏輯。

FPGA設計時常說的設計流程就是先綜合生成原理圖,再佈局佈線映射到FPGA中CLB中去。比如有16個並行總線端口輸入後經clk採樣,在原理圖看都是一樣的路徑,但由於映射到BGA引腳上,信號從PAD到16個寄存器有無數種佈線方法,它們之間的延時也是不固定的,當採樣速度很高,佈線的延時差異不能忽略時,就容易採樣錯誤,因此就要用時序約束,set input delay來描述這些信號相對於clk到來的時刻,佈局佈線時就根據這些約束保證輸入的路徑是差不多的。輸出也是同理。爲了得到更好的採樣結果,通常會將輸出輸入打1個節拍,用IOB的FF去輸出或採樣,可以保證每次佈局佈線時,從FF到PAD的時間都是固定的,而且最短。

5.阻塞和非阻塞

簡單說來,阻塞就是 = ,非阻塞就是 <=。爲什麼稱它爲阻塞呢?因爲 = 在同一個always 它是有先後執行順序的,後面的=被前面的 = 阻塞了。非阻塞就是並行的,一起運行。

懶得寫了,直接引用吧。

https://blog.csdn.net/August_cwj/article/details/77989071

限於水平,還有很多問題沒有描述,權當一個敲門磚,我們FPGAer還是應該要理解你的代碼實際上對應的是什麼電路,畢竟這是自古流傳的傳統。

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章