尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

FPGA时序约束实战指南:从原理到调试的完整方法论

FPGA时序约束实战指南:从原理到调试的完整方法论 1. 项目概述为什么时序约束是FPGA设计的“交通规则”做FPGA开发这些年我见过太多项目卡在最后一步——时序不收敛。代码仿真都过了功能逻辑也对可一上板子就是跑不到想要的频率或者干脆跑飞了。问题往往就出在时序约束上。你可以把FPGA内部的逻辑电路想象成一个超级复杂的城市交通网而时序约束就是这套交通网的“红绿灯”和“限速标志”。没有它所有信号车辆都想怎么跑就怎么跑结果必然是拥堵建立时间违例和追尾保持时间违例整个系统瘫痪。这个“终章”不是说要终结这个话题而是想把我踩过的坑、总结的经验系统地串起来形成一个完整的、能直接上手的约束方法论。网上很多资料要么太理论只讲SDC语法要么太零散只解决某个具体问题。我希望这篇内容能帮你建立起从理解时钟结构、到编写约束、再到分析报告和调试违例的完整闭环。无论你是在处理高速DDR接口、千兆以太网还是复杂的多时钟域设计这套思路都能用得上。2. 时序约束的核心思想与设计流程定位2.1 约束的本质与工具对话而非命令工具新手常有一个误区认为时序约束是给设计“上枷锁”是限制工具发挥的条条框框。恰恰相反时序约束是你与综合、布局布线工具之间的一份“设计合同”。你通过约束告诉工具“我的设计需要在这个时钟频率下稳定工作信号从A点到B点不能超过这个时间这个时钟和那个时钟之间有如下关系。” 工具如Vivado、Quartus的职责就是调动所有优化策略逻辑复制、寄存器平衡、布局优化等努力去满足这份合同。如果没有这份合同工具会默认一个非常宽松的通常是几百年才跑一个周期的时钟周期它只需要保证逻辑正确根本不会去优化你的时序。结果就是一个本来能跑200MHz的设计可能连50MHz都稳不住。所以约束不是可选项而是高质量FPGA设计的必选项。2.2 约束在设计流程中的位置一个规范的FPGA开发流程中时序约束应该何时介入绝不是等到布局布线后才想起来加。我的习惯流程是这样的设计初期架构阶段在画框图、定接口时就要同步考虑时钟架构。有几个时钟域它们之间是什么关系同步、异步接口上的数据速率是多少这些问题的答案直接决定了后续约束的框架。编码与综合阶段在编写RTL代码的同时或之后就要开始编写基础的约束文件.xdc或.sdc。至少要先定义好所有的时钟create_clock和时钟组set_clock_groups。在综合Synthesis后就可以进行一次初步的时序分析检查时钟定义是否有明显问题。实现与迭代阶段布局布线Implementation后进行详细的时序分析。此时99%的时序违例会暴露出来。你需要根据报告反复调整约束如调整set_input_delay/set_output_delay的值、添加set_max_delay等或优化RTL代码如打拍、流水线、重定时再进行新一轮的实现直到时序收敛。签核阶段在最终生成比特流前必须确保所有时序路径包括建立时间、保持时间都满足要求并且没有无法分析的异步路径通常表现为“无约束”或“跨时钟域”警告。这是项目可以“交付”的标志。注意千万不要有“先实现功能再优化时序”的想法。时序问题必须与功能开发并行处理越早考虑后期付出的代价越小。一个糟糕的时序架构到后期可能迫使你大规模重构代码成本极高。3. 时钟约束一切时序分析的基石时钟是时序参考的坐标原点。如果时钟定义错了后续所有分析都是空中楼阁。3.1 主时钟Primary Clock的定义主时钟通常指从FPGA器件外部晶振、连接器或内部硬核如PLL、MMCM的输出进入FPGA时钟网络的时钟源。使用create_clock命令定义。# Vivado XDC 示例 # 定义板卡上输入的50MHz主时钟连接到FPGA的AD11引脚 create_clock -name sys_clk -period 20.000 [get_ports sys_clk_p] # -period 单位是ns20ns对应50MHz # -name 给这个时钟起个名字后续约束会用到 # [get_ports ...] 指定时钟输入的物理引脚这里的关键是-period的取值。它直接定义了工具努力优化的目标。如果你希望设计跑100MHz这里就设10ns。工具会努力让所有相关路径的延迟都小于10ns减去寄存器的建立时间。3.2 生成时钟Generated Clock与时钟分频/倍频生成时钟是由设计内部逻辑如寄存器、PLL/MMCM产生的时钟。必须明确其与源时钟Source Clock的关系。对于PLL/MMCM输出的时钟现代工具通常能自动识别和约束。但为了清晰和可控我建议手动约束# 假设 clk_wiz_0 实例化了一个MMCM输出了 clk_out1 (100MHz) 和 clk_out2 (200MHz) # 主时钟输入 clk_in1 为 50MHz已定义 create_clock -name clk_100m -period 10.000 [get_pins clk_wiz_0/inst/clk_out1] create_clock -name clk_200m -period 5.000 [get_pins clk_wiz_0/inst/clk_out2]对于寄存器分频产生的时钟必须使用create_generated_clock# 一个简单的2分频电路 reg div2_clk; always (posedge sys_clk) div2_clk ~div2_clk; # 约束定义生成时钟源为 sys_clk在寄存器 div2_clk 的Q端产生分频比为2 create_generated_clock -name clk_div2 \ -source [get_ports sys_clk] \ -divide_by 2 \ [get_pins div2_clk_reg/Q]实操心得尽量避免使用寄存器分频产生时钟。这会引入额外的时钟偏移Skew和抖动Jitter并产生难以约束的时钟域交叉CDC路径。优先使用时钟使能Clock Enable在同一个时钟域下处理不同速率的数据流。如果必须用务必用create_generated_clock约束清楚。3.3 虚拟时钟Virtual Clock与I/O约束的桥梁虚拟时钟是一个不存在于任何物理引脚或网络上的“参考时钟”。它主要用于约束FPGA与外部芯片如DDR颗粒、ADC、DAC、处理器的接口时序。为什么需要它因为外部芯片的时钟比如DDR的CK并没有连接到FPGA的时钟输入引脚上但我们又需要以那个时钟为基准来计算FPGA引脚上数据的输入/输出延迟。这时就需要创建一个与之同频同相的虚拟时钟。# 假设外部DDR芯片的时钟是200MHz但该时钟线CK只连接到DDR颗粒未连入FPGA create_clock -name vclk_ddr -period 5.000 # 这个 vclk_ddr 就是一个虚拟时钟周期5ns200MHz后续在约束DDR的DQ数据线时就会以这个vclk_ddr为参考使用set_input_delay和set_output_delay。3.4 时钟组与异步时钟域声明这是约束中最容易出错也最危险的地方之一。你必须明确告诉工具哪些时钟之间是同步的有确定的相位关系工具需要分析时序哪些是异步的工具不需要分析它们之间的路径。# 声明两个主时钟 clkA 和 clkB 是异步的 set_clock_groups -asynchronous -group {clkA} -group {clkB} # 声明一个生成时钟与其源时钟是同步的但与其他时钟异步 # 通常工具默认生成时钟与源时钟同步无需额外声明。但显式声明更清晰。 # set_clock_groups -asynchronous -group {clk_100m} -group {clk_200m}关键点对于异步时钟域交叉Asynchronous CDC路径你必须在RTL层面做好同步处理如双寄存器同步、异步FIFO。然后通过set_clock_groups或set_false_path告诉时序分析工具“别管这条路”否则工具会报出无法满足的时序违例或者更糟它试图去优化一条本不该优化的路径反而破坏了你的同步电路。踩坑记录我曾遇到一个项目两个时钟来自不同的晶振本应是异步的。但忘记加set_clock_groups -asynchronous约束。工具疯狂地优化这两个时钟域之间的几条无关紧要的路径导致布局布线异常拥挤反而影响了主要逻辑的时序。加上异步声明后工具忽略那些路径整体时序立刻变好。4. I/O接口约束与外部世界握手的关键FPGA不是孤岛总要和ADC、DAC、DDR、CPU等外部器件通信。I/O约束就是定义这些通信协议的时序规则。4.1 输入延迟set_input_delay深度解析set_input_delay指定的是从外部芯片时钟沿触发到数据信号到达FPGA输入引脚的这段时间。这个延迟包含了外部芯片的Tco时钟到输出延迟和PCB板上的走线延迟。其约束是基于一个参考时钟的这个时钟通常是捕获数据的FPGA内部时钟或者是与之相关的虚拟时钟。# 场景FPGA通过SPI从一颗ADC读取数据。 # FPGA使用 clk_spi (50MHz) 去采样ADC输出的 data 信号。 # 已知ADC芯片手册给出在SCLK边沿后最大 Tco_max 8ns最小 Tco_min 2ns。 # PCB走线延迟估算为 1ns。 # 那么相对于 FPGA 的 clk_spi 时钟 # 最大输入延迟 Tco_max 板级延迟 8ns 1ns 9ns (用于检查建立时间) # 最小输入延迟 Tco_min 板级延迟 2ns 1ns 3ns (用于检查保持时间) # 假设 clk_spi 已定义且与ADC的SCLK同源同相 set_input_delay -clock clk_spi -max 9.000 [get_ports adc_data] set_input_delay -clock clk_spi -min 3.000 [get_ports adc_data]工具如何工作工具会计算clk_spi的时钟沿到达FPGA内部寄存器的时间加上这个寄存器的建立时间要求Tsu。然后要求时钟到达时间 Tsu 数据到达时间 输入延迟_max。这里“数据到达时间”就是信号从FPGA引脚经过IO Buffer和内部走线到达寄存器D端的时间。通过这个不等式工具就能推算出内部路径允许的最大延迟。4.2 输出延迟set_output_delay深度解析set_output_delay指定的是数据信号从FPGA输出引脚发出后到被外部芯片时钟沿捕获所允许的时间余量。它定义了数据必须提前多久稳定在引脚上。# 场景FPGA通过并行总线向一颗DAC发送数据。 # 外部DAC使用 clk_dac (100MHz) 的上升沿锁存数据。 # DAC芯片手册要求数据在时钟沿前的建立时间 Tsu_dac 2ns保持时间 Th_dac 1ns。 # PCB走线延迟估算为 1.5ns。 # 那么相对于一个与 clk_dac 同频同相的虚拟时钟 vclk_dac # 输出延迟_max Tsu_dac 板级延迟 2ns 1.5ns 3.5ns # 输出延迟_min -Th_dac 板级延迟 -1ns 1.5ns 0.5ns # 注意最小输出延迟可能是负数表示数据在时钟沿之后还需要保持一段时间。 create_clock -name vclk_dac -period 10.000 ;# 创建虚拟时钟 set_output_delay -clock vclk_dac -max 3.500 [get_ports dac_data*] set_output_delay -clock vclk_dac -min 0.500 [get_ports dac_data*]工具如何工作工具会计算vclk_dac的时钟沿在外部芯片处然后要求数据在FPGA引脚上的切换时间必须满足外部芯片的建立和保持时间要求。这反过来约束了FPGA内部从寄存器到输出引脚的路径延迟。4.3 系统同步与源同步接口的约束差异这是两个最重要的接口类型约束思路完全不同系统同步System SynchronousFPGA和外部器件共享同一个时钟源。双方的时序都以这个公共时钟为参考。上面的SPI、并行DAC例子就是典型的系统同步。约束时输入/输出延迟的参考时钟就是FPGA内部使用的那个共享时钟或与之同相的时钟。源同步Source Synchronous时钟或选通信号由发送数据的一方源随数据一起发送。比如DDR的DQS信号随DQ数据一起发送千兆以太网的RX_CLK随数据一起进来。这是高速接口的主流方案。关键点此时随路时钟DQS和数据DQ在PCB上是等长匹配的它们在到达FPGA引脚时相对相位关系是固定的。约束方法通常不需要对随路时钟create_clock而是将其视为一个普通数据信号。然后在约束数据信号DQ的set_input_delay时使用-clock_fall、-add_delay等选项来分别约束上升沿和下降沿采样的数据。更现代的方法是使用工具提供的专用IP如Xilinx的SelectIO Wizard或约束向导它们会自动生成复杂的约束处理时钟相位对齐IDELAY/ISERDES。5. 时序例外指导工具聚焦关键路径默认情况下工具会尝试优化设计中所有寄存器之间的路径。但有些路径我们不需要优化或者无法优化这时就需要使用时序例外Timing Exception。5.1 虚假路径set_false_path告诉工具这条路径根本不存在或者不需要满足任何时序要求请完全忽略它。典型应用场景跨异步时钟域CDC路径在已做好同步处理后应设为虚假路径。set_false_path -from [get_clocks clkA] -to [get_clocks clkB]上电复位或测试逻辑这些路径只在特定时刻工作正常功能运行时不需要考虑。静态配置信号比如通过SPI配置完就再也不变的寄存器输出。注意滥用set_false_path很危险。如果你错误地将一条真实的功能路径设为虚假路径工具就不会优化它可能导致实际电路在高速下失效。务必确认路径真的不需要时序检查。5.2 多周期路径set_multicycle_path告诉工具这条路径的数据不需要在单个时钟周期内稳定允许它用多个周期来完成传输。典型应用场景微处理器访问慢速外设如Flash。迭代计算单元如一个乘法器需要3个周期才能出结果。故意引入流水线打拍来改善时序但功能上允许延迟。# 一个使能信号 en 由 clk_fast (100MHz) 产生用于采样 clk_slow (10MHz) 域的信号 slow_data # 功能上en每10个快时钟周期有效一次采样一次慢时钟数据。 # 因此从 clk_fast 到 slow_data 捕获寄存器的路径有10个周期的宽松时间。 set_multicycle_path -from [get_clocks clk_fast] -to [get_clocks clk_slow] -setup 10 set_multicycle_path -from [get_clocks clk_fast] -to [get_clocks clk_slow] -hold 9 # -hold 的值通常是 -setup 的值减1这是因为保持时间检查是基于启动沿的。关键理解-setup N意味着工具将建立时间检查的时钟周期放宽到N个周期。-hold约束也必须相应调整否则会导致保持时间检查过于严格。理解“启动沿Launch Edge”和“捕获沿Capture Edge”是掌握多周期路径约束的关键。5.3 最大/最小延迟路径set_max_delay / set_min_delay直接给某条路径规定一个具体的延迟上限或下限而不是基于时钟周期来计算。这是一种更直接、更灵活的约束方式尤其适用于组合逻辑路径。异步信号经过同步器之前的路径需要约束其最大延迟防止亚稳态恢复时间不足。对某些关键路径进行特别严格的约束。# 约束一个特定的组合逻辑路径从模块A的out到模块B的in延迟不能超过15ns set_max_delay -from [get_pins moduleA/out_reg/C] -to [get_pins moduleB/in_reg/D] 15.000 # 约束一个异步复位信号从输入引脚到所有寄存器复位端的最大延迟确保复位释放基本同步 set_max_delay -from [get_ports async_rst] -to [all_registers] -datapath_only 5.0006. 时序分析实战从报告到问题定位写完约束只是开始更重要的是能看懂时序报告并据此进行调试。6.1 读懂时序摘要Timing Summary实现后的报告通常会给出一个“时序摘要”列出所有时序路径组Clock Group的最差裕量Worst Negative Slack, WNS和总违例路径数Total Negative Slack, TNS。WNS所有路径中最紧张的那条路径还差多少时间满足要求。正值表示满足有裕量负值表示违例欠裕量。TNS所有违例路径的时序欠裕量之和。它反映了时序问题的严重程度。 你的首要目标是将所有路径组的WNS和TNS都变为正数或零。6.2 分析最差路径Worst Path点击WNS为负的时钟组查看最差路径详情。报告会详细列出起点Launch Register和终点Capture Register。数据路径延迟Data Path Delay逻辑延迟Logic Delay 布线延迟Net Delay。时钟路径延迟Clock Path Delay从时钟源到起点寄存器的时钟延迟Source Latency 从时钟源到终点寄存器的时钟延迟。时钟偏斜Clock Skew起点和终点时钟到达时间的差值。**建立/保持时间要求Requirement**和实际到达时间Arrival Time。如何判断问题根源如果逻辑延迟占比很高说明组合逻辑太复杂需要优化代码插入流水线寄存器Pipeline来切割关键路径。如果布线延迟占比很高说明布局不好寄存器被工具放得太远。可以尝试增加布局约束如PBLOCK将相关逻辑锁在一起。使用register_duplication寄存器复制来减轻高扇出网络的负载。优化物理约束将关键模块放在靠近输入/输出的位置。如果时钟偏斜很大检查时钟约束是否合理时钟网络负载是否均衡。有时需要手动插入时钟缓冲器BUFG或调整时钟布局。6.3 增量编译与物理优化策略当设计规模很大只修改了局部代码时使用**增量编译Incremental Compile**可以极大地节省实现时间。它会尽量复用之前实现结果的布局布线信息。操作流程完成一次完整的实现布局布线并保存设计检查点Design Checkpoint, DCP。修改RTL或约束后在实现设置中指定之前保存的DCP作为增量编译的参考。重新运行实现。工具会尽量保持未修改部分的布局布线只对修改部分及其受影响区域进行重新优化。物理优化技巧手动布局Floorplanning对于高速模块如DDR控制器、SerDes手动规划其在FPGA芯片上的区域减少关键路径的走线距离。使用高驱动强度High Drive Strength的IO标准对于输出到重负载的引脚可以降低输出延迟。调整综合策略Synthesis StrategyVivado中可以选择“Performance_Explore”等更激进的综合策略但会延长编译时间。调整布局布线策略Implementation Strategy同样可以选择更注重性能的策略如“Performance_ExplorePostRoutePhysOpt”。7. 高级约束与特殊场景处理7.1 时序约束与时钟域交叉CDC验证时序约束和CDC验证是相辅相成的。静态时序分析STA解决同步时序问题CDC验证解决异步时序问题。流程先用set_clock_groups -asynchronous或set_false_path约束掉异步路径让STA通过。然后使用专门的CDC验证工具如SpyGlass CDC、JasperGold或Vivado的CDC报告功能检查你的同步电路双寄存器、异步FIFO、握手信号是否满足消除亚稳态的要求。常见CDC错误单比特信号跨时钟域未同步、多比特信号直接同步导致数据错拍、异步复位未做同步释放等。这些错误无法通过时序约束解决必须在RTL层面杜绝。7.2 接口约束的自动化与脚本化对于复杂的标准接口如DDR3/4、PCIe、SGMII手动编写约束既繁琐又易错。最佳实践是使用IP核Xilinx的MIGMemory Interface Generator、UltraScale的High-Speed SelectIO Wizard等IP在生成时会自动附带完整的约束文件.xdc。直接使用这些约束是最可靠的。编写Tcl脚本将常用的约束命令如创建时钟、设置I/O延迟封装成带参数的Tcl过程proc。这样在新项目中只需修改几个参数即可复用大大提高效率和一致性。版本管理约束文件.xdc和生成约束的Tcl脚本必须和RTL代码一样纳入版本控制系统如Git进行管理。7.3 时序约束在FPGA配置与在线升级中的角色在FPGA应用中有时需要动态切换配置如Multiboot或进行局部重配置Partial Reconfiguration。时序约束在这些场景下依然至关重要。Multiboot多个比特流文件存储在外部Flash中。主配置加载第一个镜像该镜像运行后可以触发加载第二个镜像。关键点两个镜像的约束必须兼容特别是时钟引脚、高速接口引脚的定义必须一致否则切换后硬件接口可能无法工作。局部重配置只改变FPGA内部某个区域的功能其余部分保持运行。关键点必须为可重配置区域RM和静态区域分别制定严格的时序约束。静态区域与RM接口的信号必须被正确约束通常使用set_false_path或set_max_delay以确保在RM切换时静态逻辑的时序不受影响。这需要精心的平面布局规划和接口时序约束。8. 常见问题排查与调试技巧实录这里记录了几个我实际项目中遇到的典型时序问题及解决方法。8.1 问题保持时间Hold Time违例且集中在IO附近现象建立时间Setup Time裕量很好但保持时间Hold出现大量违例违例路径的终点多是输入引脚附近的寄存器。分析这通常是因为set_input_delay -min的值设置得太小或为0给FPGA内部预留的保持时间窗口太苛刻。-min约束的是外部器件输出数据的最小延迟Tco_min 板级延迟_min。如果你把这个值估小了工具就会认为外部数据变化太快为了满足保持时间它必须增加数据从引脚到寄存器的延迟即插入延迟。但IO到寄存器本身的延迟很短工具很难再增加。解决重新检查外部芯片手册的Tco_min参数和PCB延迟的最小值。确保set_input_delay -min的值是合理且保守的。如果无法确定可以适当增大-min的值比如增加0.5-1ns给内部留出更多余量。在Vivado中可以对特定输入引脚使用set_input_delay -clock_fall -min ...来分别约束上升沿和下降沿有时能更精确地匹配实际接口。8.2 问题高扇出网络导致时序违例现象一个信号如复位信号、使能信号、地址线驱动了成百上千个寄存器导致该网络的布线延迟巨大成为关键路径。分析高扇出会增加布线负载从而增加网络延迟Net Delay。工具默认会尝试复制驱动寄存器来降低扇出但有时优化不足。解决手动寄存器复制Register Duplication在RTL代码中手动将这个高扇出信号用多个寄存器来产生每个寄存器驱动一部分负载。// 原始代码一个复位信号驱动所有逻辑 always (posedge clk) begin if (rst) begin reg_a 0; reg_b 0; // ... 很多寄存器 end end // 优化后复制复位驱动寄存器 reg rst_dup1, rst_dup2; always (posedge clk) begin rst_dup1 rst; rst_dup2 rst; end // 用 rst_dup1 驱动一部分逻辑用 rst_dup2 驱动另一部分逻辑使用综合属性在Vivado中可以在RTL代码或XDC中使用MAX_FANOUT属性来指导综合工具。(* MAX_FANOUT 50 *) reg high_fanout_signal; // Verilog 语法set_property MAX_FANOUT 50 [get_nets high_fanout_net] ;# XDC 语法使用全局缓冲BUFG对于真正的全局时钟、复位信号应该使用芯片专用的全局时钟网络通过BUFG驱动其延迟小、偏斜低。但BUFG资源有限不能滥用。8.3 问题跨时钟域路径未被正确约束导致工具过度优化现象时序报告中出现大量无法满足的跨时钟域路径违例或者工具运行时间异常长试图优化这些路径。分析没有对异步时钟域进行声明set_clock_groups -asynchronous或设置虚假路径set_false_path。解决仔细检查设计中的所有时钟明确它们的来源和关系。对于确定是异步的时钟对使用set_clock_groups -asynchronous进行声明。这是最推荐的方式一劳永逸。对于少数特定的、已知的异步路径可以使用set_false_path -from [get_clocks clkA] -to [get_clocks clkB]。在约束之后务必检查时序报告中的“Clock Interaction”或“Inter-Clock Paths”部分确认异步时钟域之间已被标记为“无路径No Path”或“虚假路径False Path”。8.4 问题I/O约束后时序依然不满足现象按照芯片手册计算了set_input_delay/set_output_delay但接口时序仍然违例。排查步骤检查时钟定义确认参考时钟虚拟时钟或内部时钟的频率、相位与外部芯片的时钟完全一致。一个常见的错误是忽略了时钟的占空比或反相关系。检查PCB延迟估算set_input_delay/set_output_delay中的板级延迟是估算值。如果实际PCB走线很长或阻抗不匹配实际延迟会更大。可以使用SI信号完整性仿真工具获取更精确的延迟值或在约束中留出更多余量Margin比如额外增加10%-20%的延迟值。检查数据与时钟的相位关系对于源同步接口如DDR数据和随路时钟DQS的相位关系是关键。可能需要使用set_input_delay的-clock_fall选项或使用set_input_delay和set_output_delay的-add_delay选项来分别约束上升沿和下降沿的数据。使用工具的分析功能Vivado的“Report Timing Summary”可以生成详细的接口时序报告。查看“Input/Output Delay”部分分析数据到达时间、时钟到达时间以及它们之间的差值Slack。结合波形图可以直观地看到是否满足建立/保持时间。考虑使用专用硬件对于非常高速的接口如DDR4、PCIe Gen3以上FPGA的普通IO可能无法满足时序要求。这时必须使用芯片内嵌的专用硬件资源如Xilinx的HP/HR Bank、SelectIO逻辑ISERDES/OSERDES以及对应的IP核它们经过硅片验证能提供最优的时序性能。时序约束是一门实践性极强的学问看再多的理论也不如亲手调试一个不收敛的设计来得深刻。我的建议是从一个简单的项目开始比如用FPGA驱动一个LED然后逐步加上UART、SPI、SDRAM等外设每加一个模块就学习并应用相应的约束。遇到报错不要怕仔细读报告理解工具告诉你的信息。久而久之你就能建立起一种“时序直觉”在写代码的时候就能预见到潜在的时序问题从而写出更健壮、更高性能的FPGA设计。记住好的约束是设计出来的不是调试出来的。
返回列表