有符号或无符号的运算结果

Signed or unsigned result of operation

让我们考虑三种情况:

// case 1
reg [63:0] result;
reg [15:0] number1;
reg signed [31:0] number2;

number1 = 0;
number2 = -2147483648;

result = number1 | number2;  // result[63] == 0
// case 2
reg [63:0] result;
reg [15:0] number1;

number1 = 0;

result = number1 | -32'd2147483648;  // result[63] == 1
// case 3
reg [63:0] result;
reg [15:0] number1;

number1 = 0;

result = number1 | $signed(-32'd2147483648);  // result[63] == 0

为什么案例二的结果是有符号的?为什么 verilog 以不同的方式处理这个等式?

在这种情况下,操作数的大小由 lhs 的大小定义——64 位。 System Verilog 标准提供了根据操作数和 lhs 的宽度和类型计算位宽和表达式类型的规则。在所有情况下,“|”的宽度依赖于上下文并且必须有 64 位(所有操作数和 lsh 的最大宽度)。因此,它期望所有操作数都匹配最大宽度。

案例 1:

result = number1 | number2;

结果表达式只是将两个 16 位操作数 0 扩展为 64 的 'or'。因此,第 63 位为 0。注意,没有取反

案例 2:

result = number1 | -32'd2147483648;  
result = number1 | -2147483648; // same as above
result = number1 | -number2; // same result  

一元运算符 'minus' 也是一个 context-determined 运算符。这里会发生什么,'-' 运算符会在取反之前将其操作数扩展到 64 位。结果,您将得到一个 64 位负数,其中第 63 位设置为 1。

案例 3

result = number1 | $signed(-32'd2147483648); 

这里,上下文的宽度不会通过 $signed 函数传播到它的操作数,它是 32 位宽并且是 self-determined。由于运算符“|”,上下文的类型始终是无符号的。结果,即使您将其标记为已签名,rhs 仍被视为未签名。所以,它也得到 zero-extended 到 64 位,第 63 位是 0.

2 和 3 之间的区别在于否定适用于 64 位值(在 2 中)与 32 位值(在 3 中)。在这两种情况下,该操作数都被视为无符号。

perand to $signed a self-determined width of 32. 它的否定使它在 32 位上下文中成为正数。所以,在 $signed 运算符之后,它是一个 32 位正数,它被 0 扩展为 64 位。