《Xilinx约束学习笔记》为自己阅读 Xilinx 官方 UG903 文档后的学习笔记,大多数为翻译得来,方便大家学习。

1 约束方法学

1.1 组织约束文件

Xilinx 建议将时序约束物理约束分开保存为两个不同的文件。甚至可以将针对某一个模块的约束单独保存在一个文件中。

1.1.1 综合和实现可以使用不同的约束文件

可以使用 USED_IN_SYNTHESIS 和 USED_IN_IMPLEMENTATION 属性指定约束文件是在综合或实现过程中使用。

注意:特别是IP、DCP这类使用OOC模式的模块,因为这些模块在综合过程中是一个黑盒,当顶层约束指定的约束路径为黑盒中的内容时,可能在综合过程中会报找不到目标的错误。因此,最好的方法是将约束会为两个文件,一个综合用,一个实现时用。

在工程模式中可以使用如下代码指定约束文件使用时机。

set_property USED_IN_SYNTHESIS false [get_files wave_gen_pins.xdc]
set_property USED_IN_IMPLEMENTATION true [get_files wave_gen_pins.xdc]

非工程模式中,不需要如此设置。因为什么时候使用约束文件,只和读取约束文件的时机相关。如下:其中 wave_gen_timing.xdc 会在综合和实现过程中使用,而 wave_gen_pins.xdc 只会在实现过程中使用。

read_verilog [glob src/*.v]
read_xdc wave_gen_timing.xdc
synth_design -top wave_gen -part xc7k325tffg900-2
read_xdc wave_gen_pins.xdc
opt_design
place_design
route_design

1.2 约束的顺序

推荐约束顺序如下:

## Timing Assertions Section
# Primary clocks
# Virtual clocks
# Generated clocks
# Clock Groups
# Bus Skew constraints
# Input and output delay constraints ## Timing Exceptions Section
# False Paths
# Max Delay / Min Delay
# Multicycle Paths
# Case Analysis
# Disable Timing ## Physical Constraints Section
# located anywhere in the file, preferably before or after the timing constraints
# or stored in a separate constraint file

1.3 创建综合约束

Vivado 综合将设计中的 RTL 描述转换为工艺映射网表。此过程分为多个步骤进行,包括一些时序导向的优化。FPGA 包含许多逻辑特性,可以有许多不同的应用方式。需要通过约束来引导综合引擎工作,以满足实现时所需的要求。

综合约束可以分为4类:

  • RTL Attributes
  • Timing Constraints
  • Physical and Configuration Constraints
  • Elaborated Design Constraints

1.3.1 RTL Attributes

RTL Attributes 必须写入 RTL 文件中。他们通常用来选择逻辑的某些部分的映射样式,以及保留某些寄存器和网线,或控制最终网表中的设计层次结构。

IMPORTANT: The DONT_TOUCH attribute does not obey the properties of USED_IN_SYNTHESIS and USED_IN_IMPLEMENTATION . If you use DONT_TOUCH properties in the synthesis XDC, it is propagated to implementation regardless of the value of USED_IN_IMPLEMENTATION .

注意:DONT_TOUCH 属性不受 USED_IN_SYNTHESIS 和 USED_IN_IMPLEMENTATION 的控制,当在综合约束中使用 DONT_TOUCH 时,他会传递到实现过程中,无论 USED_IN_IMPLEMENTATION 的属性值是什么。

set_property DONT_TOUCH true [get_cells fsm_reg]

1.3.2 Timing Constraints

Timing Constraints 必须通过一个或多个 XDC 文件传递给综合引擎。只有以下与建立时间分析相关的约束对综合结果有实际影响:

  • create_clock
  • create_generated_clock
  • set_input_delay
  • set_output_delay
  • set_clock_groups
  • set_false_path
  • set_max_delay
  • set_multicycle_path

1.3.3 Physical and Configuration Constraints

Physical and Configuration Constraints 会被综合算法忽略。(既然会被忽略为什么又提到?)

1.3.4 Elaborated Design Constraints

创建综合 XDC 的第一个版本时,只需要使用简单的时序约束来描述高级设计要求即可。因为此阶段的路径延迟并不准确,目的只是为了在实现开始前,尽量让综合的结果满足时序。并且在此阶段可能需要反复迭代 RTL 代码和 XDC 文件,以便查找各种网名和排除各种语法错误。

在 Elaborated Design 的创建过程中,某些 RTL 名称被修改或丢失。需要注意如下几点:

  • 网表中寄存器的名称会比在 RTL 代码中的名称多一个 _reg 的后缀。
  • 有些寄存器或网线会被吸收掉,例如二维寄存器会被综合成 Memory Block,乘除法会综合成 DSP。
  • 在使用 get_* 查询路径时,最好不要使用 -hierarchical 参数,路径中使用/显示描述路径的层级。
  • 不要对组合逻辑的网线附加约束。它们很可能会被合并到一个 LUT 中并从网表中消失。

1.4 创建实现约束

在某些情况下,综合网表中的对象名称与 Elaborated Design 中的名称不同。如果是这种情况,就必须使用正确的名称重新创建一些约束,并将它们保存在仅用于实现的 XDC 文件中。当工具可以正确加载所有 XDC 文件后,就可以运行时序分析以便:

  • 添加缺少的约束,例如输入和输出延迟。
  • 添加时序例外,例如伪路径、多周期路径和最小/最大延迟约束。
  • 识别由于设计中的长路径而导致的严重违规,修改 RTL 代码。

在综合期间,为了提高设计性能,有些寄存器可能被复制。但综合器不会把复制的单元添加到用户 XDC 约束中。如要将时序约束附加到 Vivado Synthesis 复制的对象上,根据约束的写入方式不同,复制的单元有可能不会被 XDC 约束覆盖到,这可能会影响结果的实现质量。可以使用 -include_replicated_objects 参数来避免此问题。

例如 set_false_path –from [get_cells –hierarchical *rx_reg] 可以改为 set_false_path -from [get_cells -hierarchical *rx_reg -include_replicated_objects]

下面几个例子都可以获取到被复制的单元。ORIG_CELL_NAME 表示原单元名称。另外注意 -filter -include_replicated_objects 不能一起使用,因为被复制的名称为 *reg_replica* ,会被 -filter 过滤掉。

get_cells -include_replicated_objects *rx_reg
get_cells -include_replicated_objects [get_cells -hier -filter {NAME =~ *rx_reg}]
get_cells -hierarchical -filter {NAME =~ *rx_reg || ORIG_CELL_NAME =~ *rx_reg}

1.4.1 对黑盒的约束

对于使用OOC模式的黑盒模块,顶层约束只能够访问到黑盒的输入输出脚。

  • 在 OOC 模块中自动推衍出的时钟,不能对其进行重命名。
  • 不能引用 OOC 模块内部定义的时钟名称。传播到 OOC 模块输出的时钟是根据连接到模块端口的网线命名的,而不是根据它在模块内部的名称,即使时钟在模块 XDC 内部被重命名。
  • 如果顶级约束需要引用来自 OOC 模块的时钟,则应使用诸如 get_clocks -of_objects [get_pins <MODULE_OOC_OUTPUT_CLOCK_PORT>] 之类的查询语句。

1.5 约束范围

如果有需要,可以选择将来自某个 XDC 文件的约束范围限定到特定的模块或单元。这对于在没有任何顶层信息的情况下创建和应用约束到子级模块很方便。模块级约束必须独立于顶级约束开发,并且必须尽可能通用,以便它们可以在各种环境中使用。它们也不得影响超出块范围的任何逻辑。默认情况下,Vivado 中生成的所有 IP 核都使用此机制将其约束加载到工程中。

1.5.1 XDC 范围属性

  • SCOPED_TO_REF:此属性采用模块名称。约束仅应用于指定模块的所有实例。

  • SCOPED_TO_CELLS:此属性采用分层单元名称列表。约束范围被单独应用于每个分层单元。

  • SCOPED_TO_REF + SCOPED_TO_CELLS:如果指定了这两个属性,则约束将应用于 SCOPED_TO_CELLS 列表的每个单元格,位于 SCOPED_TO_REF 指定的模块内。

# SCOPED_TO_REF 指定模块名:
set_property SCOPED_TO_REF uart_tx_ctl [get_files uart_tx_ctl.xdc] # SCOPED_TO_CELLS 指定实例名:
set_property SCOPED_TO_CELLS uart_tx_i0/uart_tx_ctl_i0 [get_files uart_tx_ctl.xdc] # SCOPED_TO_CELLS 指定实例名,SCOPED_TO_REF 指定上层模块名:
set_property SCOPED_TO_REF uart_tx [get_files uart_tx_ctl.xdc]
set_property SCOPED_TO_CELLS uart_tx_ctl_i0 [get_files uart_tx_ctl.xdc]

当一个模块被例化多次时,可使用如下约束。ORIG_REF_NAME 指定模块名。

set_property SCOPED_TO_REF [get_cells -hierarchical -filter {ORIG_REF_NAME == uart_tx_ctl}] [get_files uart_tx_ctl.xdc]

1.5.2 XDC 范围机制

除了端口,约束范围依赖于 current_instance 机制,它是 (SDC) 标准的一部分。当使用 current_instance 命令将范围设置为某个设计层次结构时,对象查询命令只能返回包含在该级别或以下级别的对象。

唯一的例外是时序时钟对象和网表端口:

  • 时序时钟对象由 create_clock 或 create_generated_clock 定义。无论当前的实例设置如何,它们在整个设计中都是可见的。 get_clocks 命令可以查询当前实例中不存在或传播到当前实例之外的时钟。 Xilinx 不建议在构建范围约束时在时钟上定义时序例外,除非时钟完全包含在当前实例中。要在 XDC 中引用时钟时,必须已经先定义了该时钟。当引用在定义之前时,可能需要更改项目中 XDC 文件的顺序。
  • 即使使用 current_instance 命令将范围设置为较低级别的实例时,get_ports 命令依然会返回顶级端口。但是,当使用 read_xdc -ref/-cells 命令读取范围为较低级别实例的 XDC 文件时,或者在设置 SCOPED_TO_REF/SCOPED_TO_CELLS 文件属性后加载设计时,get_ports 命令的行为是不同的:
    • 与 get_ports 一起使用的端口名称是作用域实例接口的端口名称,而不是顶级端口名称。
    • 如果作用域实例端口直接连接到顶级端口,则 get_ports 命令返回顶级端口,并将约束应用于顶级端口。
    • 如果在作用域实例端口和顶级端口之间存在任何单元,包括 IO 和时钟缓冲器,则 get_ports 命令变为 get_pins 命令并返回作用域实例引脚。

1.5.3 范围查询指南

  • get_cells/get_nets/get_pins 对象查询仅限于作用域实例及其子级别。其中对象的 NAME 属性显示了对象相对于顶层的完整层次结构路径,而不仅仅是范围实例。

    如果在 NAME 属性上使用 get_* 命令的 -filter 选项,则必须使用 glob 字符串匹配运算符,并提供以 * 开头的模板。例如 get_nets -hierarchical -filter {NAME =~ *clk}
  • 如果 Block/IP 的端口直接连接到顶级端口,则 get_ports 返回顶级端口。否则,get_ports 返回一个分层引脚。
  • 网表辅助命令也有范围: all_ffs 、all_latches 、all_rams 、all_registers 、all_dsps 、all_hsios 仅返回当前实例中包含的实例。
  • IO 辅助命令不能在范围约束 XDC 中使用: all_inputs 、all_outputs
  • 时钟命令没有作用域,将返回您设计的所有时序时钟。get_clocks、all_clocks
  • 可以通过使用 get_clocks -of_objects 探测网表,查询顶级和本地时钟对象。
    • 使用 get_clocks -of_objects [get_ports <interfacePinName>] 检索进入当前实例的时钟
    • 使用 get_clocks -of_objects [get_pins <instName/outPin>] 检索当前实例内部自动生成的时钟,其中 instName 是时钟生成器实例。
  • 使用 -of_objects 选项可以查询设计中的任何对象:例如:get_pins -leaf -of_objects [get_nets local_net]
  • 支持查询连接到当前实例接口网络的顶级端口:get_ports -of_objects [get_nets <scoped_instance_net>]
  • 不允许查询IP/子模块接口引脚。例如 get_pins clk 返回错误。
  • 路径跟踪命令也有作用域:all_fanin/all_fanout 遍历作用域设计并在其边界处停止。
  • 使用 get_cells/get_pins/get_nets 命令并指定详细的路径,而不是使用带有 -clock 选项的 all_registers 命令来查询连接到特定时钟的所有单元。因为 all_registers 返回的列表可能非常大,而只有少数对象需要约束。这会对运行时产生负面影响。

1.5.4 范围时序约束指南

为避免对顶层设计产生负面影响,重要的是确保给 IP 或模块编写的时序约束不会传播到其范围之外。例如,进入到 IP 或模块的两个时钟,在其范围约束 XDC 中定义不相关路径,但这种不相关性可能不适用于整个设计的其余部分。如果这两个时钟在设计的其余部分相关时,这个约束则会引起问题。再如,范围约束 XDC 文件中定义的时序例外可能比顶级约束具有更高的优先级,并且可以覆盖它们,这同样是不希望的。为避免这种情况,建议将约束应用于 IP 本地的网表对象。在两个全局时钟之间存在不相关路径的情况下,时序例外路径也必须从 IP 内的一组起点单元应用到 IP 内的另一组终点单元。这种技术被称为点对点时序例外而不是全局时序例外。

1.5.5 IP/子模块XDC的推荐约束规则

块级约束必须符合以下规则:

  1. 如果期望顶层设计中定义时钟,则不要在块级约束中创建时钟。可以使用 get_clocks -of_objects 的方式在块内查询时钟。示例:

    set blockClock [get_clocks -of_objects [get_ports clkIn]]

    如果确实需要在模块内部定义时钟,则它必须位于输入或双向端口上,并且此端口必须直接驱动输入/双向缓冲器的。再或者位于创建/转换时钟的单元的输出上。例如:带有输入缓冲器的输入时钟、时钟分频器和 GT 恢复时钟。

  2. 仅当端口直接连接到顶级端口,并且 I/O 缓冲区在 IP 内例化时,才指定输入和输出延迟。

  3. 不要定义两个未绑定到 IP 的时钟之间的时序例外。

  4. 不要按名称引用时钟,因为名称可能会因顶级时钟名称或模块被多次例化而有所不同。

  5. 如果模块可以在同一个顶层设计中多次实例化,则不要添加布局约束。

1.6 约束效率

1.6.1 检阅约束覆盖率

在编写时序约束时,应当保持约束简单,并仅在相关网表对象上指定约束。低效约束会导致更长的运行时间和更大的内存消耗。低效约束还可能产生不当约束,因为时序例外覆盖的路径可能会比预期更多,并与其他约束发生冲突。

Vivado 提供了多种获取时序例外反馈的方法:

  • 方法学检查 XDCB-1 ( report_methodology ) 报告引用大型对象集合(超过 1000)的时间约束。
  • 报告例外命令 (report_exceptions) 提供有关已定义的时序例外的覆盖和冲突信息。

Xilinx 建议仔细分析以下报告:

  • report_exceptions -scope_override

    该报告会列出顶层时序约束范围时序约束部分或全部重叠的部分。但是,它不会报告一个范围时序约束和另一个范围时序约束间的重叠部分。此选项可用于验证IP 约束没有被用户的顶级约束未覆盖 。

  • report_exceptions –coverage

    该报告为每个时序例外提供了一个逻辑路径的覆盖范围。将传递给时序例外的对象数量与有效覆盖的起点和终点数量进行比较。我们应该注意查看在对象数量和起点/终点数量之间具有显着差异的约束。

  • report_exceptions –ignored

    此报告提供了被其他时序约束覆盖的时序约束列表(例如,被 set_clock_group 覆盖的 set_false_path)。我们应该检查有覆盖的约束的正确性或删除无用的约束。

  • report_exceptions –ignored_objects

    此报告提供了被忽略的起点和终点的列表。例如,不存在从这些起点出发的路径或到不存在到达这些终点的路径。

1.6.2 提升约束运行效率

由于设计中的管脚数是单元数的数倍,因此使用 get_pins 比 get_cells 会对运行时间产生重大影响。在处理 XDC 约束(例如 open_checkpoint 运行时)或执行 Tcl 脚本时,可能会遇到运行效率下降。 Xilinx 建议利用引脚和单元对象之间的关系来加快大量引脚查询的运行时间。与其在设计中的所有引脚中直接根据引脚名称查找特定的引脚列表,不如先找到所需引脚的单元,然后再对这一次查询结果进行过滤,以此对所需引脚进行查询。

# 直接对整个设计中的所有PIN进行查询,效率低
get_pins –hier * -filter {NAME=~xx*/yy*}
# 可以替换成如下两种方法,以提升运行效率
get_pins –filter {REF_PIN_NAME=~yy*} –of [get_cells –hier xx*]
get_pins –filter {REF_PIN_NAME=~yy*} –of [get_cells –hier * -filter {NAME=~xx*}] # 如下示例,直接查询PIN
set_max_delay 15 -from [get_pins -hier -filter {NAME=~*/aclk_dpram_reg*/*/CLK}] \
-to [get_cells -hier -filter {NAME=~*/bclk_dout_reg*}] -datapath_only
# 可替换如下写法
set_max_delay 15 -from [get_pins -of [get_cells -hier –filter
{NAME =~ *aclk_dpram_reg*/*}] -filter {REF_PIN_NAME == CLK}] \
-to [get_cells -hier bclk_dout_reg*] -datapath_only

Xilinx约束学习笔记(一)—— 约束方法学的更多相关文章

  1. 【转载】【时序约束学习笔记1】Vivado入门与提高--第12讲 时序分析中的基本概念和术语

    时序分析中的基本概念和术语 Basic concept and Terminology of Timing Analysis 原文标题及网址: [时序约束学习笔记1]Vivado入门与提高--第12讲 ...

  2. Xilinx约束学习笔记(二)—— 定义时钟

    2. 定义时钟 2.1 关于时钟 为了获得最佳精度路径覆盖信息,必须正确定义时钟. 时钟要定义在时钟树的根 pin 或 port 上,称为 source point. 时钟的边缘应该由周期和波形进行组 ...

  3. Oracle 学习笔记 10 -- 约束

    本次笔记来学习约束,约束在表中无处不在. 比如,表中的数据不同意为空或者是表中id为设为主键,都是约束. 约束分类:         主键约束(PRIMARY KEY):主键表示表中一个唯一的标识,本 ...

  4. Xilinx约束学习笔记(三)—— 时序概念

    3. 时序概念 发现对于时序基础的介绍这一块,Intel 的文档竟然要比 Xilinx 的详细,因此引用了很多 Intel 的文档内容. 3.1 术语 发送沿(launch edge),指用来发送数据 ...

  5. MySQL学习笔记7——约束

    约束 约束 *约束是添加在列上的,用来约束列的! 1.主键约束(唯一标识) ***非空*** ***唯一*** ***被引用*** *当表的某一列被指定为主键后,该列就不能为空,不能有重复值出现. * ...

  6. 【学习笔记】圆方树(CF487E Tourists)

    终于学了圆方树啦~\(≧▽≦)/~ 感谢y_immortal学长的博客和帮助 把他的博客挂在这里~ 点我传送到巨佬的博客QwQ! 首先我们来介绍一下圆方树能干什么呢qwq 1.将图上问题简化到树上问题 ...

  7. Xilinx FPGA 学习笔记

    一.时序设计 方法1.通过状态机来实现,通过verilog控制FPGA,让它该快的时候快,该慢的时候慢. 方法2.FPGA中运行CPU 把逻辑控制顺序复杂的事情用C代码来实现,而实时处理部分用veri ...

  8. CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)

    QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...

  9. MongoDB学习笔记~批量插入方法的实现

    回到目录 批量插入在EF时代大叔就自己封装过,原理是将多次SQL连接和多次向SQL发送的指令减少到1次,或者1000条数据1次,而对于EF产生的语句来说,这无疑是性能高效的,因为EF这边在处理时,每个 ...

随机推荐

  1. Min25 筛学习笔记

    仅仅是 \(min25\) 筛最基本的方法,没有任何推式子的例题.(想了想还是加两道吧qwq) 这里解决的是 \(Luogu\) 那道模板题. min25 基本方法: 最基础的是两个式子: \[G(n ...

  2. 小白都能理解的TCP三次握手四次挥手

    前言 TCP在学习网络知识的时候是经常的被问到知识点,也是程序员必学的知识点,今天小杨用最直白的表述带大家来认识认识,喜欢的朋友记得点点关注哈. 何为TCP 上点官方的话:是一种面向连接(连接导向)的 ...

  3. c语言:逗号运算符

    #include <stdio.h> main() { int a,s,d; s=2,d=3; a=12+(s+2,d+4); printf("%d\n",a); in ...

  4. C语言:体现\r的结果

    #include <stdio.h> #include <windows.h> //体现\r的结果 //转义字符\r,回车,将光标移动到当前行最开始 main() { char ...

  5. AcWing 1086. 恨7不成妻(【代码简洁】标准记忆化搜索+超详解!!)

    看到这题用循环写的dp代码瑟瑟发抖~ 数位dp一般记忆化搜索的写法思维难度较低,也比较常用,这题的简洁代码应该就可以显现出其优越性 (用时4ms,可能比用循环写的dp还要快) 那这里补充一下记忆化搜索 ...

  6. Docker搭建Redis5.0并挂载数据

    记录 Docker 搭建 Redis5.0 并挂载数据过程,搭建参考自 Docker Hub 系列文章欢迎访问:https://www.itwxe.com/posts/9e76db89/ 一.简单挂载 ...

  7. Hive——基本DML语句

    Hive--基本DML语句 DML:Data Manipulation Language(数据操作语言,与关系型数据库相似) 官方手册:https://cwiki.apache.org/conflue ...

  8. MySQL中的redo log和undo log

    MySQL中的redo log和undo log MySQL日志系统中最重要的日志为重做日志redo log和归档日志bin log,后者为MySQL Server层的日志,前者为InnoDB存储引擎 ...

  9. endnote x9.3.3 for windows安装教程

    EndNote X9.3.3 是一款非常nice的实用型文献管理软件,EndNote X9功能极其强劲,便捷好用.本文提供EndNote X9.3.3安装破解激活教程.方法,内附EndNote x9. ...

  10. Android从一个Fragment跳转到另一个Fragment后原来的组件不消失

    问题描述 Activity上放置了一个Fragment,Fragment上有按钮,点了按钮后,应该跳转到另一个Fragment, but 原来的Fragment的按钮不会消失,新的Fragment不是 ...