FPGA-一个大神的博客
FPGA-一个大神的博客
简介
FPGA 工具最大的挑战是满足时序约束的要求。希望这能奏效,但有时会失败。当它失败时,我们人类有责任找出失败的原因并加以修正。这个任务有个名字:我们称之为时序闭合 。这可不是一件容易的事。
为什么时序闭合难?问题是,这些工具有一个布局和路由算法,试图以最优的方式利用 FPGA 的资源。通常,这个算法从将逻辑元素放置在 FPGA 上开始,且不费吹灰之力。然后开始一个迭代过程:工具会遍历所有路径,找出那些无法满足时序约束的路径。为了纠正这些失误,会在这些路径上采取纠正措施。最显著的是,逻辑元件被移动到 FPGA 的不同位置,并调整了布线。至于更高级的纠正措施,每个 FPGA 工具都有自己的方法。
当所有路径都满足时序约束时,实现即告完成。但实施也可能因为工具未能达到这一目标而终止,从而放弃了尝试。在这种情况下,我们能理解工具在努力停止时所取得的成果。这种结果不一定是最优的:实现过程中可能存在可以改进的路径,但工具们忙于修复其他问题。当这些方法失败时,工具们放弃了,没有尝试修复其他问题。就像工具在说:“如果实现迟早会失败,修复它也没意义。”
作为 FPGA 设计师,我们的任务是审视这种次优结果,找出时序约束目标未能实现的原因。
算法会随着时间变得更好。当有共同原因导致无法满足时序约束时,下一版本的软件会针对该情况提供具体解决方案。所以当工具失效时,通常都有充分的原因。
所以我们会看看这些工具取得了什么成就,然后问自己:为什么这些工具会失败?我们是不是提出了不可能的要求?更重要的是,我们是不是提出了不必要的要求?也许导致工具失效的障碍其实是我们根本不需要的东西。或者,优化算法的效果不够好?有时这只是运气不好:逻辑元素的初始配置可能糟糕到以至于后续提升性能的尝试注定失败。
无论问题是什么,找到失败原因就像侦探调查犯罪现场一样:事实摆在眼前,但原因往往被隐藏。这些事实大多可以在时间报告中找到,但线索并不容易暴露。必须始终问的问题是,计时报告中出了什么问题、异常或异常。就像试图找到罪犯的侦探一样,目标是找到导致问题的细节。
但要找出异常,你必须知道什么是正常:例如,对于具有特定扇形展开的网来说,正常延迟是多少?实现某个逻辑函数时,正常的逻辑电平是多少?这类问题的答案因 FPGA 而异。因此,即使一切正常,也必须通过阅读和理解计时报告来积累经验。你必须能知道当一切正常时,计时报告是什么样子,才能找到时序报告中指出问题的地方。如果你想知道为什么我之前几页要讲细节,这也是原因之一。
关键路径
当工具未能满足时序约束时,意味着至少有一条路径存在负松弛。负松弛路径称为临界路径。这个名称反映了通常的时序闭合策略:专注于临界路径通常是解决时序问题的有效方法。但我将在下面说明,这种策略有时也可能浪费时间。
当时间约束满足时,临界路径即为松弛最小的路径。这条路径通常不有趣,因为工具不会尝试以积极的松弛来改善路径。所以如果最差的路径有正的松弛,这条路径可能是最差的巧合。
但如果松弛为正且接近零(比如小于 0.2 纳秒),这可能表明该路径难以达到时序约束。这类关键路径可以被视为警告,这些路径未来可能引发麻烦(尤其是当 FPGA 逻辑变得更多,工具的精力被转移到其他路径时)。
时序报告通常包含每个时钟有限数量的关键路径。大多数 FPGA 工具的默认做法是显示少数关键路径,即使其松弛为正(即时序约束达成的时间)。这是推荐的设置。
关键路径的示例
我将从一个关键路径分析的例子开始。在这个例子中,Verilog 代码如下:
reg [24:0] calc, result;
reg [11:0] x, y, z;
always @(posedge clk)
begin
calc <= x * y + z;
result <= calc;
end
在这个例子中,@clk 的频率是 250 MHz,并且没有使用 PLL 来生成这个时钟。还假设 @x、@y 和 @z 是与 @clk 同步的寄存器。Verilog 编码中未显示给这些寄存器值的代码,因为它无关紧要。
在尝试在 Vivado 上进行该代码时,时间限制未能实现。在时间报告中,这是关键路径:
Slack (VIOLATED) : -0.239ns (required time - arrival time)
Source: x_reg[1]__0_replica_2/C
(rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns})
Destination: calc_reg[23]/D
(rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns})
Path Group: clk
Path Type: Setup (Max at Slow Process Corner)
Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns)
Data Path Delay: 4.180ns (logic 1.642ns (39.282%) route 2.538ns (60.718%))
Logic Levels: 7 (CARRY8=4 LUT3=1 LUT4=1 LUT6=1)
Clock Path Skew: -0.087ns (DCD - SCD + CPR)
Destination Clock Delay (DCD): 3.176ns = ( 7.176 - 4.000 )
Source Clock Delay (SCD): 3.864ns
Clock Pessimism Removal (CPR): 0.601ns
Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE
Total System Jitter (TSJ): 0.071ns
Total Input Jitter (TIJ): 0.000ns
Discrete Jitter (DJ): 0.000ns
Phase Error (PE): 0.000ns
Clock Net Delay (Source): 2.032ns (routing 0.396ns, distribution 1.636ns)
Clock Net Delay (Destination): 1.748ns (routing 0.365ns, distribution 1.383ns)
Location Delay type Incr(ns) Path(ns) Netlist Resource(s)
(clock clk rise edge) 0.000 0.000 r
AG12 0.000 0.000 r clk (IN)
net (fo=0) 0.000 0.000 clk_IBUF_inst/I
AG12 INBUF (Prop_INBUF_HRIO_PAD_O)
0.738 0.738 r clk_IBUF_inst/INBUF_INST/O
net (fo=1, routed) 0.105 0.843 clk_IBUF_inst/OUT
AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
0.049 0.892 r clk_IBUF_inst/IBUFCTRL_INST/O
net (fo=1, routed) 0.839 1.731 clk_IBUF
BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O)
0.101 1.832 r clk_IBUF_BUFG_inst/O
X2Y0 (CLOCK_ROOT) net (fo=106, routed) 2.032 3.864 clk_IBUF_BUFG
SLICE_X54Y54 FDRE r x_reg[1]__0_replica_2/C
SLICE_X54Y54 FDRE (Prop_HFF2_SLICEL_C_Q)
0.137 4.001 r x_reg[1]__0_replica_2/Q
net (fo=21, routed) 0.371 4.372 x[1]_repN_2
SLICE_X56Y53 LUT6 (Prop_E6LUT_SLICEL_I1_O)
0.219 4.591 r calc[23]_i_101/O
net (fo=2, routed) 0.550 5.141 calc[23]_i_101_n_0
SLICE_X54Y57 CARRY8 (Prop_CARRY8_SLICEL_DI[5]_CO[7])
0.228 5.369 r calc_reg[23]_i_30/CO[7]
net (fo=1, routed) 0.030 5.399 calc_reg[23]_i_30_n_0
SLICE_X54Y58 CARRY8 (Prop_CARRY8_SLICEL_CI_O[1])
0.163 5.562 r calc_reg[23]_i_22/O[1]
net (fo=3, routed) 0.351 5.913 calc_reg[23]_i_22_n_14
SLICE_X56Y57 LUT3 (Prop_C6LUT_SLICEL_I1_O)
0.146 6.059 r calc[23]_i_26/O
net (fo=3, routed) 0.240 6.299 calc[23]_i_26_n_0
SLICE_X55Y58 LUT4 (Prop_A6LUT_SLICEM_I0_O)
0.089 6.388 r calc[23]_i_7/O
net (fo=1, routed) 0.407 6.795 calc[23]_i_7_n_0
SLICE_X53Y57 CARRY8 (Prop_CARRY8_SLICEM_DI[2]_O[4])
0.308 7.103 r calc_reg[23]_i_2/O[4]
net (fo=1, routed) 0.538 7.641 P[20]
SLICE_X54Y56 CARRY8 (Prop_CARRY8_SLICEL_S[4]_O[7])
0.352 7.993 r calc_reg[23]_i_1/O[7]
net (fo=1, routed) 0.051 8.044 P0_out[23]
SLICE_X54Y56 FDRE r calc_reg[23]/D
(clock clk rise edge) 4.000 4.000 r
AG12 0.000 4.000 r clk (IN)
net (fo=0) 0.000 4.000 clk_IBUF_inst/I
AG12 INBUF (Prop_INBUF_HRIO_PAD_O)
0.515 4.515 r clk_IBUF_inst/INBUF_INST/O
net (fo=1, routed) 0.066 4.581 clk_IBUF_inst/OUT
AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
0.034 4.615 r clk_IBUF_inst/IBUFCTRL_INST/O
net (fo=1, routed) 0.722 5.337 clk_IBUF
BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O)
0.091 5.428 r clk_IBUF_BUFG_inst/O
X2Y0 (CLOCK_ROOT) net (fo=106, routed) 1.748 7.176 clk_IBUF_BUFG
SLICE_X54Y56 FDRE r calc_reg[23]/C
clock pessimism 0.601 7.777
clock uncertainty -0.035 7.741
SLICE_X54Y56 FDRE (Setup_HFF_SLICEL_C_D)
0.063 7.804 calc_reg[23]
required time 7.804
arrival time -8.044
slack -0.239
该路径的松弛为-0.239 纳秒,因此略微未满足时序约束。首先要检查的是这条路径的起点和终点:我们查看报告标题中的“源”和“目的地”,找到 x_reg 和 calc_reg。所以问题的根源显然是这部分:
calc <= x * y + z;
这并不令人意外,因为这是 Verilog 代码中唯一有意义的操作。在现实中,问题的逻辑部分并不那么明显。
从时间报告中还可以看出,存在大量逻辑层级:7. 组合路径过长。换句话说,@clk 的两个时钟边之间有太多工作要做。
但失败的真正原因是什么?也许是因为路由导致了 61%的延误?回想一下,有个经验法则是路由延迟通常是总延迟的 40%。所以也许可以尝试用 FPGA 工具来提升性能?然而,这不太可能成为成功的解决方案,因为工具通常在放弃实现路径时序约束的尝试之前会努力工作。
试图在@x 和@calc 之间改变逻辑函数同样徒劳:乘法是必不可少的,所以没法用更简单的方法代替。
我将在下一页介绍其他可能的解决此类问题的方法。但在这种情况下,单纯列出各种技巧并无济于事。这个简单的例子说明,有时我们需要像侦探一样思考。
没有什么能替代你的大脑
阅读计时报告时,首先要问的问题是它有什么异常。在这个例子中,答案是组合路径仅由切片组成:几乎所有 FPGA 都有指定的算术单元(DSP、算术逻辑单元,名称各异),用于请求乘法时使用。事实上,乘法和加法是此类指定逻辑中最常见的函数。所以在大多数情况下,最简单的解决方案是让工具使用指定的算术单元。该解的时间报告显示在本页底部。
但我们真正应该问的问题是,为什么要用切片而不是指定的算术单位。最常见的原因是 FPGA 所有可用的算术单元已被设计的其他部分使用。在这种情况下,必要的更改可能根本与临界路径无关:也许需要通过从设计中移除部分逻辑来释放一些算术单位。另一种可能是指示工具在设计的不同部分之间以不同的方式分配这些算术单元。
在这个例子中,使用切片代替算术单位,因为我希望这样:我故意关闭了算术单位的使用(用 Vivado 的合成器参数之一:我把 max_dsp 设为零)。但这并不意味着这个例子是人为的。有时 FPGA 工具使用了错误的参数,导致了这种情况。事实上,有时故意不使用算术单元是正确的,因为它们在设计的其他部分更为重要。
所以最简单的解决办法就是使用指定的算术单位。但如果我们必须用切片呢?同样,解决方案是间接的。回想一下,问题所在是:
calc <= x * y + z;
但请注意,这句话紧接着出现:
result <= calc;
如果@calc 只在这一行中使用,其他地方不使用,则可以将计算拆分为两阶段。这种技术通常被称为管道化。所以 Verilog 代码会变成这样:
reg [24:0] calc, result;
reg [11:0] x, y, z, z_d;
always @(posedge clk)
begin
z_d <= z;
calc <= x * y;
result <= calc + z_d;
end
在此解中,@calc 仅得到乘法的结果。@z 的价值仅在下一阶段加到@calc 上。更准确地说,加号运算位于@calc 和@z_d 之间,因为该运算发生在一个时钟周期之后。所以@result 的价值和以前完全一样。
通过这种方式解决这个问题很容易,因为@result 只是原始 Verilog 代码中@calc 的延迟复制。现实生活中,我们通常没这么幸运。
注意关键路径只涉及@calc 和@x。@z 在路径中甚至没有提及。所以这种操作的目的是减轻算术操作的负担。更准确地说,是为了减少逻辑层级的数量。
回忆一下,关键路径是优化算法执行后最差的路径。该算法不询问问题的原因。相反,它试图改善那些有负松弛的路径。所以,尽管问题的解决方案需要对@z 进行操作,但与@z 相关的路径并不是关键路径。这只是巧合,但这种情况经常发生。
该解的临界路径计时报告也显示在本页底部。它显示逻辑层级数量从7级减少到6级。因此,数据路径延迟减少了0.715纳秒,这已足够满足时序限制。
从这个例子中可以学到的教训是,关键路径并不总是问题的直接原因。问为什么这条路失败是正确的,但解决方案可能在别处。请记住,每个 FPGA 工具都有自己的工具,可以提供信息,帮助查找问题根源。值得花时间去了解这些工具并阅读它们的文档。
应尽早避免问题,而不是以后解决
如果逻辑设计从一开始就正确完成,许多关于时序收敛的工作可以避免。这需要持续意识到逻辑设计不是软件。Verilog 代码的目的不是在仿真过程中产生正确的结果。真正重要的是合成器从 Verilog 代码生成的输出。
一个好的逻辑设计始于思考逻辑应如何最好地实现其目的。这包括识别与时间安排相关的潜在障碍。
经验较少的 FPGA 设计师通常通过反复试验来开发 Verilog 代码。模拟用于验证逻辑是否如预期工作,并逐步进行修正,直到模拟输出正确。结果可能是硬件无法使用的逻辑:为了实现时序约束,Verilog 代码必须完全重写。
提前思考 Verilog 代码生成的组合路径非常重要。其理念是观察每个寄存器,并沿着组合路径直到终点。回想组合路径总是从寄存器开始,终止于寄存器。
让我们来看这个例子:
reg [15:0] a, b;
wire [16:0] x, y;
reg [33:0] z;
assign x = a + 2;
assign y = b + 3;
always @(posedge clk)
z <= x * y;
关于@a:当该寄存器发生变化时,组合路径作为第一阶段达到@x。但@x 不是登记器。@x 通过连续赋值进行更新。因此,这条路继续向前@z。因此,逻辑在这条组合路径上执行了两个重要的运算:一个算术加法和一个算术乘法。这会不会太过分了?是否需要通过流水线技术将它分成两个时钟周期?这取决于时钟频率和使用的 FPGA。
另一个重要因素是缩短组合路径的难度。有时,漫长的组合路径是不可避免的。但当路径的时序变得容易时,即使设计中有更差的路径也要改进:如果设计中有几个有问题的路径,工具通常可以通过集中精力来实现时间限制。当你能轻松满足其他路径的时间要求时,这会非常有帮助。
因此,为了获得满足时序约束的设计,没有规则限制允许或禁止什么。在该领域做出正确决策需要具备 FPGA 设计经验。使用具体 FPGA 工具的经验也很重要。唯一永远正确的规则是:当可以通过简单修改 Verilog 代码来提升时序时,就去做。别偷懒,从头就做出改变。时刻要注意时间安排。
快速编写逻辑
如前所述,目标是实现寄存器之间的短组合路径:计算下一个寄存器值的逻辑函数应当简单。换句话说,实现这些逻辑功能应需要少量的逻辑层级。
作为 FPGA 设计师,我们的任务是审视 Verilog 代码,评估其逻辑函数的复杂性。这需要了解合成器如何将 Verilog 转换为逻辑元素(LUT 及其他逻辑原语)。这些知识是通过分析时间报告获得的部分经验。更难的是,这种转换在不同 FPGA 之间是不同的。所以写出能实现快速逻辑的 Verilog 代码并不容易。
如果你是 FPGA 新手,建议花时间查看实现结果以便学习。计时报告展示了逻辑设计如何拆解为简单逻辑元素的示例。FPGA 工具还提供其他工具,用于查看低层逻辑元素。
此外,还有一些简单的规则可以帮助你:
流水线:对寄存器要慷慨。如果可能,将逻辑任务拆分成小部分,并在每步后插入寄存器。FPGA 有很多触发器(通常每个 LUT 旁边有一个触发器),因此这种寄存器的插入不会增加 FPGA 的利用率。避免流水线的唯一原因是它会让设计变得过于复杂。
当使用 if-then-else 时,避免串联过多的“else”从句。如果可以用“案例”陈述代替,通常会更好。“else”子句通常需要一个逻辑函数,确保该子句之前的所有内容都是假的。因此,多个“else”子句可能需要多个逻辑层次。
避免不必要的重置。特别是,同步复位会为逻辑函数增加一定的复杂性。这两种重置都增加了路由的难度,因为这些信号必须覆盖多个逻辑元件。关于这个话题,还有一系列单独的页面 。
不要创建庞大的状态机。没有硬性限制允许多少州。但如果状态数超过20个,你应该考虑重构设计。另外,确保合成器对大型状态机使用单热编码(默认情况下,大多数合成器都是这样)。这有助于快速生成逻辑。
内存后面加一个寄存器通常更好。让我们来看这个隐式创建的 RAM 示例:
reg [7:0] array[0:127];
reg [7:0] val;
reg [6:0] addr;
always @(posedge clk)
val <= array[addr];
这个 Verilog 代码是正确的,但请注意@val 是 RAM 的同步输出。因此,当出现上升时钟沿时,RAM 的操作开始,只有当数组的值获得后,@val 才会更新。因此@val 的时钟到输出的延迟相对较大(相比触发器)。因此,从@val 开始的路径存在固有的劣势。这可以通过增加一个寄存器来解决:
reg [7:0] array[0:127];
reg [7:0] val_d, mem_out;
reg [6:0] addr;
always @(posedge clk)
begin
mem_out <= array[addr];
val_d <= mem_out;
end
注意,这在功能上并不等价:@mem_out 是这里 RAM 的输出。只有一个时钟后,这个输出才被复制到@val_d,所以它并不是@val 的完全替代。但@val_d 是一个真实的寄存器,时钟到输出的延迟很低。在许多 FPGA 中,这个额外的寄存器是块 RAM 的一部分,因此触发器是不浪费的。我提过千万别担心浪费人字拖吗?
不幸的是,添加这样的寄存器往往会大大复杂化设计。在这种情况下,最好不要添加这个额外的寄存器,而是尽量保持组合路径@val 短。
两份额外的计时报告
我承诺会在上面题为“你的大脑无可替代”的部分提供两份计时报告。我把它们放在这里,而不是在提到它们的地方,因为它们很长,也不太相关。
注意,这两份时序报告都是相关场景的关键路径。因此,路径的起点和终点与上述路径不同。
第一个时序报告涉及第一个 Verilog 代码示例。与上述计时报告不同,工具被允许使用指定的算术单位。结果是时间限制很容易实现。
本时序报告是为 Kintex Ultrascale FPGA 生成的。在这一家族 FPGA 中,指定的算术单元称为 DSP48E2。注意路径起点和终点在同一 DSP48E2 单元。因此逻辑延迟是 100%。
Slack (MET) : 1.406ns (required time - arrival time)
Source: calc_reg/DSP_A_B_DATA_INST/CLK
(rising edge-triggered cell DSP_A_B_DATA clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns})
Destination: calc_reg/DSP_OUTPUT_INST/ALU_OUT[10]
(rising edge-triggered cell DSP_OUTPUT clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns})
Path Group: clk
Path Type: Setup (Max at Slow Process Corner)
Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns)
Data Path Delay: 2.445ns (logic 2.445ns (100.000%) route 0.000ns (0.000%))
Logic Levels: 4 (DSP_ALU=1 DSP_M_DATA=1 DSP_MULTIPLIER=1 DSP_PREADD_DATA=1)
Clock Path Skew: -0.010ns (DCD - SCD + CPR)
Destination Clock Delay (DCD): 3.392ns = ( 7.392 - 4.000 )
Source Clock Delay (SCD): 4.096ns
Clock Pessimism Removal (CPR): 0.694ns
Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE
Total System Jitter (TSJ): 0.071ns
Total Input Jitter (TIJ): 0.000ns
Discrete Jitter (DJ): 0.000ns
Phase Error (PE): 0.000ns
Clock Net Delay (Source): 2.264ns (routing 0.756ns, distribution 1.508ns)
Clock Net Delay (Destination): 1.964ns (routing 0.696ns, distribution 1.268ns)
Location Delay type Incr(ns) Path(ns) Netlist Resource(s)
(clock clk rise edge) 0.000 0.000 r
AG12 0.000 0.000 r clk (IN)
net (fo=0) 0.000 0.000 clk_IBUF_inst/I
AG12 INBUF (Prop_INBUF_HRIO_PAD_O)
0.738 0.738 r clk_IBUF_inst/INBUF_INST/O
net (fo=1, routed) 0.105 0.843 clk_IBUF_inst/OUT
AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
0.049 0.892 r clk_IBUF_inst/IBUFCTRL_INST/O
net (fo=1, routed) 0.839 1.731 clk_IBUF
BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O)
0.101 1.832 r clk_IBUF_BUFG_inst/O
X2Y1 (CLOCK_ROOT) net (fo=80, routed) 2.264 4.096 calc_reg/CLK
DSP48E2_X11Y34 DSP_A_B_DATA r calc_reg/DSP_A_B_DATA_INST/CLK
DSP48E2_X11Y34 DSP_A_B_DATA (Prop_DSP_A_B_DATA_DSP48E2_CLK_A2_DATA[9])
0.302 4.398 r calc_reg/DSP_A_B_DATA_INST/A2_DATA[9]
net (fo=1, routed) 0.000 4.398 calc_reg/DSP_A_B_DATA.A2_DATA<9>
DSP48E2_X11Y34 DSP_PREADD_DATA (Prop_DSP_PREADD_DATA_DSP48E2_A2_DATA[9]_A2A1[9])
0.182 4.580 r calc_reg/DSP_PREADD_DATA_INST/A2A1[9]
net (fo=1, routed) 0.000 4.580 calc_reg/DSP_PREADD_DATA.A2A1<9>
DSP48E2_X11Y34 DSP_MULTIPLIER (Prop_DSP_MULTIPLIER_DSP48E2_A2A1[9]_U[10])
0.994 5.574 f calc_reg/DSP_MULTIPLIER_INST/U[10]
net (fo=1, routed) 0.000 5.574 calc_reg/DSP_MULTIPLIER.U<10>
DSP48E2_X11Y34 DSP_M_DATA (Prop_DSP_M_DATA_DSP48E2_U[10]_U_DATA[10])
0.164 5.738 r calc_reg/DSP_M_DATA_INST/U_DATA[10]
net (fo=1, routed) 0.000 5.738 calc_reg/DSP_M_DATA.U_DATA<10>
DSP48E2_X11Y34 DSP_ALU (Prop_DSP_ALU_DSP48E2_U_DATA[10]_ALU_OUT[10])
0.803 6.541 r calc_reg/DSP_ALU_INST/ALU_OUT[10]
net (fo=1, routed) 0.000 6.541 calc_reg/DSP_ALU.ALU_OUT<10>
DSP48E2_X11Y34 DSP_OUTPUT r calc_reg/DSP_OUTPUT_INST/ALU_OUT[10]
(clock clk rise edge) 4.000 4.000 r
AG12 0.000 4.000 r clk (IN)
net (fo=0) 0.000 4.000 clk_IBUF_inst/I
AG12 INBUF (Prop_INBUF_HRIO_PAD_O)
0.515 4.515 r clk_IBUF_inst/INBUF_INST/O
net (fo=1, routed) 0.066 4.581 clk_IBUF_inst/OUT
AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
0.034 4.615 r clk_IBUF_inst/IBUFCTRL_INST/O
net (fo=1, routed) 0.722 5.337 clk_IBUF
BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O)
0.091 5.428 r clk_IBUF_BUFG_inst/O
X2Y1 (CLOCK_ROOT) net (fo=80, routed) 1.964 7.392 calc_reg/CLK
DSP48E2_X11Y34 DSP_OUTPUT r calc_reg/DSP_OUTPUT_INST/CLK
clock pessimism 0.694 8.086
clock uncertainty -0.035 8.050
DSP48E2_X11Y34 DSP_OUTPUT (Setup_DSP_OUTPUT_DSP48E2_CLK_ALU_OUT[10])
-0.104 7.946 calc_reg/DSP_OUTPUT_INST
required time 7.946
arrival time -6.541
slack 1.406
第二个时序报告涉及第二个 Verilog 代码示例。在这个例子中,通过流水线技术改善了情况:
Slack (MET) : 0.433ns (required time - arrival time)
Source: y_reg[1]__0/C
(rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns})
Destination: calc_reg[23]/D
(rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns})
Path Group: clk
Path Type: Setup (Max at Slow Process Corner)
Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns)
Data Path Delay: 3.465ns (logic 1.653ns (47.706%) route 1.812ns (52.294%))
Logic Levels: 6 (CARRY8=4 LUT4=2)
Clock Path Skew: -0.129ns (DCD - SCD + CPR)
Destination Clock Delay (DCD): 3.373ns = ( 7.373 - 4.000 )
Source Clock Delay (SCD): 4.040ns
Clock Pessimism Removal (CPR): 0.538ns
Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE
Total System Jitter (TSJ): 0.071ns
Total Input Jitter (TIJ): 0.000ns
Discrete Jitter (DJ): 0.000ns
Phase Error (PE): 0.000ns
Clock Net Delay (Source): 2.208ns (routing 0.756ns, distribution 1.452ns)
Clock Net Delay (Destination): 1.945ns (routing 0.696ns, distribution 1.249ns)
Location Delay type Incr(ns) Path(ns) Netlist Resource(s)
(clock clk rise edge) 0.000 0.000 r
AG12 0.000 0.000 r clk (IN)
net (fo=0) 0.000 0.000 clk_IBUF_inst/I
AG12 INBUF (Prop_INBUF_HRIO_PAD_O)
0.738 0.738 r clk_IBUF_inst/INBUF_INST/O
net (fo=1, routed) 0.105 0.843 clk_IBUF_inst/OUT
AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
0.049 0.892 r clk_IBUF_inst/IBUFCTRL_INST/O
net (fo=1, routed) 0.839 1.731 clk_IBUF
BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O)
0.101 1.832 r clk_IBUF_BUFG_inst/O
X2Y1 (CLOCK_ROOT) net (fo=121, routed) 2.208 4.040 clk_IBUF_BUFG
SLICE_X54Y88 FDRE r y_reg[1]__0/C
SLICE_X54Y88 FDRE (Prop_EFF2_SLICEL_C_Q)
0.138 4.178 r y_reg[1]__0/Q
net (fo=25, routed) 0.505 4.683 y[1]
SLICE_X53Y91 LUT4 (Prop_B6LUT_SLICEM_I0_O)
0.150 4.833 r calc[7]_i_28/O
net (fo=1, routed) 0.344 5.177 calc[7]_i_28_n_0
SLICE_X53Y89 CARRY8 (Prop_CARRY8_SLICEM_DI[2]_CO[7])
0.424 5.601 r calc_reg[7]_i_9/CO[7]
net (fo=1, routed) 0.043 5.644 calc_reg[7]_i_9_n_0
SLICE_X53Y90 CARRY8 (Prop_CARRY8_SLICEM_CI_O[0])
0.122 5.766 r calc_reg[23]_i_30/O[0]
net (fo=3, routed) 0.402 6.168 calc_reg[23]_i_30_n_15
SLICE_X51Y88 LUT4 (Prop_C5LUT_SLICEL_I0_O)
0.169 6.337 r calc[15]_i_8/O
net (fo=1, routed) 0.437 6.774 calc[15]_i_8_n_0
SLICE_X51Y92 CARRY8 (Prop_CARRY8_SLICEL_DI[1]_CO[7])
0.422 7.196 r calc_reg[15]_i_1/CO[7]
net (fo=1, routed) 0.030 7.226 calc_reg[15]_i_1_n_0
SLICE_X51Y93 CARRY8 (Prop_CARRY8_SLICEL_CI_O[7])
0.228 7.454 r calc_reg[23]_i_1/O[7]
net (fo=1, routed) 0.051 7.505 calc_reg[23]_i_1_n_8
SLICE_X51Y93 FDRE r calc_reg[23]/D
(clock clk rise edge) 4.000 4.000 r
AG12 0.000 4.000 r clk (IN)
net (fo=0) 0.000 4.000 clk_IBUF_inst/I
AG12 INBUF (Prop_INBUF_HRIO_PAD_O)
0.515 4.515 r clk_IBUF_inst/INBUF_INST/O
net (fo=1, routed) 0.066 4.581 clk_IBUF_inst/OUT
AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
0.034 4.615 r clk_IBUF_inst/IBUFCTRL_INST/O
net (fo=1, routed) 0.722 5.337 clk_IBUF
BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O)
0.091 5.428 r clk_IBUF_BUFG_inst/O
X2Y1 (CLOCK_ROOT) net (fo=121, routed) 1.945 7.373 clk_IBUF_BUFG
SLICE_X51Y93 FDRE r calc_reg[23]/C
clock pessimism 0.538 7.910
clock uncertainty -0.035 7.875
SLICE_X51Y93 FDRE (Setup_HFF_SLICEL_C_D)
0.063 7.938 calc_reg[23]
required time 7.938
arrival time -7.505
slack 0.433
这种差异没有用指定算术单元时那么明显。但这仍然足够满足时间限制。
