[原創]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
問題解決