1. 程式人生 > >[原創]FPGA編譯生成鎖存器原因與解決辦法

[原創]FPGA編譯生成鎖存器原因與解決辦法

遇到的問題:

在quartus ii中,編譯工程,報出如下警告:

Warning (335093): TimeQuest Timing Analyzer is analyzing 160 combinational loops as latches.

Quartus 官方給出的Help如下:

CAUSE: The TimeQuest Timing Analyzer found latches implemented using non-optimal 
resources (look-up tables (LUTs) with combinational feedback).  The TimeQuest analyzer 
replaces the
combinational loop with an equivalent latch. The TimeQuest analyzer treats this logic as a synchronous endpoint, and will not analyze the path through the node. ACTION: You must implement these latches with registers using asynchronous load and data signals, or remove them from your design. For more information, run the
check_timing tcl command in the TimeQuest analyzer.

以上翻譯過來就是,
原因:時序分析發現了 鎖存器(使用了非優化的資源:帶有組合邏輯反饋的查詢表)。時序分析用等效的鎖存器替代了這裡的組合邏輯環路。時序分析會把該處當做同步端點,不會分析通過這個節點的路徑時序。

措施:你必須(注意是必須)用非同步載入資料訊號的暫存器實現這些鎖存器,或者索性從設計中刪除他們。。。

這裡關於暫存器與鎖存器展開一下:

組合電路是一個真值表,一組輸入對應一組輸出,實時跟蹤變化,這樣也就容易有冒險、競爭之類的問題產生毛刺。而鎖存器就是組合電路的一種。

鎖存器特點:電平敏感

always @ (A,B)
    C <= A & B;

只要A或者B變化,條件就被觸發,C被賦值A and B

觸發器特點:邊沿敏感

always @ (posedge clk)
    C <= A & B;

只有當clk上升沿到來時,C才被賦值A and B
特別地,如果把C <= A & B; 換成 Q <= D; 這就是D觸發器的原始模型了(沒有復位訊號的D觸發器)

(非同步)暫存器特點:由觸發器構成,可以儲存N bit資料
以1 bit暫存器為例

always @ (posedge clk or negedge n_rst)

if (!n_rst)
    Q <= 0;
else 
    if (load)
        Q <= D;

當load訊號有效後的下一個clk上升沿,將輸出賦值為D。復位訊號到來,直接清零。其餘情況,保持上次的值不變。

(同步)暫存器特點:由鎖存器構成,可以儲存N bit資料
就是說輸入是地址索引,函式是真值表,儲存的資料就是 f(x), 即 真值表(輸入) = 輸出。認為這裡的輸出是與輸入同步的(雖然存在訊號的傳輸延遲)。小標題寫的儲存N bit資料 應該加引號,因為它並不是真正意義儲存。甚至不能稱其為暫存器,N bit暫存器應該是可以寫入,可以讀取。而組合邏輯電路一旦確定。其真值表也將確定,“儲存的資料”也就確定了。

關於專案中遇到的問題

在以下程式碼中,生成N多鎖存器,

module Decode(input A,input B,input C,output reg[31:0] edata,output reg[31:0] eCapData,input bCap,output reg CapSt,input n_rst,input [31:0] rstVal,input clk);

reg[1:0] state;

[email protected](posedge clk or negedge n_rst)
begin
    if(!n_rst)
    begin
        edata <= rstVal;
        state <= {A,C};
    end
    else
    begin
        state <= {A,B};
        edata <= {31'd0,A};
    *****此處省略一萬*****
    end

原因:生成鎖存器的原因是,表面上我是按照觸發器的方式在寫程式碼,實則不然。在非同步復位程式碼段,我的輸出依然由外界輸入決定,因此綜合之後產生了鎖存器。
將程式碼作如下修改,問題解決

module Decode(input A,input B,input C,output reg[31:0] edata,output reg[31:0] eCapData,input bCap,output reg CapSt,input n_rst,input [31:0] rstVal,input clk);

reg[1:0] state;

[email protected](posedge clk or negedge n_rst)
begin
    if(!n_rst)
    begin
        edata <= 32'd0;
        state <= 2'd0;
    end
    else
    begin
        state <= {A,B};
        edata <= {31'd0,A};
    *****此處省略一萬*****
    end

問題解決了,但是我還有一個問題,就是這樣的改動並不是我想要的,我就是要在n_rst為低的時候,執行edata <= rstVal; 。可以做如下處理:取消 negedge n_rst ,在語句內把!n_rst 當作是另一種使能訊號,即:

module Decode(input A,input B,input C,output reg[31:0] edata,output reg[31:0] eCapData,input bCap,output reg CapSt,input n_rst,input [31:0] rstVal,input clk);

reg[1:0] state;

[email protected](posedge clk)
begin
    if(!n_rst)
    begin
        edata <= rstVal;
        state <= {A,C};
    end
    else
    begin
        state <= {A,B};
        edata <= {31'd0,A};
    *****此處省略一萬*****
    end

問題解決