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

Subversion Repositories xmatchpro

[/] [xmatchpro/] [trunk/] [xmw4-comdec/] [lib/] [dzx/] [bit_arith_pkg_body.vhd] - Rev 9

Go to most recent revision | Compare with Previous | Blame | View Log

 
package body Bit_Arith is
 
    ----------------
    -- Utilities: --
    ----------------
  function Max (L, R: Integer) return Integer is
  begin
    if (L > R) then
      return L;
    else
      return R;
    end if;
  end Max;
 
  function Min (L, R: Integer) return Integer is
  begin
    if (L < R) then
      return L;
    else
      return R;
    end if;
  end Min;
 
    ----------------------------------
    -- Error Messages and Procedure --
    ----------------------------------
 
    constant LongVec   : string := "Vector is longer then 32" ;
    constant TruncSize : string := "Truncate to a bigger size" ;
    constant TruncErr  : string := "Overflow" ;
    constant ExtSize   : string := "Extension to a smaller size" ;
    constant I2bSize   : string := "Size is bigger then 32" ;
    constant OpLen     : string := "Operands are not in the same length" ;
    constant Undef     : string := "Undef bit in Dbit vector arithmetic" ;
    constant OvrflPlus : string := "Overflow occurred during a + operation; Carry ignored.";
    constant OvrflMinus: string := "Overflow occurred during a - operation; Borrow ignored.";
    constant ToBVSize  : string := "Number of bits specified is less than that of input operand: extra bits truncated.";
    constant ToUNeg    : string := "Input operand cannot be negative.";
    constant ToUBitNo  : string := "Number of bits specified is less than that of input operand: extra bits truncated.";
    constant ToUPos    : string := "Input operand must be non-negative.";
    constant ToSBitNo  : string := "Number of bits specified is less than that of input operand: extra bits truncated.";
    constant LongSize  : string := "Size of operand cannot be more than 32.";
    constant ShiftBitNo: string := "Shift: No of bits greater than or equal to operand bit width";
    constant size_9    : string := "A BCD digit cannot be more than 9.";
    constant Axcess_3_Gray : string := "An invalid Excess-3 GRAY digit.";
 
    procedure Message ( s : String ; v : Severity_Level) is
    begin
	    assert false report s severity v;
    end Message;
 
 
 
    ----------------------------------------
    -- Bit_Vector <=> Integer Conversions --
    ----------------------------------------
 
    function To_Integer ( v : Bit_Vector ) return Integer is
    begin
        return To_integer (Unsigned(v));
    end To_Integer ;
 
    function To_BitVector ( i : Integer ) return long is
    begin
        return Long(To_Unsigned(i, 32));
    end To_BitVector;
 
 
    -------------------------------------------------
    -- Bit_Vector Extension & Truncation functions --
    -------------------------------------------------
 
    function ext ( b : Bit_Vector ; size : Integer ) return Bit_Vector is
    variable ret : Bit_Vector ( size - 1 downto 0 ) ;
    begin
	if b'length > size then
	    Message (ExtSize, Error) ;
	    return (b) ;
	end if ;
 
	ret(b'length-1 downto 0) := b ;
 
	return(ret) ;
    end ext ;
 
 
    function trunc ( b : Bit_Vector ; size : Integer ) return Bit_Vector is
    variable ret : Bit_Vector ( size - 1 downto 0 ) ;
    variable inx: natural := 0;
    begin
	if b'length < size then
	    Message (TruncSize, Error) ;
	    return (b) ;
	end if ;
 
    	-- ret := b(size-1 downto 0) ;
 
        for I in b'reverse_range loop
           ret(inx) := b(I);
           inx := inx + 1;
           exit when inx >= size;
        end loop;
 
        return ret; 
    end trunc ;
 
 
    function To_BitVector ( i , size : Integer ) return Bit_Vector is
    begin
        return Bit_Vector(To_Unsigned(i, size));
    end  To_BitVector;
 
 
    ------------------------------
    -- Bit_Vector OP Bit_Vector --
    ------------------------------
 
    function "+" ( left , right : Bit_Vector ) return Bit_Vector is
    begin
      return Bit_Vector((Unsigned(left) + Unsigned(right)));
    end "+" ;
 
    function "-" ( left , right : Bit_Vector ) return Bit_Vector is
    begin
      return Bit_Vector((Unsigned(left) - Unsigned(right)));
    end "-" ;
 
    function "*" ( left , right : Bit_Vector ) return Bit_Vector is 
    begin
      return Bit_Vector((Unsigned(left) * Unsigned(right)));
    end "*" ;
 
    function "/" ( left , right : Bit_Vector ) return Bit_Vector is 
    begin
      return Bit_Vector((Unsigned(left) / Unsigned(right)));
    end "/" ;
 
    function "mod" ( left , right : Bit_Vector ) return Bit_Vector is
    begin
      return Bit_Vector((Unsigned(left) mod Unsigned(right)));
    end "mod" ;
 
    function "rem" ( left , right : Bit_Vector ) return Bit_Vector is
    begin
      return Bit_Vector((Unsigned(left) rem Unsigned(right)));
    end "rem" ;
 
    ---------------------------
    -- Integer OP Bit_Vector --
    ---------------------------
 
    function "+" ( left : Integer ; right : Bit_Vector ) return Bit_Vector is
    begin
    	return Bit_Vector(To_Unsigned (left, right'length) + Unsigned(right));
    end "+" ;
 
    function "-" ( left : Integer ; right : Bit_Vector ) return Bit_Vector is
    begin
    	return Bit_Vector(To_Unsigned(left, right'length) - Unsigned(right));
    end "-" ;
 
    function "*" ( left : Integer ; right : Bit_Vector ) return Bit_Vector is
    begin
    	return Bit_Vector(To_Unsigned(left, right'length) * Unsigned(right));
    end "*" ;
 
    function "/" ( left : Integer ; right : Bit_Vector ) return Bit_Vector is
    begin
    	return Bit_Vector(To_Unsigned (left, right'length) / Unsigned(right));
    end "/" ;
 
    function "mod" ( left : Integer ; right : Bit_Vector ) return Bit_Vector is
    begin
    	return Bit_Vector(To_Unsigned (left, right'length) mod Unsigned(right));
    end "mod" ;
 
    function "rem" ( left : Integer ; right : Bit_Vector ) return Bit_Vector is
    begin
    	return Bit_Vector(To_Unsigned (left, right'length) rem Unsigned(right));
    end "rem" ;
 
 
    ---------------------------
    -- Bit_Vector OP Integer --
    ---------------------------
 
    function "+"  ( left : Bit_Vector ; right : Integer ) return Bit_Vector is
    begin
    	return Bit_Vector(Unsigned(left) + To_Unsigned(right, left'length));
    end "+" ;
 
    function "-" ( left : Bit_Vector ; right : Integer ) return Bit_Vector is
    begin
    	return Bit_Vector(Unsigned(left) - To_Unsigned(right, left'length));
    end "-" ;
 
    function "*" ( left : Bit_Vector ; right : Integer ) return Bit_Vector is
    begin
    	return Bit_Vector(Unsigned(left) * To_Unsigned(right, left'length));
    end "*" ;
 
    function "/" ( left : Bit_Vector ; right : Integer ) return Bit_Vector is
    begin
    	return Bit_Vector(Unsigned(left) / To_Unsigned(right, left'length));
    end "/" ;
 
    function "mod" ( left : Bit_Vector ; right : Integer ) return Bit_Vector is
    begin
    	return Bit_Vector(Unsigned(left) mod To_Unsigned(right, left'length));
    end "mod" ;
 
    function "rem" ( left : Bit_Vector ; right : Integer ) return Bit_Vector is
    begin
    	return Bit_Vector(Unsigned(left) rem To_Unsigned(right, left'length));
    end "rem" ;
 
    --============================
    -- Signed/Unsigned routines --
    --============================
 
  function Downto_Dir (OPD: Unsigned) return Unsigned is
    variable ret: Unsigned (OPD'length-1 downto 0);
  begin
    if (OPD'left > OPD'right) then -- if already downto 
      ret := OPD;
    else
      for J in OPD'RANGE loop
        ret(OPD'right-J) := OPD(J);
      end loop;
    end if;
 
    return ret;
  end;
 
  function Downto_Dir (OPD: Signed) return Signed is
    variable ret: Signed (OPD'length-1 downto 0); 
  begin 
    if (OPD'left > OPD'right) then -- if already downto  
      ret := OPD; 
    else 
      for J in OPD'RANGE loop 
        ret(OPD'right-J) := OPD(J); 
      end loop;
    end if;
 
    return ret;
  end;
 
  function Get_Magnitude (OPD: Signed) return Unsigned is
    -- returns the magnitude of the input Signed operand.
    -- Input is a negative number.
    variable RET: Unsigned (OPD'length-1 downto 0);
    variable FOUND_1: BOOLEAN := FALSE;
  begin
    RET := UNSIGNED(OPD);
 
    -- Search for first 1 from right, after that complement every bit:
    for J in RET'REVERSE_RANGE loop
      if FOUND_1 then
        RET(J) := not RET(J);
      elsif RET(J) = '1' then
          FOUND_1 := TRUE;
      end if;
    end loop;
 
    return RET;
  end Get_Magnitude;
 
  function Unsigned_Plus (L: Unsigned; R: Unsigned) return Unsigned is
    -- Special Plus function: input sizes must be same and also must be
    -- downto dir, with 'right = 0, i.e. 15 downto 0 for example.
    variable CARRY: BIT := '0';
    variable SUM: Unsigned (L'left downto 0);
  begin
    for K in L'REVERSE_RANGE loop -- from 0th bit which is LSB.
      SUM(K) := L(K) xor R(K) xor CARRY;
      CARRY := (L(K) or R(K)) and (L(K) or CARRY) and (CARRY or R(K));
    end loop;
 
    if (CARRY = '1') then
        Message (OvrflPlus, Note);
    end if;
 
    return SUM; 
  end;
 
  function Signed_Plus (L: Signed; R: Signed) return Signed is
    -- Identical functionality to Unsigned_Plus function.
    -- Special Plus function: input sizes must be same and also must be
    -- downto dir, with 'right = 0, i.e. 15 downto 0 for example.
    variable CARRY: BIT := '0';
    variable LAST_CARRY: BIT := '0';
    variable SUM: Signed (L'left downto 0);
  begin
    for K in L'REVERSE_RANGE loop -- from 0th bit which is LSB.
      SUM(K) := L(K) xor R(K) xor CARRY;
      LAST_CARRY := CARRY;
      CARRY := (L(K) or R(K)) and (L(K) or CARRY) and (CARRY or R(K));
    end loop;
 
    if (CARRY /= LAST_CARRY) then
        Message (OvrflPlus, Note);
    end if;
 
    return SUM;
  end;
 
  function Unsigned_Minus (L: Unsigned; R: Unsigned) return Unsigned is
    -- Special Minus function: input sizes must be same and also must be
    -- downto dir, with 'right = 0, i.e. 15 downto 0 for example.
    variable BORROW: BIT := '0';
    variable DIFF: Unsigned (L'left downto 0);
  begin
    for K in L'REVERSE_RANGE loop -- from 0th bit which is LSB.
      DIFF(K) := L(K) xor R(K) xor BORROW;
      BORROW := (not L(K) and (BORROW or (R(K) and not BORROW))) or
                  (L(K) and R(K) and BORROW);
    end loop;
 
    if (BORROW  = '1') then
        Message (OvrflMinus, Note);
    end if;
 
    return DIFF;
  end;
 
 
  function Signed_Minus (L: Signed; R: Signed) return Signed is
    -- Identical functionality to Unsigned_Minus.
    -- Special Minus function: input sizes must be same and also must be
    -- downto dir, with 'right = 0, i.e. 15 downto 0 for example. 
    variable BORROW: BIT := '0'; 
    variable LAST_BORROW: BIT := '0'; 
    variable DIFF: Signed (L'left downto 0); 
  begin 
    for K in L'REVERSE_RANGE loop -- from 0th bit which is LSB.
      DIFF(K) := L(K) xor R(K) xor BORROW; 
      LAST_BORROW := BORROW;
      BORROW := (not L(K) and (BORROW or (R(K) and not BORROW))) or
                  (L(K) and R(K) and BORROW); 
    end loop; 
 
    if (BORROW  /= LAST_BORROW) then
        Message (OvrflMinus, Note);
    end if;
 
    return DIFF;
  end;
 
  function Less_Than (L: Signed; R: Signed) return Boolean is
    -- Special function: inputs of same size and decr range and 'right is 0.
  begin
    if (L(L'left) /= R(R'left)) then -- compare signs.
      return (L(L'left) = '1');
    end if;
 
    for J in L'left-1 downto 0 loop -- compae from MSB.
      if L(J) /= R(J) then
        return (R(J) = '1');
      end if;
    end loop;
 
    return FALSE;
  end Less_Than;
 
  function Less_Than_Or_Equal_To (L: Signed; R: Signed) return Boolean is
    -- Special function: inputs of same size and decr range and 'right is 0.
  begin
    if (L(L'left) /= R(R'left)) then -- compare signs. 
      return (L(L'left) = '1');
    end if; 
 
    for J in L'left-1 downto 0 loop -- compae from MSB. 
      if L(J) /= R(J) then
        return (R(J) = '1'); 
      end if; 
    end loop; 
 
    return TRUE;
  end Less_Than_Or_Equal_To;
 
  function EQUAL_TO (L: Signed; R: Signed) return Boolean is
    -- Special function: inputs of same size and decr range and 'right is 0.
  begin
    for J in L'RANGE loop -- start from MSB.
      if L(J) /= R(J) then
        return FALSE;
      end if;
    end loop;
 
    return TRUE;
  end EQUAL_TO;
 
    ---------------------------
    -- Conversion functions: --
    ---------------------------
 
    function To_Integer (u: Unsigned) return Integer is
      variable ret: Integer;
    begin
      -- First check if size of input is less than 32 bits, the Max int value.
        if (u'length >= 32) then
            Message (LongVec, Error);
        end if;
 
      ret := 0;
      -- Remember: leftmost is MSB; DO NOT go by index value of u, i.e u(0)
      -- may also be the MSB.
 
      for M3 in u'RANGE loop -- Start from MSB first.
        ret := ret * 2;
 
        if u(M3) = '1' then
          ret := ret + 1;
        end if;
      end loop;
 
      return ret;
    end To_Integer;
 
 
    function To_Integer (s: Signed) return Integer is
      variable ret: Integer;
    begin
      -- First check if size of input is less than 32 bits, the Max int value.
      if (s'length >= 32) then
          Message (LongVec , Error);
      end if;
 
      ret := 0; 
 
      for M3 in s'RANGE loop
        ret := ret * 2;
 
        if s(M3) = '1' then
          ret := ret + 1;
        end if;
      end loop;
 
      -- now check if it was a Positive or a negative number.
      if (s(s'left) = '1') then -- Negative number: take 2's complement.
        ret := ret - 2 ** s'length;
      end if; -- If Positive, ret already contains the correct result.
 
      return ret; 
    end;
 
    function To_BitVector (u: Unsigned; size: Integer) 
        return Bit_Vector is
    variable ret: Bit_Vector (size-1 downto 0) := (others => '0');
    constant Min_BITS: Integer := Min (u'length, size) - 1;
    variable TEMP: Unsigned (u'length-1 downto 0);
  begin
      if (u'length > size) then
          Message (ToBVSize, Note);
      end if;
 
    TEMP := Unsigned (Downto_Dir (u));
 
    for I in 0 to Min_BITS loop
      ret(I) := TEMP(I);
    end loop;
 
    return ret;
  end;
 
  function To_Unsigned (i, size : Integer) 
      return Unsigned is
 
    variable M1: Integer;
    variable ret : Unsigned(size-1 downto 0) := (others => '0');
  begin
    -- Input must be Positive.
      if (i < 0) then
          Message (ToUNeg, Error);
      end if;
 
    M1 := i;
 
    for J in ret'REVERSE_RANGE loop -- LSB first.
      if (M1 mod 2) = 1 then
        ret(J) := '1';
      else
        ret(J) := '0';
      end if;
 
      -- exit when (J = ret'left);
      M1 := M1 / 2;
    end loop;
 
    if (M1 /= 0) then
        Message (ToUBitNo, Note);
    end if;
 
    return ret;
  end;
 
  function To_Unsigned (s: Signed; size : Integer)  
      return Unsigned is
    variable ret : Unsigned(size-1 downto 0) := (others => '0');
    constant Min_BITS: Integer := Min (s'length, size) - 1;
    variable TEMP: Unsigned (s'length-1 downto 0);
  begin
    -- Input cannot be a negative value.
    if (s(s'left) = '1') then
      Message (ToUPos, Error);
    end if;
 
    -- Truncated if no of bits are less.
    if (s'length > size) then
       Message (ToUBitNo, Note);
    end if;
 
    TEMP := Unsigned (Downto_Dir (s));
    ret (Min_BITS downto 0) := TEMP (Min_BITS downto 0);
 
    return ret;
  end;
 
  function To_Unsigned (u: Unsigned; size: Integer)  
      return Unsigned is
    variable ret : Unsigned(size-1 downto 0) := (others => '0');
    constant Min_BITS: Integer := Min (u'length, size) - 1;
    variable TEMP: Unsigned (u'length-1 downto 0);
  begin
      if (u'length > size) then
         Message (ToUBitNo, Note);
      end if;
 
    TEMP := Unsigned (Downto_Dir (u));
    ret (Min_BITS downto 0) := TEMP (Min_BITS downto 0);
 
    return ret;
  end;
 
  function To_Signed (i, size: Integer)  return Signed is
    variable M1: Integer;
    variable ret : Signed(size-1 downto 0) := (others => '0');
 
  begin
    -- If input is negative, get its 2's complement int value which
    -- is 2 ** size - ABS(i).
 
    M1 := abs (i);
 
    for J in ret'REVERSE_RANGE loop -- from LSB.
      if (M1 mod 2) = 1 then
        ret(J) := '1';
      else
        ret(J) := '0';
      end if;
 
      -- exit when (J = ret'left);
      M1 := M1 / 2;
    end loop;
 
    if (M1 /= 0) then
      Message (ToSBitNo, Note);
    end if;
 
    -- if -ve value, complement and add 1.
    if (i < 0) then
--      ret := Get_Twos_Complement (ret);
      ret := -ret;
    else -- make sure the leftmost bit is a zero; since +ve number; number
         -- that is same size as no-of-bits will therefore get truncated.
      if (ret(ret'left) = '1') then
        Message (ToSBitNo, Note);
      end if;
 
      ret(ret'left) := '0';
    end if;
 
    return ret;
  end;
 
  function To_Signed (u: Unsigned; size: Integer) return Signed is
    variable ret : Signed(size-1 downto 0) := (others => '0');
    constant Min_BITS: Integer := Min (u'length, size) - 1;
    variable TEMP: Signed(u'length-1 downto 0);
  begin
    if (u'length > size) then
      Message(ToSBitNo, Note);
    end if;
 
 
    TEMP := Signed (Downto_Dir(u));
    ret(Min_BITS downto 0) := TEMP (Min_BITS downto 0);
    -- Make sure left most bit is zero, since orig was an Unsigned number.
    ret(ret'left) := '0';
 
    return ret;
  end;
 
  function To_Signed (s: Signed; size: Integer) return Signed is
    variable ret : Signed(size-1 downto 0) := (others => s(s'left));
    constant Min_BITS: Integer := Min (s'length, size) - 1;
    variable TEMP: Signed(s'length-1 downto 0);
  begin
    if (s'length > size) then
      Message (ToSBitNo, Note);
    end if;
 
    TEMP := Downto_Dir(s);
    ret(Min_BITS downto 0) := TEMP (Min_BITS downto 0);
 
    return ret;
  end;
 
    ----------------------------------
    -- Binary arithmetic functions: --
    ----------------------------------
 
  function "+" (L: Unsigned; R: Integer)  return Unsigned is
    constant size: Integer := L'length;
    variable new_r: Unsigned (size-1 downto 0);
    variable new_l: Unsigned (size-1 downto 0);
  begin
    new_l := To_Unsigned (L, size);
    new_r := To_Unsigned (R, size);
 
    return (Unsigned_Plus (new_l, new_r));
  end;
 
  function "+" (L: Unsigned; R: Unsigned) return Unsigned is
    constant size: Integer := Max(L'length, R'length);
    variable new_r: Unsigned (size-1 downto 0);
    variable new_l: Unsigned (size-1 downto 0);
  begin
    new_l := To_Unsigned (L, size);
    new_r := To_Unsigned (R, size);
 
    return (Unsigned_Plus (new_l, new_r));
  end;
 
  function "+" (L: Signed;   R: Signed)   return Signed is
    constant size: Integer := Max(L'length, R'length);
    variable new_r: Signed (size-1 downto 0);
    variable new_l: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (Signed_Plus (new_l, new_r));
  end;
 
-- Next 3 functions added: BHASKER:
  function "+" (L: Integer; R: Unsigned)  return Unsigned is
  begin
    return ("+"(R, L));
  end;
 
  function "+" (L: Signed;   R: Integer)   return Signed is
    constant size: Integer := L'length;
    variable new_r: Signed (size-1 downto 0);
    variable new_l: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (Signed_Plus (new_l, new_r));
  end;
 
  function "+" (L: Integer; R: Signed)  return Signed is
  begin
    return ("+"(R, L));
  end;
 
  function "-" (L: Unsigned; R: Unsigned) return Unsigned is
    constant size: Integer := Max (L'length, R'length);
    variable new_r: Unsigned (size-1 downto 0);
    variable new_l: Unsigned (size-1 downto 0);
  begin
    new_l := To_Unsigned (L, size);
    new_r := To_Unsigned (R, size);
 
    return (Unsigned_Minus(new_l, new_r));
  end;
 
  function "-" (L: Signed;   R: Signed)   return Signed is
    constant size: Integer := Max (L'length, R'length);
    variable new_r: Signed (size-1 downto 0);
    variable new_l: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (Signed_Minus(new_l, new_r));
  end;
 
-- Next 4 functions added: BHASKER:
  function "-" (L: Unsigned; R: Integer) return Unsigned is
    constant size: Integer := L'length;
    variable new_r: Unsigned (size-1 downto 0);
    variable new_l: Unsigned (size-1 downto 0);
  begin
    new_l := To_Unsigned (L, size);
    new_r := To_Unsigned (R, size);
 
    return (Unsigned_Minus(new_l, new_r));
  end;
 
  function "-" (L: Integer; R: Unsigned) return Unsigned is
    constant size: Integer := R'length;
    variable new_r: Unsigned (size-1 downto 0);
    variable new_l: Unsigned (size-1 downto 0);
  begin
    new_l := To_Unsigned (L, size);
    new_r := To_Unsigned (R, size);
 
    return (Unsigned_Minus(new_l, new_r));
  end;
 
  function "-" (L: Signed;   R: Integer)   return Signed is
    constant size: Integer := L'length;
    variable new_r: Signed (size-1 downto 0);
    variable new_l: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (Signed_Minus(new_l, new_r));
  end;
 
  function "-" (L: Integer; R: Signed) return Signed is
    constant size: Integer := R'length;
    variable new_r: Signed (size-1 downto 0);
    variable new_l: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (Signed_Minus(new_l, new_r));
  end;
 
  function "*" (L: Unsigned; R: Unsigned) return Unsigned is
    variable res, tmp_L: Unsigned (L'length+R'length-1 downto 0) 
                         := (others => '0');
  begin
    tmp_L(L'length-1 downto 0) := L;
 
    for J in R'REVERSE_RANGE loop -- Start from LSB.
      if R(J) = '1' then -- add tmp_L to res.
        res := res + tmp_L;
      end if;
 
    -- tmp_L := tmp_L(tmp_L'length-2 downto 0) & '0'; -- left shift tmp_L.
      tmp_L(tmp_L'length-1 downto 1) := tmp_L(tmp_L'length-2 downto 0);
      tmp_L(0) := '0'; -- left shift tmp_L.
    end loop;
 
    return res;
  end;
 
  function "*" (L: Signed;   R: Signed)   return Signed is
    variable ret: Signed (L'length+R'length-1 downto 0) := (others => '0');
    variable TR: Unsigned (R'length-1 downto 0) := (others => '0');
    variable TL: Unsigned (L'length-1 downto 0) := (others => '0');
    variable UL: Unsigned (L'length-1 downto 0);
    variable UR: Unsigned (R'length-1 downto 0);
 
  begin
    if (L(L'left) = '1') then
      TL := Get_Magnitude (L);
    else
--      if (L'left > L'right) then
 --       TL := L (L`left-1 downto L'right);
  --    else
   --     TL := L (L'left+1 to L'right);
    --  end if;
      UL := To_Unsigned(L, L'length);
      TL := UL (TL'RANGE);
    end if;
 
    if (R(R'left) = '1') then
      TR := Get_Magnitude (R);
    else
      UR := To_Unsigned (R, R'length);
      TR := UR (TR'RANGE);
    end if;
 
    ret := To_Signed (TL * TR, ret'length);
 
    -- add sign now.
    if ((L(L'left) = '0') and (R(R'left) = '1')) or
       ((L(L'left) = '1') and (R(R'left) = '0')) then
--      ret := Get_Twos_Complement (ret);
      ret := -ret;
    end if;
 
    return ret;
  end;
 
  function "/" (L: Unsigned; R: Unsigned) return Unsigned is 
    variable res: Unsigned (L'length-1 downto 0) := (others => '0');
    variable TL, TR: Integer;
  begin
    if (not (L'length < 32 and R'length < 32)) then
      Message (LongSize, Error);
    end if;
 
  -- assert L'length < 32 and R'length < 32
      --report "Unsigned / Unsigned: Number of bits in operand cannot be more than 32."
      --severity ERROR;
 
    TL := To_Integer (L);
    TR := To_Integer (R);
    res := To_Unsigned ((TL / TR), res'length);
 
    return res;
  end; 
 
  function "/" (L: Signed;   R: Signed)   return Signed is 
    variable res: Signed (L'length-1 downto 0) := (others => '0');
    variable TL, TR: Integer;
  begin
    if (not (L'length < 32 and R'length < 32)) then
      Message (LongSize, Error);
    end if;
 
    TL := To_Integer (L);
    TR := To_Integer (R);
    res := To_Signed ((TL / TR), res'length);
 
    return res;
  end; 
 
  function "mod" (L: Unsigned; R: Unsigned) return Unsigned is 
    variable res: Unsigned (R'length-1 downto 0) := (others => '0');
    variable TL, TR: Integer;
  begin
    if (not (L'length < 32 and R'length < 32)) then
      Message (LongSize, Error);
    end if;
 
    TL := To_Integer (L);
    TR := To_Integer (R);
    res := To_Unsigned ((TL mod TR), res'length);
 
    return res;
  end; 
 
  function "mod" (L: Signed;   R: Signed)   return Signed is 
    variable res: Signed (R'length-1 downto 0) := (others => '0');
    variable TL, TR: Integer;
  begin
    if (not (L'length < 32 and R'length < 32)) then
      Message (LongSize, Error);
    end if;
 
    TL := To_Integer (L);
    TR := To_Integer (R);
    res := To_Signed ((TL mod TR), res'length);
 
    return res; 
  end; 
 
  function "rem" (L: Unsigned; R: Unsigned) return Unsigned is 
    variable res: Unsigned (R'length-1 downto 0) := (others => '0');
    variable TL, TR: Integer;
  begin
    if (not (L'length < 32 and R'length < 32)) then
      Message (LongSize, Error);
    end if;
 
    TL := To_Integer (L);
    TR := To_Integer (R);
    res := To_Unsigned ((TL rem TR), res'length);
 
    return res;
  end; 
 
  function "rem" (L: Signed;   R: Signed)   return Signed is 
    variable res: Signed (R'length-1 downto 0) := (others => '0'); 
    variable TL, TR: Integer; 
  begin
    if (not (L'length < 32 and R'length < 32)) then
      Message (LongSize, Error);
    end if;
 
    TL := To_Integer (L);
    TR := To_Integer (R); 
    res := To_Signed ((TL rem TR), res'length); 
 
    return res; 
  end; 
 
  function "-" (L: Signed) return Signed is
    variable ret, ZERO: Signed (L'length-1 downto 0) := (others => '0');
  begin
    ret := ZERO - L;
    return ret;
  end;
 
 
  function "abs" (L: Signed) return Signed is
    variable ret: Signed (L'length-1 downto 0) := (others => '0');
  begin
    if (L(L'left) = '1') then -- if negative number.
      ret := To_Signed(Get_Magnitude(L), ret'length);
    else -- Positive number;
      ret := L;
    end if;
 
    return ret;
  end;
 
 
  function "<" (L: Unsigned; R: Unsigned) return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size downto 0);
    variable new_r: Signed (size downto 0);
  begin
    new_l := To_Signed (L, size+1); -- pad 1 zero.
    new_r := To_Signed (R, size+1); 
 
    return (Less_Than (new_l, new_r));
  end;
 
 
  function "<" (L: Signed;   R: Signed)   return Boolean is
    constant size: Integer := Max (L'length, R'length); 
    variable new_l: Signed (size-1 downto 0); 
    variable new_r: Signed (size-1 downto 0); 
  begin
    new_l := To_Signed (L, size); 
    new_r := To_Signed (R, size); 
 
    return (Less_Than (new_l, new_r));
  end;
 
  function "<=" (L: Unsigned; R: Unsigned) return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size downto 0);
    variable new_r: Signed (size downto 0);
  begin
    new_l := To_Signed (L, size+1); -- pad 1 zero.
    new_r := To_Signed (R, size+1);
 
    return (Less_Than_Or_Equal_To (new_l, new_r));
  end;
 
  function "<=" (L: Signed;   R: Signed)   return Boolean is
    constant size: Integer := Max (L'length, R'length); 
    variable new_l: Signed (size-1 downto 0); 
    variable new_r: Signed (size-1 downto 0); 
  begin
    new_l := To_Signed (L, size); 
    new_r := To_Signed (R, size); 
 
    return (Less_Than_Or_Equal_To (new_l, new_r)); 
  end; 
 
  function ">=" (L: Unsigned; R: Unsigned) return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size downto 0);
    variable new_r: Signed (size downto 0);
  begin
    new_l := To_Signed (L, size+1); -- pad 1 zero.
    new_r := To_Signed (R, size+1);
 
    return (Less_Than_Or_Equal_To (new_r, new_l));
  end;
 
  function ">=" (L: Signed;   R: Signed)   return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size-1 downto 0);
    variable new_r: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (Less_Than_Or_Equal_To (new_r, new_l));
  end;
 
  function ">" (L: Unsigned; R: Unsigned) return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size downto 0);
    variable new_r: Signed (size downto 0);
  begin
    new_l := To_Signed (L, size+1); -- pad 1 zero.
    new_r := To_Signed (R, size+1);
 
    return (Less_Than (new_r, new_l));
  end;
 
  function ">" (L: Signed;   R: Signed)   return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size-1 downto 0);
    variable new_r: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (Less_Than (new_r, new_l));
  end;
 
  function "=" (L: Unsigned; R: Integer)  return Boolean is
    constant size: Integer := L'length;
    variable new_l: Signed (size downto 0);
    variable new_r: Signed (size downto 0);
  begin
    new_l := To_Signed (L, size+1); -- pad 1 zero.
    new_r := To_Signed (R, size+1);
 
    return (EQUAL_TO (new_l, new_r));
  end;
 
  function "=" (L: Unsigned; R: Unsigned) return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size downto 0);
    variable new_r: Signed (size downto 0);
  begin
    new_l := To_Signed (L, size+1); -- pad 1 zero.
    new_r := To_Signed (R, size+1);
 
    return (EQUAL_TO (new_l, new_r));
  end;
 
  function "=" (L: Signed;   R: Signed)   return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size-1 downto 0);
    variable new_r: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (EQUAL_TO (new_l, new_r));
  end;
 
  function "/=" (L: Unsigned; R: Unsigned) return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size downto 0);
    variable new_r: Signed (size downto 0);
  begin
    new_l := To_Signed (L, size+1); -- pad 1 zero.
    new_r := To_Signed (R, size+1);
 
    return (not EQUAL_TO (new_l, new_r));
  end;
 
  function "/=" (L: Signed;   R: Signed)   return Boolean is
    constant size: Integer := Max (L'length, R'length);
    variable new_l: Signed (size-1 downto 0);
    variable new_r: Signed (size-1 downto 0);
  begin
    new_l := To_Signed (L, size);
    new_r := To_Signed (R, size);
 
    return (not EQUAL_TO (new_l, new_r));
  end;
 
  ----------------------
  -- Shift functions: --
  ----------------------
 
  function Shift_Left  (u: Unsigned; size: Natural)  return Unsigned is
    variable tmp, ret: Unsigned (u'length-1 downto 0) := (others => '0');
  begin
    if (size >= u'length) then
      Message (ShiftBitNo, Error);
    end if;
 
    tmp := Downto_Dir (u);
    ret(tmp'left downto size) := tmp ((tmp'left-size) downto 0);
    return ret;
  end;
 
  function Shift_Left  (s: Signed;   size: Natural)  return Signed is
    variable tmp, ret: Signed (s'length-1 downto 0) := (others => '0');
  begin
    if (size >= s'length-1) then
      Message (ShiftBitNo, Error);
    end if;
 
    tmp := Downto_Dir (s);
    ret((tmp'left-1) downto size) := tmp ((tmp'left-1-size) downto 0);
    --Jb Sign bit no longer being retained: Aug 18 '93:
    -- ret(tmp'left) := s(s'left); -- copy sign bit.
    return ret;
  end;
 
  function Shift_Right (u: Unsigned; size: Natural)  return Unsigned is
    variable tmp, ret: Unsigned (u'length-1 downto 0) := (others => '0');
  begin
    if (size >= u'length) then
      Message (ShiftBitNo, Error);
    end if;
 
    tmp := Downto_Dir (u);
    ret((tmp'left-size) downto 0) := tmp (tmp'left downto size);
    return ret;
  end;
 
  function Shift_Right (s: Signed; size : Natural)  return Signed is
    variable tmp, ret: Signed (s'length-1 downto 0) := (others => s(s'left));
  begin
    if (size >= s'length-1) then
      Message (ShiftBitNo, Error);
    end if;
 
    tmp := Downto_Dir (s);
    ret((tmp'left-1-size) downto 0) := tmp ((tmp'left-1) downto size);
    ret(tmp'left) := s(s'left); -- copy sign bit.
    return ret;
  end;
 
   -------------------------------
   -- preset / clear procedure: --
   -------------------------------
    procedure Preset_Clear (signal FF: out Unsigned; Pc_Value: Unsigned) is
    begin
      FF <= Pc_Value;
    end;
 
    procedure Preset_Clear (signal FF: out Signed; Pc_Value: Signed) is
    begin
      FF <= Pc_Value;
    end;
 
  --------------------------------------------------
  -- Conversion functions for FDS2 (provided by IG):
  --------------------------------------------------
  function To_Integer (OPD: BCD_BIT_VECTOR) return INTEGER is
    variable TEMP: INTEGER;               -- returning integer
    variable BCD_INDEX_COUNTER: INTEGER;  -- for BCD 4-bit counting(0 - 3)
    variable BCD_DIGIT: INTEGER;          -- BCD digit (0 - 9)
    variable BCD_WEIGHT: INTEGER;         -- weight for decimal digit(1, 10, ..)
  begin
    -- First check if size of input is less than 32 bits, the max int value.
    if (OPD'LENGTH >= 32) then
      Message(LongSize, Error);
    end if;
 
    TEMP := 0;                               
    BCD_INDEX_COUNTER := 0;
    BCD_DIGIT := 0;
    BCD_WEIGHT := 1;                          -- weight initial value 
 
    -- Remember: leftmost is MSB; DO NOT go by index value of OPD, i.e OPD(0)
    -- may also be the MSB.
    for M3 in OPD'REVERSE_RANGE loop          -- scanning from the index 0 to n
      if OPD(M3) = '1' then
        -- BCD digit calculation
        BCD_DIGIT := BCD_DIGIT + (2 ** BCD_INDEX_COUNTER);
      end if;
 
      BCD_INDEX_COUNTER := BCD_INDEX_COUNTER + 1;
 
      if BCD_INDEX_COUNTER = 4   then             -- four bits are scanned?
        if (BCD_DIGIT >= 10) then                  -- invalid BCD digit?
          Message (Size_9, Error);
        end if;
 
        TEMP := TEMP + (BCD_DIGIT * BCD_WEIGHT);  -- add integer to TEMP
        BCD_INDEX_COUNTER := 0;           -- reinitialize the BCD 4-bit counter
        BCD_DIGIT := 0;                   -- reinitialize the BCD digit
        BCD_WEIGHT := BCD_WEIGHT * 10;    -- weight is adjusted for next digit
      end if;
    end loop;
 
    return TEMP;
  end To_Integer;
 
  function To_Integer (OPD: XS_3_BIT_VECTOR) return INTEGER is
    variable TEMP: INTEGER;               -- returning integer
    variable XS_3_INDEX_COUNTER: INTEGER; -- for XS_3 4-bit counting(0 - 3)
    variable XS_3_DIGIT: INTEGER;         -- XS_3 digit (0 - 9)
    variable XS_3_WEIGHT: INTEGER;        -- weight for decimal digit(1, 10, ..)
  begin
    -- First check if size of input is less than 32 bits, the max int value.
    if (OPD'LENGTH > 32) then
      Message (LongSize, Error);
    end if;
 
    TEMP := 0;                               
    XS_3_INDEX_COUNTER := 0;
    XS_3_DIGIT := 0;
    XS_3_WEIGHT := 1;                          -- weight initial value 
 
    -- Remember: leftmost is MSB; DO NOT go by index value of OPD, i.e OPD(0)
    -- may also be the MSB.
    for M3 in OPD'REVERSE_RANGE loop          -- scanning from the index 0 to n
      -- XS_3 digit (3 - 12, due to the excesse 3) calculation
      if OPD(M3) = '1' then
        XS_3_DIGIT := XS_3_DIGIT + (2 ** XS_3_INDEX_COUNTER);   
      end if;
 
      XS_3_INDEX_COUNTER := XS_3_INDEX_COUNTER + 1;
 
      if XS_3_INDEX_COUNTER = 4   then             -- four bits are scanned?
        XS_3_DIGIT := XS_3_DIGIT -3;               -- correction the excess-3
 
        if (XS_3_DIGIT >= 10) then                  -- invalid XS_3 digit?
          Message (Size_9, Error);
        end if;
 
        TEMP := TEMP + (XS_3_DIGIT * XS_3_WEIGHT); -- add integer to TEMP
        XS_3_INDEX_COUNTER := 0;        -- reinitialize the XS_3 4-bit counter
        XS_3_DIGIT := 0;                -- reinitialize the XS_3 digit
        XS_3_WEIGHT := XS_3_WEIGHT * 10; -- weight is adjusted for next digit
      end if;
    end loop;
 
    return TEMP;
  end To_Integer;
 
  function To_Integer (OPD: XS_3_GRAY_BIT_VECTOR) return INTEGER is
    variable TEMP: INTEGER;               -- returning integer
    variable XS_3_GRAY_INDEX_COUNTER: INTEGER; -- for XS_3_GRAY 4-bit counting(0 - 3)
    variable XS_3_GRAY_DIGIT: INTEGER;    -- XS_3_GRAY digit (0 - 9)
    variable XS_3_GRAY_WEIGHT: INTEGER;   -- weight for decimal digit(1, 10, ..)
 --   variable XS_3_GRAY_INPUTS: BIT_VECTOR(3 downto 0);  -- 4-bit input segment
  begin
    -- First check if size of input is less than 32 bits, the max int value.
    if (OPD'LENGTH > 32) then
      Message (LongSize, Error);
    end if;
 
    TEMP := 0;                               
    XS_3_GRAY_INDEX_COUNTER := 0;
    XS_3_GRAY_DIGIT := 0;
    XS_3_GRAY_WEIGHT := 1;                          -- weight initial value 
 
    -- Remember: leftmost is MSB; DO NOT go by index value of OPD, i.e OPD(0)
     -- may also be the MSB.
    for M3 in OPD'REVERSE_RANGE loop          -- scanning from the index 0 to n
      XS_3_GRAY_INDEX_COUNTER := XS_3_GRAY_INDEX_COUNTER + 1;
 
      if XS_3_GRAY_INDEX_COUNTER = 4   then        -- four bits are scanned?
 
----------------------------------------------------------------------------
       if OPD(M3)='0' and OPD(M3-1)='0' and OPD(M3-2)='1' and OPD(M3-3)='0' then
          XS_3_GRAY_DIGIT := 0;
       elsif OPD(M3)='0' and OPD(M3-1)='1' and OPD(M3-2)='1' and OPD(M3-3)='0' then
          XS_3_GRAY_DIGIT := 1;
       elsif OPD(M3)='0' and OPD(M3-1)='1' and OPD(M3-2)='1' and OPD(M3-3)='1' then
          XS_3_GRAY_DIGIT := 2;
       elsif OPD(M3)='0' and OPD(M3-1)='1' and OPD(M3-2)='0' and OPD(M3-3)='1' then
          XS_3_GRAY_DIGIT := 3;
       elsif OPD(M3)='0' and OPD(M3-1)='1' and OPD(M3-2)='0' and OPD(M3-3)='0' then
          XS_3_GRAY_DIGIT := 4;
       elsif OPD(M3)='1' and OPD(M3-1)='1' and OPD(M3-2)='0' and OPD(M3-3)='0' then
          XS_3_GRAY_DIGIT := 5;
       elsif OPD(M3)='1' and OPD(M3-1)='1' and OPD(M3-2)='0' and OPD(M3-3)='1' then
          XS_3_GRAY_DIGIT := 6;
       elsif OPD(M3)='1' and OPD(M3-1)='1' and OPD(M3-2)='1' and OPD(M3-3)='1' then
          XS_3_GRAY_DIGIT := 7;
       elsif OPD(M3)='1' and OPD(M3-1)='1' and OPD(M3-2)='1' and OPD(M3-3)='0' then
          XS_3_GRAY_DIGIT := 8;
       elsif OPD(M3)='1' and OPD(M3-1)='0' and OPD(M3-2)='1' and OPD(M3-3)='0' then
          XS_3_GRAY_DIGIT := 9;
       else               -- invalid XS_3_GRAY digit!
            Message (Axcess_3_Gray, Error);
       end if;
----------------------------------------------------------------------------
----------------------------------------------------------------------------
--   This routine was replaced with above code because
--    DAZIX dvhdl does not support '&' operator
--
--        XS_3_GRAY_INPUTS := OPD(M3)&OPD(M3-1)&OPD(M3-2)&OPD(M3-3);
--
--        case XS_3_GRAY_INPUTS is
--          when "0010" => XS_3_GRAY_DIGIT := 0;
--          when "0110" => XS_3_GRAY_DIGIT := 1;
--          when "0111" => XS_3_GRAY_DIGIT := 2;
--          when "0101" => XS_3_GRAY_DIGIT := 3;
--          when "0100" => XS_3_GRAY_DIGIT := 4;
--          when "1100" => XS_3_GRAY_DIGIT := 5;
--          when "1101" => XS_3_GRAY_DIGIT := 6;
--          when "1111" => XS_3_GRAY_DIGIT := 7;
--          when "1110" => XS_3_GRAY_DIGIT := 8;
--          when "1010" => XS_3_GRAY_DIGIT := 9;
--          when others => assert FALSE     -- invalid XS_3_GRAY digit!
--                           report "CONV_TO_INT: An invalid Excess-3 GRAY digit."
--                           severity ERROR;
--        end case;
----------------------------------------------------------------------------
 
 
        TEMP := TEMP + (XS_3_GRAY_DIGIT * XS_3_GRAY_WEIGHT); -- add integer to TEMP
        XS_3_GRAY_INDEX_COUNTER := 0; -- reinitialize the XS_3_GRAY 4-bit counter
        XS_3_GRAY_DIGIT := 0;             -- reinitialize the XS_3_GRAY digit
        XS_3_GRAY_WEIGHT := XS_3_GRAY_WEIGHT * 10;  -- weight is adjusted for next digit
      end if;
    end loop;
 
    return TEMP;
  end To_Integer;
 
  function To_Integer (OPD: JOHNSON_BIT_VECTOR) return INTEGER is
    variable TEMP: INTEGER;                      -- returning integer
    variable JOHNSON_ONE_COUNTER: INTEGER;       -- for counting ones
    variable JOHNSON_ZERO_COUNTER: INTEGER;      -- for counting zeros
  begin
    -- First check if size of input is less than 32 bits, the max int value.
    assert (OPD'LENGTH < 32)
      report "CONV_TO_INT: Number of bits in input operand cannot be more than 32."
      severity ERROR;
 
    TEMP := 0;                               
    JOHNSON_ONE_COUNTER := 0;
    JOHNSON_ZERO_COUNTER := 0;
 
    -- Remember: leftmost is MSB; DO NOT go by index value of OPD, i.e OPD(0)
    -- may also be the MSB.
    for M3 in OPD'REVERSE_RANGE loop          -- scanning from the index 0 to n
      if OPD(M3) = '1' then
        JOHNSON_ONE_COUNTER := JOHNSON_ONE_COUNTER +1;
      else
        JOHNSON_ZERO_COUNTER := JOHNSON_ZERO_COUNTER +1;
      end if;
    end loop;
 
    if JOHNSON_ONE_COUNTER = 0  then 
      TEMP := 0;
    elsif OPD(OPD'LOW) = '1'    then 
      TEMP := JOHNSON_ONE_COUNTER;
    else  
      TEMP := OPD'LENGTH + JOHNSON_ZERO_COUNTER;
    end if;
 
    return TEMP;
  end To_Integer;
 
end Bit_Arith;
 
 
 
 

Go to most recent revision | 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.