Search code examples
binaryvhdlbcd

Converting 8 bit binary to BCD value


I have spent countless hours on this and I just finally decided I really need some help..so here I am.

Basically what I am doing is taking an 8 bit input from an ADC and then converting this value to BCD to display on a seven segment board. SO here is my code so far:

Library IEEE ;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use IEEE.std_logic_unsigned.all;

entity Voltage_LUT is
  Port ( scaled_value : in  unsigned(7 downto 0);
         true_value : out  STD_LOGIC_VECTOR (15 downto 0)
  );
end Voltage_LUT;

architecture Behavioral of Voltage_LUT is

  function  divide  (a : UNSIGNED; b : UNSIGNED) return unsigned is
    variable a1 : unsigned(a'length-1 downto 0):=a;
    variable b1 : unsigned(b'length-1 downto 0):=b;
    variable p1 : unsigned(b'length downto 0):= (others => '0');
    variable i : integer:=0;
  begin
    for i in 0 to b'length-1 loop
      p1(b'length-1 downto 1) := p1(b'length-2 downto 0);
      p1(0) := a1(a'length-1);
      a1(a'length-1 downto 1) := a1(a'length-2 downto 0);
      p1 := p1-b1;
      if(p1(b'length-1) ='1') then
        a1(0) :='0';
        p1 := p1+b1;
      else
        a1(0) :='1';
      end if;
    end loop;
    return a1;
  end divide;

  signal  adj: unsigned(7 downto -2);    --adjusted to max 90
  signal  max_value: unsigned(7 downto 0):= "11111111" ;    --adjusted to max 90
  signal  MSB_int: integer;   -- integer form of MSB
  signal  LSB_int: integer;    --integer form of LSB
  signal  adj2: unsigned(15 downto 0);    --converted from adjusted integer to binary
  signal  LSB: STD_LOGIC_VECTOR (3 downto 0);    --BCD for LSB
  signal  MSB: STD_LOGIC_VECTOR (3 downto 0);    --BCD for MSB
  signal  OFF: STD_LOGIC_VECTOR (3 downto 0):="1010";    --defined to be segment OFF
  signal  V: STD_LOGIC_VECTOR (3 downto 0):="1011";    --defined to be letter V

begin

  adj <= divide ( scaled_value , max_value );
  adj2 <= adj* "00001001" ;

end Behavioral;    

Essentially what I am doing is taking an 8 bit value from the ADC then expressing it as a fraction of the max value (which is 9) and then I have to convert this to BCD... but when I am running this code I am getting an error stating:

Line 38: Index value <-2> is out of range [0:2147483647] of array

I need the answer of the division to be a binary number (with decimals eg 11001.110) so that it would be accurate when I multiply it by 9...


Solution

  • The offending line is:

    signal  adj: unsigned(7 downto -2);
    

    The type unsigned does not support negative ranges. If you want to treat your result as a fixed-point value with a fractional component, you have a couple choices, including:

    • If you have VHDL-2008 compliant tools, you can use ieee.fixed_pkg, which includes the type ufixed, which does support negative indices, as you tried to do with unsigned.

    • If you don't have VHDL-2008 compliant tools, you can always just manage the binary point virtually, i.e. declare:

      signal  adj: unsigned(9 downto 0);
      

      With this method, you will need to do the bookkeeping manually, unfortunately. Since you only appear to be doing multiplies and divides, you don't have to worry about aligning the binary point, though. Whether the value is "accurate" or not depends on how you use it in subsequent logic.