1. 功耗问题从来不是小事:从一个真实翻车案例说起
去年帮一个朋友救火,他们团队做了一款基于 Zynq-7000 的边缘网关板卡,样机在实验室跑得好好的,一到现场批量部署就出问题:外壳摸上去烫手,红外测温枪一打,FPGA 结温直奔 95 度;更离谱的是,原本设计续航 8 小时的设备,实际撑不到 3 个半小时就低电告警。硬件同事第一反应是散热片太小,换了更大的铝块,温度降了 5 度,续航几乎没变。后来把功耗拆开一测才发现,动态功耗里时钟树占了大头,BRAM 和 DSP 的静态偏置也在持续漏电,散热只是把热量搬走,根本没解决“电去哪了”的问题。
这个场景在 FPGA 项目里太常见了。很多人做设计时盯着时序收敛、资源利用率、功能正确性,功耗往往是最后才想起来的事,甚至压根没纳入验收指标。但现实是,FPGA 的功耗直接决定三件事:结温是否安全、电池能撑多久、系统长期运行是否稳定。尤其是现在大量项目往边缘侧走——边缘网关、通信测试终端、便携式图像处理设备、车载采集板——这些场景没有风扇、没有大电源,功耗超标就是致命伤。
这篇文章面向的是有一定 FPGA 开发基础、正在做实际项目、被功耗问题困扰过的工程师。我会把功耗优化拆成五个可落地的硬核技巧,从时钟门控到 BRAM 管理,从 IO 标准选择到工具链分析,每个技巧都讲清楚为什么有效、怎么操作、实测效果如何、容易踩什么坑。不是理论科普,是我自己在项目里反复验证过的东西。如果你正在被“FPGA 发烫、续航崩、功耗超标”这三座大山压着,下面的内容应该能帮你省下不少试错时间。
2. 先搞清楚功耗从哪来:不测量就优化等于瞎猜
2.1 FPGA 功耗的三个组成部分
在动手优化之前,必须建立一个基本认知:FPGA 的功耗不是单一来源,它由三块构成,每块的优化手段完全不同。
静态功耗(Static Power)是器件上电就存在的漏电流功耗,跟你的逻辑设计关系不大,主要取决于工艺节点、结温和供电电压。28nm 工艺的 FPGA 静态功耗通常在几百毫瓦量级,16nm 会低一些,但老一些的 65nm 器件可能到 1W 以上。静态功耗随温度上升而增加,这就形成了一个正反馈:温度高导致漏电大,漏电大导致温度更高。所以散热设计不只是“把热排出去”,也是在切断这个恶性循环。
动态功耗(Dynamic Power)是信号翻转产生的功耗,公式是 P = α × C × V² × f。其中 α 是翻转率,C 是负载电容,V 是供电电压,f 是时钟频率。注意电压是平方项,所以降压的收益非常显著,但 FPGA 的核心电压通常由器件规格决定,可调空间有限。真正能动手的是翻转率 α、电容 C 和频率 f。时钟门控降的是 α,资源复用降的是 C,降频降的是 f。
IO 功耗(IO Power)经常被忽略,但在高速接口多的设计里占比很可观。每个 IO 的功耗取决于标准(LVCMOS、LVDS、SSTL 等)、驱动强度、翻转率和外部负载。一个 LVDS 对在几百 MHz 下翻转,功耗可能比内部一堆逻辑还大。
2.2 用工具把功耗“看见”
优化功耗的第一步不是改代码,是测量。Xilinx 的 Vivado 里有Report Power功能,综合实现之后可以生成功耗报告,分为 Vectorless 和 Vector-based 两种。Vectorless 不需要仿真数据,工具根据默认翻转率估算,精度一般但胜在快;Vector-based 需要导入 SAIF 或 VCD 文件,精度高很多,适合做最终验收。
具体操作流程是这样的:在 Vivado 里跑完 implementation,打开综合后的设计,点击 Report Power,选择输入 SAIF 文件(如果有仿真波形的话)。SAIF 文件通过仿真时在 testbench 里调用$set_toggle_region和$toggle_start/$toggle_stop生成。没有仿真数据的话,至少要把默认翻转率从 12.5% 改成你实际估计的值,否则报告会严重偏离。
Intel(Altera)平台对应的是PowerPlay Power Analyzer,逻辑类似,在 Quartus 里通过 Processing 菜单进入。它同样支持 Vectorless 和基于 VCD 的仿真驱动模式。
注意:功耗报告里的数字是估算值,不是实测值。它的价值在于相对比较——你改了一版设计,功耗报告显示动态功耗降了 30%,那实际板子上大概率也会降。但绝对值不要全信,最终还是要用电流探头或功耗分析仪实测。
2.3 建立功耗基线:优化前的必修课
我见过太多人一上来就改代码,改完发现功耗没降多少,也不知道是改错了还是本来就没空间。正确做法是先建立基线:记录当前设计的总功耗、静态功耗、动态功耗、各时钟域功耗、各资源类型功耗。Vivado 的功耗报告会按 Clock、Logic、BRAM、DSP、IO 等分类列出,这张表就是你后续优化的记分牌。
基线数据建议记录成表格,每次改动后对比。下面是我在一个图像处理项目里的基线示例(Zynq-7020,25°C 环境,核心电压 1.0V):
| 功耗类别 | 基线值 (W) | 占比 |
|---|---|---|
| 静态功耗 | 0.18 | 12% |
| 时钟树 | 0.42 | 28% |
| 逻辑资源 | 0.31 | 21% |
| BRAM | 0.26 | 17% |
| DSP | 0.19 | 13% |
| IO | 0.14 | 9% |
| 合计 | 1.50 | 100% |
这张表一眼就能看出问题:时钟树占了 28%,是最大的单一来源。后面的优化重点自然就放在时钟管理上。如果没有这张表,你可能花大量时间去优化 DSP 算法,结果只省了 0.05W,事倍功半。
3. 技巧一:时钟门控与时钟域管理,砍掉最大的功耗来源
3.1 为什么时钟树是功耗大户
时钟信号是 FPGA 里翻转率最高的信号,没有之一。它每个周期都翻转两次(上升沿和下降沿),而且时钟树要驱动成千上万个触发器的时钟端口,负载电容极大。在典型设计里,时钟树功耗能占到动态功耗的 30% 到 40%。更糟糕的是,很多设计里时钟一直在跑,但对应的逻辑大部分时间什么都不做——比如一个图像处理模块,只在帧有效期间工作,帧消隐期间时钟还在空转,白白烧电。
时钟门控的核心思想很简单:不需要工作的模块,把它的时钟停掉。时钟停了,触发器不翻转,动态功耗直接归零。这比任何逻辑优化都来得直接。
3.2 BUFGCE 的正确用法与常见误区
Xilinx 器件里实现时钟门控的标准原语是BUFGCE(Global Clock Buffer with Clock Enable)。它的功能是:CE 为高时输出时钟,CE 为低时输出恒定低电平。用法看起来很简单,但坑不少。
// 正确的 BUFGCE 例化方式 BUFGCE u_bufgce ( .I (clk_in), // 输入时钟 .CE (module_enable), // 时钟使能,来自控制逻辑 .O (clk_gated) // 门控后的时钟 );第一个坑:CE 信号必须是同步的。如果 CE 是异步信号,在它跳变的时候可能产生毛刺,导致下游触发器误触发。正确做法是把 CE 用时钟的相反沿打一拍,或者用专门的时钟使能同步器。
第二个坑:不要用组合逻辑直接生成门控时钟。我见过有人写assign gated_clk = clk & enable;,这在 ASIC 里可能勉强能用,在 FPGA 里是灾难——组合逻辑产生的时钟会走普通布线资源,skew 大、抖动大,时序根本没法收敛。必须用 BUFGCE 或 BUFHCE 这类专用原语。
第三个坑:门控粒度要合理。如果你把时钟门控做得太细,每个小模块一个 BUFGCE,BUFG 资源很快就不够用了(一个器件通常只有几十个 BUFG)。合理的做法是按功能域划分,比如图像采集域、处理域、输出域各一个门控时钟。
3.3 时钟域交叉与门控的配合
门控时钟会引入新的时钟域,跨域信号必须做同步处理。这里有个容易忽略的点:门控时钟关闭时,跨域信号的状态要保持稳定。如果时钟关了,但上游还在往这个域发数据,数据就丢了。所以门控逻辑要和握手协议配合,确保模块进入空闲态之后再关门。
我在一个多端口 DDR 读写项目里用过这样的策略:DDR 控制器有多个端口,每个端口对应一个数据流。当某个端口连续 N 个周期没有读写请求时,就把它的时钟门控关掉。实测下来,在典型负载下(三路视频流,其中一路间歇工作),时钟树功耗从 0.42W 降到了 0.27W,降幅 36%。这个收益非常可观。
实操心得:门控时钟的开关时机要留足余量。我一般设置“空闲 64 个周期后关门,收到请求后立即开门”。关门太激进会导致频繁开关,反而增加控制逻辑功耗;关门太保守则省不了多少电。64 这个数字是实测调出来的,你可以根据自己的业务节奏调整。
4. 技巧二:BRAM 与 DSP 的精细化管理,别让存储器偷偷漏电
4.1 BRAM 的功耗特性与使能控制
BRAM 是 FPGA 里另一个功耗大户,尤其在需要大量缓存的设计里(图像行缓存、FIFO、查找表)。BRAM 的功耗分两部分:读写操作时的动态功耗和待机时的静态偏置功耗。很多人以为 BRAM 不读写就不耗电,这是错的——BRAM 的存储单元需要持续供电维持数据,即使不访问也有漏电。
Vivado 综合出来的 BRAM 默认是始终使能的,只要时钟在跑,它就在耗电。优化手段是使用 BRAM 的EN(使能)端口,只在真正需要读写的时候拉高。具体做法是在例化 BRAM IP 时勾选“Enable Pin”选项,然后在逻辑里控制这个引脚。
// BRAM 使能控制示例 always @(posedge clk) begin if (bram_en) begin if (we) begin ram[addr] <= din; end else begin dout <= ram[addr]; end end end这里的关键是bram_en的生成逻辑。对于 FIFO,可以用“非空或非满”作为使能条件;对于行缓存,可以用“行有效期间”作为使能。我做过一个对比测试:一个 1024×18 的 BRAM,始终使能时功耗约 18mW,加上使能控制后降到 6mW,降幅 67%。如果一个设计里有几十个 BRAM,这个收益就非常大了。
4.2 BRAM 级联与位宽优化
另一个容易被忽略的点是BRAM 的配置方式。FPGA 里的 BRAM 块通常是 36Kb 或 18Kb 的,可以配置成不同的位宽和深度组合。如果你需要一个 512×8 的小缓存,用一个大 BRAM 去实现就是浪费——大 BRAM 的静态功耗比小 BRAM 高。
Vivado 在综合时会自动做 BRAM 映射,但它的策略是优先满足容量,不一定最优功耗。你可以手动指定用 18Kb 模式而不是 36Kb 模式,或者用分布式 RAM(LUTRAM)替代小容量 BRAM。LUTRAM 的静态功耗几乎为零,适合小容量、低频率的缓存场景。
注意:LUTRAM 用的是逻辑资源,会挤占 LUT 预算。如果设计本身 LUT 利用率就很高,用 LUTRAM 可能导致布线拥塞。我的经验是:容量小于 256 深度、位宽小于 16 的缓存,优先考虑 LUTRAM;更大的用 BRAM,但一定要加使能控制。
4.3 DSP 的功耗陷阱与复用策略
DSP 切片在 FPGA 里是硬核资源,功耗相对固定,但也不是没有优化空间。DSP 的功耗主要取决于工作频率和是否在运算。很多设计里 DSP 一直在跑,但输入数据是无效的(比如图像消隐期间),这时候 DSP 的运算结果被丢弃,功耗却照付。
优化手段有两个:一是用使能信号控制 DSP 的 CE 端口,无效数据期间停掉运算;二是时分复用 DSP,用更高的频率跑多个逻辑通道,减少 DSP 实例数量。第二种方法听起来反直觉——频率高了功耗不是更大吗?但实测下来,一个 DSP 在 200MHz 下跑两路复用,比两个 DSP 在 100MHz 下各跑一路,总功耗更低。原因是 DSP 的静态偏置功耗占比较大,减少实例数量比降低频率更有效。
我在一个双线性插值项目里验证过这个结论:原本用 4 个 DSP 并行处理,功耗 0.19W;改成 2 个 DSP 时分复用,频率从 100MHz 提到 200MHz,功耗降到 0.13W。当然,这个策略的前提是时序能收敛,200MHz 对 DSP 路径的时序要求更高,需要仔细约束。
5. 技巧三:IO 标准与驱动强度的选择,接口功耗别忽视
5.1 IO 标准对功耗的影响
IO 功耗在设计里经常被低估,尤其是高速接口多的项目。不同 IO 标准的功耗差异很大,核心因素是电压摆幅和终端匹配方式。
LVCMOS 是最常见的标准,功耗取决于电压(1.8V、2.5V、3.3V)和驱动强度。3.3V LVCMOS 的功耗明显高于 1.8V,因为电压高、摆幅大。如果外设支持 1.8V,优先用 1.8V,不要为了兼容性无脑上 3.3V。
LVDS 是差分标准,电压摆幅小(约 350mV),功耗比同频率的 LVCMOS 低很多,而且抗干扰能力强。但 LVDS 需要终端电阻,终端电阻上的功耗也要算进去。一个 100Ω 终端在 3.5mA 电流下功耗约 1.2mW,看起来不大,但如果有几十对 LVDS,加起来就不少了。
| IO 标准 | 电压 | 典型功耗(100MHz,单端) | 适用场景 |
|---|---|---|---|
| LVCMOS33 | 3.3V | 8-15mW | 低速控制、LED、按键 |
| LVCMOS18 | 1.8V | 3-6mW | 中速接口、SPI、UART |
| LVDS | 差分 | 2-4mW(含终端) | 高速视频、ADC 接口 |
| SSTL15 | 1.5V | 5-10mW | DDR 接口 |
5.2 驱动强度的精细调节
每个 IO 都有可配置的驱动强度(Drive Strength),通常有 4mA、8mA、12mA、16mA 等档位。驱动强度越大,翻转时对负载电容的充放电电流越大,功耗越高。很多设计里默认用最大驱动强度,这是浪费。
正确的做法是:根据实际负载和信号完整性需求,选择最小的够用档位。比如驱动一个 LED,4mA 就够了;驱动一个短距离的 SPI 时钟,8mA 足够;只有长走线或大负载才需要 12mA 以上。Vivado 里可以在 IO 约束文件(XDC)里指定:
# 设置 IO 驱动强度为 8mA set_property DRIVE 8 [get_ports {spi_clk}] # 设置 IO 标准为 LVCMOS18 set_property IOSTANDARD LVCMOS18 [get_ports {spi_clk}] # 关闭内部上拉(如果不需要) set_property PULLUP false [get_ports {spi_clk}]还有一个容易忽略的点:未使用的 IO 要正确配置。悬空的 IO 如果配置成输入且没有上拉/下拉,输入缓冲器会因为输入电平不确定而振荡,产生额外功耗。Vivado 默认会把未使用的 IO 设为下拉,但如果你手动改过约束,要检查一下。对于确实不用的 IO,可以设为TRISTATE并关闭输入缓冲。
5.3 高速接口的功耗取舍
做高速接口(PCIe、MIPI、千兆网)时,功耗和性能往往需要取舍。比如 PCIe 的链路宽度和速率,x4 Gen2 比 x1 Gen1 功耗高不少,但如果你的应用不需要那么大的带宽,降下来就是纯收益。MIPI 的 lane 数也是同理,能少用就少用。
我在一个 MIPI 摄像头采集项目里做过测试:原本用 4 lane、1Gbps/lane,功耗约 0.35W;改成 2 lane、800Mbps/lane,带宽刚好够用,功耗降到 0.18W。当然,这个改动需要重新验证时序和图像质量,不是无脑降就能行的。
实操心得:IO 功耗优化最容易见效的是“关掉不用的”和“降低驱动强度”,这两项几乎零风险。高速接口的降速降 lane 需要仔细评估,建议先用功耗报告估算收益,再决定是否值得改。
6. 技巧四:代码层面的功耗优化,从 RTL 开始省电
6.1 减少不必要的信号翻转
动态功耗和信号翻转率成正比,所以减少翻转就是省电。RTL 层面有很多可以优化的地方,但很多工程师写代码时只关注功能,不关注翻转。
一个典型例子是计数器。一个 32 位计数器每个周期都在翻转,如果它只是用来做分频或计时,高位其实很少变化。但综合工具不会自动帮你优化,它就是一个完整的 32 位寄存器在翻转。优化方法是:如果只需要低几位,就不要用 32 位;如果高位变化慢,可以用格雷码或者只保留必要的位。
另一个例子是状态机编码。二进制编码的状态机,状态跳转时多个位同时翻转;独热码(One-hot)虽然用的触发器多,但每次跳转只有两位变化,翻转率低。在状态数不多的情况下,独热码的总功耗可能更低。Vivado 综合时可以设置FSM_ENCODING属性来指定编码方式。
// 状态机编码示例:独热码 localparam IDLE = 4'b0001; localparam WORK = 4'b0010; localparam DONE = 4'b0100; localparam ERROR = 4'b1000;6.2 流水线与并行度的权衡
流水线(Pipeline)和并行(Parallel)是提高吞吐量的两种手段,但它们的功耗特性不同。流水线通过插入寄存器缩短关键路径,可以用更低的频率达到同样的吞吐量,频率低了动态功耗就低。并行通过复制逻辑资源提高吞吐量,资源多了电容大了,功耗自然高。
所以从功耗角度,优先用流水线而不是并行。比如一个需要 4 路并行处理的算法,如果时序允许,可以用 1 路逻辑跑 4 倍频率,或者用 4 级流水线在 1 倍频率下处理 4 路数据。前者频率高功耗大,后者频率低但资源多。实测下来,流水线方案通常比并行方案省电 20% 到 30%。
当然,流水线会增加延迟(Latency),如果系统对延迟敏感(比如实时控制),就不能无脑加流水线。这个取舍要根据具体应用来定。
6.3 时钟使能的正确使用
除了 BUFGCE 做全局时钟门控,每个触发器也有自己的时钟使能(CE)端口。在 RTL 里,如果你写if (enable) q <= d;,综合工具会自动推断出 CE,不需要额外的逻辑。但如果你写q <= enable ? d : q;,综合工具可能推断出一个多路选择器加反馈,而不是 CE,这样功耗更高。
// 推荐:综合工具推断出 CE always @(posedge clk) begin if (enable) begin q <= d; end end // 不推荐:可能推断出 MUX + 反馈 always @(posedge clk) begin q <= enable ? d : q; end这两种写法功能一样,但综合结果不同。第一种写法,触发器在 enable 为低时保持原值,时钟端口仍然在翻转,但数据端口不翻转,功耗较低。第二种写法,综合工具可能生成一个反馈回路,数据端口一直在翻转,功耗更高。养成用第一种写法的习惯,长期下来能省不少电。
7. 技巧五:工具链与约束的功耗优化,让工具帮你干活
7.1 综合与实现策略的功耗导向
Vivado 的综合和实现策略里,有专门针对功耗优化的选项。在综合设置里,-flatten_hierarchy设为rebuilt可以让工具更好地做跨层次优化,包括功耗优化。在实现设置里,place_design和route_design都有-power相关的 directive。
具体来说,place_design -directive ExtraTimingOpt和route_design -directive AggressiveExplore在时序和功耗之间做平衡。如果你的设计时序余量充足,可以用这些 directive 让工具优先优化功耗。实测下来,同样的设计,用功耗导向的 directive 比默认设置能省 5% 到 10% 的动态功耗。
还有一个容易被忽略的设置是power_opt_design。Vivado 在实现之后有一个可选的功耗优化步骤,会做一些局部的逻辑重组和时钟门控插入。这个步骤会增加编译时间,但对功耗有正面效果。我一般会在最终版本里打开它。
7.2 约束文件里的功耗相关设置
XDC 约束文件里有一些和功耗直接相关的设置。比如set_clock_groups可以告诉工具哪些时钟域是异步的,工具就不会去优化跨域路径,减少不必要的逻辑。set_false_path和set_max_delay也能减少工具在无关路径上的努力,间接降低功耗。
另外,set_power_driven相关的属性可以指导工具做功耗优化。不过这些属性在不同版本的 Vivado 里支持程度不同,用之前最好查一下对应版本的文档。
# 设置时钟组,声明异步关系 set_clock_groups -asynchronous \ -group {clk_video} \ -group {clk_ddr} \ -group {clk_ctrl} # 设置伪路径,减少工具优化努力 set_false_path -from [get_clocks clk_ctrl] -to [get_clocks clk_video]7.3 版本迭代中的功耗回归测试
功耗优化不是一次性的工作,每次设计改动都可能影响功耗。建议在项目里建立功耗回归测试流程:每次综合实现之后,自动生成功耗报告,和基线对比。如果功耗上升超过阈值(比如 10%),就触发告警,检查是哪部分改动导致的。
这个流程可以用 Tcl 脚本自动化。Vivado 支持在非工程模式下跑综合实现,然后调用report_power生成报告。把报告解析成结构化数据,存到数据库里,就能做趋势分析了。
实操心得:功耗回归测试最大的价值是防止功耗悄悄劣化。我遇到过好几次,某个功能改动看起来和功耗无关,但功耗报告显示时钟树功耗涨了 15%,查下来是新增的逻辑导致工具重新布局,时钟树变长了。如果没有回归测试,这个问题可能到样机阶段才发现。
8. 常见问题与排查技巧实录
8.1 功耗优化常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 功耗报告和实测差距大 | 翻转率估计不准 | 导入 SAIF 文件重新报告 | 用仿真波形生成 SAIF |
| 时钟树功耗占比过高 | 时钟一直在跑,无门控 | 检查各时钟域使能逻辑 | 加 BUFGCE 门控 |
| BRAM 功耗高 | 始终使能,无访问控制 | 检查 BRAM EN 端口 | 加使能逻辑 |
| IO 功耗高 | 驱动强度过大 | 检查 XDC 里的 DRIVE 设置 | 降到最小够用档位 |
| 温度高但功耗不高 | 散热设计不足 | 测结温和环境温度 | 改善散热或降频 |
| 续航不达标 | 静态功耗占比高 | 分离静态和动态功耗 | 换低功耗器件或降电压 |
8.2 三个我踩过的坑
第一个坑:门控时钟导致时序违例。我早期做时钟门控时,CE 信号是组合逻辑生成的,结果门控时钟的占空比不稳定,下游触发器的建立时间不够,时序报告一片红。后来改成同步 CE,问题解决。这个坑的教训是:门控时钟的 CE 必须同步,而且要在时钟的相反沿生成,保证门控后的时钟没有毛刺。
第二个坑:BRAM 使能控制导致数据丢失。有一次我给 BRAM 加了使能控制,但使能逻辑和读写逻辑的时序没对齐,导致某些周期数据没写进去。排查了很久才发现是使能信号比写信号晚了一个周期。后来我把使能信号和写信号用同一个条件生成,问题解决。这个坑的教训是:BRAM 的 EN 和 WE 必须严格对齐,最好用同一个组合逻辑生成。
第三个坑:功耗优化过度导致功能异常。有一次我把 DSP 的使能控制做得太激进,在数据无效期间把 DSP 完全停掉,结果 DSP 的内部状态丢失,下一帧数据来的时候输出错误。后来改成“使能为低时保持状态,但不更新输出”,问题解决。这个坑的教训是:功耗优化不能牺牲功能正确性,任何优化都要做充分的回归测试。
8.3 功耗优化的优先级建议
根据我的经验,功耗优化的投入产出比从高到低排列是这样的:
- 时钟门控:收益最大,改动量中等,风险可控。
- BRAM 使能控制:收益明显,改动量小,风险低。
- IO 驱动强度和标准优化:收益中等,改动量小,风险低。
- 代码层面的翻转优化:收益中等,改动量大,需要仔细验证。
- 工具链策略优化:收益较小,改动量小,但需要反复试验。
建议按这个顺序推进,先把容易做的做了,再啃硬骨头。不要一上来就改 RTL,那样容易引入 bug,而且收益不一定比时钟门控大。
9. 写在最后:一些个人体会
功耗优化这件事,最怕的是“想当然”。我见过太多工程师凭直觉改代码,改完不测量,结果功耗没降多少,还引入了新问题。正确的做法是:先测量,再优化,再测量。功耗报告是你的眼睛,没有它你就是盲人摸象。
另外,功耗优化不是一次性的工作,它应该贯穿整个设计流程。从架构设计阶段就要考虑功耗预算,RTL 编码时注意翻转率,综合实现时用功耗导向的策略,最后在板子上实测验证。每个阶段都做一点,累积起来效果就很可观。
最后分享一个小技巧:如果你手头没有专业的功耗分析仪,可以用万用表测电流的方式做粗略估算。在 FPGA 的供电回路上串一个采样电阻,测电阻两端的电压差,除以电阻值就是电流,乘以电压就是功耗。这个方法精度不高,但胜在简单,适合快速对比不同版本的功耗差异。我自己在早期项目里经常用这招,虽然土,但管用。