VERDVANA'S BLOG Verdvana

DC综合之时序约束


1 前言

        需要综合的design如下图所示:

img1

        其中整个设计为同步时序,而且是单边沿触发。

        需要约束的分为以下三个部分:

  • FF2输入端到FF3输入端(包含X组合电路)的路径;
  • My_Design的数据输入端到FF2的数据输入端(包含N组合电路)的路径;
  • FF3的数据输出端到My_Design的数据输出端(包含S组合电路)的路径。

2 创建时钟

2.1 新建时钟

        新建时钟信号。默认情况(没加别的属性)下新建的时钟信号占空比是50%,且是单边沿触发,而且为理想时钟,既上升下降转换时间为零、skew为0、没有时钟延迟。

        新建一个2ns周期的时钟,加在“clk”这个port上:

create_clock -period 2 [get_ports clk]

2.2 创建延迟模型

        为理想时钟建立模型,来模拟时钟的延迟。

        首先设置时钟不确定性时间,包含skew、jitter、margin。为clk建立模型,假设uncertainty为0.14:

set_clock_uncertainty -setup 0.14 [get_clocks clk]

        模拟板外延迟,如下图的延迟A,时钟源到芯片时钟端口的路径延迟为3ns:

set_clock_latency -source -max 3 [get_clocks clk]

        模拟板内延迟,如下图的延迟B,芯片时钟端口到寄存器时钟引脚的路径延迟为1ns:

set_clock_latency -max 1 [get_clocks clk]

img2

        模拟转换时间(时钟爬坡时间):

set_clock_transition 0.08 [get_clocks clk]

3 输入延迟设置

        输入延迟需要知道下图中橘黄色部分路径的延迟(外部延迟)信息,包括FF1的Tco和M组合逻辑的延迟。假设和为0.6ns:

img3

set_input_delay -max 0.6 -clock clk [get_ports A]

        DC会自动算出内部延迟和外部延迟之和,来约束使得FF1和FF2之间的时序符合要求。


4 输出延迟设置

        和输入延迟类似,需要设置外部延迟时间,包括上图的T组合逻辑延迟和FF4的建立时间:

set_output_delay -max 0.8 -clock clk [get_ports B]

5 多输入输出引脚设置

        如果给全部输入引脚都设置延迟,需要先将时钟引脚从全部输入引脚中去掉:

set_input_delay -max 0.5 -clock clk \
    [remove_from_collection[all_inputs] [get_ports clk]]

        或者:

set_input_delay -max 0.5 -clock clk [all_inputs]
remove_input_delay [get_port clk]

        如果给全部输出引脚都设置延迟,直接设:

set_output_delay -max 1.1 -clock clk [all_outputs]

6 组合路径

6.1 时序和组合电路

        如果在设计中存在下图中的F组合电路,这段路径分为了橘黄色的三部分,既FF1至FF4之间的路径。

img4

        此时就需要设置外部的输入和输出两部分延迟时间,剩下即为留给F电路的延时。

# 创建和设置时钟
···

# 设置输入输出
set_input_delay -max 0.6 -clock clk [get_ports A]
set_output_delay -max 0.8 -clock clk [get_ports B]

6.2 纯组合电路

        如果design为纯组合逻辑,如下图,则需要创建虚拟时钟:

img5         虚拟时钟必须创建名称,但不用指定port或pin:

creat_clock -name vclk -period 2

        剩下部分与上一小节相同。


7 输入输出延迟未知

        如果输入延迟与输入延迟位置,则内部延迟与外部延迟按照4:6分配。输入部分内部延迟设置为时钟周期的40%,外部延迟为60%,输出部分内部延迟也设置为40%,外部延迟设置为60%。这样设计出来的模块串接起来中间会有20%的余量。


8 其他情況

8.1 下降沿觸發

        如果第一幅圖中的FF1 是下降沿觸發的,需要對輸入延遲做修改:

create_clock    -period 2   [get_ports clk]
set_input_delay -max    0.3 -clock clk  -clock_fall [get_ports A]

        這樣算時序的時候也只剩半個週期可以折騰。

8.2 上升沿沿、下降沿觸發

        如果第一幅圖中的前一個設計是一個下降沿觸發的寄存器和一個上升沿觸發的寄存器通過一個MUX聯合觸發本設計,需要對輸入延遲做修改:

create_clock    -period 2   [get_ports clk]
set_input_delay -max    0.3 -clock clk  -clock_fall [get_ports A]
set_input_delay -max    1.2 -clock clk  -add_delay  [get_ports A]

        相當於為輸入延遲添加了兩條約束,DC會根據最差的一條進行約束。

8.3 驅動多個寄存器且觸發沿不唯一

        如果第一幅圖中的FF3要驅動的後一個設計中的多個寄存器,切其中還有下降沿觸發的,需要對輸出延遲做修改:

create_clock -period 4 p[get_ports clk]
set_output_delay -max 2.5 -clock clk [get_ports b]
set_output_delay -max 2.5 -clock clk -clock_fall -add_delay [get_ports b]

8.4 同步多時鐘

        同步多时钟是指多个时钟是由PLL等根据一个时钟生成的多个时钟,它们之间的相位是已知、可控的。

        DC會找出兩個不同時鐘的上升沿最接近的時差來分析時序。

create_clock -period 3 [get_ports clk1]
create_clock -period 2 [get_ports clk2]
set_clock_uncertainty -setup 0.10 [get_ports clk1]
set_clock_uncertainty -setup 0.12 [get_ports clk2]
set_clock_uncertainty -setup 0.15 -from [get_clocks clk1] -to [get_clocks clk2]

        从源时钟生成分频时钟:

create_generated_clock -divide_by 2 -name clk_1     \
                -source [get_ports clk] [get_pins FF1/Q]
set_clock_latency       ……   [get_clocks clk_1]
set_clock_uncertainty   ……   [get_clocks clk_1]
set_clock_transition    ……   [get_clocks clk_1]

        如果是如下电路:

img6

        从物理连接上讲,除了红色和黄色两条路径,还有从FF3到FF8和从FF7到FF4一共四条路经,但是实际上由于FF3和FF4的时钟与FF7和FF8的时钟不同,只有红色和黄色两条路径,然而DC并不能自动判断,所以需要加约束:

create_clock -period 3 [get_ports clk1]
create_clock -period 3 [get_ports clk2]
set_output_delay -max 0.15 -clock clk_1             [get_ports out]
set_output_delay -max 0.52 -clock clk_2 -add_delay  [get_ports out]

# 设置不约束的路径

set_false_path -from [get_clocks clk_1] -to [get_clocks clk_2]
set_false_path -from [get_clocks clk_2] -to [get_clocks clk_1]
# 或者用“逻辑互斥设置”
set_clock_groups -logically_exclusive -group clk_1 -group clk_2

        如果X和Y組合電路之间有物理连接,如下图:

img7

        再使用以上两条约束就不会对这一部分进行分析优化,所以需要修改:

create_clock -period 3 [get_ports clk_1]
create_clock -period 3 [get_ports clk_2]
set_output_delay -max 0.15 -clock clk_1             [get_ports out]
set_output_delay -max 0.52 -clock clk_2 -add_delay  [get_ports out]

# 设置不约束的路径

set_false_path -from [get_clocks clk_1] \
                -through [get_ports out] -to [get_clocks clk_2]
set_false_path -from [get_clocks clk_2] \
                -through [get_ports out] -to [get_clocks clk_1]

        这样只屏蔽了输出端口的两条路径,而设计内部的路径还是会分析优化的。

        如果是下图这样:

img8

        从物理连接上看,有以下四个时钟路径:

  • clk_1 -> clk_1;
  • clk_1 -> clk_2;
  • clk_2 -> clk_1;
  • clk_2 -> clk_2;

        但实际上只有两个路径:

  • clk_1 -> clk_1;
  • clk_2 -> clk_2;

        所以需要告诉DC:

create_clock -period 2 [get_ports clk_1]
create_clock -period 5 [get_ports clk_2]
set_clock_groups -logically_exclusive -group clk_1 -group clk_2

        如果不同时钟路径之间有交叉:

img9

        FF4和FF8对多个时钟敏感,所以需要约束:

create_clock -period 2 [get_ports clk_1]
create_clock -period 3 [get_ports clk_2]
create_clock -period 4 [get_ports clk_3]
create_clock -period 5 [get_ports clk_4]

set_app_var timing_enable_multiple_clocks_per_reg ture

set_clock_groups -logically_exclusive -group clk_1 -group clk_2
set_clock_groups -logically_exclusive -group clk_3 -group clk_4

8.5 异步时钟

        异步时钟之间的相位未知且不可控。异步时钟的上升沿之间的延迟不确定,所以DC对其优化没有意义,需要加命令告诉DC不要做优化:

create_clock -period 2 [get_ports clk_1]
create_clock -period 3 [get_ports clk_2]

set_clock_groups    -asynchronous -group clk_1  -group clk_2

# 或者

set_false_path -from [get_clocks clk_1] \
                -through [get_ports out] -to [get_clocks clk_2]
set_false_path -from [get_clocks clk_2] \
                -through [get_ports out] -to [get_clocks clk_1]

8.6 多周期路径

        如下图电路:

img10

        如果加法器的延迟很长,大于一个时钟周期,则为多周期路径。假设时钟周期为10ns,加法器这条路径上的延迟为50-60ns之间,则需要让FF5等待5个时钟周期再读数据(1-5个时钟周期等待,第六个时钟周期获取数据,如此循环):

create_clock -period 10 [get_ports clk]
set_multicycle_path  -setup 6   -from {FF2_reg[*]  FF3_reg[*]}  -to FF5_reg[*]
set_multicycle_path  -hold 6    -from {FF2_reg[*]  FF3_reg[*]}  -to FF5_reg[*]

        而这些只是告诉DC改在什么地方采样,实际电路钟还需要加上FF4对FF5进行控制,让FF5在该采样的时间上使能而其他时间失能。

        使用如下命令检查以上内容的异常时序约束:

report_timing_requirements  -ignored

        告辞