第5章 I/O接口约束 为了获得更精准的FPGA外部时序信息,设计者需要为FPGA的I/O(输入或输出)接口指定时序信息。Xilinx Vivado时序工具只能获取和分析FPGA器件内部的时序信息,而在FPGA器件引脚之外的时序信息,必须由设计者约束定义。set_input_delay和set_output_delay命令就是用于约束定义FPGA引脚边界之外的时序延时。本章将具体介绍使用set_input_delay和set_output_delay约束命令进行I/O接口的约束,并通过几个实例进行深入的应用讲解。 5.1输入接口约束语法 set_input_delay命令用于指定输入数据引脚相对于其时钟沿的路径延时。通常输入延时值包括了数据信号从外部芯片到FPGA引脚的板级延时以及与其板级的参考时钟之间的相对延时值。因此,输入延时值可以是正值,也可以是负值,取决于时钟相对数据信号在FPGA引脚上的相位关系。 set_input_delay命令可以应用于FPGA器件的输入数据引脚或双向数据引脚,但不适用于FPGA内部信号或时钟输入引脚。若使用set_input_delay约束时钟输入引脚,将会被时序工具忽略。set_input_delay以max和min参数分别表示约束的最大值和最小值,最大值用于建立时间检查,最小值用于保持时间检查。 set_input_delay约束命令的基本语法如下。 set_input_delay -clock -reference_pin -clock_fall -rise -max -add_delay  clock用于指定约束引脚的同步时钟(源时钟),其后的即需要指定的同步时钟名称,这个时钟可以是设计中事先定义的主时钟或虚拟时钟。  reference_pin用于指定延时值的参考时钟,其后的即需要指定的参考时钟名称。reference_pin 是可选项,不指定该选项,则指定延时值的参考时钟就是clock指定的同步时钟。  clock_fall命令选项指定输入延时约束取值相对于同步时钟的下降沿。若不指定clock_fall命令选项,Vivado时序工具将默认为clock_rise。  rise指定约束信号相对时钟的边沿关系是上升沿,也可以用fall指定为下降沿。  max表示设定最大延时值,也可以使用min设定最小延时值。若不指定min或max命令选项,则输入延时值同时用于最大和最小延时值的时序路径分析。  用于指定将应用到目标输入引脚的延时值。有效值为大于或等于0的浮点数,1.0为默认值。  用于指定约束的目标输入引脚名称。 5.2输入接口约束实例 实例5.1: 以主时钟为同步时钟的输入引脚约束 该实例定义了输入引脚为CLK0的主时钟sysClk,同时约束了max和min值同为2ns的输入延时约束。 create_clock -name sysClk -period 10 [get_ports CLK0] set_input_delay -clock sysClk 2 [get_ports DIN] 实例5.2: 以虚拟时钟为同步时钟的输入引脚约束 该实例定义了一个虚拟时钟clk_port_virt,同时约束了max和min值同为2ns的输入延时约束。 create_clock -name clk_port_virt -period 10 set_input_delay -clock clk_port_virt 2 [get_ports DIN] 实例5.3: 指定最大和最小延时值的输入引脚约束 该实例定义了输入引脚为CLK0的主时钟sysClk,同时约束了max和min值分别为4ns和1ns的输入延时约束。 create_clock -name sysClk -period 10 [get_ports CLK0] set_input_delay -clock sysClk -max 4 [get_ports DIN] set_input_delay -clock sysClk -min 1 [get_ports DIN] 实例5.4: 参考时钟下降沿的输入引脚约束 该实例对输入引脚DIN做约束,指定其相对同步时钟clk1下降沿后2ns的输入延时值。约束脚本如下。 set_input_delay -clock_fall -clock clk1 2 [get_ports DIN] 实例5.5: 同时指定同步时钟和参考时钟的输入引脚约束 该实例对输入引脚reset做约束,指定其同步时钟为wbClk,相对参考时钟wbClk_IBUF_BUFG_inst/O上升沿后2ns的输入延时值。约束脚本如下。 set_input_delay -clock wbClk 2 -reference_pin [get_pin wbClk_IBUF_BUFG_inst/O] [get_ports reset] 实例5.6: 多组参考组合的输入引脚约束 该实例对输入时钟引脚DDR_CLK_IN做主时钟约束,命名为clk_ddr,指定时钟周期为6ns。同时以clk_ddr作为同步时钟,对输入数据引脚DDR_IN分别做相对同步时钟上升沿和下降沿的输入延时约束,并分别指定其输入延时的最大值和最小值。约束脚本如下。 create_clock -name clk_ddr -period 6 [get_ports DDR_CLK_IN] set_input_delay -clock clk_ddr -max 2.1 [get_ports DDR_IN] set_input_delay -clock clk_ddr -max 1.9 [get_ports DDR_IN] -clock_fall -add_delay set_input_delay -clock clk_ddr -min 0.9 [get_ports DDR_IN] set_input_delay -clock clk_ddr -min 1.1 [get_ports DDR_IN] -clock_fall -add_delay 5.3输入接口约束分析 实例5.7: 图像传感器输入引脚约束 如图5.1所示,以图像传感器MT9V034和FPGA的接口为例。图像传感器的输出接口包括同步时钟image_sensor_pclk、8位图像数据总线image_sensor_data[7:0]、帧同步信号image_sensor_vsync和行同步信号image_sensor_href,这些信号作为输入连接到FPGA器件的引脚。在FPGA器件中,同步时钟image_sensor_pclk的上升沿采集数据信号image_sensor_data[7:0]和同步信号image_sensor_href/image_sensor_vsync, 图5.1图像传感器与FPGA接口示意图 可以对它们使用set_input_delay命令进行输入接口时序约束。 看到这个接口的时候,可以先回顾一下2.4节中提到的引脚到寄存器的时序路径模型。图5.2所示就是这样一个FPGA输入引脚的源同步接口。 图5.2FPGA输入引脚的源同步接口 按照2.4.3节的分析,可以使用如下的公式计算输入引脚进行set_input_delay约束的最大值和最小值。 (1) 用于建立时间分析的set_input_delaymax时间计算: set_input_delay(max)=-Tc2j_pcb(min)+Tco(max)+Td_pcb(max) (2) 用于保持时间分析的set_input_delaymin时间计算: set_input_delay(min)=-Tc2j_pcb(min)+Tco(max)+Td_pcb(min) 数据和时钟在PCB板上的延时值Td_pcb和Tc2j_pcb ,通过PCB的走线测量即可算出。PCB板级走线延时可以按照0.17ns/in进行换算。该实例中,假设Td_pcb(max)=0.5ns,Td_pcb(min)=0ns,Tc2j_pcb(max)=0.5ns,Tc2j_pcb(min)=0ns。 MT9V034芯片内部的时序信息,则需要查看MT9V034的芯片手册获取。如图5.3和图5.4所示,在MT9V034的芯片手册中,找到了一个最有用的时序参数tPD,它表示数据变化相对于其同步时钟PIXCLK下降沿的延时,最大值为3ns,最小值为-3ns。 图5.3MT9V034的时序参数列表截图 图5.4MT9V034的时序波形截图 根据芯片手册给出的参数,可以将tPD(数据输出相对于时钟下降沿的延时)映射到数据输出相对于时钟上升沿的延时Tco(已知同步时钟PIXCLK的时钟周期为40ns,相当于时钟沿左移20ns),那么可以得到Tco(max)=23ns,Tco(min)=17ns,示意如图5.5所示。 图5.5Tco时序参数换算 将以上获取的参数代入set_input_delay的计算公式,可以获得最大值和最小值如下。 set_input_delay(max)=-0ns+23ns+0.5ns=23.5ns set_input_delay(min)=-0.5ns+17ns+0ns=16.5ns 接下来在Vivado中进行时序约束,打开Vivado软件,进入Timing Constraints界面。 选中时钟约束分类中的Create Generated Clock,单击右侧界面的“+”号添加新的约束。如图5.6所示,对输入时钟引脚image_sensor_pclk做约束,时钟周期为40ns,命名为image_pclk。 图5.6主时钟约束 产生的约束脚本如下。 create_clock -period 40.000 -name image_pclk -waveform {0.000 20.000} [get_ports image_sensor_pclk] 如图5.7所示,找到并选择Inputs→Set Input Delay分类,单击其主页面中左上角的“+”号添加一个新的约束。 图5.7Set Input Delay约束界面 Set Input Delay最大值约束如图5.8所示,选择同步时钟Clock为新约束的image_pclk,约束引脚Objects(ports)为image_sensor_data[7:0]/image_sensor_href/image_sensor_vsync,延时值Delay value为23.5ns,勾选Delay value specifies为max。 图5.8Set Input Delay最大值约束 Set Input Delay最小值约束如图5.9所示,选择同步时钟Clock为新约束的image_pclk,约束引脚Objects(ports)为image_sensor_data[7:0]/image_sensor_href/image_sensor_vsync,延时值Delay value为16.5ns,勾选Delay value specifies为min。 图5.9Set Input Delay最小值约束 生成约束脚本如下。 set_input_delay -clock [get_clocks image_pclk] -max 23.500 [get_ports {{image_sensor_data[0]} {image_sensor_data[1]} {image_sensor_data[2]} {image_sensor_data[3]} {image_sensor_data[4]} {image_sensor_data[5]} {image_sensor_data[6]} {image_sensor_data[7]} image_sensor_href image_sensor_vsync}] set_input_delay -clock [get_clocks image_pclk] -min 16.500 [get_ports {{image_sensor_data[0]} {image_sensor_data[1]} {image_sensor_data[2]} {image_sensor_data[3]} {image_sensor_data[4]} {image_sensor_data[5]} {image_sensor_data[6]} {image_sensor_data[7]} image_sensor_href image_sensor_vsync}] 重新对工程进行编译,随后单击Open Implemented Design,查看Timing中IntraClock Paths→image_pclk的时序,如图5.10所示。 图5.10image_pclk时钟的时序报告 如图5.11和图5.12所示,这是一条建立时间路径的详细时序报告。Set_input_delay的最大值23.5ns作为Data Path的一部分进行计算,Data Path最终算得的Arrival Time为24.727ns,在FPGA内部的纯数据路径延时为24.727ns-23.5ns=1.227ns。Destination Clock Path延时为41.802ns,其中包括了时钟锁存沿40ns、时钟不确定时间-0.035ns、建立时间-0.043ns,扣除这些时间,纯时钟路径的延时为41.802ns-40ns-(-0.035ns)-(-0.043ns)=1.88ns。 图5.11建立时间时序报告1 图5.12建立时间时序报告2 以寄存器模型来标示这些延时时间参数,如图5.13所示。由于Tc2j_pcb时间已经计算到set_input_delay约束中了,所以图中标示为0。 图5.13建立时间延时标示 如图5.14和图5.15所示,这是一条保持时间路径的时序报告,Set_input_delay的最小值16.5ns同样也是作为Data Path的一部分进行计算的。Data Path最终算得的Arrival Time为19.076ns,在FPGA内部的纯路径延时为19.076ns-16.5ns=2.576ns。Destination Clock Path延时为5.632ns,其中包括了时钟锁存沿0ns、时钟不确定(clock uncertainty)时间0.035ns、保持(Hold)时间0.243ns,扣除这些时间,纯时钟路径的延时为5.632ns-0ns-0.035ns-0.243ns=5.354ns。 图5.14保持时间时序报告1 图5.15保持时间时序报告2 以寄存器模型标示这些延时时间参数,如图5.16所示。由于Tc2j_pcb时间已经计算到set_input_delay约束中了,所以图中标示为0。 图5.16保持时间延时标示 对于这个实例,只是按照第2章给出的一些基本路径分析方法,套用基本公式计算出set_input_delay命令的最大值和最小值进行时序约束和分析。下面可以变通一下,直接使用芯片手册给出的参数值,对set_input_delay命令进行一些设置改动,再看看是否能够达到一样的时序约束和分析结果。 图5.3和图5.4给出的MT9V034芯片手册截图中,时序参数tPD表示数据变化相对于其同步时钟PIXCLK下降沿的延时,最大值为3ns,最小值为-3ns。我们不做变换,就以PIXCLK的下降沿作为源时钟的参考时钟沿,可以计算得到set_input_delay的最大值和最小值如下。 set_input_delay(max)=-0ns+3ns+0.5ns=3.5ns set_input_delay(min)=-0.5ns-3ns+0ns=-3.5ns 如图5.17和图5.18所示,分别修改最大值和最小值约束的Delay Value为3.5ns和-3.5ns,设置Dealy value is relative to clock edge为fall,即延时值是相对于参考时钟的下降沿。 图5.17Set Input Delay最大值约束 图5.18Set Input Delay最小值约束 新的约束脚本如下,除了max和min后面的时间值改变了外,最重要的是还增加了clock_fall这个可选命令项。 set_input_delay -clock [get_clocks image_pclk] -clock_fall -max 3.5 [get_ports {{image_sensor_data[0]} {image_sensor_data[1]} {image_sensor_data[2]} {image_sensor_data[3]} {image_sensor_data[4]} {image_sensor_data[5]} {image_sensor_data[6]} {image_sensor_data[7]} image_sensor_href image_sensor_vsync}] set_input_delay -clock [get_clocks image_pclk] -clock_fall -min -3.5 [get_ports {{image_sensor_data[0]} {image_sensor_data[1]} {image_sensor_data[2]} {image_sensor_data[3]} {image_sensor_data[4]} {image_sensor_data[5]} {image_sensor_data[6]} {image_sensor_data[7]} image_sensor_href image_sensor_vsync}] 最后来看产生的时序报告,图5.19和图5.20是建立时间时序报告,图5.21和图5.22是保持时间时序报告。从报告中可以看到,Requirement时间都发生了变化,这主要是由于修改了源时钟的参考时钟沿,但是由于相应地修改了Dealy value,所以最终的Slack时间是一致的。 图5.19建立时间时序报告1 图5.20建立时间时序报告2 图5.21保持时间时序报告1 图5.22保持时间时序报告2 实例5.8: SPI接口的输入引脚约束 如图5.23所示,下面这个例子以FPGA和外设之间的SPI接口为例。FPGA器件作为SPI接口主机,与外设芯片进行SPI总线 图5.23SPI接口示意图 通信,对于FPGA器件的spi_miso输入数据信号,也可以使用set_input_delay命令进行时序约束。 这个例子中,外设芯片的时钟spi_clk来自FPGA器件。在FPGA器件中,使用PLL产生了一个25MHz的时钟,作为SPI接口时钟,用于驱动输出信号spi_clk。因此,首先需要约束spi_clk接口作为衍生时钟。如图5.24所示,约束定义了SPI_CLK这个衍生时钟,它的源时钟是PLL输出时钟(uut_clk_wiz_0/clk_out1),信号接口是spi_clk,与源时钟同频同相。 图5.24衍生时钟约束SPI的时钟信号 衍生时钟的约束脚本如下。 create_generated_clock -name SPI_CLK -source [get_pins uut_clk_wiz_0/clk_out1] -multiply_by 1 [get_ports spi_clk] 按照2.4.3节的分析,可以使用如下的公式计算输入引脚进行set_input_delay约束的最大值和最小值。 (1) 用于建立时间分析的set_input_delaymax时间计算: set_input_delay(max)=-Tc2j_pcb(min)+Tco(max)+Td_pcb(max) (2)用于保持时间分析的set_input_delaymin时间计算: set_input_delay(min)=-Tc2j_pcb(max)+Tco(min)+Td_pcb(min) 对于数据和时钟在PCB板上的延时值Td_pcb和Tc2j_pcb ,仍然假设Td_pcb(max)=0.5ns,Td_pcb(min)=0ns,Tc2j_pcb(max)=0.5ns,Tc2j_pcb(min)=0ns。 本实例中,假设与FPGA器件连接的外设芯片是一颗SPI Flash,型号为M25P40。如图5.25和图5.26所示,在M25P40的芯片手册中,时序参数tCLQV和tCLQX分别表示spi_miso(Q)数据变化相对于其同步时钟spi_clk(C)下降沿的延时,最大值为15ns,最小值为0ns。 图5.25M25P40的时序参数列表截图 图5.26M25P40的时序波形截图 将以上获取的参数代入set_input_delay的计算公式,可以获得最大值和最小值如下。 set_input_delay(max)=-0ns+15ns+0.5ns=15.5ns set_input_delay(min)=-0.5ns+0ns+0ns=-0.5ns 如图5.27和图5.28所示,使用GUI约束设置spi_miso信号的set_input_delay的最大值和最小值约束,注意Dealy value is relative to clock edge需要设置为fall,表示约束值是相对于时钟的下降沿的。 约束脚本如下。 set_input_delay -clock [get_clocks SPI_CLK] -clock_fall -max 15.5 [get_ports spi_miso] set_input_delay -clock [get_clocks SPI_CLK] -clock_fall -min -0.5 [get_ports spi_miso] 其中一条spi_miso路径的建立时间时序报告如图5.29和图5.30所示,对应路径的保持时间时序报告如图5.31和图5.32所示。 图5.27Set Input Delay最大值约束 图5.28Set Input Delay最小值约束 图5.29建立时间时序报告1 图5.30建立时间时序报告2 图5.31保持时间时序报告1 图5.32保持时间时序报告2 大家可以考虑一下,若set_input_delay约束的参考时钟沿为上升沿,即Dealy value is relative to clock edge设置为rise,和实例5.7一开始的分析方法一致,这个实例该如何约束?结果是否也一样呢? 另外,大家可能已经注意到了,这个实例中建立时间报告的余量(Slack)是负值,也就是说,这个时序是失败的。那如何解决呢?对于这个例子,最简单的办法是降低时钟频率,这样可用时间增加,问题总会解决。但是降低时钟频率意味着SPI通信的整体速度变慢,可能影响系统性能,所以这不是最好的解决方案。若大家再仔细分析保持时间报告,就可以发现保持时间余量非常充足,那么也可以考虑在FPGA内部将数据的采样由上升沿改为下降沿,或者更推荐的做法是,FPGA内部采样spi_miso信号的时钟相对于输出的spi_clk能够有一定的相位差,这也无形中调整了建立时间关系和保持时间关系,让这两个对立的关系能够达到一个相对的平衡。关于具体的实现,这里不再展开介绍,有兴趣的读者可以自己研究和实践。 5.4输出接口约束语法 set_output_delay命令用于指定输出数据引脚相对于其时钟沿的路径延时。通常输出延时值包括了数据信号从FPGA引脚到外部芯片的板级延时、外部芯片的建立时间和保持时间等。输出延时值可以是正值,也可以是负值。 set_output_delay命令可以应用于FPGA器件的输出数据引脚或双向数据引脚,但不适用于FPGA内部信号或时钟输出引脚。若使用set_output_delay约束时钟输出引脚,将会被时序工具忽略。set_output_delay以max和min参数分别表示约束的最大值和最小值,最大值用于建立时间检查,最小值用于保持时间检查。 set_output_delay约束命令的语法格式与set_input_delay一样,其基本语法如下。 set_output_delay -clock -reference_pin -clock_fall -rise -max -add_delay  clock用于指定约束引脚的同步时钟(源时钟),其后的即需要指定的同步时钟名称,这个时钟可以是设计中事先定义的主时钟或虚拟时钟。  reference_pin用于指定延时值的参考时钟,其后的即需要指定的参考时钟名称。reference_pin 是可选项,不指定该选项,则指定延时值的参考时钟就是clock指定的同步时钟。  clock_fall命令选项指定输出延时的取值相对于同步时钟的下降沿。若不指定clock_fall命令选项,Vivado时序工具将默认为clock_rise。  rise指定约束信号相对时钟的边沿关系是上升沿,也可以用fall指定为下降沿。  max表示设定最大延时值,也可以使用min设定最小延时值。若不指定min或max命令选项,则输出延时值同时用于最大和最小延时值的时序路径分析。  用于指定将应用到目标输出引脚的延时值。有效值为大于等于0的浮点数,1.0为默认值。  用于指定约束的目标输出引脚名称。 5.5输出接口约束实例 实例5.9: 以主时钟为同步时钟的输出引脚约束 该实例对一个输出引脚DOUT进行输出延时约束,参考时钟是事先定义好的主时钟sysClk。该约束未指定max和min,表示约束的延时值同时应用于max和min两种情况。 create_clock -name sysClk -period 10 [get_ports CLK0] set_output_delay -clock sysClk 6 [get_ports DOUT] 实例5.10: 以虚拟时钟为同步时钟的输出引脚约束 该实例对一个输出引脚DOUT进行输出延时约束,参考时钟是事先定义好的虚拟时钟clk_port_virt。该约束未指定max和min,表示约束的延时值同时应用于max和min两种情况。 create_clock -name clk_port_virt -period 10 set_output_delay -clock clk_port_virt 6 [get_ports DOUT] 实例5.11: 同时指定时钟上升沿和下降沿的输出引脚约束 该实例对一个DDR数据端口DDR_OUT进行输出延时约束,其参考时钟是事先定义好的主时钟clk_ddr。在约束中,由于输出数据引脚DDR_OUT在时钟clk_ddr的上升沿和下降沿同时需要采样,所以使用clock_fall add_delay选项额外指定了下降沿的输出延时(无clock_fall add_delay的选项默认为上升沿的输出延时约束)。 create_clock -name clk_ddr -period 6 [get_ports DDR_CLK_IN] set_output_delay -clock clk_ddr -max 2.1 [get_ports DDR_OUT] set_output_delay -clock clk_ddr -max 1.9 [get_ports DDR_OUT] -clock_fall -add_delay set_output_delay -clock clk_ddr -min 0.9 [get_ports DDR_OUT] set_output_delay -clock clk_ddr -min 1.1 [get_ports DDR_OUT] -clock_fall -add_delay 5.6输出接口约束分析 实例5.12: VGA驱动输出引脚约束 如图5.33所示,以FPGA到A/D芯片ADV7123的输出接口为例。ADV7123是一颗3路并行高速A/D芯片,用于驱动VGA接口的显示器。FPGA与ADV7123之间是一组源同步接口,输出时钟信号vga_clk,数据信号包括vga_r[4:0]、vga_g[5:0]、vga_b[4:0]、vga_rgb[2:0]、vga_vsy和vga_hsy。FPGA输出的数据信号可以使用set_output_delay命令进行时序约束。 图5.33FPGA器件与ADV7123芯片接口 可以先回顾一下在2.5节中提到的寄存器到引脚的时序路径模型。图5.34就是这样一个FPGA输出引脚的源同步接口。 图5.34FPGA输出引脚的源同步接口 按照2.5.2节的分析,可以使用如下的公式计算输出引脚进行set_output_delay约束的最大值和最小值。 (1) 用于建立时间分析的set_output_delaymax时间计算: set_output_delay(max)=Td_pcb(max)-Tc2j_pcb(min)+Tsu (2) 用于保持时间分析的set_output_delaymin时间计算: set_output_delay(min)=Td_pcb(min)-Tc2j_pcb(max)-Th 数据和时钟在PCB板上的延时值Td_pcb和Tc2j_pcb ,通过PCB的走线测量即可算出。PCB板级走线延时可以按照0.17ns/in进行换算。该实例中,假设Td_pcb(max)=0.5ns,Td_pcb(min)=0ns,Tc2j_pcb(max)=0.5ns,Tc2j_pcb(min)=0ns。 在ADV7123的芯片手册中,可以看到如图5.35和图5.36所示的接口时序参数和时序波形。在截图中,可以找到t1和t2两个参数,分别为数据采样的建立时间Tsu和保持时间Th,也即Tsu=t1=0.2ns,Th=t2=1.5ns。 图5.35ADV7123接口时序参数截图 图5.36ADV7123接口时序波形截图 代入这些已知参数,可以根据公式计算得到set_output_delay约束的最大值和最小值如下。 set_output_delay(max)=0.5ns-0ns+1.5ns=2ns set_output_delay(min)=0ns-0.5ns-0.2ns=-0.7ns 在Vivado中,首先需要进行衍生时钟约束。时钟信号vga_clk的上升沿为了更好地和同步数据的中央对齐,以获得最佳的建立时间和保持时间余量,由PLL的输出时钟(u1_clk_wiz_0/clk_out5)反向后输出,使用GUI进行衍生时钟约束如图5.37所示。该衍生时钟名称为VGA_CLK,目标引脚是vga_clk,源时钟是PLL输出时钟u1_clk_wiz_0/clk_out5,同频率,相位取反(如图中箭头指示,在GUI中勾选Invert the generated clock signal)。 图5.37衍生时钟约束 衍生时钟的约束脚本如下。 create_generated_clock -name VGA_CLK -source [get_pins u1_clk_wiz_0/clk_out5] -multiply_by 1 -invert [get_ports vga_clk] 如图5.38所示,在Timing Constrains页面中,找到并选择Outputs→Set Output Delay分类,单击其主页面中左上角的“+”号添加一个新的约束。 图5.38Set Output Delay约束界面 Set Output Delay最大值约束如图5.39所示,选择同步时钟Clock为新约束的VGA_CLK,约束引脚Objects(ports)为vga_r[4:0]、vga_g[5:0]、vga_b[4:0]、vga_rgb[2:0]、vga_vsy和vga_hsy,延时值Delay value为2ns,勾选Delay value specifies为max。 Set Output Delay最小值约束如图5.40所示,选择同步时钟Clock为新约束的VGA_CLK,约束引脚Objects(ports)为vga_r[4:0]、vga_g[5:0]、vga_b[4:0]、vga_rgb[2:0]、vga_vsy和vga_hsy,延时值Delay value为-0.7ns,勾选Delay value specifies为min。 图5.39Set Output Delay最大值约束 图5.40Set Output Delay最小值约束 生成的约束脚本如下。 set_output_delay -clock [get_clocks VGA_CLK] -max 2.0 [get_ports {{vga_g[0]} {vga_g[1]} {vga_g[2]} {vga_g[3]} {vga_g[4]} {vga_g[5]} vga_hsy {vga_r[0]} {vga_r[1]} {vga_r[2]} {vga_r[3]} {vga_r[4]} {vga_rgb[0]} {vga_rgb[1]} {vga_rgb[2]} vga_vsy {vga_b[0]} {vga_b[1]} {vga_b[2]} {vga_b[3]} {vga_b[4]}}] set_output_delay -clock [get_clocks VGA_CLK] -min -0.7 [get_ports {{vga_g[0]} {vga_g[1]} {vga_g[2]} {vga_g[3]} {vga_g[4]} {vga_g[5]} vga_hsy {vga_r[0]} {vga_r[1]} {vga_r[2]} {vga_r[3]} {vga_r[4]} {vga_rgb[0]} {vga_rgb[1]} {vga_rgb[2]} vga_vsy {vga_b[0]} {vga_b[1]} {vga_b[2]} {vga_b[3]} {vga_b[4]}}] 重新对工程进行编译,随后单击Open Implemented Design,查看Timing中的Clock Summary,如图5.41所示。这里显示了约束的衍生时钟VGA_CLK,它是PLL的输出时钟clk_out5_clk_wiz_0的同频反相时钟。时钟clk_out5_clk_wiz_0和VGA_CLK的时钟周期都是13.846ns(时钟频率是72.222MHz); 但时钟clk_out5_clk_wiz_0的上升沿和下降沿时刻是0ns和6.923ns,时钟VGA_CLK的上升沿和下降沿时刻是6.923ns和13.846ns,正好反相(180°相位差)。 图5.41Clock Summary报告 查看Timing中IntraClock Paths→VGA_CLK的时序报告,如图5.42所示。 图5.42衍生时钟VGA_CLK的报告 下面来看一条建立时间路径的详细时序报告。 如图5.44所示,源时钟延时(Source Clock Path)为-0.909ns。Data Path最终算得的Arrival Time为7.719ns,若扣除时钟延时(Source Clock Path),在FPGA内部的纯数据延时为7.719ns-(-0.909ns)=8.628ns,即如图5.43所示Summary报告中的Data Path Delay时间8.629ns(计算中可能存在四舍五入误差,最后一位偏差±1属于正常结果)。如图5.45所示,Set_output_delay的最大值2ns作为Data Path的Output Delay(取负值)进行计算。Destination Clock Path延时为9.378ns,其中包括了时钟锁存沿6.923ns、Clock Pessimism时间0.561ns、Clock Uncertainty时间-0.118ns、Output Delay时间-2ns以及纯时钟路径延时。纯时钟路径延时为9.378ns-6.923ns-0.561ns-(-0.118ns)-(-2ns)=4.012ns。 图5.43建立时间时序报告1 图5.44建立时间时序报告2 图5.45建立时间时序报告3 再回头看图5.43的Summay报告,首先注意Source一行括号中标示的源寄存器时钟是FPGA内部PLL时钟,而Destination一行括号中标示的目的寄存器时钟是VGA_CLK,即源寄存器时钟的反相。因此,Requirement是6.923ns,即半个时钟周期。最终的时序余量(Slack)为9.378ns-7.719ns=1.659ns。 若用寄存器模型标示这些延时参数,如图5.46所示。 图5.46建立时间延时标示 再来看相同路径的保持时间时序分析报告。 如图5.48所示,Source Clock Path为13.429ns,若扣除时钟发射沿(clock VGA_CLK rise edge)13.846ns,算得纯时钟路径延时为13.429ns-13.846ns=-0.417ns。Data Path最终算得的Arrival Time为16.444ns,若扣除时钟延时(Source Clock Path),在FPGA内部的纯数据延时为16.444ns-13.429ns=3.015ns,即图5.47所示Summary报告中的Data Path Delay时间。如图5.49所示,Set_output_delay的最小值0.7ns作为Data Path的Output Delay(取正值)进行计算。Destination Clock Path延时为10.416ns,其中包括了时钟锁存沿6.923ns、纯时钟路径延时、Clock Pessimism时间0.423ns、Clock Uncertainty时间0.118ns、Output Delay时间0.7ns。纯时钟路径延时为10.416ns-6.923ns-0.423ns-0.118ns-0.7ns=2.252ns。 图5.47保持时间时序报告1 图5.48保持时间时序报告2 图5.49保持时间时序报告3 再回头看图5.47的Summay报告,最终的时序余量(Slack)为16.444ns-10.416ns=6.028ns。 若用寄存器模型标示这些延时参数,如图5.50所示。 图5.50保持时间延时标示 实例5.13: SPI接口输出引脚约束 如图5.51所示,与实例5.8一样,以FPGA和外设之间的SPI接口为例。FPGA器件作为SPI接口主机,与外设芯片进行SPI总线通信,对于FPGA器件的spi_mosi输出数据信号,也可以使用set_output_delay命令进行时序约束。 图5.51SPI接口示意图 按照2.5.2节的分析,可以使用如下的公式计算输出引脚进行set_output_delay约束的最大值和最小值。 (1) 用于建立时间分析的set_output_delaymax时间计算: set_output_delay(max)=Td_pcb(max)-Tc2j_pcb(min)+Tsu (2) 用于保持时间分析的set_output_delaymin时间计算: set_output_delay(min)=Td_pcb(min)-Tc2j_pcb(max)-Th 该实例中,仍然假设Td_pcb(max)=0.5ns,Td_pcb(min)=0ns,Tc2j_pcb(max)=0.5ns,Tc2j_pcb(min)=0ns。 在M25P40的芯片手册中,可以看到如图5.52和图5.53所示的接口时序参数和时序波形。在截图中,可以找到tDVCH和tCHDX两个参数,分别为数据采样的建立时间Tsu和保持时间Th,也即Tsu=tDVCH=5ns,Th=tCHDX=5ns。 图5.52M25P40的时序参数列表截图 图5.53M25P40的时序波形截图 代入这些已知参数,可以根据公式计算得到set_output_delay的最大值和最小值时间如下。 set_output_delay(max)=0.5ns-0ns+5ns=5.5ns set_output_delay(min)=0ns-0.5ns-5ns=-5.5ns 如图5.54和图5.55所示,分别对输出数据引脚spi_mosi使用set_output_delay进行最大值和最小值约束设置。 图5.54Set Output Delay最大值约束 图5.55Set Output Delay最小值约束 约束脚本如下。 set_output_delay -clock [get_clocks SPI_CLK] -max 5.5 [get_ports spi_mosi] set_output_delay -clock [get_clocks SPI_CLK] -min -5.5 [get_ports spi_mosi] 查看一条路径的建立时间的时序报告,如图5.56和图5.57所示。 图5.56建立时间时序报告1 查看同一条路径的保持时间的时序报告,如图5.58和图5.59所示。 图5.57建立时间时序报告2 图5.58保持时间时序报告1 图5.59保持时间时序报告2