Verilog 中的有符号和无符号乘法问题

Signed and Unsigned Multiplication Problem in Verilog

最近在研究近似乘法,想写一个动态段乘法(DSM)的Verilog代码。它建议你在你的数字中找到第一个值为 1 的索引,然后取它旁边的其他 3 个索引来形成一个代表 8 位数字的 4 位数字然后你应该乘以这些 4 位数字而不是 8 位然后一些转变以获得最终结果它实际上对硬件有很大帮助..但我的问题是关于这些段的乘法因为有时它们应该被认为是有符号的而有时是无符号的我有我代码的最后3行:(a和b 是输入的 8 位数字),m1 和 m2 是我写的段 m,m2 作为 reg signed [3:0] 和 a 和 b 作为输入 signed [7:0] 这是我的代码:

    assign out = ({a[7],b[7]}==2'b11)||({a[7],b[7]}==2'b00) ? ($unsigned(m1)*$unsigned(m2)) << (shift_m1+shift_m2) : 16'dz;
assign out = ({a[7],b[7]}==2'b01) ? ($signed({1'b0,m1})*$signed(m2)) << (shift_m1+shift_m2) : 16'dz;
assign out = ({a[7],b[7]}==2'b10) ? ($signed(m1)*$signed({1'b0,m2})) << (shift_m1+shift_m2) : 16'dz;

但在仿真中,Verilog 始终将段视为无符号段并进行无符号乘法,即使我注意到有符号或无符号标记... 谁能帮忙?我在Whosebug和其他地方阅读了所有关于这个问题的问题,但仍然无法解决这个问题...

非自定操作数的规则规定,如果一个操作数是无符号的,则结果也是无符号的。 16'dz 未签名。

条件运算符i ? j : k有条件操作数i自定,但是jk这两个选择是在一个基于赋值或表达它是的一部分。移位运算符i << j的移位量操作数j自定。

IEEE 1800-2017 SystemVerilog LRM.

中的 11.6.1 表达式位长度规则 部分解释了所有上下文规则

您可以使用带符号的文字 16'sdz 来获得您想要的结果。

但是,对于某些不允许在您的设备中使用 z 状态的技术,您编写的逻辑可能无法综合。正确且更易读的方法是使用 case 语句:

alway @(*) case({a[7],b[7]})
  2'b00, 
  2'b11: out = $unsigned(m1)*$unsigned(m2) << shift_m1+shift_m2;
  2'b01: out = $signed({1'b0,m1})*m2       << shift_m1+shift_m2;
  2'b10: out = m1*$signed({1'b0,m2})       << shift_m1+shift_m2;
endcase