目录
一、前言
前面已经针对Vivado时序Timing报告相关的如Minimum pulse width,datasheet等进行了详解,本文再对其中的Report CDC使用进行解说。
二、Report CDC
2.1 Report CDC
CDC(Clock Domain Crossings)中文含义为跨时钟域,也即时序路径的launch clock和capture clock为不同的时钟,可以报告潜在的不安全的跨时钟域路径(如可能导致亚稳态或数据一致性问题)。在生成CDC报告前,必须确保设计约束合理,无缺失的时钟约束,Report CDC只会分析和报告源时钟和目的时钟被约束了的路径。
2.2 配置界面
通过菜单栏“Reports->Timing->Report CDC”进入到Report CDC界面
配置界面如下图
相关配置项的含义如下
Results name(报告名称):为CDC报告设置一个名称,将在Vivado的结果窗口显示
Clocks(时钟):设置要进行跨时钟分析的时钟
a)From(起点): 指定分析的发起时钟,双击后面的选择图标(三个点)可以进入到发起时钟的设置窗口
b)To:指定分析的捕获时钟,双击后面的选择图标(三个点)可以进入到捕获时钟的设置窗口,同发起时钟类似
Report from Cells(报告单元): 限制CDC报告中分析包含指定单元cells的时序路径。
File Output(文件输出):将CDC报告结果以txt文件导出到指定路径下,默认是Overwrite,即覆盖已存在的报告文件,如果选择Append则是将新的报告结果追加到已有内容的后面
Options(选项):
a)Suspend message limits during command:勾选则表示忽略Messages数量限制。
b)Ignore command errors (quiet mode): 勾选表示当执行Report CDC命令时忽略错误。
Apply Waivers(使用Waivers): 该设置为默认配置,当生成CDC报告时,会将所有Waivers用于设计中,也可以使用Create Waiver命令将Waivers添加到设计中。
Report only waived paths: 执行CDC报告时仅有CDC路径中创建了Waiver的路径
Ignore waivers(忽略Waivers): 分析所有的CDC路径时忽略设计中所有定义的Waivers。
Open in a new tab: 执行时序报告后是否在一个新的标签中打开,如果没有勾选,新的报告结果将会覆盖旧的结果
Open in Timing Analysis layout: 执行完CDC分析后是否打开布局窗口(Device窗口)
2.3 CDC报告
CDC报告内容由General Information,Summary,CDC Detail三个部分组成
2.3.1 General Information
General Information中包含了报告类型,设计名称,器件,Vivado版本,报告运行时间,以及生成CDC报告的命令。
2.3.2 Summary
Summary分Clock pair,Type,waived三个方向来展示CDC报告
1) clock pair
Clock pair是根据时序对来分析跨时钟域路径。详细内容表格如下图
Severity:对CDC路径的风险等级分类,有Critical和Warning和Info三个级别
Source Clock:源时钟
Destination Clock:目的时钟
CDC Type:CDC类型,No common primary clock表示无共同的主时钟,Safely Timed表示有共同的主时钟,如生成时钟与主时钟的关系
Exceptions:显示源时钟与目的时钟间是否存在时序例外约束,Exceptions对应的值含义如下图
Endpoints:源时钟与目的时钟的路径上终点的数目
2) By type
Summary(by type)展示的报告如下图
Severity:跨时钟域影响大小,分为Info(信息级), Warning(告警级), Critical(严重级)
ID:不同的ID代表不同的类型,如CDC-1表示1比特跨时钟域,CDC-4表示多比特跨时钟域,CDC-10表示在同步器前检测到组合逻辑。
Count:对应CDC ID的跨时钟域数量
Description:对CDC类型含义进行说明
常见的CDC类型见下图,CDC1-3为单比特场景,CDC4-6为多比特场景,CDC7-9为异步复位,CDC10为组合逻辑等
默认情况下,Report CDC仅报告每个终点和时钟对的单个违例,当一个终点存在多个违例时,优先报告优先级更高的CDC,不同CDC的优先级如下图,从上往下优先级依次降低。
2.3.3 CDC Details
CDC Details报告了设计中所有的跨时钟域路径,按照时钟对来展示
Severity/ID/Description:解释同上
Depth:同步器的数量
Exception: CDC路径上的时序例外约束,如下图设置了false path
Source/Destination:源时钟和目标单元
Category:CDC路径的安全性分类,分为安全safe,不安全unsafe,未知Unknown,No Async_Reg等
2.4 Waiver
在前面的小节中提到了Waiver相关的设置项,Waiver不仅针对CDC路径有效,对设计规则检查DRC,检查违例的方法也有效。如果路径被设置了Waiver,在report_cdc,report_drc, or report_methodology结果中不会被分析
在未对路径设置Waiver时,CDC报告中Summary(by waived endpoints) 中内容为空
2.4.1 设置Waiver
在设置Waiver前可以先查看CDC路径的方案图Schematic,进入CDC Details中
选中路径后可以通过Schemaic或快捷键F4进入方案图中,看出clk_group2和clk_group1的关系
设置Waiver同样在选中路径后的右键菜单中进行
进入Create Waiver,user为用户名,Description为创建的waiver设置说明
设置完后该路径自动置灰
点击rerun后,该路径将不会存在CDC Details中,将出现在Summary(by waiver)中
Create Waiver也支持同时对多条CDC设置,只要在CDC Details中同时选中多条路径即可
tcl command preview中同时显示了两条create_waiver命令
Summary(by waived endpoints)中Waived endpoints为2。
2.4.2 报告查看
方法1:在tcl console中执行report_cdc -waiver可以查看设置的waiver详情
也可使用report_waiver命令
方法2:执行Report CDC时Waivers中勾选Report only waived paths
此时Summary或CDC Details中都只会报告设置了waivers的路径
方法3:tcl console中使用report_cdc -details -show_waiver,无论CDC是否设置Waiver都会被报告
2.4.3 去除Waiver设置
在设置了waiver后会发现菜单栏和工具栏都没有相关的取消Waiver的操作,此时须在tcl console使用命令delete_waivers [get_waivers -type cdc]可以移除所有设置的waiver
也可只移除指定CDC类型的Waiver,如移除类型为CDC-1中设置的Waiver
命令为:delete_waivers [get_waivers -filter {ID == CDC-1}]
三、工程设计
module all_timing(CLKIN1,CLKIN2,CLKINSEL,CLKFBIN,d1,rst,clk_group1,clk_group2,ff_group2_a,clk_false,clk_max,clk_multi,ff_false,ff_group,ff_group2,ff_pll,ff_max,ff_multi);
input CLKIN1,CLKIN2,CLKINSEL,CLKFBIN,d1,rst;
input clk_group1,clk_group2,clk_false,clk_max,clk_multi;
output reg ff_false,ff_group,ff_group2,ff_group2_a,ff_pll,ff_max,ff_multi;
reg ff1;
wire CLKOUT0;
PLLE2_ADV #(
.BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW
.CLKFBOUT_MULT(8), // Multiply value for all CLKOUT, (2-64)
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360.000-360.000).
// CLKIN_PERIOD: Input clock period in nS to ps resolution (i.e. 33.333 is 30 MHz).
.CLKIN1_PERIOD(0.0),
.CLKIN2_PERIOD(0.0),
// CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for CLKOUT (1-128)
.CLKOUT0_DIVIDE(1),
.CLKOUT1_DIVIDE(2),
.CLKOUT2_DIVIDE(4),
.CLKOUT3_DIVIDE(5),
.CLKOUT4_DIVIDE(1),
.CLKOUT5_DIVIDE(1),
// CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for CLKOUT outputs (0.001-0.999).
.CLKOUT0_DUTY_CYCLE(0.4),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT5_DUTY_CYCLE(0.5),
// CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for CLKOUT outputs (-360.000-360.000).
.CLKOUT0_PHASE(0.0),
.CLKOUT1_PHASE(0.0),
.CLKOUT2_PHASE(0.0),
.CLKOUT3_PHASE(0.0),
.CLKOUT4_PHASE(0.0),
.CLKOUT5_PHASE(0.0),
.COMPENSATION("EXTERNAL"), // ZHOLD, BUF_IN, EXTERNAL, INTERNAL
.DIVCLK_DIVIDE(1), // Master division value (1-56)
// REF_JITTER: Reference input jitter in UI (0.000-0.999).
.REF_JITTER1(0.0),
.REF_JITTER2(0.0),
.STARTUP_WAIT("FALSE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE")
)
PLLE2_ADV_inst (
// Clock Outputs: 1-bit (each) output: User configurable clock outputs
.CLKOUT0(CLKOUT0), // 1-bit output: CLKOUT0
.CLKOUT1(CLKOUT1), // 1-bit output: CLKOUT1
.CLKOUT2(CLKOUT2), // 1-bit output: CLKOUT2
// Feedback Clocks: 1-bit (each) output: Clock feedback ports
.CLKFBOUT(CLKFBOUT), // 1-bit output: Feedback clock
// Clock Inputs: 1-bit (each) input: Clock inputs
.CLKIN1(CLKIN1), // 1-bit input: Primary clock
.CLKIN2(CLKIN2), // 1-bit input: Secondary clock
// Control Ports: 1-bit (each) input: PLL control ports
.CLKINSEL(CLKINSEL), // 1-bit input: Clock select, High=CLKIN1 Low=CLKIN2
.RST(rst), // 1-bit input: Reset
// Feedback Clocks: 1-bit (each) input: Clock feedback ports
.CLKFBIN(CLKFBIN) // 1-bit input: Feedback clock
);
// End of PLLE2_ADV_inst instantiation
always@(posedge CLKOUT0,negedge rst)
if(!rst)
begin
ff1<=1'b0;
end
else begin
ff1<=d1;
end
always@(posedge CLKIN1,negedge rst)
if(!rst)
ff_pll<=1'b0;
else begin
ff_pll<=ff1;
end
always@(posedge clk_group1,negedge rst)
if(!rst)
ff_group<=1'b0;
else begin
ff_group<=d1;
end
always@(posedge clk_group2,negedge rst)
if(!rst)
ff_group2<=1'b0;
else begin
ff_group2<=ff_group;
end
always@(posedge clk_group2)
if(rst)
ff_group2_a<=1'b0;
else begin
ff_group2_a<=ff_group;
end
always@(posedge clk_false,negedge rst)
if(!rst)
ff_false<=1'b0;
else begin
ff_false<=ff_group2;
end
always@(posedge clk_max,negedge rst)
if(!rst)
ff_max<=1'b0;
else begin
ff_max<=ff_group2;
end
always@(posedge clk_multi,negedge rst)
if(!rst)
ff_multi<=1'b0;
else begin
ff_multi<=ff_group2;
end
endmodule
四、参考资料
《ug906-vivado-design-analysis-en-2023.2.pdf》