This website uses cookies. By using this site, you consent to the use of cookies. For more information, please take a look at our Privacy Policy.
Home > FPGA Technical Tutorials > Design Recipes for FPGAs Using Verilog and VHDL > ALU Functions > Two’s Complement

TABLE OF CONTENTS

Xilinx FPGA FPGA Forum

Two’s Complement

FONT SIZE : AAA

An integral part of subtraction in logic systems is the use of two’s complement. This enables us to execute a subtraction function using only an adder rather than requiring a separate subtraction function. Two’s complement is an extension to the basic ones’ complement (or basic inversion of bits) previously considered.

If we consider an unsigned number system based on 4 bits, then the range of the numbers is 0 to 15 (0000 to 1111). If we consider a signed system, however, the most significant bit (MSB) is considered to be the sign (+ or −) of the number system and therefore the range of numbers with 4 bits will instead be from −8 to +7. The method of conversion from positive to negative number in binary logic is a simple two-stage process of first inverting all the bits and then adding 1 to the result.

Consider an example. Take a number 00112. In signed number form, the MSB is 0, so the number is positive and the lower three bits 011 can be directly translated into decimal 3. To get the two’s complement (−3), we first invert all the bits to get 1100, and then add a single bit to get the final two’s complement value 1101. To check that this is indeed the inverse in binary, simple add the number 0011 to its two’s complement 1101 and the result should be 0000.

In a signed system the range of numbers is −(2N − 1) to +(2N − 1 − 1) whereas in the unsigned system the range is defined by 0 to +(2N − 1). The signed system allows both positive and negative numbers; however, the maximum magnitude is effectively half the magnitude of the unsigned system.

This function can be implemented simply in VHDL using the following model:

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

entity twoscomplement is

generic (

n : integer := 8

);

port (

input : in std_logic_vector((n−1) downto 0);

output : out std_logic_vector((n−1) downto 0)

);

end;

architecture simple of twoscomplement is

begin

process(input)

variable inv : unsigned((n−1) downto 0);

begin

inv := unsigned(NOT input);

inv := inv + 1;

output <= std_logic_vector(inv);

end process;

end;

As can be seen from the VHDL, we operate using logic functions first (NOT) and then convert to unsigned to utilize the addition function (inv + 1), and finally convert the result back into a std_logic_vector type. Also notice that the generic n allows this model to be configured for any data size. In this example, the test bench is used to check that the function is operating correctly by using two test circuits back to back, inverting and re-inverting the input word and checking that the function returns the same value. While this does not guarantee correct operation (the same bug could be present in both transforms!), it is a simple quick check that is very useful and makes generation of test data and checks very easy, as the input and final output signal check can be XORed to check for differences.

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

entity twoscomplementtest is

end twoscomplementtest ;

architecture stimulus of twoscomplementtest is

signal rst : std_logic := ’0’;

signal clk : std_logic:=’0’;

signal count : std_logic_vector (7 downto 0);

signal inverse : std_logic_vector (7 downto 0);

signal check : std_logic_vector (7 downto 0);

component twoscomplement

port(

input : in std_logic_vector(7 downto 0);

output : out std_logic_vector(7 downto 0)

);

end component;

for all : twoscomplement use entity work.twoscomplement ;

begin

CUT1: twoscomplement port map(input=>count,output=>inverse);

CUT2: twoscomplement port map(input=>inverse,output=>check);

−− clock and reset process

clk <= not clk after 1 us;

process

begin

rst<=’0’,’1’ after 2.5 us;

wait;

end process;

−− generate data

process(clk, rst)

variable tempcount : unsigned(7 downto 0);

begin

if rst = ’0’ then

tempcount := (others => ’0’);

elsif rising_edge(clk) then

tempcount := tempcount + 1;

end if;

count <= std_logic_vector(tempcount );

end process;

end;

  • XC5VLX110-3FFG1760C

    Manufacturer:Xilinx

  • FPGA Virtex-5 LX Family 110592 Cells 65nm Technology 1V 1760-Pin FCBGA
  • Product Categories: FPGAs (Field Programmable Gate Array)

    Lifecycle:Active Active

    RoHS:

  • XC2V2000-5BFG957I

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 2M Gates 24192 Cells 750MHz 0.15um Technology 1.5V 957-Pin FCBGA
  • Product Categories: FPGAs (Field Programmable Gate Array)

    Lifecycle:Obsolete -

    RoHS:

  • XC2V2000-5FFG896I

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 2M Gates 24192 Cells 750MHz 0.15um Technology 1.5V 896-Pin FCBGA
  • Product Categories: FPGAs (Field Programmable Gate Array)

    Lifecycle:Obsolete -

    RoHS:

  • XC5VLX110T-1FF1136I

    Manufacturer:Xilinx

  • FPGA Virtex-5 LXT Family 110592 Cells 65nm Technology 1V 1136-Pin FCBGA
  • Product Categories: FPGAs

    Lifecycle:Active Active

    RoHS: No RoHS

  • XC5VLX110T-1FFG1738C

    Manufacturer:Xilinx

  • FPGA Virtex-5 LXT Family 110592 Cells 65nm Technology 1V 1738-Pin FCBGA
  • Product Categories: FPGAs (Field Programmable Gate Array)

    Lifecycle:Active Active

    RoHS:

Need Help?

Support

If you have any questions about the product and related issues, Please contact us.