Verilog如何处理负数?

won*_*ton 14 verilog negative-number

例如,假设我有一个reg [7:0] myReg 我赋值的值-8'D69

我知道Verilog将它存储为2的补码,所以它应该存储为

10111011
Run Code Online (Sandbox Code Playgroud)

我现在的问题是,如果我要对它进行操作,比如myReg/2

它会评估到-34?或者它需要10111011然后把它变成187然后执行分裂,返回93?

Mor*_*gan 14

你需要记住这-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
Run Code Online (Sandbox Code Playgroud)

得到:

a      : 01011101,  93
b      : 11011110,  -34 
c >>>1 : 01011101,  93
d >>>1 : 11011101,  -35
Run Code Online (Sandbox Code Playgroud)

>> x向右移动x个位置,>>> x右移x个位置,但符号扩展为签名类型.

注意:/2在我的例子中也是四舍五入,>>>将向下舍入/截断.


小智 6

例如,假设我有一个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;
Run Code Online (Sandbox Code Playgroud)

*关于表达式求值的完整规则要复杂得多,但基本上任何表达式的结果都是无符号的,除非所有操作数都是有符号的.

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
Run Code Online (Sandbox Code Playgroud)