带符号的二进制乘法和带符号的二进制除法
答
一个例子可能是照亮的。
module top;
reg [3:0] a;
reg [3:0] b;
reg [7:0] r1;
reg [7:0] r2;
initial begin
a = 4'hc;
b = 4'h5;
r1 = a * b; // 12 * 5
r2 = $signed(a) * $signed(b); //-4 * 5
$display("r1 = %b", r1);
$display("r2 = %b", r2);
end
endmodule
结果:
r1 = 00111100 (60)
r2 = 11101100 (-20)
所不同的是带符号的数字利用向量作为符号的指示符的MSB(见here,没有真正阅读此),该转移可表达的号码范围从[0..2^n-1]
到[-2^(n-1)..2^(n-1)-1]
几件事情需要注意:
- Verilog很奇怪,只会产生一个签名结果,如果都 操作数被签名。
- 您可以将一个reg/wire标记为
reg signed [3:0] foo
或$signed
系统任务。如果你有子表达式,你想把它视为有符号的,后者通常很有用。例如,即使原始变量被签名,取一个向量片也总是无符号的。 - 我提供的链接还涵盖了乘以有符号数量时获得正确答案所需机制的轻微变化。
对于Verilog的行为划分的目的基本上是相同的,虽然除非处理严格的2的权力通常是不可合成的。
答
只是有点不同基于Brian的例子
的Verilog签名VS无符号算术视图导致符号传播和关系操作的差异。如果不涉及符号扩展,对2进制数据的正则运算产生相同的有符号和无符号结果
所以在这种情况下,如果r1和r2的大小为'4'(作为操作数)相同的结果:
r1 = 1100 was (60)
r2 = 1100 was (-20)
在Brian的情况下,表达式结果的大小是8; Verilog将扩展您的操作数以占用8位空间。在签约的情况下,“一”,它会唱歌扩展它,这将会使的区别:
unsigned a[3:0] <1100> --> tmp[7:0] --> 00001100
signed a[3:0] <1100> --> tmp[7:0] --> 11111100
因此,如果[3]为“1”,它被认为是一个标志,并得到迹象升为剩下。现在,您的算术看起来如下:
unsigned: tmpa(00001100) * tmpb(00000101) --> 00111100
signed: tmpa(11111100) * tmpb(00000101) --> 11101100
当显示所述第二结果为整数,则尚未被符号扩展到32位,并且将显示为(-20)