在高速信號采集的過程中,經常會因為電路設計或者其他原因,原本設計好對應的data_clk與data經過線路傳輸之后在接收端時序上不能很好的對應,這可能會造成采樣數據的錯位。
如果用了各種物理電路上的辦法都沒法解決后,可以嘗試使用Idelay(針對Xilinx,Altera應該也有相應的原語)。
Xilinx每個系列可能Idelay的名字會有一些差異,但差異不大,在K7系列下,Idelay的原語叫做Idelay2。
Idelay2原語示例:
(* IODELAY_GROUP = "RX_FRAME" *) // 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("VAR_LOAD"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
.IDELAY_VALUE(INIT_VALUE), // 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("DATA") // DATA, CLOCK input signal
)
IDELAYE2_inst (
.CNTVALUEOUT(cnt_value), // 5-bit output: Counter value output
.DATAOUT(rx_frame_dly), // 1-bit output: Delayed data output
.C(sys_clk), // 1-bit input: Clock input
.CE(1'b0), // 1-bit input: Active high enable increment/decrement input
.CINVCTRL(1'b0), // 1-bit input: Dynamic clock inversion input
.CNTVALUEIN(tap_value), // 5-bit input: Counter value input
.DATAIN(rx_frame), // 1-bit input: Internal delay data input
.IDATAIN(1'b0), // 1-bit input: Data input from the I/O
.INC(1'b0), // 1-bit input: Increment / Decrement tap delay input
.LD(1'b1), // 1-bit input: Load IDELAY_VALUE input
.LDPIPEEN(1'b0), // 1-bit input: Enable PIPELINE register to load data input
.REGRST(1'b0) // 1-bit input: Active-high reset tap-delay input
);
針對其中經常用到的變量,功能如下:
DELAY_SRC常量,這個常量可以選DATAIN或IDATAIN,區別在于IDATAIN的數據輸入要求經過BUF產生,常用于BUF的輸出信號,Input端口信號;DATAIN只要求FPGA內部邏輯產生的信號就可以。
IDELAY_TYPE,設置IDELAY2的模式;FIXED代表延時值固定,一般用在確定好參數后使用,VARIBLE,VAR_LOAD,VAR_LOAD_PIPE都是動態改變延時值,VARIBLE可以自動增大減小,后兩個是根據CINVALUEIN端口動態改變延時值,一般選用VAR_LOAD。
IDELAY_VALUE,是初始化的值,在FIXED模式下,就是固定的延時值
REFCLK_FREQUENCY,指的Idelay的參考時鐘的頻率,一般選用200M,這個后面會具體講。
SIGNAL_PATTERN,這個有DATA和CLOCK兩個選項,影響Vivado對信號時序分析的路徑。
端口中,
CNTVALUEIN是設置延時值,用于手動調試;
CNTVALUEOUT輸出當前延時值,便于調試觀測;
C是數據時鐘,但CE不是時鐘使能,而是延時值tap自動增加減少使能,所以我選擇拉低;
CINVCTRL,INC,LDPIPEEIN,REGRST不怎么用,全拉低;
在上面的DELAY_SRC選擇了哪一個,就在對應的數據端口連接數據,另一個數據端口拉低,比如DELAY_SRC設定為"DATAIN",選擇DATAIN端口輸入數據,IDATAIN端口拉低;
因為需要手動調節延時值,所以LD拉高,只有LD拉高才能動態載入CNTVALUEIN的延時值
前面說到參考時鐘,Idelay之所以延時,CINVALUEIN對應的延時值多少就跟這個地方有關系了,參考時鐘不是隨便設的,這跟另一個原語IDELAYCTRL有關:
(* IODELAY_GROUP = "RX_FRAME" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
IDELAYCTRL IDELAYCTRL_inst (
.RDY(idelay_rdy), // 1-bit output: Ready output
.REFCLK(ref_clk), // 1-bit input: Reference clock input
.RST(rst) // 1-bit input: Active high reset input
);
這個原語端口很少,連接對應200M的參考時鐘,復位信號,輸出一個ready信號;
看起來這個原語并沒有什么有用的輸出;但其實它的作用是給Idelay2提供了延時的依據;之所以可以精確延時并不是說我們在REFCLK_FREQUENCY填一個200就可以了,而是這個IDELAYCTRL 的作用,通過(* IODELAY_GROUP = "RX_FRAME" *)將IDELAYCTRL 和Idelay2連接起來,"RX_FRAME"類似于組名,可以隨意改,同一組的組名要一樣。
200MHz 對應1個時鐘周期5ns,Idelay將其分為64tap,每個tap延時值大概是78ps,Idelay可調的最大tap為31,也就是延時值控制在0-31tap;
同樣,為了減小相同參考時鐘下Idelay2與IDELAYCTRL 的FPGA內部走線延時,必須使用IODELAY_GROUP將它們綁定在一起,使用方法參考上面的做法。
注意,IDELAYCTRL 的REFCLK輸入時鐘一定要經過BUFG輸出再接入。
效果:
沒加Idelay
沒有加Idelay,并串轉換中找不到幀頭
加入Idelay
加了Idelay,找到幀頭
總結:
使用方法都在上面,對于多bit信號可以使用generate for 生成塊。
調試這個的時候遇到過一個問題,C端口沒有連接到正常的時鐘,連接到一個根本沒有定義的信號,Vivado做好事不留名的直接幫我拉低到地,導致我在VAR_LOAD模式下一直無法正常改變延時值,CNTVALUEOUT與CINVALUEIN不正確,最后打開Schematic看RTL圖才找到問題。
這一系列都是Xilinx中SelectIO的內容,包括I/ODDR,I/OBUFDS,下一篇就會講到ISERDES,并串轉換的一種用法,Idelay經常與ISERDES一同出現,解決高速串行通信上的問題。
審核編輯:劉清
-
FPGA
+關注
關注
1626文章
21677瀏覽量
601998 -
串行通信
+關注
關注
4文章
569瀏覽量
35299 -
高速信號
+關注
關注
1文章
222瀏覽量
17677
發布評論請先 登錄
相關推薦
評論