OpenCores
URL https://opencores.org/ocsvn/g729a_codec/g729a_codec/trunk

Subversion Repositories g729a_codec

[/] [g729a_codec/] [trunk/] [VHDL/] [G729A_asip_basic_pkg.vhd] - Rev 2

Compare with Previous | Blame | View Log

-----------------------------------------------------------------
--                                                             --
-----------------------------------------------------------------
--                                                             --
-- Copyright (C) 2013 Stefano Tonello                          --
--                                                             --
-- This source file may be used and distributed without        --
-- restriction provided that this copyright statement is not   --
-- removed from the file and that any derivative work contains --
-- the original copyright notice and the associated disclaimer.--
--                                                             --
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         --
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    --
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   --
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        --
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  --
-- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  --
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  --
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         --
-- POSSIBILITY OF SUCH DAMAGE.                                 --
--                                                             --
-----------------------------------------------------------------
 
---------------------------------------------------------------
-- Basic data types
---------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all; 
use IEEE.numeric_std.all;
 
library WORK;
use WORK.G729A_ASIP_PKG.all;
 
package G729A_ASIP_BASIC_PKG is
 
  constant MIN_16 : SDWORD_T := (SDLEN-1 => '1', others => '0'); 
 
  constant MAX_16 : SDWORD_T := (SDLEN-1 => '0', others => '1'); 
 
  constant MIN_32 : LDWORD_T := (LDLEN-1 => '1', others => '0'); 
 
  constant MAX_32 : LDWORD_T := (LDLEN-1 => '0', others => '1'); 
 
  subtype SHORT_SHIFT_T is integer range -SDLEN to SDLEN-1;
 
  subtype LONG_SHIFT_T is integer range -LDLEN to LDLEN-1;
 
  -- These additional types have been defined to handle overflow
  -- conditions: valid range top/bottom values are used to flag
  -- overflow.
 
  subtype SHORT_SHIFT_OVF_T is integer range -SDLEN to SDLEN;
 
  subtype LONG_SHIFT_OVF_T is integer range -LDLEN to LDLEN;
 
  ------------------------------------
  -- Convert hex digit string to signed value 
  ------------------------------------
 
  function hex_to_signed(XSTR : string;LEN : integer) return signed;
 
  ------------------------------------
  -- Convert LDWORD_T-type value to SDWORD_T-type
  ------------------------------------
 
  procedure sature(
    LVAL : in LDWORD_T;
    SVAL : out SDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  -- Get absolute value of SDWORD_T-type value
  ------------------------------------
 
  function abs_s(SVAL : SDWORD_T) return SDWORD_T;
 
  ------------------------------------
  -- Shift Left (WORD-type value)
  ------------------------------------
 
  procedure shl(
    SVALI : in SDWORD_T;
    SHFT : in  SHORT_SHIFT_T;
    SVALO : out SDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  -- Shift Right (WORD-type value)
  ------------------------------------
 
  procedure shr(
    SVALI : in SDWORD_T;
    SHFT : in  SHORT_SHIFT_T;
    SVALO : out SDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  -- Multiply (WORD-type result)
  ------------------------------------
 
  procedure mult(
    PROD : in LDWORD_T;
    RES : out SDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  -- Long Multiply (DWORD-type result)
  ------------------------------------
 
  procedure L_mult(
    PROD : in LDWORD_T;
    RES : out LDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  -- Get 2's complement of SDWORD_T-type value
  ------------------------------------
 
  function negate(SVAL : SDWORD_T) return SDWORD_T;
 
  ------------------------------------
  -- Long Addition/Subtraction 
  -- (DWORD-type result)
  ------------------------------------
 
  procedure L_add_sub(
    SUM : in LDWORD_T;
    AS : in std_logic;
    SA : in std_logic;
    SB : in std_logic;
    RES : out LDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  -- Get 2's complement of LDWORD_T-type value
  ------------------------------------
 
  function L_negate(LVAL : LDWORD_T) return LDWORD_T;
 
  ------------------------------------
  --  Long Shift Left (DWORD-type result)
  ------------------------------------
 
  procedure L_shl(
    LVALI : in LDWORD_T;
    SHFT : in  LONG_SHIFT_T;
    LVALO : out LDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  --  Long Shift Right (DWORD-type result)
  ------------------------------------
 
  procedure L_shr(
    LVALI : in LDWORD_T;
    SHFT : in  LONG_SHIFT_T;
    LVALO : out LDWORD_T;
    OVF : out std_logic
  );
 
  ------------------------------------
  -- Get absolute value of LDWORD_T-type value
  ------------------------------------
 
  function L_abs(LVAL : LDWORD_T) return LDWORD_T;
 
  ------------------------------------
  -- Get normalization shift amount
  -- (for a SDWORD_T-type value)
  ------------------------------------
 
  function norm_s(SVAL : SDWORD_T) return  SHORT_SHIFT_T;
 
  ------------------------------------
  -- Divide (WORD-type operands and result)
  ------------------------------------
 
  --function div_s(DD,DR : SDWORD_T) return SDWORD_T;
 
  ------------------------------------
  -- Get normalization shift amount
  -- (for a LDWORD_T-type value)
  ------------------------------------
 
  function norm_l(LVAL : LDWORD_T) return  LONG_SHIFT_T;
 
  ------------------------------------
 
  --function pos_overflow(VAL : LDWORD_T) return std_logic;
 
  --function neg_overflow(VAL : LDWORD_T) return std_logic;
 
end G729A_ASIP_BASIC_PKG;
 
package body G729A_ASIP_BASIC_PKG is
 
  ------------------------------------
 
  function hex_to_signed(XSTR : string;LEN : integer) return signed is
    variable VAL : signed(XSTR'length*4-1 downto 0);
    variable DGT : std_logic_vector(3 downto 0);
  begin
    for i in 1 to XSTR'length loop
      case XSTR(i) is
        when '0' => DGT := "0000";
        when '1' => DGT := "0001";
        when '2' => DGT := "0010";
        when '3' => DGT := "0011";
        when '4' => DGT := "0100";
        when '5' => DGT := "0101";
        when '6' => DGT := "0110";
        when '7' => DGT := "0111";
        when '8' => DGT := "1000";
        when '9' => DGT := "1001";
        when 'a' => DGT := "1010";
        when 'b' => DGT := "1011";
        when 'c' => DGT := "1100";
        when 'd' => DGT := "1101";
        when 'e' => DGT := "1110";
        when others => DGT := "1111";
      end case;
      for j in 3 downto 0 loop 
        VAL((XSTR'length-i)*4+j) := DGT(j);
      end loop;
    end loop;
    return(VAL(LEN-1 downto 0));
  end function;
 
  ------------------------------------
 
  procedure sature(
    LVAL : in LDWORD_T;
    SVAL : out SDWORD_T;
    OVF : out std_logic
  ) is
    constant ALL_ZERO : LDWORD_T := to_signed(0,LDLEN);
    constant ALL_ONE : LDWORD_T := not(ALL_ZERO);
    variable TMP : LDWORD_T;
  begin
    TMP := shift_right(LVAL,SDLEN-1);
    if((LVAL > 0) and not(TMP = ALL_ZERO)) then
      -- positive overflow
      SVAL := MAX_16;
      OVF := '1';
    elsif((LVAL < 0) and  not(TMP = ALL_ONE)) then
      -- negative overflow
      SVAL := MIN_16;
      OVF := '1';
    else
      -- exact result
      SVAL := LVAL(SDLEN-1 downto 0);
      OVF := '0';
    end if;
  end sature;
 
  ------------------------------------
 
  function abs_s(SVAL : SDWORD_T) return SDWORD_T is
  begin
    if(SVAL = MIN_16) then
      return(MAX_16);
    elsif(SVAL < 0) then
      return(-SVAL);
    else
      return(SVAL);
    end if;
  end function;
 
  ------------------------------------
 
  procedure shl(
    SVALI : in SDWORD_T;
    SHFT : in  SHORT_SHIFT_T;
    SVALO : out SDWORD_T;
    OVF : out std_logic
  ) is
    constant ALL_ZERO : SDWORD_T := to_signed(0,SDLEN);
    variable TMP : SDWORD_T;
  begin
    if(SVALI = ALL_ZERO) then
      SVALO := SVALI;
      OVF := '0';
    elsif(SHFT >= 0) then
      TMP := shift_left(SVALI,SHFT);
      if(TMP = ALL_ZERO)then
        if(SVALI < 0) then
          SVALO := MIN_16;
        else
          SVALO := MAX_16;
        end if;
        OVF := '1';
      else
        SVALO := TMP;
        OVF := '0';
      end if;
    else
      SVALO := shift_right(SVALI,-SHFT);
      OVF := '0';
    end if;
  end shl;
 
  ------------------------------------
 
  procedure shr(
    SVALI : in SDWORD_T;
    SHFT : in  SHORT_SHIFT_T;
    SVALO : out SDWORD_T;
    OVF : out std_logic
  ) is
    constant ALL_ZERO : SDWORD_T := to_signed(0,SDLEN);
    variable TMP : SDWORD_T;
  begin
    if(SVALI = ALL_ZERO) then
      SVALO := SVALI;
      OVF := '0';
    elsif(SHFT <= 0) then
      TMP := shift_left(SVALI,-SHFT);
      if(TMP = ALL_ZERO)then
        if(SVALI < 0) then
          SVALO := MIN_16;
        else
          SVALO := MAX_16;
        end if;
        OVF := '1';
      else
        SVALO := TMP;
        OVF := '0';
      end if;
    else
      SVALO := shift_right(SVALI,SHFT);
      OVF := '0';
    end if;
  end shr;
 
  ------------------------------------
 
  -- This procedure takes WLEN x WLEN multiplication
  -- result, right-shift it by WLEN-1 bits and
  -- convert it to WLEN-bits with saturation.
  -- Actual multiplication must be performed before
  -- invoking this procedure.
 
  procedure mult(
    PROD : in LDWORD_T;
    RES : out SDWORD_T;
    OVF : out std_logic
  ) is
    variable TMP : LDWORD_T;
  begin 
    TMP := shift_right(PROD,SDLEN-1);
    sature(TMP,RES,OVF);
  end mult;
 
  ------------------------------------
 
  -- This procedure takes WLEN x WLEN multiplication
  -- result and left-shift it by 1, checking for 
  -- overflow
 
  procedure L_mult(
    PROD : in LDWORD_T;
    RES : out LDWORD_T;
    OVF : out std_logic
  ) is
    constant OVFVAL : LDWORD_T := hex_to_signed("40000000",LDLEN);
  begin 
    if(PROD = OVFVAL) then
      RES := MAX_32;
      OVF := '1';
    else
      RES := shift_left(PROD,1);
      OVF := '0';
    end if;
  end L_mult;
 
  ------------------------------------
 
  -- This procedure generates -SVAL value.
  -- If SVAL = MIN_16 (minimum signed integer)
  -- negate result can't be exact, and is
  -- approximated to MAX_16.
 
  function negate(SVAL : SDWORD_T) return SDWORD_T is
  begin
    if(SVAL = MIN_16) then
      return(MAX_16);
    else
      return(-SVAL);
    end if;
  end function;
 
  ------------------------------------
 
  -- This procedure takes LDLEN-bit
  -- addition/subtraction result and
  -- operand signs, and checks for overflow.
 
  procedure L_add_sub(
    SUM : in LDWORD_T;
    AS : in std_logic;
    SA : in std_logic;
    SB : in std_logic;
    RES : out LDWORD_T;
    OVF : out std_logic
  ) is
    variable ST : std_logic;
    variable IOVF : std_logic;
  begin
    ST := SUM(LDLEN-1);
    -- overflow flag
    if(AS = '1') then
      -- addition
      if(ST = '1') then
        IOVF := not(SA or SB);
      else
        IOVF := (SA and SB);
      end if;
    else
      -- subtraction
      if(ST = '1') then
        IOVF := (not(SA) and SB);
      else
        IOVF := (SA and not(SB));
      end if;
    end if;
    -- saturated result
    if(IOVF = '0') then
      RES := SUM;
    elsif(ST = '0') then
      RES := MIN_32;
    else
      RES := MAX_32;
    end if;
    OVF := IOVF;
  end L_add_sub;
 
  ------------------------------------
 
  -- This procedure generates -LVAL value.
  -- If LVAL = MIN_32 (minimum signed integer)
  -- negate result can't be exact, and is
  -- approximated to MAX_32.
 
  function L_negate(LVAL : LDWORD_T) return LDWORD_T is
  begin
    if(LVAL = MIN_32) then
      return(MAX_32);
    else
      return(-LVAL);
    end if;
  end function;
 
  ------------------------------------
 
  procedure L_shl(
    LVALI : in LDWORD_T;
    SHFT : in  LONG_SHIFT_T;
    LVALO : out LDWORD_T;
    OVF : out std_logic
  ) is
    constant ALL_ZERO : LDWORD_T := to_signed(0,LDLEN);
    variable TMP : LDWORD_T;
  begin
    if(LVALI = ALL_ZERO) then
      LVALO := LVALI;
      OVF := '0';
    elsif(SHFT >= 0) then
      TMP := shift_left(LVALI,SHFT);
      if(TMP = ALL_ZERO)then
        if(LVALI < 0) then
          LVALO := MIN_32;
        else
          LVALO := MAX_32;
        end if;
        OVF := '1';
      else
        LVALO := TMP;
        OVF := '0';
      end if;
    else
      LVALO := shift_right(LVALI,-SHFT);
      OVF := '0';
    end if;
  end L_shl;
 
  ------------------------------------
 
  procedure L_shr(
    LVALI : in LDWORD_T;
    SHFT : in  LONG_SHIFT_T;
    LVALO : out LDWORD_T;
    OVF : out std_logic
  ) is
    constant ALL_ZERO : LDWORD_T := to_signed(0,LDLEN);
    variable TMP : LDWORD_T;
  begin
    if(LVALI = ALL_ZERO) then
      LVALO := LVALI;
      OVF := '0';
    elsif(SHFT <= 0) then
      TMP := shift_left(LVALI,-SHFT);
      if(TMP = ALL_ZERO)then
        if(LVALI < 0) then
          LVALO := MIN_32;
        else
          LVALO := MAX_32;
        end if;
        OVF := '1';
      else
        LVALO := TMP;
        OVF := '0';
      end if;
    else
      LVALO := shift_right(LVALI,SHFT);
      OVF := '0';
    end if;
  end L_shr;
 
  ------------------------------------
 
  function L_abs(LVAL : LDWORD_T) return LDWORD_T is
  begin
    if(LVAL = MIN_32) then
      return(MAX_32);
    elsif(LVAL < 0) then
      return(-LVAL);
    else
      return(LVAL);
    end if;
  end function;
 
  ------------------------------------
 
  function norm_s(SVAL : SDWORD_T) return  SHORT_SHIFT_T is
    constant ALL_ZERO : SDWORD_T := to_signed(0,SDLEN);
    constant ALL_ONE : SDWORD_T := not(ALL_ZERO);
    variable TMP : SDWORD_T;
    variable NRM :  SHORT_SHIFT_T;
  begin
    if(SVAL = ALL_ZERO) then
      return(0);
    elsif(SVAL = ALL_ONE) then
      return(SDLEN-1);
    else
      if(SVAL < 0) then
        TMP := not(SVAL);
      else
        TMP := SVAL;
      end if;
 
      if(TMP(SDLEN-2) = '1') then NRM := 0;
      elsif(TMP(SDLEN-3) = '1') then NRM := 1;
      elsif(TMP(SDLEN-4) = '1') then NRM := 2;
      elsif(TMP(SDLEN-5) = '1') then NRM := 3;
      elsif(TMP(SDLEN-6) = '1') then NRM := 4;
      elsif(TMP(SDLEN-7) = '1') then NRM := 5;
      elsif(TMP(SDLEN-8) = '1') then NRM := 6;
      elsif(TMP(SDLEN-9) = '1') then NRM := 7;
      elsif(TMP(SDLEN-10) = '1') then NRM := 8;
      elsif(TMP(SDLEN-11) = '1') then NRM := 9;
      elsif(TMP(SDLEN-12) = '1') then NRM := 10;
      elsif(TMP(SDLEN-13) = '1') then NRM := 11;
      elsif(TMP(SDLEN-14) = '1') then NRM := 12;
      elsif(TMP(SDLEN-15) = '1') then NRM := 13;
      else NRM := 14;
      end if;
 
--      case TMP is
--        when "0000000000000001" => NRM := 15; 
--        when "000000000000001-" => NRM := 14; 
--        when "00000000000001--" => NRM := 13; 
--        when "0000000000001---" => NRM := 12; 
--        when "000000000001----" => NRM := 11; 
--        when "00000000001-----" => NRM := 10; 
--        when "0000000001------" => NRM := 9; 
--        when "000000001-------" => NRM := 8; 
--        when "00000001--------" => NRM := 7; 
--        when "0000001---------" => NRM := 6; 
--        when "000001----------" => NRM := 5; 
--        when "00001-----------" => NRM := 4; 
--        when "0001------------" => NRM := 3; 
--        when "001-------------" => NRM := 2; 
--        when others => NRM := 1; 
--      end case;
      return(NRM);
    end if;
  end function;
 
  ------------------------------------
 
  function norm_l(LVAL : LDWORD_T) return  LONG_SHIFT_T is
    constant ALL_ZERO : LDWORD_T := to_signed(0,LDLEN);
    constant ALL_ONE : LDWORD_T := not(ALL_ZERO);
    variable TMP : LDWORD_T;
    variable NRM :  LONG_SHIFT_T;
  begin
    if(LVAL = ALL_ZERO) then
      return(0);
    elsif(LVAL = ALL_ONE) then
      return(LDLEN-1);
    else
      if(LVAL < 0) then
        TMP := not(LVAL);
      else
        TMP := LVAL;
      end if;
      NRM := 0;
      for i in 0 to LDLEN-2 loop
        if(TMP (i) = '1') then
          NRM := (LDLEN-2)-i; 
        end if;
      end loop;
 
      if(TMP(LDLEN-2) = '1') then NRM := 0;
      elsif(TMP(LDLEN-3)  = '1') then NRM := 1;
      elsif(TMP(LDLEN-4)  = '1') then NRM := 2;
      elsif(TMP(LDLEN-5)  = '1') then NRM := 3;
      elsif(TMP(LDLEN-6)  = '1') then NRM := 4;
      elsif(TMP(LDLEN-7)  = '1') then NRM := 5;
      elsif(TMP(LDLEN-8)  = '1') then NRM := 6;
      elsif(TMP(LDLEN-9)  = '1') then NRM := 7;
      elsif(TMP(LDLEN-10) = '1') then NRM := 8;
      elsif(TMP(LDLEN-11) = '1') then NRM := 9;
      elsif(TMP(LDLEN-12) = '1') then NRM := 10;
      elsif(TMP(LDLEN-13) = '1') then NRM := 11;
      elsif(TMP(LDLEN-14) = '1') then NRM := 12;
      elsif(TMP(LDLEN-15) = '1') then NRM := 13;
      elsif(TMP(LDLEN-16) = '1') then NRM := 14;
      elsif(TMP(LDLEN-17) = '1') then NRM := 15;
      elsif(TMP(LDLEN-18) = '1') then NRM := 16;
      elsif(TMP(LDLEN-19) = '1') then NRM := 17;
      elsif(TMP(LDLEN-20) = '1') then NRM := 18;
      elsif(TMP(LDLEN-21) = '1') then NRM := 19;
      elsif(TMP(LDLEN-22) = '1') then NRM := 20;
      elsif(TMP(LDLEN-23) = '1') then NRM := 21;
      elsif(TMP(LDLEN-24) = '1') then NRM := 22;
      elsif(TMP(LDLEN-25) = '1') then NRM := 23;
      elsif(TMP(LDLEN-26) = '1') then NRM := 24;
      elsif(TMP(LDLEN-27) = '1') then NRM := 25;
      elsif(TMP(LDLEN-28) = '1') then NRM := 26;
      elsif(TMP(LDLEN-29) = '1') then NRM := 27;
      elsif(TMP(LDLEN-30) = '1') then NRM := 28;
      elsif(TMP(LDLEN-31) = '1') then NRM := 29;
      else NRM := 30;
      end if;
 
--      case TMP is
--        when "00000000000000000000000000000001" => NRM := 31; 
--        when "0000000000000000000000000000001-" => NRM := 30; 
--        when "000000000000000000000000000001--" => NRM := 29; 
--        when "00000000000000000000000000001---" => NRM := 28; 
--        when "0000000000000000000000000001----" => NRM := 27; 
--        when "000000000000000000000000001-----" => NRM := 26; 
--        when "00000000000000000000000001------" => NRM := 25; 
--        when "0000000000000000000000001-------" => NRM := 24; 
--        when "000000000000000000000001--------" => NRM := 23; 
--        when "00000000000000000000001---------" => NRM := 22; 
--        when "0000000000000000000001----------" => NRM := 21; 
--        when "000000000000000000001-----------" => NRM := 20; 
--        when "00000000000000000001------------" => NRM := 19; 
--        when "0000000000000000001-------------" => NRM := 18; 
--        when "000000000000000001--------------" => NRM := 17; 
--        when "00000000000000001---------------" => NRM := 16; 
--        when "0000000000000001----------------" => NRM := 15; 
--        when "000000000000001-----------------" => NRM := 14; 
--        when "00000000000001------------------" => NRM := 13; 
--        when "0000000000001-------------------" => NRM := 12; 
--        when "000000000001--------------------" => NRM := 11; 
--        when "00000000001---------------------" => NRM := 10; 
--        when "0000000001----------------------" => NRM := 9; 
--        when "000000001-----------------------" => NRM := 8; 
--        when "00000001------------------------" => NRM := 7; 
--        when "0000001-------------------------" => NRM := 6; 
--        when "000001--------------------------" => NRM := 5; 
--        when "00001---------------------------" => NRM := 4; 
--        when "0001----------------------------" => NRM := 3; 
--        when "001-----------------------------" => NRM := 2; 
--        when others => NRM := 1; 
--      end case;
      return(NRM);
    end if;
  end function;
 
  ------------------------------------
 
--  function pos_overflow(VAL : LDWORD_T) return std_logic is
--    variable SVAL : LDWORD_T;
--  begin
--    if(VAL(LDLEN-1) = '1') then
--      return('0');
--    else
--      SVAL := shift_right(VAL,SDLEN-1);
--      if(SVAL = 0) then
--        return('0');
--      else
--        return('1');
--      end if;
--    end if;
--  end function;
--
--  function neg_overflow(VAL : LDWORD_T) return std_logic is
--    variable SVAL : LDWORD_T;
--  begin
--    if(VAL(LDLEN-1) = '0') then
--      return('0');
--    else
--      SVAL := not(shift_right(VAL,SDLEN-1));
--      if(SVAL = 0) then
--        return('0');
--      else
--        return('1');
--      end if;
--    end if;
--  end function;
 
end G729A_ASIP_BASIC_PKG;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.