需求问题:需要使用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) 布局中发现,寄存器进行了备份
(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的布线是固定的)。