ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vivado时序违约本质与实战修复指南

Vivado时序违约本质与实战修复指南 1. 什么是Vivado时序违约它不是报错而是设计“没跑稳”的体检报告你第一次在Vivado里点下“Run Implementation”眼睁睁看着综合、布局布线一路绿灯最后却在“Timing Summary”窗口里弹出一行醒目的红色文字“Timing constraints are not met”——那一刻很多人本能地以为是代码写错了、约束写漏了甚至怀疑是不是license没激活。其实不然。时序违约Timing Violation根本不是语法错误而是一份FPGA设计的“心电图异常报告”它不告诉你电路不能工作但明确警告你——当前频率下信号在芯片内部走线、经过逻辑门、穿越寄存器的整个旅程时间预算已经超支。它背后牵扯的是setup time建立时间和hold time保持时间这两个物理世界不可逾越的铁律是数字电路稳定运行的底层基石。我带过几十个FPGA初学者项目发现一个高频误区把时序违约当成“编译失败”来处理。结果就是反复改代码、删逻辑、加流水线折腾三天问题依旧。直到某天他盯着Timing Report里那条路径的“Slack -1.23ns”发呆我才告诉他“别改功能先搞懂这条路径为什么慢。”——因为Vivado的时序分析不是在检查你的Verilog写得漂不漂亮而是在用纳秒级精度模拟信号从一个触发器出发经过组合逻辑再到达下一个触发器的全过程。它算的是真实物理延迟导线电阻电容带来的RC延时、LUT查找表的开关时间、多路复用器的传播延迟、时钟树的skew……这些参数全来自Xilinx官方工艺库如UltraScale的Kintex-7器件库不是仿真模型而是流片实测数据。所以当你看到“WNS (Worst Negative Slack) -0.89ns”意味着最差情况下数据比时钟晚了0.89纳秒才稳定下来——这0.89ns就是setup time被突破的缺口。更关键的是时序违约往往藏在异步信号的交接处。比如你用UART接收外部串口数据或者用SPI读取ADC采样值这些信号源完全独立于你的FPGA主时钟域。Vivado默认会把它们当作“黑盒输入”不做跨时钟域同步分析直到你手动添加set_input_delay约束它才开始计算外部数据沿到达FPGA引脚后还要经过IOB缓冲器、内部走线、再到第一个寄存器这一整段路径是否满足setup/hold要求。很多“生成比特流失败”的案例根源不在逻辑本身而在你忘了告诉Vivado“这个pin上的信号是从50MHz晶振驱动的MCU过来的它的数据有效窗口只有±2ns”。所以这篇小结不教你如何“绕过”时序违约而是带你亲手拆开Vivado Timing Analyzer的引擎盖看清setup/hold time怎么算、为什么异步信号是重灾区、哪些操作是真能救命的“手术刀”哪些只是掩耳盗铃的“创可贴”。它适合正在调试Zynq SOC、做高速ADC采集、或是刚被时序报告吓懵的新手——只要你手里有块Kintex/Virtex/UltraScale系列板子正对着那个红色WNS发愁这篇就是为你写的实战笔记。2. 时序违约的本质Setup与Hold Time的物理真相与数学表达要真正驯服时序违约必须回到数字电路的物理起点触发器Flip-Flop不是理想开关它对输入信号有严苛的时间窗口要求。这个窗口由两个硬性参数定义——setup time建立时间和hold time保持时间。Vivado的时序分析引擎本质上就是在一个时钟周期内反复验证每一条路径是否满足这两个不等式。很多人死记硬背“setup是数据提前到hold是数据保持住”却不知道背后的晶体管级原理当D端信号在CLK上升沿到来前太晚到达内部传输门还没完全导通Q端就可能锁存到错误电平而如果CLK上升沿后D端信号过早翻转反馈锁存器的维持环路会被破坏导致亚稳态metastability。Vivado不会直接告诉你“这里可能亚稳态”但它会用hold violation的红色警报把你拉回现实。2.1 Setup Time为什么必须“提前到”且提前量精确到皮秒Setup timetsu的定义是在时钟有效沿如上升沿到来之前数据信号必须稳定并保持不变的最小时间。它的物理来源有两个核心部分第一是触发器内部的预充电与采样路径延迟。以Xilinx 7系列FF为例CLK信号进入触发器后需经过时钟缓冲器BUFG、内部时钟树分叉、再到每个FF的时钟输入端CK这段路径存在固有skew偏斜。同时D端信号从IOB或内部逻辑出发经布线资源到达FF的D端也存在RC延迟。Vivado的时序引擎会为每条路径提取精确的延迟值Tclk_q时钟从CLK引脚到FF CK端的延迟含BUFG delay clock tree skewTco时钟有效沿到达CK后Q端输出变化所需时间clock-to-out delayTlogic组合逻辑路径的传播延迟LUT delay routing delayTsetupFF厂商规定的最小建立时间Xilinx手册中给出如K7为0.2ns于是setup约束的数学表达式为Tclk_q Tco Tlogic ≤ Tperiod - Tsetup其中Tperiod是时钟周期如10ns对应100MHz。Vivado做的就是对所有从FF.Q出发、经组合逻辑、再到下一个FF.D的路径计算左边总和并与右边最大允许值比较。一旦左边 右边即产生setup violation。举个实操例子你在Vivado中设置主时钟为100MHzTperiod10ns但某条关键路径上用了3级LUT级联做复杂运算Tlogic实测达6.5ns加上Tclk_q1.2ns、Tco0.8ns左边总和8.5ns。此时右边10ns - 0.2ns9.8ns看似还有余量。但若该路径的时钟树skew较大如因布局分散导致Tclk_q实际为1.8ns则左边1.80.86.59.1ns仍安全。可一旦你添加一个跨时钟域的FIFO其内部指针比较逻辑引入额外2ns延迟左边瞬间突破9.8nsWNS立刻变红。这就是为什么“加一级流水线”常被推荐——它把长组合逻辑拆成两段每段Tlogic降低3ns虽增加一级寄存器延迟但整体时序余量反而扩大。2.2 Hold Time为什么“保持住”比“提前到”更难防Hold timethold的定义是在时钟有效沿到来之后数据信号必须继续保持稳定的最小时间。它的物理根源在于触发器内部的采样保持电路CLK上升沿触发采样后D端信号需维持足够时间确保锁存器完成电荷转移并稳定输出。Xilinx器件的thold通常极小K7为0.0ns至0.1ns但这绝不意味着可以忽略。真正的hold风险几乎全部来自时钟偏斜clock skew和数据路径延迟失配。Hold约束的数学表达式为Tclk_q Thold ≤ Tco Tlogic注意这里不涉及时钟周期只关注同一时钟沿触发的前后关系。Vivado会检查“本周期CLK沿到达FF1.CK后FF1.Q翻转经TcoTlogic到达FF2.D与此同时同一CLK沿经另一路径到达FF2.CK”。若FF2.CK比FF1.CK晚到即clock skew为正而FF2.D又因布线短而早到则FF2可能在CLK沿到达前就采样到旧数据导致hold violation。提示Vivado默认对hold分析使用“zero-skew”假设即认为所有FF的CK端时钟到达时间完全一致。但在实际布局中尤其当FF分布在芯片不同区域时skew可达数百皮秒。因此hold violation常在布局布线Place Route阶段才暴露综合阶段Synthesis往往看不到。这也是为什么“综合通过但实现失败”如此常见——综合只估算逻辑延迟而PR才确定真实布线长度和时钟树结构。2.3 异步信号时序违约的“隐形炸弹”异步信号如按键、UART_RX、外部ADC_DRDY是时序违约的高发区原因在于它们完全游离于FPGA主时钟域之外。Vivado无法预知其跳变时刻只能依赖你提供的set_input_delay和set_output_delay约束来建模。若约束缺失或错误Vivado会按“最坏情况”处理假设外部信号在任意时刻跳变从而导致setup/hold窗口被无限压缩。例如你用100MHz主时钟采样一个50MHz外部时钟域的信号。若未添加约束Vivado默认该输入信号的建立/保持窗口为0即要求数据在CLK沿到来前/后瞬间稳定——这在物理上不可能。正确做法是# 假设外部时钟与FPGA主时钟同源如共用晶振则用set_input_delay指定数据有效窗口 set_input_delay -clock clk_100MHz -max 8.0 [get_ports uart_rx] set_input_delay -clock clk_100MHz -min 2.0 [get_ports uart_rx] # 这表示uart_rx信号在clk_100MHz上升沿前2ns至8ns内有效窗口宽6ns若外部时钟完全异步如独立晶振则必须用两级寄存器同步synchronizer并在约束中声明set_clock_groups -asynchronous -group [get_clocks clk_100MHz] -group [get_clocks ext_clk] # 此命令告诉Vivado这两个时钟域无相位关系不要做跨域时序分析否则Vivado会强行计算跨时钟域路径必然报出大量虚假violation。我曾帮一个客户调试ADC接口其DRDY信号由外部25MHz晶振驱动但约束文件里只写了create_clock -name adc_clk -period 40.0 [get_ports drdy]结果Vivado试图在100MHz主时钟下分析drdy到内部寄存器的路径WNS低至-12ns。加上set_clock_groups后违规数归零——因为Vivado终于明白“这两拨时钟压根儿不打算握手”。3. Vivado时序分析全流程拆解从约束编写到报告解读的实操细节Vivado的时序分析不是一键魔法而是一套严谨的“建模-求解-验证”流程。很多人卡在第一步约束文件XDC写不对后面全是空中楼阁。下面我以一个典型Zynq SoC工程为例带你走完从约束编写、实现运行到报告精读的完整链路所有步骤均基于Vivado 2023.1实测参数可直接抄作业。3.1 约束文件XDC编写三类核心约束的编写逻辑与避坑指南XDC文件是Vivado时序分析的“宪法”它告诉工具哪些是时钟、数据何时有效、路径有何特殊要求。一份合格的XDC必须包含三类约束第一类时钟定义create_clock / create_generated_clock这是所有时序分析的起点。常见错误是混淆“物理时钟”与“逻辑时钟”。例如你用PS端PL_CLK输出一个100MHz时钟到PL但误在XDC中写# ❌ 错误直接对PL_CLK引脚创建时钟忽略PS内部分频 create_clock -name clk_100MHz -period 10.0 [get_ports PL_CLK]正确做法是在Zynq Block Design中PS的FCLK_CLK0已配置为100MHzVivado会自动将该时钟从PS传递到PL。你只需在XDC中声明其到达PL端口的延迟# ✅ 正确声明PS输出时钟在PL端口的到达特性 create_clock -name fclk_clk0 -period 10.0 [get_pins zynq_ultra_ps_e_0/pl_clk0] # 若PL_CLK引脚连接到fclk_clk0则自动关联对于MMCM/PLL生成的时钟必须用create_generated_clock# 假设MMCM实例名为inst/mmcm_adv_inst输出端口为clk_out1 create_generated_clock -name clk_200MHz -source [get_pins inst/mmcm_adv_inst/CLKIN1] \ -divide_by 1 -multiply_by 2 [get_pins inst/mmcm_adv_inst/CLKOUT1]第二类输入/输出延迟约束set_input_delay / set_output_delay这是异步信号的生命线。关键参数-max和-min必须基于真实硬件手册计算。以AD9280 ADC为例其数据手册标明tDSData Setup Time 2.5nstDHData Hold Time 1.5nstJITClock Jitter 0.3nsFPGA输入端时钟与数据的skewPCB走线差异 ±0.5ns则输入延迟约束应为# -max 数据最晚有效时刻 tDS tJIT PCB_skew_max 2.5 0.3 0.5 3.3ns # -min 数据最早有效时刻 -(tDH - tJIT - PCB_skew_min) -(1.5 - 0.3 - 0.5) -0.7ns set_input_delay -clock clk_100MHz -max 3.3 [get_ports adc_data[*]] set_input_delay -clock clk_100MHz -min -0.7 [get_ports adc_data[*]]注意-min为负值是正常的它表示数据可在时钟沿之前就有效。若此处填正值Vivado会误判为数据必须在CLK后才有效导致setup分析过于保守。第三类伪路径与多周期路径set_false_path / set_multicycle_path这是“精准外科手术”的关键。例如你的设计中有复位信号rst_n它从按键经去抖逻辑生成最终异步复位所有FF。Vivado默认会对rst_n到每个FF的路径做时序分析但复位是异步事件无需满足setup/hold。此时必须声明# rst_n是异步复位所有FF的rst端口都不参与时序分析 set_false_path -from [get_ports rst_n] -to [get_cells -hierarchical -filter {ref_name FDRE || ref_name FDSE}]再如一个计数器每10个时钟周期产生一次有效信号其使能路径的延迟允许跨越多个周期# 使能信号valid_en的建立时间允许2个周期保持时间允许1个周期 set_multicycle_path -from [get_pins cnt_reg/Q] -to [get_pins en_ff/D] -setup -cycle 2 set_multicycle_path -from [get_pins cnt_reg/Q] -to [get_pins en_ff/D] -hold -cycle 13.2 实现流程中的关键节点与参数调优Vivado的Implementation分为三个阶段Synthesis综合、Optimization优化、Place Route布局布线。每个阶段都有影响时序的关键参数Synthesis阶段synth_design命令的-directive参数决定综合策略。默认default适合通用逻辑但对时序关键路径应改用Explore或RuntimeOptimizedsynth_design -top top_module -part xc7z020clg400-1 -directive ExploreExplore会尝试多种映射方案耗时增加30%但WNS改善可达15%。我实测一个FFT核在default下WNS-0.45ns切换Explore后变为0.12ns。Optimization阶段关键参数是opt_design的-directive。Flow_PerfOptimized_high会激进地插入缓冲器、复制逻辑、调整寄存器位置但可能增加功耗。对资源紧张的设计可用Flow_PerfOptimized_low平衡。Place Route阶段place_design的-directive中ExploreWithRoutable比默认Default多做10次布局迭代显著改善长路径布线。route_design的-directive选择NoTimingRelaxation默认或TimingOptimized。后者强制布线器优先满足时序但可能增加布线拥塞。当WNS接近临界值如-0.1ns时启用此选项常能“压线过关”。3.3 Timing Report深度解读定位瓶颈路径的四步法Vivado生成的report_timing_summary是诊断核心但90%的人只看第一行WNS。真正有效的分析需四步穿透第一步锁定最差路径Worst Path在Report窗口点击“WNS”列按降序排列找到WNS最负的路径。双击该路径打开详细视图。重点关注Path Type: 是setup还是hold两者修复策略完全不同。From/To: 起始和结束寄存器名称确认是否为关键功能路径如DDR控制器地址线。Delay (ns): 列出各段延迟如net delay布线延迟、cell delayLUT/FF延迟。若net delay占比超40%说明布线过长需优化布局。第二步分析延迟构成在详细路径视图中展开“Path Details”查看每一级逻辑的延迟分解。例如| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |......若某级LUT的cell delay高达1.8ns远超典型0.3ns说明该LUT被配置为复杂函数应考虑拆分逻辑。第三步检查时钟树与skew在Report中切换到“Clock Network”视图查看关键路径的时钟源。若From和To寄存器的时钟来自不同BUFGskew可能达500ps。此时应强制使用同一BUFG# 将两个FF的时钟都约束到同一个BUFG输出 create_clock -name clk_main -period 10.0 [get_pins bufg_inst/O] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_main]第四步验证修复效果每次修改约束或代码后必须重新运行report_timing_summary并对比WNS变化。切忌只看“是否变绿”而要关注数值从-0.89ns提升到-0.12ns虽仍违规但说明方向正确若从-0.89ns恶化到-1.45ns则修改有误。4. 实战解决方案库针对高频场景的可落地修复策略面对时序违约不能只靠“加流水线”这一招鲜。我整理了六类高频场景的精准修复方案每一种都经过多个项目实测附带参数计算和效果预估。4.1 长组合逻辑路径用流水线还是逻辑重构当一条路径包含超过5级LUT级联如FIR滤波器系数乘加Tlogic极易超标。两种主流方案方案A插入一级流水线推荐新手在长路径中间插入寄存器将延迟均分。例如原路径Tlogic7.2ns插入一级后变为两段各3.6ns。Vivado会自动优化寄存器位置但需手动指定# 在Verilog中添加寄存器并用综合属性锁定位置 (* keep true *) reg [31:0] mid_reg; always (posedge clk) mid_reg long_logic_out;效果WNS改善约0.5~1.2ns但增加1周期延迟对实时性要求高的系统需评估。方案B逻辑重构推荐资源充足项目将串行运算改为并行。例如一个16抽头FIR原设计用单个乘法器循环计算Tlogic6.8ns。重构为4个乘法器并行计算再用加法树合并并行后单路Tlogic降至1.5ns加法树深度3级Tlogic_add0.9ns总Tlogic1.50.92.4ns改善4.4ns代价LUT资源增加约3倍但时序余量大幅提升。实操心得我曾调试一个视频缩放IP原设计用单线程处理像素WNS-1.8ns。改用4路并行后WNS0.3ns且帧率提升2.3倍。关键点在于并行化后Vivado能将4路逻辑布局在相邻CLB中布线延迟反而降低。4.2 跨时钟域同步两级寄存器为何有时不够异步信号同步是hold violation重灾区。标准做法是两级DFF但某些场景需三级场景高频率异步信号如100MHz外部时钟域两级同步器的MTBF平均无故障时间公式为MTBF exp( (tsu thold) / (f_clk * f_async * τ) )其中τ为FF亚稳态分辨时间Xilinx K7约0.3ns。当f_async100MHzf_clk200MHz时两级MTBF约10^5秒27小时风险极高。此时应改用三级同步器增加一级FF或在第二级FF后加脉冲展宽电路确保采样稳定场景复位信号异步释放PS端产生的复位信号rst_n经PL逻辑传递到外设。若仅两级同步可能因skew导致部分模块提前退出复位。解决方案# 在XDC中声明复位为异步且不参与时序分析 set_false_path -from [get_ports rst_n] set_false_path -to [get_ports rst_n] # 同时在RTL中用同步释放逻辑 always (posedge clk) begin rst_sync1 rst_n; rst_sync2 rst_sync1; rst_sync3 rst_sync2; end assign rst_out rst_sync3; // 使用三级同步输出4.3 IO接口时序如何设置input/output delay才不翻车ADC/DAC接口是setup/hold violation高发区。以AD9783 DAC为例其时序要求tDS 1.2ns, tDH 0.8nsFPGA输出时钟clk_out与数据data_out的PCB走线长度差为0.8ns则output delay约束为# -max 数据最晚必须稳定的时刻 tDS PCB_skew 1.2 0.8 2.0ns # -min 数据最早可变化的时刻 -(tDH - PCB_skew) -(0.8 - 0.8) 0.0ns set_output_delay -clock clk_out -max 2.0 [get_ports dac_data[*]] set_output_delay -clock clk_out -min 0.0 [get_ports dac_data[*]]注意-min0.0表示数据可在CLK沿同时变化这符合DAC的“时钟上升沿锁存”特性。若填负值Vivado会误判为数据必须提前稳定导致过度优化。4.4 时钟约束错误BUFGMUX与MMCM的常见陷阱很多“时序违约”实为时钟约束错误。典型陷阱陷阱1BUFGMUX未正确约束当设计中用BUFGMUX切换两个时钟源时Vivado默认只分析主时钟路径。需显式声明# 假设BUFGMUX输出为clk_mux输入为clk_a和clk_b create_clock -name clk_a -period 10.0 [get_ports clk_a_in] create_clock -name clk_b -period 8.0 [get_ports clk_b_in] # 告诉Vivadoclk_mux的时钟来自这两个源且切换无glitch set_clock_groups -physically_exclusive -group [get_clocks clk_a] -group [get_clocks clk_b]陷阱2MMCM输出时钟相位偏移未建模若MMCM配置了PHASE参数如90度但XDC中未体现Vivado按0相位分析必然报错。正确做法# 在create_generated_clock中加入-phase选项 create_generated_clock -name clk_200MHz_p90 -source [get_pins mmcm_inst/CLKIN1] \ -phase 90.0 -multiply_by 2 [get_pins mmcm_inst/CLKOUT1]4.5 布局布线优化如何让Vivado“听懂”你的意图当WNS卡在-0.1ns附近微调布局常能破局技巧1Pblock区域约束将时序关键模块如DDR控制器放入固定Pblock避免被布局器分散create_pblock pblock_ddr add_cells_to_pblock pblock_ddr [get_cells ddr_ctrl*] resize_pblock pblock_ddr -add {SLICE_X10Y20:SLICE_X30Y50}技巧2寄存器绑定LOC对关键路径的起始/结束寄存器手动指定位置# 将FF1绑定到特定SLICE缩短布线距离 set_property LOC SLICE_X15Y30 [get_cells ff1] # 将FF2绑定到相邻SLICE set_property LOC SLICE_X15Y31 [get_cells ff2]实测相邻SLICE间布线延迟比跨列降低40%WNS可改善0.2ns。4.6 时序例外处理false path与multicycle path的精确应用滥用set_false_path是重大隐患。必须严格区分真正可设为false path的场景异步复位/置位信号rst_n, set_nJTAG调试信号tck, tms手动控制的测试模式信号test_mode严禁设为false path的场景任何参与功能逻辑的使能信号en, valid跨时钟域的握手信号req, ack——应使用set_clock_groupsmulticycle path的精确计算一个状态机每3个时钟周期跳转一次其next_state逻辑的建立时间允许3周期# 从当前状态寄存器Q到next_state寄存器D的路径 set_multicycle_path -from [get_cells state_reg/Q] -to [get_cells next_state_reg/D] \ -setup -cycle 3 # 保持时间仍为1周期因状态跳转后需立即稳定 set_multicycle_path -from [get_cells state_reg/Q] -to [get_cells next_state_reg/D] \ -hold -cycle 15. 常见问题速查表与独家避坑经验在数十个项目中我总结出一份高频问题速查表覆盖从约束错误到工具Bug的全场景。每一条都附带真实案例和解决耗时。问题现象根本原因解决方案平均耗时WNS在Synthesis阶段为正PR后变负综合仅估算逻辑延迟PR确定真实布线长度和时钟树skew运行opt_design -directive ExploreWithRoutable强制优化布线20分钟Timing Report中显示“no paths found”约束文件中create_clock目标引脚不存在或时钟未驱动任何寄存器用report_clocks确认时钟是否被识别用get_ports检查引脚名拼写5分钟异步FIFO的读写指针路径报大量violation未声明set_clock_groups -asynchronousVivado强行分析跨域路径在XDC中添加set_clock_groups -asynchronous -group [get_clocks wr_clk] -group [get_clocks rd_clk]2分钟ILA核采样时钟报setup violationILA的采样时钟未正确约束Vivado按默认IO时钟分析为ILA的clk端口单独创建时钟create_clock -name ila_clk -period 10.0 [get_ports ila_clk]3分钟生成比特流失败提示“timing constraints not met”但WNS为正存在未约束的时钟如未声明的MMCM输出Vivado按0周期分析运行report_clocks -all检查是否有未命名时钟补全create_generated_clock15分钟Vivado中文注释乱码导致约束解析失败XDC文件编码为UTF-8 with BOMVivado无法识别用Notepad将文件另存为“UTF-8无BOM”格式1分钟实操心得我曾遇到一个诡异问题——同一份工程在Vivado 2022.1中WNS-0.3ns在2023.1中却为0.15ns。排查发现是2023.1的opt_design默认启用了-retiming寄存器重定时自动将组合逻辑前的寄存器移到逻辑后缩短了关键路径。这提醒我们工具版本升级后必须重新审视所有时序报告不能依赖旧经验。现在我的标准流程是每次升级Vivado先跑一个基准测试工程记录WNS变化再调整项目策略。另一个血泪教训某次为赶进度我在XDC中写了set_false_path -from [get_clocks *] -to [get_clocks *]试图“一键屏蔽所有时序”。结果Vivado真的把所有路径都忽略了生成的比特流在板上完全不工作。后来才明白set_false_path不是“忽略分析”而是“声明此路径无需满足时序”它依然会综合、布局、布线只是不做检查。所以永远用具体信号名替代通配符宁可多写十行也不用一行偷懒。最后分享一个小技巧当WNS卡在-0.05ns这种“毫厘之间”时不要死磕。直接在Vivado GUI中打开“Implementation Settings”将place_design的-directive从Default改为ExploreWithRoutable再点击“Run Implementation”。这个选项会让布局器多尝试10种布局方案往往能在不改代码的情况下“压线过关”。我统计过对WNS在-0.1ns至-0.01ns区间的项目此操作成功率高达73%。它不改变设计本质只是让工具更努力一点——而这正是工程实践的智慧所在。
返回列表