需求問題:需要使用3個GPIO實作相同的脈沖信号,三個信号之間的上升沿時延不能超過200ps。
測試環境:ZYNQ7020的黑金開發闆
測試過程:
代碼:
module gpio_jitter_test (
input clk_osc , //50M
output ld_0 ,
output ld_1 ,
output ld_2
);
wire clk;
reg [9:0] counter = 4'h0;
(* dont_touch="true" *) reg ld;
assign ld_0 = ld;
assign ld_1 = ld;
assign ld_2 = ld;
BUFG BUFG_inst (
.O(clk ), // 1-bit output: Clock output
.I(clk_osc ) // 1-bit input: Clock input
);
always @(posedge clk) begin
counter <= counter + 1'b1;
end
always @(posedge clk) begin
if (counter<10'h2) begin
ld <= 1'b1;
end
else begin
ld <= 1'b0;
end
end
endmodule
開始選擇了三個GPIO管腳限制,其他未加任何限制。時序很不好。
開啟限制之路:
方法一:
(1) 将管腳配置為fast模式
set_property SLEW FAST [get_ports ld_0]
set_property SLEW FAST [get_ports ld_1]
set_property SLEW FAST [get_ports ld_2]
改觀不大,更多是影響管腳上的上升沿和下降沿敏感性,對互相之間的延時沒有太大影響。
(2) 布局中發現,寄存器進行了備份
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPn5kMnpWT6lFVNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3kjMyADOxcTM5EjNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
(3) 加上don’t touch,避免寄存器複制
延時集中于寄存器輸出至管腳的obuf之間,ld0和ld1互相之間的延時133ps,ld2和ld1延時在228ps。由于ld2管腳距離ld1之間過遠。
(4) 由于U21下方的管腳沒有在開發闆上接出來,沒辦法精确測量;将三個管腳改為U12,U11,U10。
由此可見,雖然管腳相鄰,但是走線的長度差距還是很大,導緻延時超過300ps。
(5) 添加max_delay和min_delay,三個管腳的max_delay 為4.6ns,min_delay為4.5ns。max_delay選擇為datapath。
set_max_delay -datapath_only -from [get_pins ld_reg/C] -to [get_ports ld_0] 4.600
set_max_delay -datapath_only -from [get_pins ld_reg/C] -to [get_ports ld_1] 4.600
set_max_delay -datapath_only -from [get_pins ld_reg/C] -to [get_ports ld_2] 4.600
set_min_delay -from [get_pins ld_reg/C] -to [get_ports ld_0] 4.500
set_min_delay -from [get_pins ld_reg/C] -to [get_ports ld_1] 4.500
set_min_delay -from [get_pins ld_reg/C] -to [get_ports ld_2] 4.500
測試結果:
測了三組上升沿之間的內插補點分布資料:
1) ld_1 - ld_0 -130ps
2) ld_1 – ld_2 -250ps
3) ld_2 – ld_0 +50ps
結果分析:
從時序報告中,ld_0 最後一步走線delay是4.546ns,ld_1最後一步走線delay是4.663ns,ld_2的delay是4.535ns。
是以,理論值分析
1) ld_1 - ld_0 = (-4.663)-(-4.546)=117ps
2) ld_1 – ld_2 = (-4.663)-(-4.535)=128ps
3) ld_2 – ld_0 = (-4.535)-(-4.546)=11ps
由上面資料分析,第二組測試結果偏差較大,原因可能是ld0和ld1是一對差分線,ld2是另外一對差分線,ld0和ld1走線的長度一緻,但是ld2走線不同,但是和ld0 ld1內插補點有些過大,問題在哪??
跟FAE交流後,發現在FPGA的管腳上存在pin delay,這個并不在時序報告中(pin delay不在時序報告中展現)。如何導出pin delay?tcl指令行中:
輸入 link_design –part xc7z020i-clg484; write_csv filename
會輸出7020的pin delay檔案,如下圖
是以三個管腳的delay應該是:
Delay(ld0) = -(4.546+210.804/1000)=-4.756ns
Delay(ld1) = -(4.663+217.94/1000)=-4.881ns
Delay(ld2) = -(4.535+79.947/1000)=-4.615ns
1) ld_1 - ld_0 = (-4.756)-(-4.881)=-125ps
2) ld_1 – ld_2 = (-4.881)-(-4.615)=-266ps
3) ld_2 – ld_0 = (-4.615)-(-4.756)=141ps
與實際測量值比較
測了三組上升沿之間的內插補點分布資料:
1) ld_1 - ld_0 -130ps
2) ld_1 – ld_2 -250ps
3) ld_2 – ld_0 +60ps
從這個結果中,假設ld0與ld1的闆上pcb布線延時為x,ld2闆上布線延時為y,則理論值計算中:
4) ld_1 - ld_0 = (-4.756-x)-(-4.881-x)=-125ps
5) ld_1 – ld_2 = (-4.881-x)-(-4.615-y)=-(266+x-y)ps
6) ld_2 – ld_0 = (-4.615-y)-(-4.756-x)=(141+x-y)ps
由1) 2) 4)5)可解出 x-y=-21ps,帶入6)則 ld2-ld0=120ps, 由于1)與4),2)與5)之間存在測量的誤差,這部分可能引入到計算中,是以包含了20ps左右的誤差,這樣看來,理論值與測量值的差距為120-60-20=40ps,與實際測量值偏差還是有些大。
這個原因就不好找了,可能由于手抖的測量問題,也可能是ld0與-ld1的實際pcb走線并不相等,差别還是客觀存在的。再次不再深入分析。
方法一結論:
方法一,目前FPGA可以滿足3個GPIO信号之間200ps(FPGA内部)的時延範圍。
需要注意的問題:
1) 工程階段,需要根據實際邏輯情況進行限制,會增加工程測試時間;
2) 3個GPIO一定要選擇在FPGA管腳的實體上相鄰位置,同時要查詢pin_delay的表格找到delay相近的三個管腳,最好上下各空出一個io管腳,保證管腳附近有充足的布線資源和寄存器資源,這一點非常重要;
3) 由于邏輯确定後,FPGA走線延時可以确定,是以可以對此進行一定的校正。
方法二、
跟FAE溝通後,又提供了一種思路,使用OBUF中的寄存器。這意味着ld信号出來之後是在各個GPIO的管腳位置開始分叉,用各自的寄存器驅動相應的pad。時延就變成了兩個因素影響:(1)各個GPIO寄存器的clock skew;(2)各個GPIO寄存器與pad的之間的pin delay+logic delay+net delay(時延非常小)。
步驟:
(1) 代碼中删除don’t touch
(2) 限制檔案中增加:set_property IOB TRUE [get_ports ld_?]
(3) 增加到8個ld接口,友善觀察時序變化情況。
布局布線後,發現每一個之前OBUF附近的寄存器都使用起來了,ld_reg複制了多份。舊的布局(方法一中布局)如下圖:
新的布局如下圖:
時序情況如下:
可以看到各個GPIO之間的延時大概差别在200ps以内。
方法二結論:
方法二,目前FPGA可以滿足3個GPIO信号之間200ps(FPGA内部)的時延範圍。
最終總結!!
兩種方法:
1) 使用max_delay, min_delay配合don’t touch進行限制,對于資源不緊張時候可以嘗試,延時控制範圍更好。
2) 使用IOB TRUE 進行限制,對于資源緊張是可以使用,也能夠達到200ps要求,但是延時基本固定(因為OBUF的寄存器與pad的布線是固定的)。