VIVADO时序违例优化详解
VIVADO时序违例优化详解
在FPGA设计中,时序违例是一个常见的问题,它可能导致逻辑功能错误、性能下降和可靠性降低。本文将详细介绍时序违例的概念、影响以及在VIVADO中的具体优化方法,包括时钟树设计优化、数据路径调整、时序约束设置等。通过本文,读者将能够掌握解决时序违例问题的实用技巧,提升FPGA设计能力。
VIVADO时序违例优化
知识点
在FPGA设计中,时序违例是指设计中的时序要求无法满足的情况。这通常发生在时钟频率过高或数据路径延迟过长时,导致信号无法在规定的时间内稳定或传输。
带来的影响
- 逻辑功能问题:时序违例可能导致FPGA设计的逻辑功能出错。由于时序不满足要求,数据可能无法在正确的时钟周期内被捕获或传输,从而导致设计的输出结果与预期不一致。这种不确定性可能导致系统在某些情况下无法正常工作。
- 性能问题:时序违例会限制设计的最高运行频率。如果设计存在时序违例,那么系统可能无法达到预期的时钟频率,从而影响整体性能。这可能导致系统处理速度变慢,无法满足应用需求。
- 可靠性问题:频繁的时序违例会增加电路元件的应力,可能导致器件老化加速,从而影响使用寿命和可靠性。此外,时序违例还可能导致电路中信号冒险和噪声增加,进一步加剧不确定性,降低系统的可靠性。
解决方案
- 优化时钟树设计
- 通过时钟树平衡技术来确保时钟信号同时到达所有触发器。这有助于减少时钟偏差,从而满足时序要求。
- 使用MMCM或PLL等时钟管理单元来优化时钟信号的质量和稳定性。
- 合理设置时钟频率,避免过高或过低的时钟频率导致时序违例。
- 调整数据路径
- 通过简化逻辑或使用更高效的逻辑结构来减少信号通过的逻辑级数。这有助于减少信号延迟,从而满足时序要求
- 通过重新排列逻辑顺序,减少关键路径上的延迟。例如,可以通过重新设计逻辑,使得信号通过更少的逻辑门到达目的地。
- 调整时序约束
- 设置合理的时序约束,避免过于严格的约束导致不必要的优化。同时,也要确保约束足够严格以满足设计要求。
- 优化异步信号处理
- 对于异步时钟域之间的信号传递,要使用适当的同步机制来避免时序违例。例如,可以使用双寄存器同步或FIFO等缓冲机制来确保信号的稳定传递。
vivado 时序优化
上面说了那么多套话,最重要的还是要知道如何解决问题。
如上图,为我的一个工程的时序,先分析以下上面几个指标所代表的含义:
Worst Negative Slack (WNS)
WNS代表最差负时序裕量。在时序分析中,WNS是衡量设计中最差性能的一个指标。它表示在所有路径中,时序裕量最小的那个负值。如果WNS的值很大(即负得很多),那么意味着设计中有一些路径的时序性能非常差,可能需要进一步优化。Total Negative Slack (TNS)
TNS代表总的负时序裕量。它是所有负时序裕量路径之和,即所有不满足时序要求的路径的裕量总和。TNS反映了设计中整体时序性能的一个范围。如果TNS的值很大,说明设计中有较多的路径不满足时序要求,这可能会对整个系统的性能产生负面影响。Number of Failing Endpoints
有多少个端点(或路径)未能满足时序要求。它表示存在时序违例的端点数量。如果Number of Failing Endpoints的值很大,说明设计中有较多的路径存在时序问题,需要重点关注和优化。Total Number of Endpoints
所有被分析的端点(或路径)的总数。它提供了时序分析的一个全局视角,帮助设计师了解整个设计的规模和复杂度。Total Number of Endpoints的值通常用于评估时序分析的全面性和准确性。
操作流程
本人也是刚开始研究vivado的时序优化,了解还不全面;下面的步骤也是自己琢磨出来的,如有错误请指正
下面一步一步优化上面工程的时序。
实现完成后(run implementation),点开时序分析汇总:
点击【OK】
按下面点开:
黄色框住的即为需要优化的时序,随机点进去一个,可以看到具体情况。主要关注的是From -To信号的违例两端
右键一行,点击 Schematic
在这里,可以清晰看到信号违例的两端:
到这里,我们就可以回到代码,找到这个信号,分析是否符合要求,有无跨时钟的现象等。
如果觉得该时序违例对工程不会构成影响,则可以忽略该违例(仅适用于固定在端口上的数据、缓存数据,不会一直随时钟改变):
点击【OK】
之后再重新 [run implementation],该时序违例消失,同时约束文件中会生成:
set_false_path -from [get_pins u_aurora_64b66b_top/u_aurora_64b66b_0/inst/aurora_64b66b_0_core_i/aurora_lane_2_i/lane_init_sm_i/lane_up_flop_i/C] -to [get_pins {u_vio/inst/PROBE_IN_INST/probe_in_reg_reg[4]/D}]
同时忽略多个违例
看下面这个违例:
有该路径有130条违例。但是你点进去只显示了10条。下面让他们全部显示出来:
点击[options],将[number of paths per group] 改为130:
这样就可以显示全部的违例情况。我发现这些为例全部为 ILA 的时钟问题,如果想将这130条全部忽略,该如何做:
保存完之后,会在 约束文件中生成一句话:
set_false_path -from [get_pins {u_rfsoc_wrapper/rfsoc_i/ps_samp_RnM/Dual_Flip_Flop_sync_0/inst/bram_wrdata_1_reg[*]/C}] -to *
跨时钟传输
如果发现自己必须跨时钟传输数据,比如:在时钟A下的数据data想在时钟B下处理。如何处理才能避免时序违例呢?
握手协议
握手协议是一种确保数据在稳定时进行采集和传输的方法。这种方法特别适用于对数据传输精度有严格要求的情况。以下是握手协议的一个基本流程:
- 数据准备:在时钟A域中,当数据data准备好后,发送一个启动信号(如信号A)到时钟B域。
- 数据传输:在时钟B域中,接收到启动信号后,开始准备接收数据。此时,时钟A域将数据data发送到时钟B域。
- 数据确认:时钟B域接收到数据后,可以发送一个确认信号(如信号B)回时钟A域,表示数据已成功接收。
- 数据锁定与释放:在时钟A域中,接收到确认信号后,可以锁定数据(即不再改变数据),并开始准备下一个数据的传输。同时,时钟B域可以开始处理接收到的数据。在处理完成后,时钟B域可以发送一个信号告诉时钟A域数据已被处理,此时时钟A域可以释放锁定的数据。
打两拍
打两拍法通常用于处理单bit信号,通过定义两个寄存器对输入的信号进行延拍,以确保信号的稳定性。以下是打两拍法的基本步骤: - 第一拍采样:在时钟A的上升沿(或下降沿),将输入信号data采样到第一个寄存器中。
- 第二拍确认:在时钟A的下一个上升沿(或下降沿),将第一个寄存器中的值采样到第二个寄存器中。此时,第二个寄存器中的值已经是稳定的了,可以将其传输到时钟B域中进行处理。
需要注意的是,打两拍法并不能完全消除亚稳态,但可以大大降低其出现的概率。
always @(posedge clkA or posedge rstA) begin
if (rstA) begin
data_sync1 <= 1'b0;
end else begin
data_sync1 <= data_from_clkA;
end
end
always @(posedge clkB or posedge rstB) begin
if (rstB) begin
data_sync2 <= 1'b0;
end else begin
data_sync2 <= data_sync1;
end
end
// 使用 data_sync2 作为 clkB 域中的有效数据
注意,该操作vivado的时序仍认为是违例的,它的判定条件就是看两端的时钟是否为同一个时钟。根据自己的分析来判断能否忽略
异步FIFO,双口RAM
对于多bit数据的跨时钟域传输,可以使用异步FIFO或双口RAM来解决问题。
- 异步FIFO:FIFO(First In First Out)是一种先进先出的存储器。在异步FIFO中,数据的写入和读出可以在不同的时钟域中进行。例如,可以在时钟A域中将数据写入FIFO,然后在时钟B域中从FIFO中读出数据。这种方法特别适用于数据产生速率和数据处理速率不匹配的情况。
- 双口RAM:双口RAM是一种具有两个独立访问端口的存储器。每个端口都可以独立地进行读写操作,并且可以在不同的时钟域中进行。因此,可以在时钟A域中将数据写入双口RAM的一个端口,然后在时钟B域中从另一个端口读出数据。这种方法特别适用于需要同时访问同一数据的不同时钟域的情况。
注释
记录自己第一次解决时序问题,应该有一些操作或者解释并不官方,后续有什么问题会补充。