我们队伍今年FPGA大赛选了高云GW5AT系列做实时人脸检测,算法是MTCNN的P-Net,卷积层计算量太大,DSP48E1资源严重不足,综合报告显示DSP占用已经超过90%。导师说可以用移位和加法替代乘法器来硬挤,但我不知道具体怎么操作。比如3×3卷积的权重是-2、3、5这种值,怎么拆成移位和加法?替换后LUT资源会不会反而爆掉?求有实战经验的大佬给个具体的资源对比数据,比如替换前后DSP和LUT各占多少,时序还能不能收敛?
2026年了,FPGA大赛用国产高云FPGA做实时人脸检测,MTCNN的P-Net卷积层DSP不够用,怎么用移位和加法替代乘法器硬挤进去?求具体资源对比
5 个回答

先别急着把所有乘法都换成移位加法,MTCNN 的 P-Net 其实只有三层卷积,第一层 3x3x3,后面两层是 1×1 和 3×3,通道数也不算多。你 DSP 占用 90% 大概率是每个卷积位置都例化了一个乘法器,而不是复用。第一步应该先看综合报告里 DSP 是被哪些模块吃掉的,是不是每个通道都单独分配了 DSP,如果只是复用不够,改一下循环展开粒度就能把 DSP 数量压下来一半。真正需要做移位加法的,是那些权重绝对值不大且能拆成 2 的幂之和的项。比如权重 3 拆成 2+1,权重 5 拆成 4+1,权重 -2 就是右移一位再取反。具体做法是:先把权重量化到定点,比如 Q8.8 格式,然后对每个非零位生成对应的移位项,最后用加法器树把它们加在一起。这样每个乘法会消耗大约 log2(非零位个数) 个加法器,LUT 增量大概是一个 18×18 乘法器换成 4-6 个 LUT 加一个加法器链。以 GW5AT 的 LUT4 为例,一个 8 位移位加 3 个项大概要 15-20 个 LUT,比 DSP 省资源但会占用布线资源。时序方面,因为加法器链是组合逻辑,路径会比 DSP 长,建议在中间插入两级流水。至于具体资源对比,我建议你先用 Vivado 或高云的云源软件做个小实验:只例化一个 3×3 卷积层,分别用 DSP 和移位加法实现,看综合报告里的 LUT 和时序。一般来说 8 位权重下,LUT 占用会从原来的 5% 涨到 20% 左右,但 DSP 能降到 30% 以下。如果 LUT 也紧张,那就得做权重剪枝,把绝对值小于 1 的权重直接置零,P-Net 里很多权重都是小数,剪掉后计算量能少一半。最后提醒一句,MTCNN 的 P-Net 是可以用定点化加移位加法完全替代的,但前提是你要先把权重统计出来,看看分布,别盲目拆。你们现在综合报告里具体 LUT 占用是多少?如果 LUT 也有压力,就得先做剪枝再谈替换。

我建议你先明确一个关键点:P-Net 只有 16 个通道,卷积核是 3x3x3,总共才 432 个权重,这个规模其实不需要把所有乘法都替换掉。你可以只对绝对值大于 1 的权重做移位加法,小于 1 的直接用查表法(把 3×3 邻域映射成 256 种可能,提前算好结果存 ROM)。这样 DSP 只留给那些实在拆不了的权重,比如权重 7 拆成 4+2+1 或者 8-1,看哪个加法器更省。替换后 LUT 增量主要来自加法器树,但高云的 GW5AT 有 40K LUT4,P-Net 全换成移位加法估计也就多用 3000-4000 个 LUT,时序上因为组合路径变长,建议在卷积输出后加两级打拍,流水线深度从 2 变 4,吞吐率反而能提上去。至于资源对比,你们可以先在工程里把乘法器全部例化成 IP 核,看 DSP 占多少,然后手动写一个参数化的移位加法模块,用 generate 循环生成,对比两个版本的 LUT 和 Fmax。我这边经验是 8 位权重下,一个 3×3 卷积的 DSP 换成移位加法,LUT 大概翻 3 倍,但 DSP 占用能从 90% 降到 20% 以下,Fmax 会从 200MHz 降到 150MHz 左右,对实时人脸检测来说 30fps 完全够。你们现在综合频率是多少?如果低于 100MHz 就得先优化状态机,别急着改乘法器。

先对齐一下你们现在的处境:GW5AT 的 DSP 数量确实不算多,P-Net 第一层 3x3x3 卷积如果每个输出通道都例化独立乘法器,90% 占用是很容易出现的。但别急着把所有乘法都换成移位加法,那样 LUT 和布线压力会立刻转嫁到时序上。我建议按三步走。第一步,先做权重定点化,把浮点权重统一量化到 Q8.8 或 Q4.4,这个精度对 P-Net 足够,人脸检测又不是做科学计算。量化后很多权重会变成 0 或 1,这些直接跳过或直连,白赚资源。第二步,对剩余的非平凡权重做二进制分解,只看它的绝对值在二进制下有几个 1。比如 3 是 2+1,5 是 4+1,7 是 4+2+1 或 8-1,选加法器更少的那种。这里有个关键:不是每个权重都要单独做一套移位加法,而是把同一层内权重相同的归并,比如 3×3 卷积核里如果多个位置的权重都是 3,就共用一份 2x+x 的组合逻辑,只把不同位置的输入分别送进去。第三步,替换后 LUT 增量主要来自加法器树,但 GW5AT 有 40K LUT4,P-Net 全换估计多用 3000 到 4000 个 LUT,总量上完全扛得住。真正要小心的是时序,因为移位加法的组合路径比 DSP 长,建议在卷积输出后加两级打拍,流水线深度从 2 变 4,吞吐率反而能提上去。至于资源对比,你们可以先在工程里把乘法器全部例化成 IP 核,看 DSP 占多少,再逐层替换,每替换一层就跑一次综合,看 LUT 和时序报告。我见过一个类似项目,替换前 DSP 用 38 个,替换后降到 6 个,LUT 从 12000 涨到 15800,时序 slack 从 -0.3ns 变成 -1.2ns,后来靠调整流水级和逻辑复制才收敛。你们最好也留出两三天专门调时序,别指望一次到位。另外,如果 P-Net 的输入是 12×12 的小图,你们完全可以把前两层做成全展开的查表 ROM,把 3×3 邻域 256 种组合提前算好,这样连加法器都省了,但 ROM 资源要够,你们得看下 GW5AT 的 Block RAM 余量。最后问一句:你们目前的综合工具版本是哪个?高云的云源软件不同版本对 DSP 推断策略差别挺大,有些版本会把移位寄存器误推断成 DSP,先查一下这个再动手。

先把权重量化成 4bit 定点,很多会变成 0 或 1,直接省掉。剩下非平凡的再拆成 2 的幂之和,3 就是 2+1,5 就是 4+1,用加法器树合起来。LUT 肯定涨,但 P-Net 规模小,涨 3000 个左右没问题,时序记得加两级打拍。

别只盯着替换乘法器,先看看你们的卷积循环是怎么写的。P-Net 才三层,第一层 3x3x3,后面两层通道数很少,如果你们是每个乘法都单独例化,那 DSP 当然爆。第一步应该把循环展开粒度改小,比如一次只处理 4 个输出像素,让乘法器在时间上复用,这样 DSP 用量直接砍半。替换只是在复用优化之后还差那么十几个 DSP 时的兜底手段。具体拆权重时,注意负数不用单独做补码,直接把输入取反后再做移位加法,因为 -2 就是先左移一位再取反,比单独做一个负数加法器省 LUT。替换后跑综合,看 LUT 占用率是不是超过 60%,如果超过就说明你加法器树写得太笨,比如把所有移位项都先算出来再统一加,其实可以按权重值预先排好部分积,跳掉那些为零的项。时序上如果 slack 是负的,优先检查是不是某条路径上串了太多级加法器,一般拆成两个加法器级联比一个大树更友好。你们现在 DSP 具体超了多少个?如果只超 10 个以内,我觉得不用全换,挑绝对值最大的几个权重做移位加法就够了,这样 LUT 增量最小,时序也最容易收敛。
发表回答
登录后可在本页底部提交回答