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

18 篇文章 11 订阅
11 篇文章 92 订阅

目录

 

DDR采样简述

第一种模型(不带PLL)

实际操作

总结约束

实际工程

顶层代码

时钟约束

input delay约束

查看时序报告

解决办法

添加原语

原语解释

查看时序报告

时序分析

总结

往期系列博客


 

DDR采样简述

在之前分析了SDR采样,也就是单边采样,接下来介绍DDR采样,也就是双边采样,在实验应用中,DDR采样也是很广泛的,比如CMOS、DRAM、ADC、千兆以太网等,都是DDR接口的,因此也需要去分析时序是否正确,学会如何去进行时序约束。

在SDR中,介绍了两种时序模型,一种是带有PLL的时序模型,另外一种是不带PLL的时序模型。在DDR中也是一样的,同样存在这两种模型。

同样是上游器件和下游器件,下游器件是FPGA,上游器件可以是以太网接口或者是ADC等。其中存在的延迟也在图中有呈现。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

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

第一种模型(不带PLL)

首先分析第一种时序模型,不带有PLL的时序模型。

在SDR中,由上升沿作为发射沿,下一个上升沿作为采样沿,同时作为下一个数据的发射沿。存在上升沿时刻的最大、最小值。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

在DDR中,由上升沿作为发射沿,同一周期中的下一个下降沿作为采样沿,同时作为下一个数据的发射沿。与SDR还有一点不同的是,DDR不仅存在上升沿时刻的最大、最小值,还存在下降沿时刻的最大、最小值。因为上升沿和下降沿都会被作为发射沿和采样沿。同时,还可以发现上升沿的最大最小的范围和下降沿的最大最小范围是不一定相同的。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

此时序模型是不加PLL的,并且采用的是边沿采样,也就是说当前下降沿采样的数据是由上一个上升沿发射出来的,下一个上升沿采样的数据是由上一个下降沿发射出来的。因此,就可以得到发射沿和采样沿的关系,两者可以说是相互补的,如果发射沿为上升沿,那么采样沿就为下降沿;如果发射沿为下降沿,那么采样沿就为上升沿。后面在Vivado中分析时序时就可以按照这种方式看。

实际操作

以一个实际的例子进行分析,以下是索尼的一款CMOS器件的手册,其中它的输出包括SDR和DDR,在之前已经分析并实操了它的SDR的采样模式,这次就看它的DDR采样模式。

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

总结约束

Rise Max = T/2 + skew_afe = 9.259ns + 2ns = 11.259ns

Rise Min = T/2 - skew_afe = 9.259ns - 2ns = 7.259ns

Fall Max = T/2 + skew_afe = 9.259ns + 2ns = 11.259ns

Fall Min = T/2 - skew_afe = 9.259ns - 2ns = 7.259ns

实际工程

利用之前的工程继续做DDR的约束

顶层代码

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         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 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

其他模块的代码和之前的工程一致,这里就不添加进来了

对工程做布局布线,完成后打开布线设计

0b917f3d52074a0eb98f0bc9c69ded6b.png

 

打开之后点击编辑时序约束

5af55364a88647a5aaf2076bfb9bc18e.png

 

时钟约束

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

input delay约束

这里要对四个input delay进行约束,分别为上升沿的max、min和下降沿的max、min

约束内容为以下:

Rise Max = T/2 + skew_afe = 9.259ns + 2ns = 11.259ns
Rise Min = T/2 - skew_afe = 9.259ns - 2ns = 7.259ns
Fall Max = T/2 + skew_afe = 9.259ns + 2ns = 11.259ns
Fall Min = T/2 - skew_afe = 9.259ns - 2ns = 7.259ns

上升沿的最大值

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

上升沿的最小值

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

下降沿的最大值

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

下降沿的最小值

同样需要作不覆盖处理

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

此种边缘对齐的时序模型是不带有PLL的情况,促使布线工具尽量增加时钟布线延迟,也就是图中使时钟尽可能的向右移动,使得建立时间满足要求。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

此时的XDC约束文件为

set_property IOSTANDARD LVCMOS33 [get_ports rx_clk]
set_property PACKAGE_PIN J19 [get_ports rx_clk]
set_property PACKAGE_PIN H22 [get_ports rx_ctrl]
set_property IOSTANDARD LVCMOS33 [get_ports rx_ctrl]
set_property PACKAGE_PIN K22 [get_ports {rx_dat[0]}]
set_property PACKAGE_PIN K21 [get_ports {rx_dat[1]}]
set_property PACKAGE_PIN J22 [get_ports {rx_dat[2]}]
set_property PACKAGE_PIN J20 [get_ports {rx_dat[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[0]}]
set_property PACKAGE_PIN M18 [get_ports tx_dv]
set_property IOSTANDARD LVCMOS33 [get_ports tx_dv]
set_property PACKAGE_PIN K18 [get_ports tx_clk]
set_property IOSTANDARD LVCMOS33 [get_ports tx_clk]
set_property PACKAGE_PIN M22 [get_ports {tx_d[0]}]
set_property PACKAGE_PIN L18 [get_ports {tx_d[1]}]
set_property PACKAGE_PIN L19 [get_ports {tx_d[2]}]
set_property PACKAGE_PIN L20 [get_ports {tx_d[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[0]}]
set_property PACKAGE_PIN W19 [get_ports sdrclk]
set_property PACKAGE_PIN Y22 [get_ports sdrden]
set_property PACKAGE_PIN V20 [get_ports {sdrdata[0]}]
set_property PACKAGE_PIN U20 [get_ports {sdrdata[1]}]
set_property PACKAGE_PIN AB22 [get_ports {sdrdata[2]}]
set_property PACKAGE_PIN AB21 [get_ports {sdrdata[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports sdrclk]
set_property IOSTANDARD LVCMOS33 [get_ports {sdrdata[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports sdrden]
set_property PACKAGE_PIN Y21 [get_ports tout]
set_property IOSTANDARD LVCMOS33 [get_ports tout]
set_property PACKAGE_PIN Y18 [get_ports sysclk]
set_property IOSTANDARD LVCMOS33 [get_ports sysclk]
create_clock -period 18.518 -name sdrclk -waveform {0.000 9.259} [get_ports sdrclk]
set_input_delay -clock [get_clocks *] -rise -max 2.000 [get_ports {{sdrdata[0]} {sdrdata[1]} {sdrdata[2]} {sdrdata[3]} sdrden}]
set_input_delay -clock [get_clocks *] -rise -min -2.000 [get_ports {{sdrdata[0]} {sdrdata[1]} {sdrdata[2]} {sdrdata[3]} sdrden}]
create_clock -period 18.518 -name rx_clk -waveform {0.000 9.259} [get_ports rx_clk]
set_input_delay -clock [get_clocks rx_clk] -rise -max 11.259 [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 7.259 [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 11.259 [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 7.259 [get_ports {rx_ctrl {rx_dat[0]} {rx_dat[1]} {rx_dat[2]} {rx_dat[3]}}]

重新对工程进行布局布线,然后打开布线设计,此时就看到时序出现了违例。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

查看时序报告

report timing看具体的时序报告

针对rx_clk进行分析

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

在number of paths per group选择100,number of paths per endpoint选择10,都尽可能的选大一些

number of paths per group:表示显示多少组的时序报告分析,从最差开始排列

number of paths per endpoint:表示选择的是有多少种的发射采样关系,比如上升沿发射,下降沿采样这就是一种关系,也有下降沿发射,上升沿采样,这也是一种关系。在这里设定为10中,但实际没有10种,因此会把所有的种类都显示出来。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

可以看到,建立时间出现了违例,保持时间是正常的

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

点开path1查看时序报告

数据时间到达的时间为11.714ns

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

时钟实际到达的时间为10.727ns

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

数据达到的时间比时钟达到的时间长,说明时钟的布线过于短,数据比时钟晚到,因此时钟采不到数据,造成建立时间的违例。应想办法尽量延长时钟的布线。

解决办法

在之前的input delay中进行的约束只是表述了时钟和数据的关系,告诉时序约束工具需要帮我们实现怎样的数据时钟关系,但是工具也可能做不到,这时候就需要人为的添加代码,手动的延长时钟的延时,以满足时序要求。

添加原语

在左侧菜单栏中点击原语

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_12,color_FFFFFF,t_70,g_se,x_16

 

依次选择以下选项

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

在顶层文件中添加其中的原语内容,同时将assign rx_clk_90 = rx_clk这句代码内容注释。

原语解释

原语中的有每句的解释,这句原语的目的很简单,就是为了让时钟中的延时增大,可以看到原语中让输入时钟rx_clk先通过IDATAIN然后经过一段时间的延时,再从DATAOUT给到rx_clk_90作为输出时钟,这其中的延时时间长短可以通过IDELAY_VALUE这个参数进行设定,这里先设定为18.

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
);

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(18),                // 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
   )
   IDELAYE2_inst_dv (
      .CNTVALUEOUT(), // 5-bit output: Counter value output
      .DATAOUT(rx_clk_90),         // 1-bit output: Delayed data output
      .C(1'b0),                     // 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(5'd0),   // 5-bit input: Counter value input
      .DATAIN(1'b0),           // 1-bit input: Internal delay data input
      .IDATAIN(rx_clk),         // 1-bit input: Data input from the I/O
      .INC(1'b0),                 // 1-bit input: Increment / Decrement tap delay input
      .LD(1'b0),                   // 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
   );

查看时序报告

重新布局布线,然后reload并report timing查看时序报告,操作和之前的一样。

可以看到时序恢复了正常,点开path101路径查看详细的时序报告。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

时序分析

以建立时间分析为例,保持时间的分析方法是一样的。

数据实际到达的时间为11.714ns

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

时钟实际到达的时间为12.832ns,与之前的作比较,可以看到时钟到达的时间明显增大了,其中增大的部分就是刚刚添加原语的部分,红框中的IDELAY2,这部分的延时有1.556ns。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATGluZXN0LTU=,size_20,color_FFFFFF,t_70,g_se,x_16

 

根据建立时间的计算公式,可以得出建立时间余量为1.119ns,满足时序的要求。

总结

当以第一种模型分析也就是不带有PLL的模型分析时,如果按照我们设定的约束,时序约束工具无法达到我们的要求,这时候就需要人为的更改代码,比如添加原语来增大时钟或数据的延时来满足时序要求。

往期系列博客

 【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边沿对齐,不同时序模型实操练习

 

 

  • 8
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linest-5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值