15

For instance, say I have a reg [7:0] myReg I assign it the value -8'D69

I know Verilog stores it as 2's complement so it should be stored as

10111011

The question I have now is if I were to perform an operation on it, say myReg/2

Would it evaluate to -34? Or would it take 10111011 and turn it into 187 then perform the division, returning 93?

toolic
  • 57,801
  • 17
  • 75
  • 117
wonton
  • 7,568
  • 9
  • 56
  • 93

4 Answers4

15

You need to remember that -8d69 is just a bit pattern. reg is a type which holds bit patterns. It is the type of variable that instructs / to perform signed or unsigned arithmetic.

If this is for synthesis bare in mind that you want to try and avoid dividers, you really want to try and avoid signed dividers. It will likely synthesis smaller with >>> 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

Gives:

a      : 01011101,  93
b      : 11011110,  -34 
c >>>1 : 01011101,  93
d >>>1 : 11011101,  -35

>> x Shifts right by x places, >>> x Shifts right x places but sign extends for signed types.

NB: the /2 is also rounding up in my examples, >>> will round down/truncate.

Morgan
  • 19,934
  • 8
  • 58
  • 84
6

For instance, say I have a reg [7:0] myReg I assign it the value -8'D69

This actually isn't a signed number but instead an expression consisting of a unary negation applied to a positive constant. If the expression was -8'd130 the result would overflow. Signed constants are declared as 8'sd69 or just 69.

The question I have now is if I were to perform an operation on it, say myReg/2

myReg is unsigned so the expression result will also be unsigned*. If you need the result to be signed than all operands must be signed. There are a couple ways to achieve this:

//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;

*The complete rules regarding expression evaluation are much more complex but basically the result of any expression is unsigned, unless all operands are signed.

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

I'll add that 1. Data types bit and reg are unsigned, by default. 2. Data types int, integer, longint, shortint, and byte are signed, by default. 3. All these data types can take a signed or unsigned qualifier to change the default.

So, assigning -8'D69 to myReg does an implicit conversion to 187. Then, myReg/2 = 187/2 = 93, unsigned. It's important to understand when and how SystemVerilog does implicit type conversions in expressions and assignments.

Steve K
  • 2,124
  • 16
  • 19
1

The best place to check is the Language Reference Manual. Predictably, given Verilog's "eh" attitude to proper typing, it's a bit of a mess.

unsigned and signed

Basically signed doesn't affect the actual data stored in the variable/net, but it does affect what the arithmetic operators do in some case. The obvious case is comparison, but also multiplication and division would behave differently. Addition and subtraction should be the same for both signed and unsigned.

comparison

Note especially that when one or more of the operands is unsigned it is treated as an unsigned comparison, which is different to what you would expect from C. So if we have

byte a = -10;        // byte is signed
logic [7:0] b = 10;  // this is unsigned

Then a > b is true.

equality

Again if at least one operator is unsigned then it treats them both as unsigned so if we have:

byte a = -1;
logic [7:0] b = 255;

Then a == b is true.

Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • Thanks @Timmmmmmmmm .. This comment "Again if at least one operator is unsigned then it treats them both as unsigned so if we have", is true and helped! – AZ123 Feb 20 '23 at 18:28