FPGA时序约束(解决满足建立和保持时间,最大时钟频率确定,避免时序违规,优化性能,支持多时钟域设计,支持异步接口等等问题)

一、引言

FPGA(现场可编程门阵列)在现代电子设计中扮演着举足轻重的角色。由于其高度的灵活性和可重配置性,FPGA被广泛应用于各种领域,如通信、图像处理、控制系统等。然而,随着设计复杂度的不断提高,时序约束成为了FPGA设计中不可或缺的一部分。本文将详细介绍FPGA时序约束的原理、应用,并通过一个案例分析来展示如何在设计中实施时序约束。

二、FPGA时序约束原理

FPGA时序约束主要关注设计中的时序要求,确保信号在FPGA内部传输和处理时满足特定的时间限制。这些时间限制包括建立和保持时间、最大时钟频率等。时序约束的目的是确保设计在各种操作条件下都能正确、稳定地运行。

时序约束的实现通常依赖于FPGA开发工具中的时序分析工具。这些工具可以自动分析设计中的时序路径,并生成时序报告。设计者可以根据时序报告中的信息来调整设计参数或添加时序约束,以满足设计要求。

三、FPGA时序约束应用

  1. 满足建立和保持时间:FPGA内部的逻辑单元(如查找表、寄存器等)在数据传输时有一定的建立和保持时间要求。时序约束确保在时钟边沿之前,输入信号有足够的时间稳定(满足建立时间),并在时钟边沿之后一段时间内保持不变(满足保持时间),从而确保数据能够正确地在FPGA内部传输和处理。

  2. 最大时钟频率确定:时序约束帮助设计者确定FPGA设计可以稳定运行的最高时钟频率。通过分析和优化设计的时序路径,设计者可以找到设计中的关键路径(即具有最长延迟的路径),并根据该路径的延迟来确定设计的最大时钟频率。

  3. 避免时序违规:在FPGA设计中,如果信号在传输或处理过程中的延迟超出了其时序约束,就可能导致时序违规(timing violation)。时序违规会导致设计无法正常工作,甚至可能损坏FPGA芯片。时序约束用于确保设计中的所有信号都满足其时序要求,从而避免时序违规的发生。

  4. 优化性能:除了满足基本的时序要求外,时序约束还可以用于优化FPGA设计的性能。例如,通过调整时序约束中的延迟参数,设计者可以平衡设计中的功耗、性能和面积等因素,以实现更优的设计效果。

  5. 支持多时钟域设计:在复杂的FPGA设计中,可能涉及到多个时钟域(即使用不同时钟频率的区域)。时序约束需要确保不同时钟域之间的信号能够正确地进行同步和传输,以避免跨时钟域的时序问题。

  6. 支持异步接口:当FPGA与外部设备或系统进行通信时,可能涉及到异步接口(即使用不同时钟源的接口)。时序约束需要确保在这些异步接口上正确地进行数据交换和同步操作。

四、案例分析

1.周期约束

周期约束是附加在时钟网路上的基本时序约束,以保证时钟区域内所有同步组件的时序满足要求。

常用的工程策略是:附加的时钟周期约束的时长为期望值的90%,即约束的最高频率是实际工作频率的110% 左右。

约束信号\] PERIOD = { 周期长度} {HIGH \| LOW} \[ 脉冲持续时间\];其中,\[\] 内的内容为可选项,{} 中的内容为必选项,"\|"表示选择项。\[ 约束信号\] 可为"Net net_name"或"TIMEGRP group_name",前者表示周期约束作用到线网所驱动的同步元件上,后者表示约束到TIMEGRP所定义的信号分组上( 如触发器、锁存器以及RAM 等)。{ 周期长度} 为要求的时钟周期,可选用ms、s、ns以及ps 等单位,默认值为ns,对单位不区分大小写。{HIGH \| LOW} 用于指定周期内第一个脉冲是高电平还是低电平。\[ 脉冲持续时间\] 用于指定第一个脉冲的持续时间,可选用ms、s、ns 以及ps 等单位,默认值为ns,如果缺省该项,则默认为50% 的占空比。如语句: Net" clk_100MHz" period = 10ns High 5ns; 指定了信号clk_100MHz 的周期为10ns,高电平持续的时间为5ns,该约束将被添加到信号clk_100MHz所驱动的元件上。 推荐方法常用于约束具有复杂派生关系的时钟网络,其基本语法为: TIMESPEC" TS_identifier" = PERIOD" TNM_reference" {周期长度}{HIGH \| LOW} \[ 脉冲持续时间\]; 其中,TIMESPEC 是一个基本时序相关约束,用于标志时序规范。"TS_identifier"由关键字TS 和用户定义的identifier 表示,二者共同构成一种时序规范,称为TS 属性定义,可在约束文件中任意引用,大大地丰富了派生时钟的定义。在使用时,首先要定义时钟分组,然后再添加相应的约束,如: **NET" clk_50MHz" =" syn_clk";** **TIMESPECT" TS_syn_clk" = PERIOD" syn_clk" 20 HIGN 10;** TIMESPEC 利用识别符定义派生时钟的语法为: **TIMESPEC" TS_identifier2" = PERIOD" timegroup_name" " TS_identifier1"\[\* \| /\] 倍数因子 \[+\| -\] phasevalue \[ 单位\]** 其中,TS_identifier2 是要派生定义的时钟,TS_identifier1 为已定义的时钟,"倍数因子"用于给出二者周期的倍数关系,phasevalue 给出二者之间的相位关系。如: 定义系统时钟clk_syn : **TIMESPEC" clk_syn" = PERIOD" clk" 5ns;** **下面给出其反相时钟clk_syn_180 以及2 分频时钟clk_syn_half :** **TIMESPEC" clk_syn_180" = PERIOD" clk_180" clk_syn PHASE + 2.5ns;** **TIMESPEC" clk_syn_180" = PERIOD" clk_half" clk_syn / 2;** ### 2.偏移约束 偏移约束也是一类基本时序约束,规定了外部时钟和数据输入输出引脚之间的相对时序关系,只能用于端口信号,不能应用于内部信号,包括OFFSET_IN_BEFORE,OFFSET_IN_AFTER,OFFSET_OUT_BEFORE,OFFSET_OUT_ AFTER 等4 类基本约束。偏移约束的基本语法为: **OFFSET = \[IN \| OUT\]" offset_time" \[units\] {BEFORE \| AFTER}" clk_name"\[TIMEGRP" group_name"\];** 其中\[IN \| OUT\] 说明约束的是输入还是输出。"offset_time"为数据和有效时钟沿之间的时间差,{BEFORE\| AFTER}表明该时间差是在有效时钟之前还是之后,"clk_name"为有效时钟的名字,\[TIMEGRP "group_name"\] 是用户添加的分组信号,在缺省时,默认为时钟clk_name 所驱动的所有触发器。偏移约束通知布局布线器输入数据的到达时刻,从而可准确调整布局布线的过程,使约束信号建立时间满足要求。 ### (1)"OFFSET IN"偏移约束 "OFFSET IN "偏移约束是输入偏移约束,有OFFSET_IN_AFTER 和OFFSET_IN_BEFORE 两种,前者定义了输入数据在有效时钟到达多长时间后可以到达芯片的输入管脚,这样可以得到芯片内部的延迟上限,从而对那些与输入引脚相连的组合逻辑进行约束;后者定义数据比相应的有效时钟沿提前多少时间到来,是与其相连的组合逻辑的最大延时,否则在时钟沿到来时,数据不稳定,会发生采样错误。输入偏移的时序关系如图所示。 ![df8b61116f034fc78f8a5608133fb929.jpg](https://file.jishuzhan.net/article/1792330780148502530/0012399028360fba175562ae45bb6803.webp) 例如: **NET" DATA_IN" OFFSET = IN 10.0 BEFORE" CLK_50MHz";** 表明在时钟信号CLK_50MHz 上升沿到达前的10ns 内,输入信号DATA_IN 必须到达数据输入管脚。 **NET" DATA_IN" OFFSET = IN 10.0 AFTER" CLK_50MHz";** 表明在时钟信号CLK_50MHz 上升沿到达后的10ns 内,输入信号DATA_IN 必须到达数据输入管脚。 ### (2)"OFFSET OUT"偏移约束 "OFFSET OUT"偏移约束是输出偏移约束,有OFFSET_OUT_AFTER 和OFFSET_OUT_BEFORE 两种,前者定义了输出数据在有效时钟沿之后多长时间稳定下来,是芯片内部输出延时的上限;后者定义了在下一个时钟信号到来之前多长时间必须输出数据,是下一级逻辑建立时间的上限。 例如: **NET" DATA_OUT" OFFSET = OUT 10.0 BEFORE" CLK_50MHz";** 表明在时钟信号CLK_50MHz 上升沿到达前的10ns 内,输出信号DATA_OUT 信号必须离开数据输出管脚。 **NET" DATA_OUT" OFFSET = OUT 10.0 AFTER" CLK_50MHz";** 表明在时钟信号CLK_50MHz 上升沿到达后的10ns 内,输出信号DATA_OUT 信号必须一直保持在数据输出管脚上。 ## 3.分组约束 分组约束可有效管理大量的触发器、寄存器和存储器单元,将其分为不同的组,每组附加各自的约束,在大型设计中有着广泛的应用。 ### (1)TNM/TNM_NET 约束 TNM/TNM_NET 约束用于选出可构成一个分组的元件,并对其重新命名,然后整体添加约束。除了IBUFG和BUFG 外,所有的FPGA 内部元件都可以用TNM 来命名,其语法规则为: **{NET\|INST\|PIN}" ob_name" TNM =" New_name";** 其中"ob_name"为NET、INST 以及PIN 的名称,New_name 为分组的名称。例如: **INST ff1 TNM = MY_FF1;** **NIST ff2 TNM = MY_FF1;** 将实例ff1 与ff2 添加到新分组MY_FF1 中。 此外,TNM 语法也支持通配符"?"和"\*",提高了在大规模设计中添加分组约束的效率。 当TNM 约束附加在线网上时,则该路径上所有的同步元件都会被添加到分组中,但不会穿过IBUFG 组件; 当TNM 约束附加到宏或原语的管脚上,则被该引脚驱动的所有同步元件会被添加到新分组中;当TNM 约束附加到原语或宏上,则将原语或宏添加到新的分组中。 TNM_NET 约束专门用来完成网线的分组,与TNM 不同的是,TNM 可以穿越IBUFG/BUFG。因此,如果把TNM 约束添加到端口上,则只能定义该端口;而要是把TNM_NET 添加到端口上,则可穿越BUFG,受该端口驱动的所有组件都将被添加到分组中。 ### (2)TIMEGRP 约束 TIMEGRP 用于分组合并和拆分,将多个分组形成一个新的分组。其合并分组的语法为: TIMEGRP" New_group" =" Old_group1" " Old_group2" ... ; 其中,New_group 为新建的分组,而Old_group1 和Old_group2 以及...为要合并的已有分组。 拆分分组的语法为: **TIMEGRP" New_group" =" Old_group1" EXCEPT" Old_group2";** 其中Old_group2 是Old_group1 的子集,New_group 为Old_group1 中除去Old_group2 之外所有的部分。 ### (3)TPSYNC 约束 TPSYNC 用于将那些不是管脚和同步元件的组件定义成同步元件,以便可以利用任意点来作为时序规范的终点和起点。其相应的语法为: **{NET\|INST\|PIN}" ob_name" TPSYNC=" New_part";** 将TPSYNC 约束附加在网线上,则该网线的驱动源为同步点;附加在同步元件的输出管脚上,则同步元件中驱动该管脚的源为同步点;附加在同步元件上,则输出管脚为同步点;附加在同步元件的输入管脚上,则该引脚被定义成同步点。 ### (4)TPTHRU 约束 TPTHRU 用于定义一个或一组路径上的关键点,可使用户定义出任意期望的路径。其相应的语法为: **{NET\|INST\|PIN}" ob_name" TPTHRU =" New_name";** 例如,在图 所示场景中,从A1 到A2 有两条路径,其中逻辑1 的延迟很大,需要提取出来完成特定的约束: ![aa83410c813f402aa46bda846df1a53a.jpg](https://file.jishuzhan.net/article/1792330780148502530/115a0606d34e647d63e42bb450e45465.webp) TPTHRU约束示例场景: **INST" A1" TNM =" S";** **INST" A2" TNM =" E";** **NET" A1toA2_1" TPTHRU =" M";** **TIMESPEC" SME" = FROM" S" THRU" M" TO" B" 10;** 其中第三句指令利用TPTHRU 定义了中间点"M",然后第4 句在此基础上定义了通过M 点的整条路径,从两条平行的路径中挑出了期望路径。 ### 4.局部约束 局部约束包括FROM_TO 约束、最大延时约束、最大偏移约束、虚假路径、系统时钟抖动约束、多周期路径和多时钟域约束等。在实际开发中,正如本章前沿所述,时序是设计出来,而不是靠约束自动得到的,因此这里不再对局部约束作过多讨论。 ## 五、总结 FPGA时序约束是确保FPGA设计在各种操作条件下都能满足其时序要求的关键技术。通过合理设置和应用时序约束,设计者可以确保设计的正确性、稳定性和性能优化。在FPGA设计中,时序约束的应用体现在满足建立和保持时间、确定最大时钟频率、优化性能、支持多时钟域设计和支持异步接口等方面。通过案例分析,我们可以看到时序约束在实际设计中的具体实现方法。

相关推荐
BanyeBirth1 分钟前
C++高精度算法(加、减、乘)
开发语言·c++·算法
houliabc1 分钟前
C语言个人笔记
c语言·数据结构·笔记·算法
Allen Wurlitzer21 分钟前
算法刷题记录——LeetCode篇(1.9) [第81~90题](持续更新)
算法·leetcode·职场和发展
@MrLiu22 分钟前
# 深度学习中的优化算法详解
人工智能·深度学习·算法·优化器
阳洞洞25 分钟前
leetcode 377. Combination Sum IV
算法·leetcode·动态规划·完全背包问题
阿巴~阿巴~1 小时前
蓝桥杯 C/C++ 组历届真题合集速刷(一)
c语言·c++·算法·蓝桥杯
_x_w1 小时前
【12】数据结构之基于线性表的排序算法
开发语言·数据结构·笔记·python·算法·链表·排序算法
瀚海澜生1 小时前
链表系列入门指南(二):吃透这几题,链表解题不再难
后端·算法
爱编码的傅同学2 小时前
数据结构(五)——AVL树(平衡二叉搜索树)
数据结构·算法
Bonnie_12152 小时前
02-redis-数据结构实现原理
数据结构·redis·算法