例如,假设我有一个reg [7:0] myReg
我给它赋值-8'D69
我知道 Verilog 将其存储为 2 的补码,因此应将其存储为
10111011
我现在的问题是,如果我要对其执行操作,比如 myReg/2
它会评估为-34吗?还是将 10111011 转换为 187 然后执行除法,返回 93?
例如,假设我有一个reg [7:0] myReg
我给它赋值-8'D69
我知道 Verilog 将其存储为 2 的补码,因此应将其存储为
10111011
我现在的问题是,如果我要对其执行操作,比如 myReg/2
它会评估为-34吗?还是将 10111011 转换为 187 然后执行除法,返回 93?
你需要记住这-8d69
只是一个模式。reg 是一种保存位模式的类型。它是指示/
执行有符号或无符号算术的变量类型。
如果这是为了综合考虑你想尽量避免使用分隔符,你真的想尝试避免有符号的分隔符。它可能会合成更小>>> 1
reg [7:0] a;
reg signed [7:0] b;
reg [7:0] c;
reg signed [7:0] d;
initial begin
a = -8'd69 ;
b = -8'd69 ;
c = -8'd69 ;
d = -8'd69 ;
#10ns;
a = a/2 ;
b = b/2 ;
#10ns;
$display("a : %8b, %d", a, a);
$display("b : %8b, %d", b, b);
$display("c >>>1 : %8b, %d", c>>>1, c>>>1);
$display("d >>>1 : %8b, %d", d>>>1, d>>>1);
end
给出:
a : 01011101, 93
b : 11011110, -34
c >>>1 : 01011101, 93
d >>>1 : 11011101, -35
>> x
右移 x 位,>>> x
右移 x 位,但符号扩展为有符号类型。
注意:/2
在我的示例中也是四舍五入,>>>
将向下舍入/截断。
例如,假设我有一个 reg [7:0] myReg 我给它赋值 -8'D69
这实际上不是一个有符号数,而是一个由应用于正常数的一元否定组成的表达式。如果表达式是-8'd130
结果将溢出。有符号常量被声明为8'sd69
或69
。
我现在的问题是,如果我要对其执行操作,比如 myReg/2
myReg
是无符号的,因此表达式结果也将是无符号的*。如果您需要对结果进行签名,则必须对所有操作数进行签名。有几种方法可以实现这一点:
//Declare the reg as signed and divide by a signed value
reg signed [7:0] myReg;
assign result = myReg/2;
//Use system functions
assign result = $signed(myReg)/2;
*关于表达式求值的完整规则要复杂得多,但基本上任何表达式的结果都是无符号的,除非所有操作数都有符号。
reg signed [7:0] a;
reg [7:0] b;
initial
begin
result = a; //Signed
result = a * a; //Signed
result = a * 10; //Signed
result = $unsigned(a); //Unsigned
result = a[0]; //Unsigned
result = a[7:0]; //Unsigned
result = {a,a}; //Unsigned
result = 10{a}; //Unsigned
result = a + b; //Unsigned
result = a * b; //Unsigned
end
我将添加 1。默认情况下,数据类型 bit 和 reg 是无符号的。2. 默认情况下,数据类型 int、integer、longint、shortint 和 byte 是有符号的。3. 所有这些数据类型都可以使用有符号或无符号限定符来更改默认值。
因此,将 -8'D69 分配给 myReg 会隐式转换为 187。然后,myReg/2 = 187/2 = 93,无符号。了解 SystemVerilog 何时以及如何在表达式和赋值中进行隐式类型转换非常重要。