【Xilinx Vivado 时序分析/约束系列11】FPGA开发时序分析/约束-FPGA DDR-PLL接口的 input delay 约束优化方法

目录

DDR-PLL 简述

实际操作

实际工程

顶层代码

PLL配置

添加时钟约束

添加 input delay 约束

添加 False Path

Setup Time

Hold Time

Multicycle约束

解决办法

PLL配置

发现问题

建立时间中

保持时间中

添加 False Path

 总结

往期系列博客


DDR-PLL 简述

在之前介绍了 DDR-Direct 的时序模型,也就是不带有 PLL 的普通时序模型,这节重点介绍带有 PLL 的模型,在SDR采样模型中也介绍到这两种时序模型,因此同样的也会带有 PLL 的时序模型,PLL 的功能也是一样,可以对时钟进行偏移,可以正偏移也可以负偏移,对应的是时钟的延时增大和减小。

在分析时,默认PCB数据路径延迟Td_bd和PCB时钟路径延迟Tc_bd是一致的,因此在分析到达FPGA管脚的时钟和数据的状态时,只需要知道在上游器件的管脚的时钟和数据的状态,就可以对FPGA的时钟和数据进行约束,分析时钟和数据的相位关系即可。

以下是时序图,在DDR-Direct中有详细的分析,这里不多介绍。

这种时序模型可以用在input带有 PLL 的情况和不带有 PLL 的情况,带有 PLL 情况下采样时钟相移为正时需要进行 false path + Multicycle 约束,否则分析报告不正确。

实际操作

这次依然以索尼的一款CMOS器件的手册为例。

时钟频率为54Mhz,即周期为18.519ns,半周期为9.259ns。在参数表中可以看到Max skew为2ns,因此,从图中可以看出第一个下降沿作为采样沿时的数据是由上一个上升沿发射出来的,此时图中箭头1所指的时刻为input delay的最小值,而箭头2的时刻为input delay的最大值;同样的,当第一个下降沿作为发射沿发射数据时,下一个上升沿作为采样沿,此时的input delay的最大、最小值分别为箭头3、4所指的时刻。

这里需要注意的是,由于这里采用的是PLL对时钟进行移相,所以会产生一个新的时钟,因此要对时序约束工具进行多一些的操作,让时序工具能够正确的识别到,以免给出错误的时序报告。

实际工程

依然是 DDR-Direct 的实验工程,只需对顶层文件做个小改动。

顶层代码

将上一节加入的IDELAY2原语注释或删除,并例化PLL,将rx_clk作为输入,rx_clk_90作为输出。

module top_ioddr(
    input wire        rx_clk,
    input wire        rx_ctrl,
    input wire    [3:0] rx_dat,
  //tx
    output  wire    tx_clk,
    output  wire [3:0]  tx_d,
    output  wire    tx_dv,
    input	wire 	sdrclk,
    input	wire 	[3:0]	sdrdata,
    input	wire 	sdrden,
    input	wire 	sysclk,
    output	reg 	tout 	
	);
wire RDY;
wire rst;
wire rx_clk_90;
wire rx_en;
wire [7:0] rx_data;

reg tx_en1,tx_en2;
reg [7:0] tx_data1,tx_data2;
wire	sdrclk1;
assign rst =0;
//assign rx_clk_90 = rx_clk;

 IDELAYCTRL IDELAYCTRL_inst (
.RDY(RDY),       // 1-bit output: Ready output
.REFCLK(sysclk), // 1-bit input: Reference clock input
.RST(1'b0)        // 1-bit input: Active high reset input
);


clk_wiz_0 clk_gen0
   (
    // Clock out ports
    .clk_out1(rx_clk_90),     // output clk_out1
   // Clock in ports
    .clk_in1(rx_clk));      // input clk_in1

assign sdrclk1 = sdrclk;

always @(posedge rx_clk_90 or posedge rst) begin
	if (rst == 1'b1) begin
		tx_data1 <= 'd0;
	end
	else if (rx_en == 1'b1) begin
		tx_data1 <= rx_data+ rx_data -1;
	end
end

always @(posedge rx_clk_90 or posedge rst) begin
	if (rst == 1'b1) begin
		tx_data2 <= 'd0;
	end
	else if (tx_en1 == 1'b1) begin
		tx_data2 <= tx_data1+ tx_data1 -5;
	end
end

always @(posedge rx_clk_90 ) begin
	tx_en1 <= rx_en;
end

always @(posedge rx_clk_90 ) begin
	tx_en2 <= tx_en1;
end

	iddr_ctrl inst_iddr_ctrl
		(
			.rx_clk_90 (rx_clk_90),
			.rst       (rst),
			.rx_dat    (rx_dat),
			.rx_ctrl   (rx_ctrl),
			.rx_en     (rx_en),
			.rx_data   (rx_data)
		);

	oddr_ctrl inst_oddr_ctrl
		(
			.sclk    (rx_clk_90),
			.tx_dat  (tx_data2),
			.tx_en   (tx_en2),
			.tx_c    (rx_clk_90),
			.tx_data (tx_d),
			.tx_dv   (tx_dv),
			.tx_clk  (tx_clk)
		);

//sdr clock domain

reg [3:0] sdrdata_r1,sdrdata_r2;
reg 	sdrden_r1,sdrden_r2;

always @(posedge sdrclk1 ) begin
	{sdrdata_r2,sdrdata_r1} <= {sdrdata_r1,sdrdata};
end
always @(posedge sdrclk1 ) begin
	{sdrden_r2,sdrden_r1} <= {sdrden_r1,sdrden};
end

always @(posedge sdrclk1) begin
	if(sdrden_r2 == 1'b1) begin
		tout <= (&sdrdata_r1)|(&sdrdata_r2);
	end
	else begin
		tout <= (^sdrdata_r2);
	end
end

endmodule

PLL配置

设置向右相移30°,也就是1/12个周期,大约为1.543ns。

对工程布局布线,完成之后可以打开布线设计,并编辑时序约束。

添加时钟约束

对 rx_clk 进行约束,周期为18.518ns

添加 input delay 约束

需要对四个 input delay 进行约束,分别为上升沿的Max、Min,下降沿的Max、Min。

以上升沿的Max作为示例,最大为2ns

下降沿的 Max 设定为2ns,并勾选 no overwrite

注意!在对下降沿进行约束时,在图中箭头所指的参数需要勾选,表示此约束是否会覆盖之前上升沿所做的约束,因为本次实验是DDR双沿采样,上升沿和下降沿既作发射沿也作采样沿,因此在定义下降沿约束时,需要作不覆盖之前约束的操作,而之前的SDR则不需要。

input delay 约束汇总如图

CTRL+S 保存点开XDC约束文件即可看到刚刚添加的约束信息

create_clock -period 18.518 -name sdrclk -waveform {0.000 9.259} [get_ports sdrclk]
set_input_delay -clock [get_clocks rx_clk] -rise -max 2.000 [get_ports {rx_ctrl {rx_dat[0]} {rx_dat[1]} {rx_dat[2]} {rx_dat[3]}}]
set_input_delay -clock [get_clocks rx_clk] -rise -min -2.000 [get_ports {rx_ctrl {rx_dat[0]} {rx_dat[1]} {rx_dat[2]} {rx_dat[3]}}]
set_input_delay -clock [get_clocks rx_clk] -clock_fall -fall -max -add_delay 2.000 [get_ports {rx_ctrl {rx_dat[0]} {rx_dat[1]} {rx_dat[2]} {rx_dat[3]}}]
set_input_delay -clock [get_clocks rx_clk] -clock_fall -fall -min -add_delay -2.000 [get_ports {rx_ctrl {rx_dat[0]} {rx_dat[1]} {rx_dat[2]} {rx_dat[3]}}]

从下图可以看到,在不对时序作false path的约束时,约束工具会把一些不必要的路径,在对下表的内容做约束后,上升沿与上升沿之间是不需要分析建立时间的,上升沿和下降沿之间也不需要做保持时间。

添加 False Path

在timing constraints中的exceptions中的set false path添加

Setup Time

首先对两个上升沿之间的建立时间做false path,From是rx_clk的上升沿,To是PLL输出的时钟的上升沿。

下降沿同理

并在options中设定为上升沿rise的mark

Hold Time

再对保持时间做false path,From是rx_clk的上升沿,To是PLL输出的时钟的下降沿。

另一个From是rx_clk的下降沿,To是PLL输出的时钟的上升沿。

在options中设定为hold time的mark

Multicycle约束

这时候就会避免掉一些错误的时序报告,但是仍然有一些错误的报告,比如rx_clk的上升沿与PLL输出的时钟的上升沿之间(L1r与C2r之间)作保持时间的分析。这时候就需要做另外一种约束Multicycle约束。

同样的,在Exceptions中添加Multicycle,需要让PLL的上升沿左移一个,即让C2r变成C0r,设置成-1即可

下降沿的设置也是一样的。不多赘述。

options中设定为hold time。

保存后就可以看到XDC文件中有了 false path 和 Multicycle 的约束文件

set_false_path -setup -rise_from [get_clocks rx_clk] -rise_to [get_clocks [get_clocks -of_objects [get_pins clk_gen0/inst/mmcm_adv_inst/CLKOUT0]]]
set_false_path -setup -fall_from [get_clocks rx_clk] -fall_to [get_clocks [get_clocks -of_objects [get_pins clk_gen0/inst/mmcm_adv_inst/CLKOUT0]]]
set_false_path -hold -rise_from [get_clocks rx_clk] -fall_to [get_clocks [get_clocks -of_objects [get_pins clk_gen0/inst/mmcm_adv_inst/CLKOUT0]]]
set_false_path -hold -fall_from [get_clocks rx_clk] -rise_to [get_clocks [get_clocks -of_objects [get_pins clk_gen0/inst/mmcm_adv_inst/CLKOUT0]]]
set_multicycle_path -hold -rise_from [get_clocks rx_clk] -rise_to [get_clocks [get_clocks -of_objects [get_pins clk_gen0/inst/mmcm_adv_inst/CLKOUT0]]] -1
set_multicycle_path -hold -fall_from [get_clocks rx_clk] -fall_to [get_clocks [get_clocks -of_objects [get_pins clk_gen0/inst/mmcm_adv_inst/CLKOUT0]]] -

重新reload一下时序报告可以看到,时序出现了违例,通过看时序报告可以得出这个时序报告是正确的。只有在时序报告是正确的情况下,再去做时序约束才是有意义的,如果时序报告给的是错的,那时序约束也是无用功。时序报告是正确的,即使是违例的,我们再去调整也不麻烦。因此学会让时序工具给出正确的时序报告比懂得如何约束更重要!

report timing可以看到保持时间出现了违例

解决办法

现在得到了正确的时序报告,如何去修正时序呢,利用PLL的移相的功能就可以实现,既然是保持时间出现了违例,就说明是时钟的延时过大,只需要将PLL向左相移60°,即可恢复时序正常。

PLL配置

双击打开PLL配置界面,将相移改成-60即可

重新布局布线,由于这次是将PLL向左相移,所以在刚刚向右移的PLL所设定的Falsh Path和Multicycle删除掉,然后重新 reload 并 report time 查看时序报告。

发现问题

这时候看可以看到时序恢复了正常。但是有些余量是不正常的

建立时间中

rx_clk的rise到PLL的rise是不对的

rx_clk的fall到PLL的fall是不对的

保持时间中

rx_clk的fall到PLL的rise是不对的

rx_clk的rise到PLL的fall是不对的

添加 False Path

这四种情况所得到的建立时间和保持时间是不对的,因此需要把他们利用false path进行剔除。

添加四个false path

另外,不需要添加Multicycle,因为在使用PLL时,向右相移时才需要添加Multicycle,而向左相移则不需要添加。

重新reload可以看到给出的是正确的时序,并且时序恢复了正常。

 总结

如何得到正确的时序报告比如何解决时序违例更重要,知道问题的根,才能更好的解决问题!在用PLL进行时序优化时,注意看是否需要添加 False Path 和 Multicycle,以及怎么添加这些约束。

往期系列博客

 【Xilinx Vivado时序分析/约束系列1】FPGA开发时序分析/约束-寄存器间时序分析

 【Xilinx Vivado时序分析/约束系列2】FPGA开发时序分析/约束-建立时间

 ​​​​​​【Xilinx Vivado时序分析/约束系列3】FPGA开发时序分析/约束-保持时间

 【Xilinx Vivado时序分析/约束系列4】FPGA开发时序分析/约束-实验工程上手实操

 【Xilinx Vivado时序分析/约束系列5】FPGA开发时序分析/约束-IO时序分析

 【Xilinx Vivado时序分析/约束系列6】FPGA开发时序分析/约束-IO时序输入延时

 【Xilinx Vivado时序分析/约束系列7】FPGA开发时序分析/约束-FPGA单沿采样数据input delay时序约束实操

 【Xilinx Vivado时序分析/约束系列8】FPGA开发时序分析/约束-FPGA数据中间采样、边缘采样PLL时序优化实操

 【Xilinx Vivado时序分析/约束系列9】FPGA开发时序分析/约束-FPGA单沿数据input delay边沿对齐,不同时序模型实操练习

 【Xilinx Vivado 时序分析/约束系列10】FPGA开发时序分析/约束-FPGA DDR-Direct接口的 input delay 约束优化方法

猜你喜欢

转载自blog.csdn.net/m0_61298445/article/details/124086197