Lecture 16 – Signed Integers and Arithmetic Part I

Ryan Robucci

Table of Contents

References

Signed and Unsigned Integers

Unsigned Interpretation:
i=0n1(2ixi)=\displaystyle\sum_{i=0}^{n-1}(2^i x_i)=
2n1xn1+i=0n2(2ixi)\displaystyle \textcolor{red}{2^{n-1} x_{n-1} } + \sum_{i=0}^{n-2}(2^i x_i )

Signed Interpretation (MSB used for representing Negative Numbers)

2n1xn1+i=0n2(2ixi)\displaystyle \textcolor{red}{-2^{n-1}x_{n-1} } + \sum_{i=0}^{n-2}(2^i x_i )

Negative Numbers in Two's Complement (2NX2^N-X)

Two's Complement Wheel

Helps visualize

  • bit interpretation
  • modular arithmetic
    • e.g. (X+Y)%24(X+Y)\%2^4
  • overflow
image src:https://stackoverflow.com/questions/55145028/binary-ones-complement-in-python-3, though origin uncertain

Conversion Arithmetic

Conversion for 4-bit Data

Bits
x3x2x1x0x_3x_2x_1x_0
Unsigned relation Signed
1111 15 +1616\xtofrom[+16]{-16} 1=2415\textcolor{red}{-1}=2^4-15
1110 14 +1616\xtofrom[+16]{-16} 2=2414\textcolor{red}{-2}=2^4-14
1101 13 +1616\xtofrom[+16]{-16} 3=2413\textcolor{red}{-3}=2^4-13
1100 12 +1616\xtofrom[+16]{-16} 4=2412\textcolor{red}{-4}=2^4-12
1011 11 +1616\xtofrom[+16]{-16} 5=2411\textcolor{red}{-5}=2^4-11
1010 10 +1616\xtofrom[+16]{-16} 6=2410\textcolor{red}{-6}=2^4-10
1001 9 +1616\xtofrom[+16]{-16} 7=249\textcolor{red}{-7}=2^4-9
1000 8 +1616\xtofrom[+16]{-16} 8=248\textcolor{red}{-8}=2^4-8
0111 7\textcolor{blue}{7} = +7\textcolor{blue}{+7}
0110 6\textcolor{blue}{6} = +6\textcolor{blue}{+6}
0101 5\textcolor{blue}{5} = +5\textcolor{blue}{+5}
0100 4\textcolor{blue}{4} = +4\textcolor{blue}{+4}
0011 3\textcolor{blue}{3} = +3\textcolor{blue}{+3}
0010 2\textcolor{blue}{2} = +2\textcolor{blue}{+2}
0001 1\textcolor{blue}{1} = +1\textcolor{blue}{+1}
0000 0\textcolor{blue}{0} = +0\textcolor{blue}{+0}

Visual Example: Sine Wave transmitted using 5-bit data:

Two's Complement as Complement-and-Increment

Ones Complement

Sign-Magnitude

Truncation and Extension for Integers (in C)

In C, if a mix of signed and unsigned operands of the same rank are provided to an operator, operands are first cast to be unsigned (dumb conversion (e.g. -1\rightarrowbig number)).

Signed/Unsigned Casting may be followed by length adjustment.

Extension/truncation of signed value:

alt

Truncation

Signed and Unsigned Integral Extension

Assignment to a longer type is done with either zero or sign extension depending on the source type:

Long/short unsigned/signed Conversion Rules

(C/C++) Combinations of (dest type) = (source type) to consider

LHS=RHS( unsigned long)=(unsigned long)( unsigned long)=( signed long)( signed long)=(unsigned long)( signed long)=( signed long)(unsigned short)=(unsigned long)(unsigned short)=( signed long)( signed short)=(unsigned long)( signed short)=( signed long)( unsigned long)=(unsigned short)( unsigned long)=( signed short)( signed long)=(unsigned short)( signed long)=( signed short)(unsigned short)=(unsigned short)(unsigned short)=( signed short)( signed short)=(unsigned short)( signed short)=( signed short)\begin{align*} \rm LHS &= RHS \\ \text{( unsigned long)} &= \text{(unsigned long)} \\ \text{( unsigned long)} &= \text{( signed long)} \\ \text{( signed long)} &= \text{(unsigned long)} \\ \text{( signed long)} &= \text{( signed long)} \\ \\ \text{(unsigned short)} &= \text{(unsigned long)}\\ \text{(unsigned short)} &= \text{( signed long)}\\ \text{( signed short)} &= \text{(unsigned long)}\\ \text{( signed short)} &= \text{( signed long)}\\ \\ \text{( unsigned long)} &= \text{(unsigned short)}\\ \text{( unsigned long)} &= \text{( signed short)}\\ \text{( signed long)} &= \text{(unsigned short)}\\ \text{( signed long)} &= \text{( signed short)}\\ \\ \text{(unsigned short)} &= \text{(unsigned short)}\\ \text{(unsigned short)} &= \text{( signed short)}\\ \text{( signed short)} &= \text{(unsigned short)}\\ \text{( signed short)} &= \text{( signed short)} \end{align*}

Long/short unsigned/signed Verilog Conversion Rule Demos

Verilog

module conversion_demo;

wire [7:0] 
  u8x = 8'b11111111;              
wire signed [7:0] 
  s8x = 8'b11111111;   
wire [15:0]       
  u16x = 16'b1111_1111_1111_1111;    
wire signed [15:0] 
  s16x = 16'b1111_1111_1111_1111;   
wire        [15:0] u16y_ux = u8x;   
wire        [15:0] u16y_sx = s8x;
wire signed [15:0] s16y_ux = u8x;   
wire signed [15:0] s16y_sx = s8x;   

wire        [7:0] u8y_ux = u16x;    
wire        [7:0] u8y_sx = s16x;
wire signed [7:0] s8y_ux = u16x;    
wire signed [7:0] s8y_sx = s16x;   

initial begin
#0;
$display("u16y_ux:%16b,%7d",u16y_ux,u16y_ux);
//u16y_ux: 0000000011111111,     255
$display("u16y_sx:%16b,%7d",u16y_sx,u16y_sx);
//u16y_sx: 1111111111111111,   65535
$display("s16y_ux:%16b,%7d",s16y_ux,s16y_ux);
//s16y_ux: 0000000011111111,     255
$display("s16y_sx:%16b,%7d",s16y_sx,s16y_sx);
//s16y_sx: 1111111111111111,      -1
$display(" u8y_ux: %16b, %7d",u8y_ux,u8y_ux);
//u8y_ux:         11111111,      255
$display(" u8y_sx: %16b, %7d",u8y_sx,u8y_sx);
//u8y_sx:         11111111,      255
$display(" s8y_ux: %16b, %7d",s8y_ux,s8y_ux);
//s8y_ux:         11111111,       -1
$display(" s8y_sx: %16b, %7d",s8y_sx,s8y_sx);
//s8y_sx:         11111111,       -1
end
endmodule

C/C++

unsigned short u16x = 0xFFFF;              
signed short s16x = 0xFFFF;   
unsigned int u32x = 0xFFFFFFFF;    
signed int s32x = 0xFFFFFFFF;   
unsigned int u32y_u16x = u16x;   
unsigned int u32y_s16x = s16x;
signed int s32y_u16x = u16x;   
signed int s32y_s16x = s16x;   
unsigned short u16y_u32x = u32x;    
unsigned short u16y_s32x = s32x;
signed short s16y_u32x = u32x;    
signed short s16y_s32x = s32x;   

printf("sizeof(short) :%lu\n",sizeof(short));
printf("sizeof(int)   :%lu\n",sizeof(int));
printf("---\n");
printf("u32y_u16x: %10u\n",u32y_u16x);
printf("u32y_s16x: %10u\n",u32y_s16x);
printf("s32y_u16x: %10d\n",s32y_u16x);
printf("s32y_s16x: %10d\n",s32y_s16x);
printf("u16y_u32x: %10u\n",u16y_u32x);
printf("u16y_s32x: %10u\n",u16y_s32x);
printf("s16y_u32x: %10d\n",s16y_u32x);
printf("s16y_s32x: %10d\n",s16y_s32x);
sizeof(short) :2
sizeof(int)   :4
---
u32y_u16x:      65535
u32y_s16x: 4294967295
s32y_u16x:      65535
s32y_s16x:         -1
u16y_u32x:      65535
u16y_s32x:      65535
s16y_u32x:         -1
s16y_s32x:         -1

Review Points on Bit Length

Not All Adder Structures are Alike

Knowing the options for implementation of addition on a given platform in the context of algorithm implementation is important. There are tradeoffs for size and speed. An overview of adders is provided in a later lecture.

Verilog: Sign Extension along with Addition

wire signed [7:0] x,y;
wire signed [15:0] s1,s2;

assign s1 = {8{x[7]},x} + 
            {8{y[7]},y} // explicit sign
                        // extension

assign s2 = x + y; // implicit sign extension

Run-time Overflow Detection for Addition

C (for reference only)

Takeaway

  • Addition overflow possible only if input signs are same, in which case is indicated by the result is a different sign after the operation is performed
  • If native word-size is used, may be able to use hardware overflow flag
    • Otherwise, might sign-extention first or otherwise need to provide software to check appropriate bits
  • A pre-overflow operation check on the input operands is give by example for SIGNED INT: ((a>0) && (b>(INT_MAX-a))) | ((a<0) && (b<(INT_MIN+a)))

Run-time Overflow Detection for Subtraction

Takeaway