前言
- 數字同步邏輯中應盡量避免產生鎖存器,因為鎖存器容易引起競爭、冒險,同時靜態時序分析工具也很難分析穿過鎖存器的路徑。FPGA里面的latch是由查找表產生的。
- 由於fpga生成的latch路徑和時延不確定,因此fpga內不建議用latch(除非一些場景必須使用組合邏輯和latch解決,且對latch的應用很了解)。
- 芯片IC設計的路徑和時延是固定的,因此IC設計是可以使用latch的。
一、對鎖存器理解
1、鎖存器的概念
- 鎖存器是一種在異步時序電路系統中,對輸入信號脈沖電平敏感(電平觸發)的存儲單元,在時鍾脈沖的電平作用下改變狀態。
- 鎖存器在數據未鎖存時,輸出端的信號隨輸入信號變化,就像信號通過一個緩沖器;一旦鎖存信號有效,則數據被鎖存,輸入信號不起作用。因此,鎖存器也被稱為透明鎖存器,指的是不鎖存時輸出對於輸入是透明的。
- 一個鎖存器可以存儲1bit的信息,通常,鎖存器會多個一起出現,如4位鎖存器,8位鎖存器。
2、鎖存器與觸發器的相同點和區別
(1)相同點
- 鎖存器和觸發器都是具有記憶功能的二進制存貯器件,是組成各種時序邏輯電路的基本器件之一。
- 由於latch和FF(Flip-Flop)二者都是時序邏輯,因此其輸出不但同當前的輸入相關,還與上一時間的輸出相關。
(2)區別
- latch同其所有的輸入信號相關,當輸入信號變化時latch就變化,沒有時鍾端;DFF受時鍾控制,只有在時鍾觸發時才采樣當前的輸入,產生輸出。
- latch由電平觸發,非同步控制,在使能信號有效時latch相當於通路(即相當於延遲一拍的導線),在使能信號無效時latch鎖定,保持輸出狀態不變;DFF由時鍾沿觸發,同步控制。
- latch最大的危害在於不能過濾毛刺,這對於下一級電路是極其危險的; 因為同步電路信號的變化都發生在時鍾沿,只要毛刺不出現在D觸發器時鍾的沿口並且不滿足數據的建立和保持時間,就不會對系統造成危害(由於毛刺很短,多為幾納秒, 基本上都不可能滿足數據的建立和保持時間)。因此可以說,D觸發器的D輸入端對毛刺信號不敏感。在FPGA設計中,只要能用D觸發器的地方,就不用latch。
- 相對DFF來說,latch對輸入電平敏感,受布線延遲影響較大。
- 相對DFF來說,latch將靜態時序分析變得極為復雜。
二、什么樣的代碼容易生成鎖存器
1、敏感列表是電平觸發才可能生成鎖存器latch
(1)可能生成鎖存器代碼示例
- 由於代碼中的判斷語句、條件語句 沒有給出所有可能情況下的輸出,導致綜合器認為 這些未指定的情況下輸出保持不變。這樣的代碼會綜合為鎖存器。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//判斷條件未包含敏感列表的全部可能條件:data_in是3bit,共有8種數值,下面僅對2種取值情況進行判斷,這種電路會生成鎖存器。xilinx綜合生成的【鎖存器ldcp】如下圖2
always @(data_in)
if(data_in == 3'd2) data_out <= 3'd1; else if(data_in == 3'd1) data_out <= 3'd2; //作為判斷條件內的變量未包含到敏感列表內:這里的判斷條件(data_in1 == 3'd1)沒有放到敏感列表里,因此會生成鎖存器 always @(data_in) if(data_in == 3'd2) data_out <= 3'd1; else if(data_in1 == 3'd1) data_out <= 3'd2; else data_out <= 3'd0; //case語句未完全遍歷所有case條件,並且未包含default語句:敏感列表內的data_in總共有8種數值情況,而case條件僅有2種,且沒有default語句,因此會綜合生成鎖存器latch always @(data_in) case(data_in) 2'd1:data_out <= data_in; 2'd2:data_out <= data_in1; //default:data_out <= 'd0; endcase |
(2)時鍾延觸發的邏輯都不會生成鎖存器
1)xilinx綜合生成的【寄存器fdce】如下圖。
1
2 3 4 5 6 7 |
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0) data_out <= 3'd0; else if(data_in == 3'd1) data_out <= 3'd2; //else //時鍾沿觸發和異步復位,綜合器會進行識別,因此若不寫else也不會生成鎖存器 // data_out <= 3'd0; |
1
2 3 4 5 6 |
always @(posedge sclk or negedge rst_n) begin
if(1'b0 == rst_n) //低電平有效,不受異步時鍾控制,為D觸發器的異步清0端口 sum <= 0; else if(1'b1 == En) //D觸發器的時鍾使能端口 sum <= a + b; end |
2、如何避免生成鎖存器
(1)敏感列表內的變量不全,賦值號右邊的變量必須放在敏感列表內;作為判斷條件的
變量一定要放到敏感列表內,判斷條件一定要包含敏感列表變量取值的
全部可能情況。
(2)使用完備的if...else語句,即if...else語句必須有else結束賦值。
(3)為每個輸入條件設計輸出操作,為case 語句設置default操作。特別是狀態機設計中,最好有一個default狀態轉移,且每個狀態最好也都有一個default操作。
(4)使用case語句,特別是在狀態機設計時,盡量附加綜合約束屬性,綜合為完全條件case語句(full case)。目前大多數綜合工具都支持full case的綜合約束屬性。
(5)仔細檢查綜合報告,目前大多數綜合器對所綜合出的latch都會包“warning”。
3、xilinx綜合工具綜合處的鎖存器結構

