Verilog实现动态段乘法(DSM)时有/无符号乘法仿真异常求解
Verilog动态段乘法符号处理异常解决方案
问题根因
符号转换失效是三个Verilog语法隐式规则共同导致的:
- 三态值
16'dz属于无符号类型,你用三条assign语句对同一个out变量做三态驱动时,仿真器会将所有分支的表达式统一推导为无符号类型,你手动加的$signed转换会被全局类型推导覆盖。 - 你使用的移位运算符
<<属于逻辑移位,默认按无符号规则处理运算数,就算乘法结果是signed类型,经过逻辑移位后也会被转为无符号值。 - 将signed类型的
m1/m2和无符号的1'b0做位拼接时,Verilog会先将signed变量隐式转为无符号值再拼接,后续的$signed转换已经无法恢复原本的符号含义。
修复方案
代码修改示例
// 首先确认out变量声明为signed类型 wire signed [15:0] out; wire [1:0] sign_pair = {a[7], b[7]}; // 先单独完成符号乘法,避免其他运算干扰符号推导 wire signed [7:0] mul_res; assign mul_res = (sign_pair == 2'b00 || sign_pair == 2'b11) ? $signed({1'b0, $unsigned(m1)}) * $signed({1'b0, $unsigned(m2)}) : sign_pair == 2'b01 ? $signed({1'b0, $unsigned(m1)}) * $signed(m2) : $signed(m1) * $signed({1'b0, $unsigned(m2)}); // 用算术移位<<<做位移,保留符号位,shift参数转signed避免隐式转换 assign out = mul_res <<< $signed(shift_m1 + shift_m2);
关键修改说明
- 移除了所有三态输出逻辑,用单条多路选择赋值完成符号分支判断,避免无符号
z值干扰类型推导 - 乘法运算单独用signed类型变量承接,运算优先级高于移位,避免上下文类型污染
- 移位改用算术移位运算符
<<<,自动保留乘法结果的符号位 - 拼接前对m1/m2先做
$unsigned转换明确提取数值位,避免signed变量隐式转换导致的数值错误
内容的提问来源于stack exchange,提问作者Seyed Kian
相关产品推荐
相关产品推荐

