--------------------------------------------------------------------------
--
--  Bit-vector arithmetic package interface.
--
--  Does arithmetic and logical operations on bit vectors, treating them
--  as either unsigned or signed (two's complement) integers.  Leftmost bit
--  is most-significant or sign bit, rightmost bit is least-significant
--  bit.  Dyadic operations need the two arguments to be of the same
--  length; however, their index ranges and directions may differ.  Results
--  must be of the same length as the operands.
--
--------------------------------------------------------------------------


package bv_arithmetic is

  function bv_to_natural ( bv : in bit_vector ) return natural;

  function natural_to_bv ( nat : in natural;
      	      	      	   length : in natural ) return bit_vector;

  function bv_to_integer ( bv : in bit_vector ) return integer;

  function integer_to_bv ( int : in integer;
      	      	      	   length : in natural ) return bit_vector;

  procedure bv_add ( bv1, bv2 : in bit_vector;
      	       	     bv_result : out bit_vector;
		     overflow : out boolean );

  function "+" ( bv1, bv2 : in bit_vector ) return bit_vector;

  procedure bv_sub ( bv1, bv2 : in bit_vector;
      	       	     bv_result : out bit_vector;
		     overflow : out boolean );

  function "-" ( bv1, bv2 : in bit_vector ) return bit_vector;

  procedure bv_addu ( bv1, bv2 : in bit_vector;
      	       	      bv_result : out bit_vector;
		      overflow : out boolean );

  function bv_addu ( bv1, bv2 : in bit_vector ) return bit_vector;

  procedure bv_subu ( bv1, bv2 : in bit_vector;
      	       	      bv_result : out bit_vector;
		      overflow : out boolean );

  function bv_subu ( bv1, bv2 : in bit_vector ) return bit_vector;

  procedure bv_neg ( bv : in bit_vector;
                     bv_result : out bit_vector;
                     overflow : out boolean );

  function "-" ( bv : in bit_vector ) return bit_vector;

  procedure bv_mult ( bv1, bv2 : in bit_vector;
      	       	      bv_result : out bit_vector;
		      overflow : out boolean );

  function "*" ( bv1, bv2 : in bit_vector ) return bit_vector;

  procedure bv_multu ( bv1, bv2 : in bit_vector;
      	       	       bv_result : out bit_vector;
		       overflow : out boolean );

  function bv_multu ( bv1, bv2 : in bit_vector ) return bit_vector;

  procedure bv_div ( bv1, bv2 : in bit_vector;
      	       	     bv_result : out bit_vector;
		     div_by_zero : out boolean;
                     overflow : out boolean );

  function "/" ( bv1, bv2 : in bit_vector ) return bit_vector;

  procedure bv_divu ( bv1, bv2 : in bit_vector;
      	       	      bv_quotient : out bit_vector;
		      bv_remainder : out bit_vector;
		      div_by_zero : out boolean );

  procedure bv_divu ( bv1, bv2 : in bit_vector;
      	       	      bv_quotient : out bit_vector;
		      div_by_zero : out boolean );

  function bv_divu ( bv1, bv2 : in bit_vector )  return bit_vector;

  function bv_lt ( bv1, bv2 : in bit_vector ) return boolean;

  function bv_le ( bv1, bv2 : in bit_vector ) return boolean;

  function bv_gt ( bv1, bv2 : in bit_vector ) return boolean;

  function bv_ge ( bv1, bv2 : in bit_vector ) return boolean;

  function bv_sext ( bv : in bit_vector;
      	      	     length : in natural ) return bit_vector;

  function bv_zext ( bv : in bit_vector;
      	      	     length : in natural ) return bit_vector;

end ;



package body bv_arithmetic is

  ----------------------------------------------------------------
  --  Type conversions
  ----------------------------------------------------------------

  function bv_to_natural ( bv : in bit_vector ) return natural is

    variable result : natural := 0;

  begin
    for index in bv'range loop
      result := result * 2 + bit'pos( bv(index) );
    end loop;
    return result;
  end ;


  function natural_to_bv ( nat : in natural;
      	      	      	   length : in natural ) return bit_vector is

    variable temp : natural := nat;
    variable result : bit_vector(length - 1 downto 0) := (others => '0');

  begin
    for index in result'reverse_range loop
      result(index) := bit'val( temp rem 2 );
      temp := temp / 2;
      exit when temp = 0;
    end loop;
    return result;
  end ;


  function bv_to_integer ( bv : in bit_vector ) return integer is

    variable temp : bit_vector(bv'range);
    variable result : integer := 0;

  begin
    if bv(bv'left) = '1' then	  -- negative number
      temp := not bv;
    else
      temp := bv;
    end if;
    for index in bv'range loop	  -- sign bit of temp = '0'
      result := result * 2 + bit'pos( temp(index) );
    end loop;
    if bv(bv'left) = '1' then
      result := (-result) - 1;
    end if;
    return result;
  end ;


  function integer_to_bv ( int : in integer;
      	      	      	   length : in natural ) return bit_vector is

    variable temp : integer;
    variable result : bit_vector(length - 1 downto 0) := (others => '0');

  begin
    if int < 0 then
      temp := - (int + 1);
    else
      temp := int;
    end if;
    for index in result'reverse_range loop
      result(index) := bit'val( temp rem 2 );
      temp := temp / 2;
      exit when temp = 0;
    end loop;
    if int < 0 then
      result := not result;
      result(result'left) := '1';
    end if;
    return result;
  end ;


  ----------------------------------------------------------------
  --  Arithmetic operations
  ----------------------------------------------------------------

  procedure bv_add ( bv1, bv2 : in bit_vector;
      	       	     bv_result : out bit_vector;
		     overflow : out boolean ) is

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv_result'length - 1 downto 0);
    variable carry_in : bit;
    variable carry_out : bit := '0';

  begin
    if bv1'length /= bv2'length or bv1'length /= bv_result'length then
--      report "bv_add: operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        carry_in := carry_out;  -- of previous bit
        result(index) := op1(index) xor op2(index) xor carry_in;
        carry_out := (op1(index) and op2(index))
        	      	   or (carry_in and (op1(index) xor op2(index)));
      end loop;
      bv_result := result;
      overflow := carry_out /= carry_in;
    end if;
  end ;


  function "+" ( bv1, bv2 : in bit_vector ) return bit_vector is

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv1'length - 1 downto 0);
    variable carry_in : bit;
    variable carry_out : bit := '0';

  begin
    if bv1'length /= bv2'length then
--      report """+"": operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        carry_in := carry_out;  -- of previous bit
        result(index) := op1(index) xor op2(index) xor carry_in;
        carry_out := (op1(index) and op2(index))
        	      	   or (carry_in and (op1(index) xor op2(index)));
      end loop;
    end if;
    return result;
  end;


  procedure bv_sub ( bv1, bv2 : in bit_vector;
      	       	     bv_result : out bit_vector;
		     overflow : out boolean ) is

    -- subtraction implemented by adding ((not bv2) + 1), ie -bv2

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv_result'length - 1 downto 0);
    variable carry_in : bit;
    variable carry_out : bit := '1';

  begin
    if bv1'length /= bv2'length or bv1'length /= bv_result'length then
--      report "bv_sub: operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        carry_in := carry_out;  -- of previous bit
        result(index) := op1(index) xor (not op2(index)) xor carry_in;
        carry_out := (op1(index) and (not op2(index)))
        	      	   or (carry_in and (op1(index) xor (not op2(index))));
      end loop;
      bv_result := result;
      overflow := carry_out /= carry_in;
    end if;
  end ;


  function "-" ( bv1, bv2 : in bit_vector ) return bit_vector is

    -- subtraction implemented by adding ((not bv2) + 1), ie -bv2

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv1'length - 1 downto 0);
    variable carry_in : bit;
    variable carry_out : bit := '1';

  begin
    if bv1'length /= bv2'length then
--      report """-"": operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        carry_in := carry_out;  -- of previous bit
        result(index) := op1(index) xor (not op2(index)) xor carry_in;
        carry_out := (op1(index) and (not op2(index)))
        	      	   or (carry_in and (op1(index) xor (not op2(index))));
      end loop;
    end if;
    return result;
  end;


  procedure bv_addu ( bv1, bv2 : in bit_vector;
      	       	      bv_result : out bit_vector;
		      overflow : out boolean ) is

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv_result'length - 1 downto 0);
    variable carry : bit := '0';

  begin
    if bv1'length /= bv2'length or bv1'length /= bv_result'length then
--      report "bv_addu: operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        result(index) := op1(index) xor op2(index) xor carry;
        carry := (op1(index) and op2(index))
                 or (carry and (op1(index) xor op2(index)));
      end loop;
      bv_result := result;
      overflow := carry = '1';
    end if;
  end ;


  function bv_addu ( bv1, bv2 : in bit_vector ) return bit_vector is

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv1'length - 1 downto 0);
    variable carry : bit := '0';

  begin
    if bv1'length /= bv2'length then
--      report "bv_addu: operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        result(index) := op1(index) xor op2(index) xor carry;
        carry := (op1(index) and op2(index))
                 or (carry and (op1(index) xor op2(index)));
      end loop;
    end if;
    return result;
  end ;


  procedure bv_subu ( bv1, bv2 : in bit_vector;
      	       	      bv_result : out bit_vector;
		      overflow : out boolean ) is

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv_result'length - 1 downto 0);
    variable borrow : bit := '0';

  begin
    if bv1'length /= bv2'length or bv1'length /= bv_result'length then
--      report "bv_subu: operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        result(index) := op1(index) xor op2(index) xor borrow;
        borrow := (not op1(index) and op2(index))
        	      	or (borrow and not (op1(index) xor op2(index)));
      end loop;
      bv_result := result;
      overflow := borrow = '1';
    end if;
  end ;


  function bv_subu ( bv1, bv2 : in bit_vector ) return bit_vector is

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    variable result : bit_vector(bv1'length - 1 downto 0);
    variable borrow : bit := '0';

  begin
    if bv1'length /= bv2'length then
--      report "bv_subu: operands of different lengths"
--      severity failure;
    else
      for index in result'reverse_range loop
        result(index) := op1(index) xor op2(index) xor borrow;
        borrow := (not op1(index) and op2(index))
        	      	or (borrow and not (op1(index) xor op2(index)));
      end loop;
    end if;
    return result;
  end ;


  procedure bv_neg ( bv : in bit_vector;
                     bv_result : out bit_vector;
                     overflow : out boolean ) is

    constant zero : bit_vector(bv'range) := (others => '0');

  begin
    bv_sub( zero, bv, bv_result, overflow );
  end ;


  function "-" ( bv : in bit_vector ) return bit_vector is

    constant zero : bit_vector(bv'range) := (others => '0');

  begin
    return zero - bv;
  end ;


  procedure bv_mult ( bv1, bv2 : in bit_vector;
      	       	      bv_result : out bit_vector;
		      overflow : out boolean ) is

    variable negative_result : boolean;
    variable op1 : bit_vector(bv1'range) := bv1;
    variable op2 : bit_vector(bv2'range) := bv2;
    variable multu_result : bit_vector(bv1'range);
    variable multu_overflow : boolean;
    variable abs_min_int : bit_vector(bv1'range) := (others => '0');

  begin
    if bv1'length /= bv2'length or bv1'length /= bv_result'length then
--      report "bv_mult: operands of different lengths"
--      severity failure;
    else
      abs_min_int(bv1'left) := '1';
      negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1');
      if op1(op1'left) = '1' then
        op1 := - bv1;
      end if;
      if op2(op2'left) = '1' then
        op2 := - bv2;
      end if;
      bv_multu(op1, op2, multu_result, multu_overflow);
      if negative_result then
        overflow := multu_overflow or (multu_result > abs_min_int);
        bv_result := - multu_result;
      else
        overflow := multu_overflow or (multu_result(multu_result'left) = '1');
        bv_result := multu_result;
      end if;
    end if;
  end ;


  function "*" ( bv1, bv2 : in bit_vector ) return bit_vector is

    variable negative_result : boolean;
    variable op1 : bit_vector(bv1'range) := bv1;
    variable op2 : bit_vector(bv2'range) := bv2;
    variable result : bit_vector(bv1'range);

  begin
    if bv1'length /= bv2'length then
--      report """*"": operands of different lengths"
--      severity failure;
    else
      negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1');
      if op1(op1'left) = '1' then
        op1 := - bv1;
      end if;
      if op2(op2'left) = '1' then
        op2 := - bv2;
      end if;
      result := bv_multu(op1, op2);
      if negative_result then
        result := - result;
      end if;
    end if;
    return result;
  end ;


  procedure bv_multu ( bv1, bv2 : in bit_vector;
      	       	       bv_result : out bit_vector;
		       overflow : out boolean ) is

    alias op1 : bit_vector(bv1'length - 1 downto 0) is bv1;
    alias op2 : bit_vector(bv2'length - 1 downto 0) is bv2;
    constant len : natural := bv1'length;
    constant accum_len : natural := len * 2;
    variable accum : bit_vector(accum_len - 1 downto 0) := (others => '0');
    constant zero : bit_vector(accum_len - 1 downto len):= (others => '0');
    variable addu_overflow : boolean;

  begin
    if bv1'length /= bv2'length or bv1'length /= bv_result'length then
--      report "bv_multu: operands of different lengths"
--      severity failure;
    else
      for count in 0 to len - 1 loop
        if op2(count) = '1' then
          bv_addu( accum(count + len - 1 downto count), op1,
                   accum(count + len - 1 downto count), addu_overflow);
          accum(count + len) := bit'val(boolean'pos(addu_overflow));
        end if;
      end loop;
      bv_result := accum(len - 1 downto 0);
      overflow := accum(accum_len-1 downto len) /= zero;
    end if;
  end ;


  function bv_multu ( bv1, bv2 : in bit_vector ) return bit_vector is

    -- Use bv_multu with overflow detection, but ignore overflow flag

    variable result : bit_vector(bv1'range);
    variable tmp_overflow : boolean;

  begin
    bv_multu(bv1, bv2, result, tmp_overflow);
    return result;
  end ;


  procedure bv_div ( bv1, bv2 : in bit_vector;
      	       	     bv_result : out bit_vector;
		     div_by_zero : out boolean;
                     overflow : out boolean ) is

    --  Need overflow, in case divide b"10...0" (min_int) by -1
    --  Don't use bv_to_int, in case size bigger than host machine!

    variable negative_result : boolean;
    variable op1 : bit_vector(bv1'range) := bv1;
    variable op2 : bit_vector(bv2'range) := bv2;
    variable divu_result : bit_vector(bv1'range);

  begin
    if bv1'length /= bv2'length or bv1'length /= bv_result'length then
--      report "bv_div: operands of different lengths"
--      severity failure;
    else
      negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1');
      if op1(op1'left) = '1' then
        op1 := - bv1;
      end if;
      if op2(op2'left) = '1' then
        op2 := - bv2;
      end if;
      bv_divu(op1, op2, divu_result, div_by_zero);
      if negative_result then
        overflow := false;
        bv_result := - divu_result;
      else
        overflow := divu_result(divu_result'left) = '1';
        bv_result := divu_result;
      end if;
    end if;
  end ;


  function "/" ( bv1, bv2 : in bit_vector ) return bit_vector is

    variable negative_result : boolean;
    variable op1 : bit_vector(bv1'range) := bv1;
    variable op2 : bit_vector(bv2'range) := bv2;
    variable result : bit_vector(bv1'range);

  begin
    if bv1'length /= bv2'length then
--      report """/"": operands of different lengths"
--      severity failure;
    else
      negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1');
      if op1(op1'left) = '1' then
        op1 := - bv1;
      end if;
      if op2(op2'left) = '1' then
        op2 := - bv2;
      end if;
      result := bv_divu(op1, op2);
      if negative_result then
        result := - result;
      end if;
    end if;
    return result;
  end ;


  procedure bv_divu ( bv1, bv2 : in bit_vector;
      	       	      bv_quotient : out bit_vector;
		      bv_remainder : out bit_vector;
		      div_by_zero : out boolean ) is

    constant len : natural := bv1'length;
    constant zero_divisor : bit_vector(len-1 downto 0) := (others => '0');
    alias dividend : bit_vector(bv1'length-1 downto 0) is bv1;
    variable divisor : bit_vector(bv2'length downto 0) := '0' & bv2;
    variable quotient : bit_vector(len-1 downto 0);
    variable remainder : bit_vector(len downto 0) := (others => '0');
    variable ignore_overflow  : boolean;

  begin
    if bv1'length /= bv2'length
	   or bv1'length /= bv_quotient'length or bv1'length /= bv_remainder'length then
--      report "bv_divu: operands of different lengths"
--      severity failure;
    else
      --  check for zero divisor
      if bv2 = zero_divisor then
        div_by_zero := true;
        return;
      end if;
      --  perform division
      for iter in len-1 downto 0 loop
        if remainder(len) = '0' then
	  -- Since sll doesn't appear to be around anymore we'll have to do
	  -- the following line the old fashioned way - single bit assignments.
          --remainder := remainder sll 1;
	  remainder(15) := remainder(14);
	  remainder(14) := remainder(13);
	  remainder(13) := remainder(12);
	  remainder(12) := remainder(11);
	  remainder(11) := remainder(10);
	  remainder(10) := remainder(9);
	  remainder(9) := remainder(8);
	  remainder(8) := remainder(7);
	  remainder(7) := remainder(6);
	  remainder(6) := remainder(5);
	  remainder(5) := remainder(4);
	  remainder(4) := remainder(3);
	  remainder(3) := remainder(2);
	  remainder(2) := remainder(1);
	  remainder(1) := remainder(0);
          remainder(0) := dividend(iter);
          bv_sub(remainder, divisor, remainder, ignore_overflow);
        else
	  -- Since sll doesn't appear to be around anymore we'll have to do
	  -- the following line the old fashioned way - single bit assignments.
          --remainder := remainder sll 1;
	  remainder(15) := remainder(14);
	  remainder(14) := remainder(13);
	  remainder(13) := remainder(12);
	  remainder(12) := remainder(11);
	  remainder(11) := remainder(10);
	  remainder(10) := remainder(9);
	  remainder(9) := remainder(8);
	  remainder(8) := remainder(7);
	  remainder(7) := remainder(6);
	  remainder(6) := remainder(5);
	  remainder(5) := remainder(4);
	  remainder(4) := remainder(3);
	  remainder(3) := remainder(2);
	  remainder(2) := remainder(1);
	  remainder(1) := remainder(0);
          remainder(0) := dividend(iter);
          bv_add(remainder, divisor, remainder, ignore_overflow);
        end if;
      quotient(iter) := not remainder(len);
      end loop;
      if remainder(len) = '1' then
        bv_add(remainder, divisor, remainder, ignore_overflow);
      end if;
      bv_quotient := quotient;
      bv_remainder := remainder(len - 1 downto 0);
      div_by_zero := false;
    end if;
  end ;


  procedure bv_divu ( bv1, bv2 : in bit_vector;
      	       	      bv_quotient : out bit_vector;
		      div_by_zero : out boolean ) is

    variable ignore_remainder : bit_vector(bv_quotient'range);

  begin
    bv_divu(bv1, bv2, bv_quotient, ignore_remainder, div_by_zero);
  end ;


  function bv_divu ( bv1, bv2 : in bit_vector ) return bit_vector is

    variable result : bit_vector(bv1'range);
    variable tmp_div_by_zero : boolean;

  begin
    bv_divu(bv1, bv2, result, tmp_div_by_zero);
    return result;
  end ;


  ----------------------------------------------------------------
  --  Arithmetic comparison operators.
  --  Perform comparisons on bit vector encoded signed integers.
  --  (For unsigned integers, built in lexical comparison does
  --  the required operation.)
  ----------------------------------------------------------------

  function bv_lt ( bv1, bv2 : in bit_vector ) return boolean is

    variable tmp1 : bit_vector(bv1'range) := bv1;
    variable tmp2 : bit_vector(bv2'range) := bv2;

  begin
--    assert bv1'length = bv2'length
--      report "bv_lt: operands of different lengths"
--      severity failure;
    tmp1(tmp1'left) := not tmp1(tmp1'left);
    tmp2(tmp2'left) := not tmp2(tmp2'left);
    return tmp1 < tmp2;
  end ;


  function bv_le ( bv1, bv2 : in bit_vector ) return boolean is

    variable tmp1 : bit_vector(bv1'range) := bv1;
    variable tmp2 : bit_vector(bv2'range) := bv2;

  begin
--    assert bv1'length = bv2'length
--      report "bv_le: operands of different lengths"
--      severity failure;
    tmp1(tmp1'left) := not tmp1(tmp1'left);
    tmp2(tmp2'left) := not tmp2(tmp2'left);
    return tmp1 <= tmp2;
  end ;


  function bv_gt ( bv1, bv2 : in bit_vector ) return boolean is

    variable tmp1 : bit_vector(bv1'range) := bv1;
    variable tmp2 : bit_vector(bv2'range) := bv2;

  begin
--    assert bv1'length = bv2'length
--      report "bv_gt: operands of different lengths"
--      severity failure;
    tmp1(tmp1'left) := not tmp1(tmp1'left);
    tmp2(tmp2'left) := not tmp2(tmp2'left);
    return tmp1 > tmp2;
  end ;


  function bv_ge ( bv1, bv2 : in bit_vector ) return boolean is

    variable tmp1 : bit_vector(bv1'range) := bv1;
    variable tmp2 : bit_vector(bv2'range) := bv2;

  begin
--    assert bv1'length = bv2'length
--      report "bv_ged: operands of different lengths"
--      severity failure;
    tmp1(tmp1'left) := not tmp1(tmp1'left);
    tmp2(tmp2'left) := not tmp2(tmp2'left);
    return tmp1 >= tmp2;
  end ;


  ----------------------------------------------------------------
  --  Extension operators - convert a bit vector to a longer one
  ----------------------------------------------------------------

  function bv_sext ( bv : in bit_vector;
      	      	     length : in natural ) return bit_vector is

    alias bv_norm : bit_vector(bv'length - 1 downto 0) is bv;
    variable result : bit_vector(length - 1 downto 0) := (others => bv(bv'left));
    variable src_length : natural := bv'length;

  begin
    if src_length > length then
      src_length := length;
    end if;
    result(src_length - 1 downto 0) := bv_norm(src_length - 1 downto 0);
    return result;
  end ;


  function bv_zext ( bv : in bit_vector;
      	      	     length : in natural ) return bit_vector is

    alias bv_norm : bit_vector(bv'length - 1 downto 0) is bv;
    variable result : bit_vector(length - 1 downto 0) := (others => '0');
    variable src_length : natural := bv'length;

  begin
    if src_length > length then
      src_length := length;
    end if;
    result(src_length - 1 downto 0) := bv_norm(src_length - 1 downto 0);
    return result;
  end ;


end ;

