-- +---------------------------+
-- |   Copyright 1996 DOULOS   |
-- |      Generic Library      |
-- |    opened: 25 Nov 1995    |
-- +---------------------------+

-- Synthesis script: read -f vhdl ops_2sC.bdy

library ieee;
library vfp;

package body twos_complement_operators is
  use ieee.std_logic_1164.all;
  use vfp.twos_complement_types.all;
  use vfp.generic_functions.all;
  use vfp.generic_conversions.all;
  use vfp.std_operators.all;
  
function "not" (                      -- 25.11.95
  a: twos_complement 
) return twos_complement is
  variable yi: twos_complement(a'length-1 downto 0);
begin
  for i in 0 to a'length-1 loop
    yi(i) := not (a(i));
  end loop;
  return yi;
end "not";
    
function "and" (                      -- 24.11.95
  a, b: twos_complement 
) return twos_complement is
  variable y: twos_complement(a'length-1 downto 0);
begin
  if (a'length /= b'length) then
    assert false
      report "Error 0000." & 
             "Library = vfp." & 
             "Package Body = twos_complement_operators." & 
             "Function = and." & 
             "The wordlength of a and b MUST be the same."
      severity error;
  else
    for i in 0 to a'length-1 loop
      y(i) := a(i) and b(i);
    end loop;
  end if;
  return y;
end "and";
    
function "or" (                           -- 25.11.95
  a, b: twos_complement 
) return twos_complement is
  variable y: twos_complement(a'length-1 downto 0);
begin
  if (a'length /= b'length) then
    assert false
      report "Error 0001." & 
             "Library = vfp." & 
             "Package Body = twos_complement_operators." & 
             "Function = or." & 
             "The wordlength of a and b MUST be the same."
      severity error;
  else
    for i in 0 to a'length-1 loop
      y(i) := a(i) or b(i);
    end loop;
  end if;
  return y;
end "or";
    
function "xor" (                           -- 25.11.95
  a, b: twos_complement 
) return twos_complement is
  variable y: twos_complement(a'length-1 downto 0);
begin
  if (a'length /= b'length) then
    assert false
      report "Error 0001." & 
             "Library = vfp." & 
             "Package Body = twos_complement_operators." & 
             "Function = xor." & 
             "The wordlength of a and b MUST be the same."
      severity error;
  else
    for i in 0 to a'length-1 loop
      y(i) := a(i) xor b(i);
    end loop;
  end if;
  return y;
end "xor";

function "nand" (                           -- 25.11.95
  a, b: twos_complement 
) return twos_complement is
  variable y: twos_complement(a'length-1 downto 0);
begin
  if (a'length /= b'length) then
    assert false
      report "Error 0001." & 
             "Library = vfp." & 
             "Package Body = twos_complement_operators." & 
             "Function = nand." & 
             "The wordlength of a and b MUST be the same."
      severity error;
  else
    for i in 0 to a'length-1 loop
      y(i) := a(i) nand b(i);
    end loop;
  end if;
  return y;
end "nand";

function "nor" (                           -- 25.11.95
  a, b: twos_complement 
) return twos_complement is
  variable y: twos_complement(a'length-1 downto 0);
begin
  if (a'length /= b'length) then
    assert false
      report "Error 0001." & 
             "Library = vfp." & 
             "Package Body = twos_complement_operators." & 
             "Function = nor." & 
             "The wordlength of a and b MUST be the same."
      severity error;
  else
    for i in 0 to a'length-1 loop
      y(i) := a(i) nor b(i);
    end loop;
  end if;
  return y;
end "nor";

-- function "xnor" (                           -- 25.11.95
--   a, b: twos_complement 
-- ) return twos_complement is
--   variable y: twos_complement(a'length-1 downto 0);
-- begin
--   if (a'length /= b'length) then
--     assert false
--       report "Error 0001." & 
--              "Library = vfp." & 
--              "Package Body = twos_complement_operators." & 
--              "Function = xnor." & 
--              "The wordlength of a and b MUST be the same."
--       severity error;
--   else
--     for i in 0 to a'length-1 loop
--       y(i) := a(i) xnor b(i);
--     end loop;
--   end if;
--   return y;
-- end "xnor";
 
function "+" (                      -- 25.11.95
  a, b: twos_complement 
) return twos_complement is
  constant y_length: integer := longest (a, b);
  variable a_sign_extended, b_sign_extended: twos_complement(y_length-1 downto 0);
  variable y: twos_complement(y_length-1 downto 0);
  variable carry: std_ulogic;
begin
  carry := '0';
  if (a'length < b'length) then
    for i in b'length-1 downto a'length loop
      a_sign_extended(i) := a(a'length-1);
    end loop;
    a_sign_extended(a'length-1 downto 0) := a;
    for i in 0 to b'length-1 loop
      y(i) := a_sign_extended(i) xor b(i) xor carry;
      carry := (a_sign_extended(i) and b(i)) or
               (a_sign_extended(i) and carry) or
               (b(i) and carry);
    end loop;
  elsif (a'length > b'length) then
    for i in a'length-1 downto b'length loop
      b_sign_extended(i) := b(b'length-1);
    end loop;
    b_sign_extended(b'length-1 downto 0) := b;
    for i in 0 to a'length-1 loop
      y(i) := a(i) xor b_sign_extended(i) xor carry;
      carry := (a(i) and b_sign_extended(i)) or
               (a(i) and carry) or
               (b_sign_extended(i) and carry);
    end loop;
  else                            -- i.e., (a'length = b'length)
    for i in 0 to a'length-1 loop
      y(i) := a(i) xor b(i) xor carry;
      carry := (a(i) and b(i)) or
               (a(i) and carry) or
               (b(i) and carry);
    end loop;
  end if;
  return y;
end "+";

function "-" (                      -- 29.11.95
  a, b: twos_complement 
) return twos_complement is
  constant y_length: integer := longest (a, b);
  variable a_sign_extended, b_sign_extended: twos_complement(y_length-1 downto 0);
  variable y: twos_complement(y_length-1 downto 0);
  variable carry: std_ulogic;
begin
  carry := '1';
  if (a'length < b'length) then
    for i in b'length-1 downto a'length loop
      a_sign_extended(i) := a(a'length-1);
    end loop;
    a_sign_extended(a'length-1 downto 0) := a;
    for i in 0 to b'length-1 loop
      y(i) := a_sign_extended(i) xor (not b(i)) xor carry;
      carry := (a_sign_extended(i) and (not b(i))) or
               (a_sign_extended(i) and carry) or
               (not (b(i)) and carry);
    end loop;
  elsif (a'length > b'length) then
    for i in a'length-1 downto b'length loop
      b_sign_extended(i) := b(b'length-1);
    end loop;
    b_sign_extended(b'length-1 downto 0) := b;
    for i in 0 to a'length-1 loop
      y(i) := a(i) xor (not b_sign_extended(i)) xor carry;
      carry := (a(i) and (not b_sign_extended(i))) or
               (a(i) and carry) or
               ((not b_sign_extended(i)) and carry);
    end loop;
  else                            -- i.e., (a'length = b'length)
    for i in 0 to a'length-1 loop
      y(i) := a(i) xor (not b(i)) xor carry;
      carry := (a(i) and (not b(i))) or
               (a(i) and carry) or
               ((not b(i)) and carry);
    end loop;
  end if;
  return y;
end "-";
  
function "*" (                      -- 30.11.95
  a, b: twos_complement 
) return twos_complement is
  constant y_length: integer := a'length + b'length;
  variable y_sign: std_ulogic;
--  variable a_1sC, multiplicand: twos_complement(a'length-1 downto 0);
--  variable b_1sC, multiplier: twos_complement(b'length-1 downto 0);
  variable a_1sC, multiplicand: std_ulogic_vector(a'length-1 downto 0);
  variable b_1sC, multiplier: std_ulogic_vector(b'length-1 downto 0);
  variable carry: std_ulogic; 
--  variable partial_product: twos_complement(a'length-1 downto 0);
  variable partial_product: std_ulogic_vector(a'length-1 downto 0);
  variable product_lsb: twos_complement(b'length-1 downto 0);
  variable product: twos_complement(y_length-1 downto 0);
  variable y_1sC: twos_complement(y_length-1 downto 0);
  variable y: twos_complement(y_length-1 downto 0);
begin
-- firstly, the sign of the result is extracted               --   BB x 02
  y_sign := a(a'length-1) xor b(b'length-1);                  --    1
-- second, the operands are converted to absolute values      --
  if (a(a'length-1) = '1') then                               --
    a_1sC := to_std_ulogic_vector (not a);                                           --    44
    carry := '1';                                             --
    for i in 0 to a'length-1 loop                             --  0 1 2 3 4 5 6 7
      multiplicand(i) := a_1sC(i) xor carry;                  --  1 0 1 0 0 0 1 0
      carry := a_1sC(i) and carry;                            --  0 0 0 0 0 0 0 0
    end loop;                                                 --    45 
  else                                                        --
    multiplicand := to_std_ulogic_vector (a);                                        --
  end if;                                                     --
  if (b(b'length-1) = '1') then                               --
    b_1sC := to_std_ulogic_vector (not b);                                           --
    carry := '1';                                             --
    for i in 0 to b'length-1 loop                             --
      multiplier(i) := b_1sC(i) xor carry;                    --
      carry := b_1sC(i) and carry;                            --
    end loop;                                                 --
  else                                                        --
    multiplier := to_std_ulogic_vector (b);                                          --    02
  end if;                                                     --
-- thirdly, the multiplication of the absolute values takes place
  for i in 0 to (multiplicand'length - 1) loop                --
    partial_product(i) := '0';                                --    00
  end loop;                                                   --
  for i in 0 to multiplier'length-1 loop                      --                  0 1 2 3 4 5 6 7
    if (multiplier(i) = '1') then                             --
--      partial_product := partial_product(a'length-1 downto 1) + multiplicand;  -- 
      partial_product := partial_product + multiplicand;  -- 
      product_lsb(i) := partial_product(0);                          --
      partial_product := '0' & partial_product(a'length-1 downto 1);  -- 
    else                                                             --
      product_lsb(i) := partial_product(0);                          --           0
      partial_product := '0' & partial_product(a'length-1 downto 1); --           0
    end if;                                                          --         pp = 00
  end loop;                                                           --        lsb = 8A
-- now the result's absolute value is converted to it's 2's complement value
  product := to_twos_complement (partial_product) & product_lsb;                       --
  if (y_sign = '1') then                                          --
    y_1sC := not product;                                         --   FF75
    carry := '1';                                                 --
    for i in 0 to y_1sC'length-1 loop                             --
      y(i) := y_1sC(i) xor carry;                                 --
      carry := y_1sC(i) and carry;                                --
    end loop;                                                     --   FF76
  else                                                            --
    y := product;                                                 --
  end if;                                                         --
  return y;                                                       --
end "*";

function "/" (                      -- 29.11.95
  a, b: twos_complement 
) return twos_complement is
  constant y_length: integer := a'length + b'length; 
  constant a_extended_length: integer := b'length-1;
  variable y_sign: std_ulogic;
  variable a_1sC, a_abs: twos_complement(a'length-1 downto 0);
  variable b_1sC, b_abs: twos_complement(b'length-1 downto 0);
  variable carry: std_ulogic; 
  variable a_extended: twos_complement(a_extended_length-1 downto 0);
  variable dividend_match: twos_complement(b'length-1 downto 0);
  variable quotient: twos_complement(a'length-1 downto 0);
  variable remainder: twos_complement(b'length-1 downto 0);
  variable quotient_abs, quotient_1sC: twos_complement(a'length-1 downto 0);
  variable remainder_abs, remainder_1sC: twos_complement(b'length-1 downto 0);
  variable y: twos_complement(y_length-1 downto 0);
begin
-- firstly, the sign of the result is extracted
  y_sign := a(a'length-1) xor b(b'length-1);
-- second, the operands are converted to absolute values
  if (a(a'length-1) = '1') then
    a_1sC := not a;
    carry := '1';
    for i in 0 to a'length-1 loop
      a_abs(i) := a_1sC(i) xor carry;
      carry := a_1sC(i) and carry;
    end loop;
  else
    a_abs := a;
  end if;
  if (b(b'length-1) = '1') then
    b_1sC := not b;
    carry := '1';
    for i in 0 to b'length-1 loop
      b_abs(i) := b_1sC(i) xor carry;
      carry := b_1sC(i) and carry;
    end loop;
  else
    b_abs := b;
  end if;
-- thirdly, the division of the absolute values takes place
  for i in a_extended_length-1 downto 0 loop
    a_extended(i) := '0';
  end loop;
  dividend_match(b_abs'length-1 downto 1) := a_extended;
  for i in a_abs'length-1 downto 0 loop
    dividend_match := dividend_match(b_abs'length-1 downto 1) & a_abs(i);
    if (b_abs <= dividend_match) then
      dividend_match := dividend_match - b_abs;
      quotient_abs(i) := '1';
    else
      quotient_abs(i) := '0';
    end if;
  end loop; 
  remainder_abs := dividend_match;
-- now the result's absolute value is converted to it's 2's complement value
-- note that the sign of the remainder follows the sign of the dividend
  if (y_sign = '1') then
    quotient_1sC := not quotient_abs;
    carry := '1';
    for i in 0 to quotient_1sC'length-1 loop
      quotient(i) := quotient_1sC(i) xor carry;
      carry := quotient_1sC(i) and carry;
    end loop;
  else
    quotient := quotient_abs;
  end if;    
  if (a(a'length-1) = '1') then
    remainder_1sC := not remainder_abs;
    carry := '1';
    for i in 0 to remainder_1sC'length-1 loop
      remainder(i) := remainder_1sC(i) xor carry;
      carry := remainder_1sC(i) and carry;
    end loop;
  else
    remainder := remainder_abs;
  end if;    
  y := quotient & remainder;
  return y;
end "/";
    
function "mod" (                      -- 2.12.95
  a, b: twos_complement 
) return twos_complement is
  constant y_length: integer := a'length + b'length; 
  constant a_extended_length: integer := b'length-1;
  variable a_1sC, a_abs: twos_complement(a'length-1 downto 0);
  variable b_1sC, b_abs: twos_complement(b'length-1 downto 0);
  variable carry: std_ulogic; 
  variable a_extended: twos_complement(a_extended_length-1 downto 0);
  variable dividend_match: twos_complement(b'length-1 downto 0);
  variable remainder: twos_complement(b'length-1 downto 0);
  variable remainder_abs, remainder_1sC: twos_complement(b'length-1 downto 0);
  variable y: twos_complement(b'length-1 downto 0);
begin
-- firstly, the operands are converted to absolute values
  if (a(a'length-1) = '1') then
    a_1sC := not a;
    carry := '1';
    for i in 0 to a'length-1 loop
      a_abs(i) := a_1sC(i) xor carry;
      carry := a_1sC(i) and carry;
    end loop;
  else
    a_abs := a;
  end if;
  if (b(b'length-1) = '1') then
    b_1sC := not b;
    carry := '1';
    for i in 0 to b'length-1 loop
      b_abs(i) := b_1sC(i) xor carry;
      carry := b_1sC(i) and carry;
    end loop;
  else
    b_abs := b;
  end if;
-- secondly, the division of the absolute values takes place
  for i in a_extended_length-1 downto 0 loop
    a_extended(i) := '0';
  end loop;
  dividend_match(b_abs'length-1 downto 1) := a_extended;
  for i in a_abs'length-1 downto 0 loop
    dividend_match := dividend_match(b_abs'length-1 downto 1) & a_abs(i);
    if (b_abs <= dividend_match) then
      dividend_match := dividend_match - b_abs;
    end if;
  end loop; 
  remainder_abs := dividend_match;
-- now the result's absolute value is converted to it's 2's complement value
-- note that the sign of the remainder follows the sign of the dividend
  if (a(a'length-1) = '1') then
    remainder_1sC := not remainder_abs;
    carry := '1';
    for i in 0 to remainder_1sC'length-1 loop
      remainder(i) := remainder_1sC(i) xor carry;
      carry := remainder_1sC(i) and carry;
    end loop;
  else
    remainder := remainder_abs;
  end if;    
  y := remainder;
  return y;
end "mod";
    
function "rem" (                      -- 2.12.95
  a, b: twos_complement 
) return twos_complement is
  constant y_length: integer := a'length + b'length; 
  constant a_extended_length: integer := b'length-1;
  variable a_1sC, a_abs: twos_complement(a'length-1 downto 0);
  variable b_1sC, b_abs: twos_complement(b'length-1 downto 0);
  variable carry: std_ulogic; 
  variable a_extended: twos_complement(a_extended_length-1 downto 0);
  variable dividend_match: twos_complement(b'length-1 downto 0);
  variable remainder: twos_complement(b'length-1 downto 0);
  variable remainder_abs, remainder_1sC: twos_complement(b'length-1 downto 0);
  variable y: twos_complement(b'length-1 downto 0);
begin
-- firstly, the operands are converted to absolute values
  if (a(a'length-1) = '1') then
    a_1sC := not a;
    carry := '1';
    for i in 0 to a'length-1 loop
      a_abs(i) := a_1sC(i) xor carry;
      carry := a_1sC(i) and carry;
    end loop;
  else
    a_abs := a;
  end if;
  if (b(b'length-1) = '1') then
    b_1sC := not b;
    carry := '1';
    for i in 0 to b'length-1 loop
      b_abs(i) := b_1sC(i) xor carry;      
      carry := b_1sC(i) and carry;
    end loop;
  else
    b_abs := b;
  end if;
-- secondly, the division of the absolute values takes place
  for i in a_extended_length-1 downto 0 loop
    a_extended(i) := '0';
  end loop;
  dividend_match(b_abs'length-1 downto 1) := a_extended;
  for i in a_abs'length-1 downto 0 loop
    dividend_match := dividend_match(b_abs'length-1 downto 1) & a_abs(i);
    if (b_abs <= dividend_match) then
      dividend_match := dividend_match - b_abs;
    end if;
  end loop; 
  remainder_abs := dividend_match;
-- now the result's absolute value is converted to it's 2's complement value
-- note that the sign of the remainder follows the sign of the dividend
  if (a(a'length-1) = '1') then
    remainder_1sC := not remainder_abs;
    carry := '1';
    for i in 0 to remainder_1sC'length-1 loop
      remainder(i) := remainder_1sC(i) xor carry;
      carry := remainder_1sC(i) and carry;
    end loop;
  else
    remainder := remainder_abs;
  end if;    
  y := remainder;
  return y;
end "rem";        

function "**" (                      -- 2.12.95
  a, b: twos_complement 
) return twos_complement is
  variable y: twos_complement(a'length-1 downto 0);
begin
  assert false
    report "Error 0001." &                                
           "Library = vfp." &                             
           "Package Body = twos_complement_operators." &   
           "Function = **." &                              
           "The function (twos_complement) ** (twos_complement) is not supported." &
           "However, to_twos_complement(to_integer(twos_complementy) ** to_integer(twos_complement)) is supported."                              
-- See the to_integer and the to_twos_complement conversion functions
    severity error;
  y := a;
  return y;
end "**";

function "abs" (                      -- 2.12.95
  a: twos_complement 
) return twos_complement is
-- the function abs_wordlength returns a'length+1 if a is
-- -2(N-1) otherwise it returns a'length
  constant y_length: integer := abs_wordlength(a); 
  variable a_1sC: twos_complement(a'length-1 downto 0);
  variable carry: std_ulogic;
  variable y: twos_complement(y_length-1 downto 0);
begin
  if (y_length = a'length+1) then
    y(a'length) := '1';
  end if;
  if (a(a'length-1) = '1') then
    a_1sC := not a;
    carry := '1';
    for i in 0 to a'length-1 loop
      y(i) := a_1sC(i) xor carry;
      carry := a_1sC(i) and carry;
    end loop;
  else
    y := a;
  end if;
  return y;
end "abs";

function "+" (                      -- 2.12.95
  a: twos_complement 
) return twos_complement is
  variable y: twos_complement(a'length-1 downto 0);
begin
  assert false
    report "Warning 0001." &                                
           "Library = vfp." &                             
           "Package Body = twos_complement_operators." &   
           "Function = +." &                              
           "The function + (twos_complement) is defined as ... " &
           "    <return_value> := <actual_parameter>    " &
           "Thus there is no point in taking the positive value of a twos_complement object."                              
    severity warning;
  y := a;
  return y;
end "+";

function "-" (                      -- 2.12.95
  a: twos_complement 
) return twos_complement is
-- the function abs_wordlength returns a'length+1 if a is
-- -2(N-1) otherwise it returns a'length
  constant y_length: integer := abs_wordlength(a); 
  variable a_1sC: twos_complement(a'length-1 downto 0);
  variable carry: std_ulogic;
  variable y: twos_complement(y_length-1 downto 0);
begin
  if (y_length = a'length+1) then
    y(a'length) := '0';
  end if;
  a_1sC := not a;
  carry := '1';
  for i in 0 to a'length-1 loop
    y(i) := a_1sC(i) xor carry;
    carry := a_1sC(i) and carry;
  end loop;
  return y;
end "-";

-- an alternative body
-- take the 2s complement vectors & convert them to 
-- integers. Then add the integers.

end twos_complement_operators;



<div align="center"><br /><script type="text/javascript"><!--
google_ad_client = "pub-7293844627074885";
//468x60, Created at 07. 11. 25
google_ad_slot = "8619794253";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><br />&nbsp;</div>