我们在使用大位宽乘法器时,有时受到工艺的限制,乘法器位宽太大,时序收不下来,这时候需要将其拆为若干个小位宽乘法再相加,并在其中插入寄存器,即可解决以上问题。
其核心原理是乘法交换律。
我们以两个16bit无符号数相乘为例。
a[15:0] * b[15:0]
a[15:0] = a[15:8]<<8 + a[7:0]
b[15:0] = b[15:8]<<8 + b[7:0]
a[15:0] * b[15:0] = (a[15:8]<<8 + a[7:0]) * (b[15:8]<<8 + b[7:0])
= ((a[15:8]<<8) * (b[15:8]<<8)) + ((a[15:8]<<8) * b[7:0]) + (a[7:0] * (b[15:8]<<8)) + (a[7:0] * b[7:0])
= (a[15:8])* b[15:8])<<16 + (a[15:8] * b[7:0])<<8 + (a[7:0] * b[15:8])<<8 + (a[7:0] * b[7:0])
对于有符号数
$signed(a[15:0]) = - a[15]*2^15 + a[14]*2^14 + a[13]*2^13 + ...... + a[0]*2^0
$signed(b[15:0]) = - b[15]*2^15 + b[14]*2^14 + b[13]*2^13 + ...... + b[0]*2^0
因此
$signed(a[15:0]) = $signed(a[15:8]<<8) + a[7:0]
$signed(b[15:0]) = $signed(b[15:8]<<8) + b[7:0]
$signed(a[15:0]) * $signed(b[15:0]) = ($signed(a[15:8]<<8) + a[7:0]) * ($signed(b[15:8]<<8) + b[7:0])
= ($signed(a[15:8]<<8) * $signed(b[15:8]<<8) + ( $signed(a[15:8]<<8) * b[7:0]) + (a[7:0] * $signed(b[15:8]<<8)) + (a[7:0] * b[7:0])
= ($signed(a[15:8] * $signed(b[15:8])<<16 + ( $signed(a[15:8] * b[7:0])<<8 + (a[7:0] * $signed(b[15:8]))<<8 + (a[7:0] * b[7:0])
寄存器加在小乘法器后即可