-----------------------------------------------------
--Generated by Utility gen_entity.pl by Aviral Mittal
-----------------------------------------------------
--Following is a pkg file, defining some commonly used vhdl functions.
-- Version 2.0
--
--
--------------------------------------------------------------------------------
-- Changes wrt prev release.
-- 2.0 : new functions added
-- sext : Sign Extend
-- bit_reverse : Reverse the order of bits of a vector
-- shln : shift left by 'n' bits
-- ccitt_crc_16 : CRC
-- Date : 28 Oct 2009
--
--
-- 1.0 a new function addition called tc i.e twos compliment.
-- Date of Release 18 Jan 2006
--------------------------------------------------------------------------------
--$Author: amittal $
--------------------------------------------------------------------------------
--$Date: Fri May  1 20:23:09 2009 $
--------------------------------------------------------------------------------
--$Revision: 1.5 $
--------------------------------------------------------------------------------
--$Log: fun_pkg.vhdl.rca $
--
-- Revision: 1.5 Fri May  1 20:23:09 2009 amittal
-- made shln synthesizeable
--
-- Revision: 1.4 Fri Jan 30 13:58:41 2009 amittal
-- corrected ccitt_crc_16 function
--
-- Revision: 1.2 Fri Jul 11 11:14:01 2008 amittal
-- Added Shift functions
--------------------------------------------------------------------------------
--$Revision: 1.5 $
--------------------------------------------------------------------------------
--$KeysEnd$
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

PACKAGE fun_pkg IS

  FUNCTION NextGray(G1:std_logic_vector) return std_logic_vector;
  --this function implements a length independent gray counter.
  --No arithmatic operators are used.

  FUNCTION bin2gray(B1:std_logic_vector) return std_logic_vector;
  --this function converts a binary count to gray count

  FUNCTION gray2bin(G1:std_logic_vector) return std_logic_vector;
  --this function converts a gray count to binary count

  FUNCTION crr(s1:std_logic_vector;index:integer) return std_logic_vector;
             --crr=CircularRotateRight
              --this function Circular Rotates Right 's1' by 'index'

  FUNCTION crl(s1:std_logic_vector;index:integer) return std_logic_vector;
              --crl=CircularRotateLeft
              --this function Circular Rotates Right 's1' by 'index'

  FUNCTION incr_vec(s1:std_logic_vector;en:std_logic) return std_logic_vector;
  --This function increments an std_logic_vector type by '1', without
  --using any arithmatic

  FUNCTION dcr_vec(s1:std_logic_vector;en:std_logic) return std_logic_vector;
  --This function decrements an std_logic_vector type by '1', without
  --using any arithmatic

  FUNCTION all_ones(s1:std_logic_vector) return std_logic;
  --This function returns if the input vector has all ones and no zeros

  FUNCTION all_zeros(s1:std_logic_vector) return std_logic;
  --This function returns if the input vector has all zeros and no ones

  FUNCTION mux1(a0:std_logic;a1:std_logic;sel:std_logic) return std_logic;
  --one bit mux, handy to be used in combinational assignmets

  FUNCTION mux_vec(a0:std_logic_vector;a1:std_logic_vector;sel:std_logic) return  std_logic_vector;
  --multi bit mux, handy to be used in combinational assignmets

  FUNCTION if_eq(s1:std_logic_vector;s2:std_logic_vector) return std_logic;
  --returns a '1' iff s1=s2(s1 and s2 MUST be of equal no of bits

  FUNCTION inv_if_one(s1:std_logic_vector;en:std_logic) return std_logic_vector;
  --retruns a 1's compilment of s1, if en is '1' otherwise s1 as such is returned
  FUNCTION inv(s1:std_logic_vector) return std_logic_vector;
  --retruns a 1's compilment of s1 i.e invert of s1;

  FUNCTION myabs(s1:std_logic_vector) return std_logic_vector;
                  --this function returns an absolute value of a vector

  FUNCTION twos_comp(s1:std_logic_vector) return std_logic_vector;
  --returns a twos compliment of s1
  --To make things more clear: It returns s1 itself if s1(s1'high) = '0'. Since
  --if s1(s1'high) i.e msb of s1 is '0', then the input no is +ive and hence
  --no processing is done on s1. On the other hand, if s1(s1'high) is -ive
  --then each bit in s1 is inverted and then s1 is inremented by '1'

  FUNCTION tc(s1:std_logic_vector) return std_logic_vector;
  --returns a twos compliment of a s1.
  --No matter if the input is -ive or +ive. It will return a
  --twos compliment of the input vector.
  --IE if the input number is -ive, output will be +ive number
  --if the input number is +ive, the output will be a -ive number
  --
  FUNCTION sshr(s1:std_logic_vector) return std_logic_vector;
  -- Signed Shift right
  -- performes shift right i.e >> i.e / 2, msb = 0, suitable for signed;
  FUNCTION zshr(s1:std_logic_vector) return std_logic_vector;
  -- UnSigned Shift right
  -- performes shift right i.e >> i.e / 2, msb = 0, suitable for unsigned;
  FUNCTION shl(s1:std_logic_vector) return std_logic_vector;
  -- performes shift left i.e << i.e x 2, lsb = 0;
  FUNCTION csshr(s1:std_logic_vector;s2:std_logic) return std_logic_vector;
  -- Conditional Signed Shift right, if s2= 1, shift, otherwise return original
  -- performes shift right i.e >> i.e / 2, msb = 0, suitable for signed;
  FUNCTION czshr(s1:std_logic_vector;s2:std_logic) return std_logic_vector;
  -- Conditional UnSigned Shift right;shift when s2 = '1'
  -- performes shift right i.e >> i.e / 2, msb = 0, suitable for unsigned;
  FUNCTION zshrn(s1:std_logic_vector;n:integer) return std_logic_vector;
  -- UnSigned Shift right by n bits
  -- performes shift right i.e >> i.e / 2, msb = 0, suitable for unsigned;
  FUNCTION sshrn(s1:std_logic_vector;nn:integer) return std_logic_vector;
  -- Signed Shift right by n bits
  -- performes shift right i.e >> i.e / 2, msb = 0, suitable for signed;

  FUNCTION sext(s1:std_logic_vector;nn:integer) return std_logic_vector;
  -- sign extend an std_logic_vector by nn bits
  -- Example s1 = 10101010, nn = 3, return = 11110101010

  FUNCTION shln(s1:std_logic_vector;nn:integer) return std_logic_vector;
  -- shift left by nn bits, add nn 0s to LSBs
  -- Example s1 = 11111101, nn = 3, return = 11101000
 

  FUNCTION ccitt_crc_16(s1:std_logic_vector;ser_in:std_logic) return std_logic_vector;
  --Calculates the next CRC value as per ccitt_crc_16
  --X^16 + X^12 + X^5 + 1

  FUNCTION bit_reverse(s1:std_logic_vector) return std_logic_vector;
  --It reverses the bits of std_logic_vector
  --ie LSB becomes MSB and vice-versa
  --Example 01100000 becomes 00000110
 

END fun_pkg;
PACKAGE body fun_pkg IS
--Function Declaration Section
  FUNCTION bin2gray(B1:std_logic_vector) return std_logic_vector is
    VARIABLE G1 : std_logic_vector(B1'high downto B1'low) ;
    BEGIN
    G1(G1'high):=B1(B1'high);
    for i in B1'high-1 downto B1'low loop
      G1(i) := B1(i+1) XOR B1(i);
    end loop;
    return G1;
    end bin2gray; -- end function

  FUNCTION gray2bin(G1:std_logic_vector) return std_logic_vector is
    VARIABLE B1 : std_logic_vector(G1'high downto G1'low) ;
    BEGIN
    B1(G1'high):=G1(B1'high);
    for i in G1'high-1 downto G1'low loop
      B1(i) := B1(i+1) XOR G1(i);
    end loop;
    return B1;
    end gray2bin; -- end function

  FUNCTION crr(s1:std_logic_vector;index:integer) return std_logic_vector is
              --crr=CircularRotateRight
              --this function Circular Rotates Right 's1' by 'index'
    variable z : std_logic_vector(s1'high downto s1'low);
    begin
    --pragma translate_off
    --pragma coverage_off
    if(index >= s1'length) then
    assert false
      report "crr: rotate index is greater than variable length can't rotate" severity error;
    end if;
    if(index < 0) then
    assert false
      report "crr: rotate index is negative,can't rotate" severity error;
    end if;
    --pragma coverage_on
    --pragma translate_on
    if(index = 0) then
      z:=s1;
    else
      for jj in 1 to s1'high loop
        z:= s1(jj-1 downto 0) & s1(s1'high downto jj);
        if(jj = index) then
          exit;
        end if;
      end loop;
    end if;
    return z;
  end crr; -- end function

  function crl(s1:std_logic_vector;index:integer) return std_logic_vector is
              --crl=CircularRotateLeft
              --this function Circular Rotates Right 's1' by 'index'
    variable z : std_logic_vector(s1'high downto s1'low);
    begin
    --pragma translate_off
    --pragma coverage_off
    if(index >= s1'length) then
    assert false
      report "crl: rotate index is greater than variable length can't rotate" severity error;
    end if;
    if(index < 0) then
    assert false
      report "crl: rotate index is negative,can't rotate" severity error;
    end if;
    --pragma coverage_on
    --pragma translate_on
    if(index = 0) then
      z:=s1;
    else
      for jj in 1 to s1'high loop
        z:= s1(s1'high-jj downto 0) & s1(s1'high downto s1'high-jj+1);
        if(jj = index) then
          exit;
        end if;
      end loop;
    end if;
    return z;
  end crl; -- end function
 
 
 

FUNCTION incr_vec(s1:std_logic_vector;en:std_logic) return std_logic_vector is
                  --this function increments a std_logic_vector type by '1'
        VARIABLE V : std_logic_vector(s1'high downto s1'low) ;
        VARIABLE tb : std_logic_vector(s1'high downto s1'low);
        BEGIN
        tb(s1'low) := en;
        V := s1;
        for i in (V'low + 1) to V'high loop
            tb(i) := V(i - 1) and tb(i -1);
        end loop;
        for i in V'low to V'high loop
            if(tb(i) = '1') then
                V(i) := not(V(i));
            end if;
        end loop;
        return V;
        end incr_vec; -- end function

FUNCTION  dcr_vec(s1:std_logic_vector;en:std_logic) return std_logic_vector is
                  --this function decrements a std_logic_vector type by '1'
        VARIABLE V : std_logic_vector(s1'high downto s1'low) ;
        VARIABLE tb : std_logic_vector(s1'high downto s1'low);
        BEGIN
        tb(s1'low) := not(en);
        V := s1;
        for i in (V'low + 1) to V'high loop
            tb(i) := V(i - 1) or tb(i -1);
        end loop;
        for i in V'low to V'high loop
            if(tb(i) = '0') then
                V(i) := not(V(i));
            end if;
        end loop;
        return V;
        end dcr_vec; -- end function

FUNCTION all_ones(s1:std_logic_vector) return std_logic is
                  --this function tells if all bits of a vector are '1'
                  --return value Z is '1', then vector has all 1 bits
        --VARIABLE V : std_logic_vector(s1'high downto s1'low) ;
        VARIABLE Z : std_logic;
        BEGIN
        Z := s1(s1'low);
        FOR i IN (s1'low+1) to s1'high LOOP
            Z := Z AND s1(i);
        END LOOP;
        RETURN Z;
        END all_ones; -- end function

FUNCTION all_zeros(s1:std_logic_vector) return std_logic is
                  --this function tells if all bits of a vector are '0'
                  --return value Z if '1', then vector has all 0 bits
        --VARIABLE V : std_logic_vector(s1'high downto s1'low) ;
        VARIABLE Z : std_logic;
        BEGIN
        Z := '0';
        FOR i IN (s1'low) to s1'high LOOP
            Z := Z OR s1(i);
        END LOOP;
        RETURN not(Z);
        END all_zeros; -- end function

FUNCTION mux1(a0:std_logic;a1:std_logic;sel:std_logic) return std_logic is
        --a 1 bit mux, handy to be used combinational assignments.
        --output = a0, if sel = 0,
        --output = a1,if sel = 1.
        VARIABLE Z: std_logic;
        BEGIN
          IF(sel = '0') THEN
            Z := a0;
          ELSE
            Z := a1;
          END IF;
        RETURN Z;
        END mux1; -- end function

FUNCTION mux_vec(a0:std_logic_vector;a1:std_logic_vector;sel:std_logic)
return std_logic_vector is
        --a vectored mux, handy to be used combinational assignments.
        --output = a0, if sel = 0,
        --output = a1,if sel = 1.
        VARIABLE Z: std_logic_vector(a0'high downto a0'low);
        BEGIN
          IF(sel = '0') THEN
            Z := a0;
          ELSE
            Z := a1;
          END IF;
        RETURN Z;
        END mux_vec; -- end function

FUNCTION if_eq(s1:std_logic_vector;s2:std_logic_vector) return std_logic is
        --this function returns a value of '1' if the passed
        --input1 vector is equal to the input2 value
        --Usage:
        -- mybit = if_eq(sig1,const1);
        -- where sig1 and const1 are equal in widths
        -- This function works only with 'constant' types
        -- The function must be passed a 'constant' type
        -- for its variable 'const1', otherwise potential problems may
        -- arise
        VARIABLE V : std_logic_vector(s1'high downto s1'low) ;
        VARIABLE Z : std_logic;
        BEGIN
        FOR i IN (s1'high) downto (s1'low) LOOP
          V(i) := s1(i) XOR s2(i);
        END LOOP;
        Z := all_zeros(V);
        RETURN Z;
        END if_eq; -- end function
 

FUNCTION inv_if_one(s1:std_logic_vector;en:std_logic) return std_logic_vector is
                  --this function inverts all the bits of a vector if
                  --'en' is '1'.
        VARIABLE Z : std_logic_vector(s1'high downto s1'low);
        BEGIN
        FOR i IN (s1'low) to s1'high LOOP
            Z(i) := en XOR s1(i);
        END LOOP;
        RETURN Z;
        END inv_if_one; -- end function

FUNCTION inv(s1:std_logic_vector) return std_logic_vector is
                  --this function inverts all the bits of input vector
        VARIABLE Z : std_logic_vector(s1'high downto s1'low);
        BEGIN
        FOR i IN (s1'low) to s1'high LOOP
            Z(i) := NOT(s1(i));
        END LOOP;
        RETURN Z;
        END inv; -- end function

FUNCTION twos_comp(s1:std_logic_vector) return std_logic_vector is
        VARIABLE Z : std_logic_vector(s1'high downto s1'low);
        --Finds twos compliment of an std_logic_vector type.
        --will do nothing to +ive numbers.(which have their msb='0'
        BEGIN
          Z := inv_if_one(s1,s1(s1'high));
          Z := incr_vec(Z,s1(s1'high));
        RETURN Z;
        END twos_comp; -- end function
FUNCTION tc(s1:std_logic_vector) return std_logic_vector is
        VARIABLE Z : std_logic_vector(s1'high downto s1'low);
        --Finds twos compliment of an std_logic_vector type.
        --No matter input is -ive or +ive, it will always return
        --output = NOT(input) + 1;
        BEGIN
          Z := inv(s1);
          Z := incr_vec(Z,'1');
        RETURN Z;
        END tc; -- end function
FUNCTION myabs(s1:std_logic_vector) return std_logic_vector is
          --this function returns an absolute value of a vector
          --This is same as the function 'twos_comp' above
        VARIABLE V : std_logic_vector(s1'high downto s1'low) ;
        BEGIN
        for i in V'low to V'high loop
          V(i) := s1(i) XOR s1(s1'high);
        end loop;
        V := incr_vec(V,s1(s1'high));
        return V;
        end myabs; -- end function

FUNCTION NextGray(G1:std_logic_vector) return std_logic_vector is
    VARIABLE G2 : std_logic_vector(G1'high downto G1'low) ;
    VARIABLE B1 : std_logic_vector(G1'high downto G1'low) ;
    VARIABLE tb : std_logic_vector(G1'high downto G1'low);
    BEGIN
    if(G1'length <= 2) then
    assert false
      report "NextGray: Min Vector Length in Function is 3" severity error;
    end if;

    if(all_zeros(not(G1(G1'high)) & G1(G1'high-1 downto G1'low)) = '1') then
      G2 := (others => '0');
      return G2;
    end if;
    B1 := gray2bin(G1);
    tb(G1'low) := not(B1(B1'low));

    tb(G1'low + 1) := G1(G1'low) and B1(B1'low);

    for i in (G1'low + 2) to G1'high loop
      tb(i) := all_zeros( not(G1(i-1)) & G1(i-2 downto G1'low) & not(B1(B1'low)) );
    end loop;

    G2:=G1;
    for i in G1'low to G1'high loop
     if(tb(i) = '1') then
       G2(i) := not(G2(i));
     end if;
    end loop;
 

    return G2;
    end NextGray; -- end function

  FUNCTION sshr(s1:std_logic_vector) return std_logic_vector is
    variable r : std_logic_vector(s1'high downto s1'low);
  begin
    r(r'high) := s1(s1'high);
    r(r'high -1 downto 0) := s1(s1'high downto 1);
    return r;
  end sshr;

  FUNCTION csshr(s1:std_logic_vector;s2:std_logic) return std_logic_vector is
    variable r : std_logic_vector(s1'high downto s1'low);
  begin
    if(s2 = '1') then
      r(r'high) := s1(s1'high);
      r(r'high -1 downto 0) := s1(s1'high downto 1);
    else
      r := s1;
    end if;
    return r;
  end csshr;

  FUNCTION zshr(s1:std_logic_vector) return std_logic_vector is
    variable r : std_logic_vector(s1'high downto s1'low);
  begin
    r(r'high) := '0';
    r(r'high -1 downto 0) := s1(s1'high downto 1);
    return r;
  end zshr;

  FUNCTION czshr(s1:std_logic_vector;s2:std_logic) return std_logic_vector is
    variable r : std_logic_vector(s1'high downto s1'low);
  begin
    if(s2 = '1') then
      r(r'high) := '0';
      r(r'high -1 downto 0) := s1(s1'high downto 1);
    else
      r := s1;
    end if;
    return r;
  end czshr;
--------------------------------------------------------------------------------
--IMP NOTE: the following function zshrn is not synthesizeable at the moment
--------------------------------------------------------------------------------
  FUNCTION zshrn(s1:std_logic_vector;n:integer) return std_logic_vector is
--------------------------------------------------------------------------------
    variable r : std_logic_vector(s1'high downto s1'low);
  begin
    --pragma translate_off
    --pragma coverage_off
    if(n < 0) then
    assert false
      report "zshrn: shift index is negative,can't rotate" severity error;
    end if;
    --pragma translate_on
    --pragma coverage_on
    r := s1;
    if(n = 0) then
      return r;
    end if;
    r(r'high downto r'high-(n-1)) := (others => '0');
    r(r'high -n downto 0) := s1(s1'high downto n);
    return r;
  end zshrn;

  FUNCTION sshrn(s1:std_logic_vector;nn:integer) return std_logic_vector is
    variable rr : std_logic_vector(s1'high downto s1'low);
  begin
    --pragma translate_off
    --pragma coverage_off
    if(nn < 0) then
    assert false
      report "sshrn: shift index is negative,can't rotate" severity error;
    end if;
    --pragma translate_on
    --pragma coverage_on
    if(nn = 0) then
      rr := s1;
    else
      rr := (others => s1(s1'high));
      for ii in s1'high downto 0 loop
        rr(ii-nn) := s1(ii);
        if(ii = nn) then
          exit;
        end if;
      end loop;
    end if;
    return rr;
  end sshrn;
 

  FUNCTION shl(s1:std_logic_vector) return std_logic_vector is
    variable r : std_logic_vector(s1'high downto s1'low);
  begin
    r(r'low) := '0';
    r(r'high downto 1) := s1(s1'high-1 downto 0);
    return r;
  end shl;

  FUNCTION ccitt_crc_16(s1:std_logic_vector;ser_in:std_logic) return std_logic_vector is
  --Calculates the next CRC value as per ccitt_crc_16
  --X^16 + X^12 + X^5 + 1
    variable r : std_logic_vector(s1'high downto s1'low);
  begin
    r(15)          := s1(14);
    r(14)          := s1(13);
    r(13)          := s1(12);
    r(12)          := s1(11) xor s1(15) xor ser_in;
    r(11)          := s1(10);
    r(10)          := s1(9);
    r(9)           := s1(8);
    r(8)           := s1(7);
    r(7)           := s1(6);
    r(6)           := s1(5);
    r(5)           := s1(4)  xor s1(15) xor ser_in;
    r(4)           := s1(3);
    r(3)           := s1(2);
    r(2)           := s1(1);
    r(1)           := s1(0);
    r(0)           := s1(15) xor ser_in;

    return r;
  end ccitt_crc_16;

  FUNCTION sext(s1:std_logic_vector;nn:integer) return std_logic_vector is
    variable rr : std_logic_vector(s1'high+nn downto s1'low);
  begin
    if(nn < 0) then
    assert false
      report "sext: index nn is negative,can't sign extend" severity error;
    end if;
    rr(s1'high downto s1'low) := s1;
    for ii in s1'high+nn downto s1'high+1 loop
      rr(ii) := s1(s1'high);
    end loop;
    return rr;
  END sext;

  FUNCTION shln(s1:std_logic_vector;nn:integer) return std_logic_vector is
  -- shift left by nn bits, add nn 0s to LSBs
  -- Example s1 = 11111101, nn = 3, return = 11101000
  --It is in effect unsigned multiplication by 2^nn
    variable rr : std_logic_vector(s1'high downto s1'low);
  begin
    if(nn < 0) then
    assert false
      report "shln: shift index nn is negative,can't shift" severity error;
    end if;
    if(nn = 0) then
      rr := s1;
    else
      rr := (others => '0');
      for ii in s1'high downto s1'low+1 loop
        rr(ii) := s1(ii-nn);
        if(ii = nn) then
          exit;
        end if;
      end loop;
    end if;
    return rr;
  end shln;

  FUNCTION bit_reverse(s1:std_logic_vector) return std_logic_vector is
     variable rr : std_logic_vector(s1'high downto s1'low);
  begin
    for ii in s1'high downto s1'low loop
      rr(ii) := s1(s1'high-ii);
    end loop;
    return rr;
  end bit_reverse;
 

--Function Declaration Section Ends
END fun_pkg;