10、布局规划(Floorplanning):静态区域的物理约束、动态区域的Pblock分配、资源利用率预估

布局规划,说白了就是给芯片画地皮。

你想想看,一个FPGA芯片上那么多资源——LUT、DSP、BRAM、FF——你得决定哪块逻辑放哪。特别是做动态部分重构,这事儿就更讲究了。静态区域和动态区域不能打架,否则重构的时候,轻则报错,重则跑飞。

我个人习惯,在开始写RTL之前,先把Floorplanning画个七七八八。别等到综合完了再调,那时候改起来,真叫一个痛苦。

10.1 静态区域的物理约束

静态区域,就是那些永远在线、不参与重构的逻辑。比如时钟管理、复位同步、通信接口、控制状态机。这些逻辑必须固定位置,不能因为重构而受影响。

静态区域的核心约束:

  • 锁定位置:用 set_property LOC 把关键单元钉死在特定SLICE或Pblock里。
  • 避免跨区域路径:静态逻辑和动态逻辑之间的接口,必须走专用的静态总线或寄存器桥。我见过有人直接把动态模块的信号拉到静态区域,结果重构时信号毛刺满天飞。
  • 时钟域隔离:静态区域的时钟树不要穿过动态Pblock。否则重构时时钟抖动会传染。

经验之谈:我在一个项目中,静态区域里放了AXI互联和DDR控制器。当时没注意,把DDR的时钟缓冲放到了动态区域附近。结果每次重构完,DDR读写就偶尔出错。后来把时钟缓冲挪到静态区域正中央,问题就消失了。

10.2 动态区域的Pblock分配

Pblock,就是动态模块的“地盘”。每个可重构分区(RP)都需要一个独立的Pblock。分配Pblock时,有几个硬性指标:

  1. 形状尽量方正:长方形或正方形最好。L型、T型Pblock会导致布线资源浪费,综合工具容易报“资源不足”。
  2. 包含完整资源列:FPGA的DSP和BRAM是按列分布的。如果你的动态模块用了DSP,Pblock必须覆盖整列DSP资源,不能只切一半。
  3. 预留10%-20%余量:别把Pblock塞得满满当当。综合工具在布局时需要有“呼吸空间”。我一般留15%的余量,很少遇到布局失败。

小技巧:在Vivado里,用 create_pblock 命令创建Pblock后,立刻用 resize_pblock 调整边界。我习惯先画一个比预估大20%的框,然后慢慢往里缩,直到工具报错为止。这样能找到最紧凑的边界。

10.3 资源利用率预估

资源预估,不能光看RTL综合报告。综合报告的数字是“理想状态”,实际布局布线后,资源占用会多出10%-30%。

我常用的预估方法:

  • 按模块粒度统计:把每个动态模块的LUT、FF、DSP、BRAM分别列出来。别只看总和,要看峰值。比如一个模块用了100个DSP,另一个用了50个,但两个模块不会同时运行,那Pblock里只需要放100个DSP的资源。
  • 考虑布线资源:LUT和FF的占用率不要超过70%。超过这个数,布线器就会开始绕远路,时序很难收敛。
  • BRAM和DSP要单独算:这两种资源是列状分布的。如果Pblock只覆盖了2列BRAM,但你的模块需要3列,那就算每列只用了10%,也放不下。必须扩大Pblock的列数。

注意:我曾经在一个项目里,预估动态模块用了40%的LUT,结果实际布局时发现LUT利用率到了65%。原因是综合工具把一些查找表逻辑优化成了分布式RAM,占用了额外的资源。所以,一定要在综合后、布局前,跑一次 report_utilization 确认。

10.4 知识体系结构图

下面这张图,把布局规划的核心逻辑串起来了。静态区域、动态Pblock、资源预估,三者互相影响。

布局规划(Floorplanning)核心逻辑 静态区域约束 • 锁定关键单元位置 • 避免跨区域路径 • 时钟域隔离 • 专用接口桥接 动态Pblock分配 • 形状方正 • 覆盖完整资源列 • 预留10%-20%余量 • 每个RP独立Pblock 资源利用率预估 • 按模块粒度统计 • LUT/FF占用率<70% • BRAM/DSP按列计算 • 综合后确认实际值 三者关系 静态区域划定边界 → Pblock分配动态区域 → 资源预估验证可行性 常见坑点 • Pblock形状不规则导致布线失败 • 资源预估忽略布线资源 • 静态区域时钟穿过动态Pblock • 未预留余量导致布局失败

10.5 实际操作中的避坑指南

嗯,这里要注意。布局规划不是一次搞定的。我通常要迭代3-5轮。

第一轮:根据RTL综合报告,画一个大概的Pblock。这时候别太细,先看能不能跑通。

第二轮:跑一次PR(部分重构)流程,看工具报什么错。常见错误是“Pblock资源不足”或“跨区域路径未约束”。

第三轮:根据错误调整Pblock边界,或者挪动静态区域的关键单元。有时候需要把某个DSP从静态区域移到动态区域,或者反过来。

我曾经遇到一个项目,动态模块用了大量移位寄存器(SRL)。SRL在FPGA里是占用LUT资源的,但综合报告里把它算在LUT里,没单独列出来。结果Pblock的LUT利用率到了85%,布局器直接罢工。后来我把Pblock扩大了两列CLB,才解决问题。所以,资源预估一定要看 report_utilization -hierarchical 的详细报告,别只看汇总。

10.6 资源利用率预估表格

下面这个表格,是我做项目时常用的预估模板。每个动态模块单独一行,最后汇总。

模块名称 LUT FF DSP BRAM 备注
RP_0(图像处理) 8500 6200 24 12 含SRL,LUT需多估15%
RP_1(通信协议) 3200 2800 0 4 逻辑为主,资源稳定
RP_2(加密加速) 12000 9800 48 8 DSP密集,注意列对齐
合计 23700 18800 72 24 预留20%余量后约28440 LUT

你看,光看合计还不够。RP_2的48个DSP,如果Pblock只覆盖了2列DSP(每列24个),那就刚好够。但如果覆盖了3列,但其中一列只有16个,那就不够。所以,资源分布比资源总数更重要

我的习惯:在Vivado里打开Device视图,把Pblock画好后,用 report_utilization -pblock pblock_name 查看每个Pblock的资源占用。如果某个资源类型利用率超过70%,我就开始警惕了。超过80%,基本要调整Pblock边界。

布局规划这事儿,说白了就是“先画圈,再填内容,最后微调”。静态区域是地基,动态Pblock是房间,资源预估是测量家具尺寸。地基不稳,房间歪了,家具塞不进去——整个项目就得返工。所以,花时间在Floorplanning上,绝对值得。