從最初學FPGA到現在,遇到過太多bug,但都沒有寫過博客記錄,因為多數問題都比較簡單且網上有比較好的答案。
但最近發現一個布局布線的報錯,并不是因為邏輯導致的,而是用戶不清楚布局布線導致的,且網上基本上相關的解答,因此把原因分析出來。
01 相關問題報錯
最近一些群友碰到了如下問題,報錯信息為:
[Place 30-719] Sub-optimal placement for a global clock-capable IO pin-IDELAY-BUFG pair. If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .xdc file to demote this message to a WARNING. However, the use of this override is highly discouraged. These examples can be used directly in the .xdc file to override this clock rule.
< set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets dclk_r] >
u_IDELAYE2 (IDELAYE2.DATAOUT) is locked to IDELAY_X0Y78
and dclk_r_BUFG_inst (BUFG.I) is provisionally placed by clockplacer on BUFGCTRL_X0Y1。
圖1 place 30-719報錯
按照錯誤提示,在xdc中添加如下約束,然后重新綜合、布局布線。
圖2 添加約束
然后出現如下錯誤,很多人可能會直接出現下面的錯誤,原因都是一樣的。 報錯信息:
[Place 30-650] Non IO buffer dclk_IBUF_BUFG_inst{BUFG} is driving IDATAIN pin of IDELAY instance u_IDELAYE2. This will lead to unroutable situation. IDATAIN pin of IDELAY instance should always get signal from IO buffer or GND.
[Place 30-99] Placer failed with error: 'Implementation Feasibility check failed, Please see the previously displayed individual error or warning messages for more details.'
Please review all ERROR, CRITICAL WARNING, and WARNING messages during placement to understand the cause for failure.
[Common 17-69] Command failed: Placer could not place all instances
圖3 報錯信息
上述報錯其實很奇怪,因為程序中idelaye2的IDATAIN是連接到FPGA輸入管腳的,并沒有什么問題,報錯不是很準確。
這個錯誤在網上好像還沒有具體的講解,本文解析一下具體原因,以及如何避免。
02復現錯誤
之所以出現這個問題,是由于不了解信號進入fpga的走線,錯誤使用idelaye信號導致的。
提供如下例程,輸入時鐘dclk與輸入數據din對齊,為了穩定采集輸入數據,內部使用idelaye2對dclk延時24.72ns。然后內部使用兩個ila,分別查看dclk延時前后采集到的輸入數據是否一致。
//--############################################################################################### //--# //--# File Name : top //--# Designer : 數字站 //--# Tool : Vivado 2017.4 //--# Design Date : 2024 //--# Description : //--# Version : 0.0 //--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode) //--# //--############################################################################################### module top ( input clk ,//系統時鐘信號; input rst ,//系統復位信號,高電平有效; input dclk ,//串行時鐘輸入; input din ,//輸入數據; output reg dout //輸出數據信號; ); reg [9 : 0] din_r ; wire dclk_r ; wire clk_200m ; //例化鎖相環,生成idelaye2需要的200MHz時鐘信號; clk_wiz_0 u_clk_wiz ( .clk_out1 ( clk_200m ),// output clk_out1 .reset ( rst ),// input reset .clk_in1 ( clk ) // input clk_in1 ); (* IODELAY_GROUP = "IODELAY_0" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYCTRL u_IDELAYCTRL ( .RDY ( ),// 1-bit output: Ready output .REFCLK ( clk_200m ),// 1-bit input: Reference clock input .RST ( rst ) // 1-bit input: Active high reset input ); //例化idelaye2對時鐘信號進行延時24*78+600=24.72ns; (* IODELAY_GROUP = "IODELAY_0" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYE2 #( .CINVCTRL_SEL ("FALSE" ),//Enable dynamic clock inversion (FALSE, TRUE) .DELAY_SRC ("IDATAIN" ),//Delay input (IDATAIN, DATAIN) .HIGH_PERFORMANCE_MODE ("FALSE" ),//Reduced jitter ("TRUE"), Reduced power ("FALSE") .IDELAY_TYPE ("FIXED" ),//FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE .IDELAY_VALUE (24 ),//Input delay tap setting (0-31) .PIPE_SEL ("FALSE" ),//Select pipelined mode, FALSE, TRUE .REFCLK_FREQUENCY (200.0 ),//IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0). .SIGNAL_PATTERN ("CLOCK" ) //DATA, CLOCK input signal ) u_IDELAYE2 ( .CNTVALUEOUT ( ),//5-bit output: Counter value output .DATAOUT ( dclk_r ),//1-bit output: Delayed data output .C ( clk_200m ),//1-bit input: Clock input .CE ( 1'b1 ),//1-bit input: Active high enable increment/decrement input .CINVCTRL ( 'd0 ),//1-bit input: Dynamic clock inversion input .CNTVALUEIN ( 'd0 ),//5-bit input: Counter value input .DATAIN ( 'd0 ),//1-bit input: Internal delay data input .IDATAIN ( dclk ),//1-bit input: Data input from the I/O .INC ( 'd0 ),//1-bit input: Increment / Decrement tap delay input .LD ( 'd0 ),//1-bit input: Load IDELAY_VALUE input .LDPIPEEN ( 'd0 ),//1-bit input: Enable PIPELINE register to load data input .REGRST ( rst ) //1-bit input: Active-high reset tap-delay input ); //移位輸出數據; always@(posedge dclk_r)begin {dout,din_r[9:0]} <= {din_r[9:0],din}; end //ila使用延時前的時鐘采集din_r的數據; ila_0 u_ila_0 ( .clk (dclk ),// input wire clk .probe0 (din_r ) // input wire [9:0] probe0 ); //ila使用延時后的時鐘采集din_r的數據; ila_0 u_ila_1 ( .clk (dclk_r ),// input wire clk .probe0 (din_r ) // input wire [9:0] probe0 ); endmodule
上述例程的邏輯思路和代碼大家應該都能夠理解,也沒有邏輯錯誤。然后使用vivado創建工程,綜合,分配管教腳,最后布局布線。
綜合不會出現問題,因為沒有邏輯和語法錯誤,但布局布線后會出現圖3的錯誤,如下圖所示。
圖4 復現問題
03分析問題
是不是覺得很離譜?邏輯沒問題,為什么布局布線失敗。
需要通過正常的工程,才能分析出錯誤的原因,因此先將兩個ila相關的代碼注釋掉,如下所示。
//--############################################################################################### //--# //--# File Name : top //--# Designer : 數字站 //--# Tool : Vivado 2017.4 //--# Design Date : 2024 //--# Description : //--# Version : 0.0 //--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode) //--# //--############################################################################################### module top ( input clk ,//系統時鐘信號; input rst ,//系統復位信號,高電平有效; input dclk ,//串行時鐘輸入; input din ,//輸入數據; output reg dout //輸出數據信號; ); reg [9 : 0] din_r ; wire dclk_r ; wire clk_200m ; //例化鎖相環,生成idelaye2需要的200MHz時鐘信號; clk_wiz_0 u_clk_wiz ( .clk_out1 ( clk_200m ),// output clk_out1 .reset ( rst ),// input reset .clk_in1 ( clk ) // input clk_in1 ); (* IODELAY_GROUP = "IODELAY_0" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYCTRL u_IDELAYCTRL ( .RDY ( ),// 1-bit output: Ready output .REFCLK ( clk_200m ),// 1-bit input: Reference clock input .RST ( rst ) // 1-bit input: Active high reset input ); //例化idelaye2對時鐘信號進行延時24*78+600=24.72ns; (* IODELAY_GROUP = "IODELAY_0" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYE2 #( .CINVCTRL_SEL ("FALSE" ),//Enable dynamic clock inversion (FALSE, TRUE) .DELAY_SRC ("IDATAIN" ),//Delay input (IDATAIN, DATAIN) .HIGH_PERFORMANCE_MODE ("FALSE" ),//Reduced jitter ("TRUE"), Reduced power ("FALSE") .IDELAY_TYPE ("FIXED" ),//FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE .IDELAY_VALUE (24 ),//Input delay tap setting (0-31) .PIPE_SEL ("FALSE" ),//Select pipelined mode, FALSE, TRUE .REFCLK_FREQUENCY (200.0 ),//IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0). .SIGNAL_PATTERN ("CLOCK" ) //DATA, CLOCK input signal ) u_IDELAYE2 ( .CNTVALUEOUT ( ),//5-bit output: Counter value output .DATAOUT ( dclk_r ),//1-bit output: Delayed data output .C ( clk_200m ),//1-bit input: Clock input .CE ( 1'b1 ),//1-bit input: Active high enable increment/decrement input .CINVCTRL ( 'd0 ),//1-bit input: Dynamic clock inversion input .CNTVALUEIN ( 'd0 ),//5-bit input: Counter value input .DATAIN ( 'd0 ),//1-bit input: Internal delay data input .IDATAIN ( dclk ),//1-bit input: Data input from the I/O .INC ( 'd0 ),//1-bit input: Increment / Decrement tap delay input .LD ( 'd0 ),//1-bit input: Load IDELAY_VALUE input .LDPIPEEN ( 'd0 ),//1-bit input: Enable PIPELINE register to load data input .REGRST ( rst ) //1-bit input: Active-high reset tap-delay input ); //移位輸出數據; always@(posedge dclk_r)begin {dout,din_r[9:0]} <= {din_r[9:0],din}; end //ila使用延時前的時鐘采集din_r的數據; //ila_0 u_ila_0 ( // .clk (dclk ),// input wire clk // .probe0 (din_r ) // input wire [9:0] probe0 //); //ila使用延時后的時鐘采集din_r的數據; //ila_0 u_ila_1 ( // .clk (dclk_r ),// input wire clk // .probe0 (din_r ) // input wire [9:0] probe0 //); endmodule重新綜合、實現工程后,在“IMPLEMENTATION”界面下雙擊“open Implemented Design”,如下所示。
圖5 打開布局布線
在“Device”界面中找到DCLK引腳,如下圖所示。
圖6 Device界面
如下圖所示,首先點擊圖中1處,就能查看芯片內部的實際走線了,如下圖所示,左邊為DCLK對應的管腳,信號進入管腳后,沿著綠色的走線,先到達idelaye2的輸入,經過延時后輸出到ILOGIC。
圖7 DCLK輸入走線
將上圖中idelaye2和ilogic部分放大,如下圖所示,藍色走線是DCLK管腳輸入,紅色是idelaye2輸出繞過ilogic進入FPGA內部邏輯的走線。
圖8 信號走線
上述是輸入信號進入FPGA管腳,經過idelaye2延時,繞過ilogic進入FPGA內部邏輯的走線。注意這部分是專用走線(固定不變的走線,只要使用idelaye2,不使用ilogic,走線就不會變),不是可編程的。
同時用戶需要知道,外部信號進入FPGA管腳后,只有經過ilogic(包括繞過)才能被FPGA內部邏輯所使用。
接下來分析不使用idelaye2的信號輸入走線,找到din信號對應管腳,如下圖所示。
圖9 din進入fpga走線
放大din在ilogic部分的走線,如下所示。din的管腳輸入信號不經過idelaye2,同時繞過ilogic后輸入到FPGA內部邏輯。
圖10 din的ilogic走線
對比圖8和圖10就能找到前文出現錯誤的原因了。如果使用了經過idelaye2延時前后的同一個管腳輸入信號,該如何走線?
如下圖所示,在進入內部邏輯之前,都需要繞過ilogic。藍色和紫色為idelaye2延時前的信號進入內部邏輯的走線,而紅色和紫色為idelaye2延時后的信號進入內部邏輯的走線,紫色為兩個信號重合的走線。
一根線不能同時傳輸兩個信號,因此布局布線失敗。
圖11 idelaye2延時前后的信號走線
回到前文的問題,ila0使用了dclk沒有經過idlaye2延時的信號作為時鐘信號,而ila1使用dclk經過idelaye2延時后的信號作為時鐘信號。
同時使用了dclk延時前后的信號,最終導致布局布線失敗。
04解決辦法
上述問題的原因就是內部邏輯同時使用idelaye2延時前后的兩個信號導致的,最直接的方法就是不這么去用,始終只使用其中一個就可以避免。
如果實在要這么用,也有其他方法,只不過會導致管腳到idelaye2的走線比較長,而且不是專用走線(每次布局后如果idelaye2位置發生變化,則走線延時也會變),引入的延時不穩定性會導致調試很麻煩,且不易于移植,一般不建議這么做。
具體實現思路是,既然內部要同時使用idelaye2延時前后的信號,而dclk引腳繞過ilogic的走線知有一條,那么就先讓不經過idelaye2的信號進入內部邏輯,然后在使用其余管腳的idelaye2來對輸入的信號進行延時,這樣不就解決了?
對應代碼如下所示,將兩個ila的注釋取消,同時將idelaye2的DELAY_SRC參數設置為DATAIN,輸入來自內部邏輯。
//--############################################################################################### //--# //--# File Name : top //--# Designer : 數字站 //--# Tool : Vivado 2017.4 //--# Design Date : 2024 //--# Description : //--# Version : 0.0 //--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode) //--# //--############################################################################################### module top ( input clk ,//系統時鐘信號; input rst ,//系統復位信號,高電平有效; input dclk ,//串行時鐘輸入; input din ,//輸入數據; output reg dout //輸出數據信號; ); reg [9 : 0] din_r ; wire dclk_r ; wire clk_200m ; //例化鎖相環,生成idelaye2需要的200MHz時鐘信號; clk_wiz_0 u_clk_wiz ( .clk_out1 ( clk_200m ),// output clk_out1 .reset ( rst ),// input reset .clk_in1 ( clk ) // input clk_in1 ); (* IODELAY_GROUP = "IODELAY_0" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYCTRL u_IDELAYCTRL ( .RDY ( ),// 1-bit output: Ready output .REFCLK ( clk_200m ),// 1-bit input: Reference clock input .RST ( rst ) // 1-bit input: Active high reset input ); //例化idelaye2對時鐘信號進行延時24*78+600=24.72ns; (* IODELAY_GROUP = "IODELAY_0" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL IDELAYE2 #( .CINVCTRL_SEL ("FALSE" ),//Enable dynamic clock inversion (FALSE, TRUE) .DELAY_SRC ("DATAIN" ),//Delay input (IDATAIN, DATAIN) .HIGH_PERFORMANCE_MODE ("FALSE" ),//Reduced jitter ("TRUE"), Reduced power ("FALSE") .IDELAY_TYPE ("FIXED" ),//FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE .IDELAY_VALUE (24 ),//Input delay tap setting (0-31) .PIPE_SEL ("FALSE" ),//Select pipelined mode, FALSE, TRUE .REFCLK_FREQUENCY (200.0 ),//IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0). .SIGNAL_PATTERN ("CLOCK" ) //DATA, CLOCK input signal ) u_IDELAYE2 ( .CNTVALUEOUT ( ),//5-bit output: Counter value output .DATAOUT ( dclk_r ),//1-bit output: Delayed data output .C ( clk_200m ),//1-bit input: Clock input .CE ( 1'b1 ),//1-bit input: Active high enable increment/decrement input .CINVCTRL ( 'd0 ),//1-bit input: Dynamic clock inversion input .CNTVALUEIN ( 'd0 ),//5-bit input: Counter value input .DATAIN ( dclk ),//1-bit input: Internal delay data input .IDATAIN ( 'd0 ),//1-bit input: Data input from the I/O .INC ( 'd0 ),//1-bit input: Increment / Decrement tap delay input .LD ( 'd0 ),//1-bit input: Load IDELAY_VALUE input .LDPIPEEN ( 'd0 ),//1-bit input: Enable PIPELINE register to load data input .REGRST ( rst ) //1-bit input: Active-high reset tap-delay input ); //移位輸出數據; always@(posedge dclk_r)begin {dout,din_r[9:0]} <= {din_r[9:0],din}; end //ila使用延時前的時鐘采集din_r的數據; ila_0 u_ila_0 ( .clk (dclk ),// input wire clk .probe0 (din_r ) // input wire [9:0] probe0 ); //ila使用延時后的時鐘采集din_r的數據; ila_0 u_ila_1 ( .clk (dclk_r ),// input wire clk .probe0 (din_r ) // input wire [9:0] probe0 ); endmodule
圖12 idelaye2對內部信號延時
重新綜合、布局布線,然后打開“Device”界面,找到dclk引腳。如下圖所示DCLK進入FPGA后,通過藍色走線到達bufg輸入,然后經過粉色走線到達右上角的一個管腳的idelaye2,然后黃色走線是idelaye2輸出信號。
圖13 修改后的布局
由此可知采用這種方式時藍色、粉色、黃色走線都是很長的,導致延時特別大,有興趣的用戶可以看下時序報告,這個延時可能會比idelaye2能夠調節范圍還大,因此不建議使用。
這種使用方式不同芯片的idelaye2布局也基本上不相同,所以移植其實也麻煩。
除了約束以外,可以利用某些手段(比如bufr)去限制idelaye2布局位置,來減小走線延時,但相比專用走線,還是沒有優勢。
這種問題能夠體現對于底層器件的理解,平時有時間可以留意一下器件布局布線的方式。
來源: 本文轉載自數字站公眾號
-
FPGA
+關注
關注
1626文章
21678瀏覽量
602004 -
時鐘
+關注
關注
10文章
1721瀏覽量
131377 -
布線
+關注
關注
9文章
766瀏覽量
84295 -
輸入信號
+關注
關注
0文章
447瀏覽量
12542
原文標題:輸入信號繞過ilogic布線沖突引發的問題(idelaye2使用)
文章出處:【微信號:FPGA研究院,微信公眾號:FPGA研究院】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論