Chisel中SInt*SInt变UInt*SInt:卷积加速器FIR模块计算异常
卷积加速器FIR模块集成后符号乘法异常排查与解决
问题现象
- 基于Chisel开发卷积神经网络加速器,卷积单元采用3个一维FIR滤波器实现
- FIR模块独立测试时结果正确,但集成到DLA后出现乘法运算异常:原本应为
SInt*SInt的运算被错误处理为UInt*SInt,例如输入-29(8位SInt)被当作227(8位UInt)参与乘法,导致计算结果完全错误 - 所用FIR模块的Chisel实现代码如下:
class OneDemConvGen(wgh_num:Int=3, ipt_wid:Int = 8, wgh_wid:Int=8, psum_wid:Int=32) extends Module{ val io = IO(new Bundle() { val in = Input(SInt(ipt_wid.W)) val weights = Input(Vec(wgh_num, SInt(wgh_wid.W))) val psum = Output(SInt(psum_wid.W)) }) val muls = Seq.fill(wgh_num)(Wire(SInt(psum_wid.W))).zip(io.weights).map({case (p, w) => p := io.in*w; p}) val sum = muls.fold(0.S)((a, b) => RegNext(a+b, 0.S)) io.psum := sum }
可能原因
- 顶层信号类型不匹配:DLA顶层连接FIR模块
io.in的信号被错误定义为UInt,或连接时发生了隐式类型转换。Chisel中UInt赋值给SInt会直接按位复制,符号位被当作数据位,导致有符号数被解析为无符号数。 - 信号路径的位宽处理错误:输入信号在传递到FIR模块前,被执行了无符号扩展(
zext)或截断操作,破坏了原有的符号信息。 - 累加环节的类型隐式转换:集成后累加路径中混入
UInt类型信号,导致RegNext处理时出现类型异常。
解决方案
- 检查顶层信号连接:确认DLA顶层中传递给FIR
io.in的信号类型为SInt(ipt_wid.W)。若顶层使用UInt信号,需显式转换为SInt:// 示例:将UInt信号转换为SInt后连接到FIR输入 firModule.io.in := topUIntSignal.asSInt() - 修正信号路径的位宽扩展方式:追踪输入信号到FIR模块的完整路径,将所有无符号扩展(
zext)替换为符号扩展(sext),确保符号位正确保留。 - 显式指定乘法操作的符号类型:在乘法语句中显式扩展操作数的位宽并指定符号类型,避免隐式转换问题:
// 修改乘法语句,确保按有符号位宽处理 p := (io.in.sext(psum_wid.W) * w.sext(psum_wid.W)).asSInt - 明确累加器的位宽与类型:将
fold的初始值显式指定位宽,确保类型一致性:val sum = muls.fold(0.S(psum_wid.W))((a, b) => RegNext(a+b, 0.S(psum_wid.W)))
验证步骤
- 抓取集成后FIR模块
io.in的波形,确认其值是否为预期的有符号数(例如-29的补码是否被正确识别为SInt) - 检查DLA中是否存在对输入信号的截取、拼接等操作导致符号位丢失
内容的提问来源于stack exchange,提问作者Shuo Ran
相关产品推荐
相关产品推荐

