我们队今年FPGA大赛选了紫光同创的板子做YOLOv5s目标检测,综合之后发现DSP48资源直接爆了,瓶颈在3×3卷积那几层的乘法器。查了说可以用分布式算术DA把乘法换成LUT查找表,但网上教程都是讲FIR滤波器的,卷积怎么套用DA完全没头绪。有没有大佬给个具体拆解步骤?比如权重位宽怎么定、LUT怎么分组、输入数据怎么重排才能不爆LUT?我们是第一次用国产FPGA,资源比想象中紧,求个能落地的方案,谢谢!
2026年FPGA大赛用紫光同创跑YOLOv5s,DSP48不够用,怎么用分布式算术把乘法替换掉?求具体拆解步骤
4 个回答

先别急着上DA,紫光同创的LUT6资源也不算多,你把权重位宽压到8bit,每个3×3卷积核拆成3行,每行9个乘加用一个DA查找表,输入按位切片后查表再移位累加,LUT消耗大概是DSP方案的1.5到2倍,但能腾出DSP给后面残差块。关键是权重先做符号扩展,别把负数搞成无符号查表。

说实话,第一次用国产FPGA就硬上YOLOv5s,DSP爆掉只是第一关,BRAM和LUT后面大概率也会紧。DA的思路本身没问题,但直接套FIR那种单通道串行DA在卷积里会死得很惨,因为卷积是窗口滑动,输入数据有大量重叠。我建议你换个角度:把卷积拆成按输出通道分组的并行DA,每个输出通道单独一个查找表,输入是9个像素的对应bit位拼接,这样查表次数从9次降到1次,代价是LUT翻倍。具体步骤:先把权重量化到8bit有符号,按bit位拆成8个平面,每个平面对应一个查找表,表内容是该bit位下9个像素权重的部分积之和;输入数据也按bit位切片,9个像素的同一bit拼成9bit地址去查表,查完结果按bit权重移位累加,最后加上偏置。LUT开销估算:一个8bit权重、9输入的部分积表需要2^9=512个LUT6,每输出通道8个表就是4096,你一个3×3卷积层如果有32个输出通道,光这一层就是13万LUT,肯定爆。所以必须分组,比如把9个输入分成3组,每组3输入,查表结果先组内累加再组间累加,这样每组表只要2^3=8个LUT6,3组加累加器,每通道LUT降到几百个。还有个坑:DA适合权重固定的情况,YOLO的权重在推理时是固定的,所以可以提前用脚本生成查找表内容,别在RTL里算。另外,紫光同创的LUT结构是6输入,你拼9bit地址要拆两次,注意布线拥塞,最好在综合属性里把DA模块的LUT保持层级,别让工具乱优化。你们要是时间紧,其实可以考虑把部分层改用Winograd,但那个更复杂,DA至少思路清晰。

你这个问题我建议先做个资源预算再动手。YOLOv5s的3×3卷积主要集中在backbone的C3模块里,那些层的输入输出通道数都很大,直接整层做DA不现实。一个可行做法是只对权重绝对值最大的那几层做DA,其余层保留DSP,毕竟你只是DSP不够,不是完全没有。具体拆解时,把权重位宽从16bit压到8bit,精度损失在mAP上大概0.5以内,但LUT消耗能降一半。输入数据不用重排,直接按bit切片,每个时钟沿取9个像素的同一bit,拼成9bit地址查表,查表结果在下一级做移位累加,累加器宽度要留够,比如8bit权重乘8bit输入,部分积最大是16bit,累加9次再加偏置,输出建议用20bit防止溢出。流水线方面,查表和累加之间插一级寄存器,累加里再做两级树形加法,这样时钟能跑到150MHz左右。另外提醒一句,紫光同创的PDS工具对DA这种多级LUT链的优化不如Vivado,你最好在综合选项里关掉自动retiming,手动插流水级,不然时序容易崩。你们板子具体型号是什么?如果LUT也紧张,我可以再给你算算哪些层能合并。

我去年用紫光同创的PGL22G做过一次类似的移植,也是YOLOv5s,DSP不够,最后靠DA硬撑下来的。先说结论:别指望把整个3×3卷积都换成DA,那样LUT必爆,正确做法是分层处理,只对DSP消耗最大的那几层做DA替换,其他层继续用DSP。具体拆解步骤我给你捋一遍。第一步,定权重位宽。我建议直接压到8bit有符号,再往下掉精度就不太行了,mAP可能掉1个点以上,大赛里不划算。第二步,输入数据重排。这是最关键的一步,卷积和FIR不一样,它是窗口滑动的,同一像素会被多个窗口复用。所以你不能像FIR那样串行进来,得先把输入特征图按行缓存,然后用移位寄存器同时输出3×3窗口的9个像素。紫光同创的BRAM够用的话,用双口RAM做行缓存,每行存一个特征图宽度,三行缓存就能拼出窗口。第三步,LUT分组。把9个像素的同一bit位拼成9bit地址,查一张表,表里存的是该bit位下9个权重与输入bit的部分积之和。权重8bit,所以每个输出通道需要8张表,每张表512个LUT6。一个输出通道光查表就4096个LUT6,这还没算移位累加和偏置。所以建议按输出通道分组,每4个输出通道一组,共用输入数据,这样输入读取次数能降下来。第四步,累加器设计。查表结果按bit权重移位累加,8bit权重就是8级移位累加,每一级加完插一级寄存器,最后加偏置。累加器宽度建议20bit,因为8bit乘8bit部分积最大16bit,累加9次再加偏置,20bit够用,再宽就浪费LUT了。最后说个坑,紫光同创的LUT6实际是6输入查找表,但有些文档会写LUT5,你写代码时直接用LUT6原语就行,别被文档绕晕。你们现在综合后DSP爆了多少?如果只是超了20%以内,其实可以只换掉C3模块里通道数最大的那几层,其他层保持DSP不动,这样LUT压力也小很多。
发表回答
登录后可在本页底部提交回答