-- Model Name : Concurrent - Synthesis Utilities -- Author : Armita Peymandoust -- Last Updated : 09 / 15 / 1996 -- This document is © copyrighted by the Author.

LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
--
PACKAGE synthesis_utilities IS
  FUNCTION all_or (v : std_logic_vector) RETURN std_logic;
  FUNCTION addsub_cv (a, b : std_logic_vector; cin : std_logic; add_sub : std_logic) 
  RETURN std_logic_vector;
----------
  SUBTYPE nibble IS std_logic_vector (3 DOWNTO 0);
  TYPE nibble_node;
  TYPE nibble_node_ptr IS ACCESS nibble_node;
  TYPE nibble_node IS RECORD
    val    : nibble;
    link   : nibble_node_ptr; --for link list;  
  END RECORD;
----------
  SUBTYPE byte IS std_logic_vector (7 DOWNTO 0);
  TYPE byte_node;
  TYPE byte_node_ptr IS ACCESS byte_node;
  TYPE byte_node IS RECORD
    val    : byte;
    link   : byte_node_ptr; --for link list;  
  END RECORD;
----------
  SUBTYPE twelve IS std_logic_vector (11 DOWNTO 0);
  TYPE twelve_node;
  TYPE twelve_node_ptr IS ACCESS twelve_node;
  TYPE twelve_node IS RECORD
    val    : twelve;
    link   : twelve_node_ptr; --for link list;  
  END RECORD;
-----------

END synthesis_utilities;
--

PACKAGE BODY synthesis_utilities IS

---------------------
  FUNCTION all_or (v : std_logic_vector) RETURN std_logic IS
    VARIABLE temp : std_logic;
  BEGIN
    temp := '0';
    FOR i IN v'RANGE LOOP
      temp := temp OR v(i);
    END LOOP;
    RETURN temp;
  END all_or; 
  FUNCTION addsub_cv (a, b : std_logic_vector; cin : std_logic; add_sub : std_logic) 
  RETURN std_logic_vector IS
    --for adding add_sub is 0, for subtracting add_sub is 1
    --left bits of a and b are sign bit
    VARIABLE r: std_logic_vector (a'LEFT + 2 DOWNTO 0); --intermediate result
    -- Left two bits of r are for v and c respectively
    VARIABLE c: std_logic_vector (a'LEFT DOWNTO 0);     --intermediate carry
    VARIABLE a_sign, b_sign: std_logic;                 --sign bits of a and b
    VARIABLE cin_signed : std_logic;                    --complement cin for sub
    VARIABLE b_signed : std_logic_vector (b'RANGE);     --complement b for sub
  BEGIN
    cin_signed := cin XOR add_sub;
    FOR i IN b'RANGE LOOP
      b_signed (i) := b(i) XOR add_sub;
    END LOOP; 
    a_sign := a(a'LEFT); 
    b_sign := b_signed(b'LEFT);
    r(0) := a(0) XOR b_signed(0) XOR cin_signed;
    c(0) := ((a(0) XOR b_signed(0)) AND cin_signed) OR (a(0) AND b_signed(0));
    FOR i IN 1 TO (a'LEFT) LOOP
      r(i) := a(i) XOR b_signed(i) XOR c(i-1);
      c(i) := ((a(i) XOR b_signed(i)) AND c(i-1)) OR (a(i) AND b_signed(i));
    END LOOP;
    r(a'LEFT+1) := c(a'LEFT);
    IF a_sign = b_sign AND r(a'LEFT) /= a_sign
      THEN r(a'LEFT+2) := '1'; --overflow
    ELSE r(a'LEFT+2) := '0'; END IF;
    RETURN r;
  END addsub_cv;
END synthesis_utilities;