Electronic – Read decimal value of a 4-bit binary input

fpgavhdl

I am quite a rookie in the VHDL world, but I seem to have hold of the basics.
Atm I am working on a project, which involves me to take a 4-bit binary input (switches), read this value and convert it to decimal values.

This far I have variables (count_ones, count_tens) which are supposed to contain the decimal value of the input.

My current code is as following:

architecture Behavioral of Seven_Seg_Counter is

    signal      count_ones      :   integer range 0 to 9 := 0;
    signal      count_tens      :   integer range 0 to 9 := 0;
    signal      count_hundreds  :   integer range 0 to 9 := 0;
    signal      count_thousands :   integer range 0 to 9 := 0;
    signal      prescaler       :   integer := 0;
    signal      anode           :   integer range 1 to 4 := 1;
    signal      digit           :   STD_LOGIC_VECTOR(3 downto 0) := "1110";

begin
    Calculate: process (CLK)
        variable        countings           :   integer range 0 to 9 := 0;

    begin
        if rising_edge(CLK) then
            if INPUT(3) = '1' then
                countings := 8;
            else
                countings := 0;
            end if;
            if INPUT(2) = '1' then
                countings := countings + 4;
            else
                countings := 0;
            end if;
            if INPUT(1) = '1' then
                countings := countings + 2;
            else
                countings := 0;
            end if;
            if INPUT(0) = '1' then
                countings := countings + 1;
            else
                countings := 0;
            end if;

            for I in 1 to 9 loop
                if countings > 9 then
                    countings := countings  - 10;
                    count_tens <= count_tens + 1;
                else
                    count_tens <= 0;
                end if;
            end loop;

            for G in 1 to 9 loop
                if countings > 0 then
                    countings := countings - 1;
                    count_ones <= count_ones + 1;
                else
                    count_ones <= 0;
                end if;
            end loop;
        end if;
    end process;

    process (anode, count_thousands, count_hundreds, count_tens, count_ones) -- Bestemmer output som funktion signalerne anode (segmentvælger) og count_XX (den decimale værdi)
    begin
        case anode is
            when 1 => 
                case count_ones is
                                          --abcdefg
                    when 0 => sseg <= "0000001"; -- 0
                    when 1 => sseg <= "1001111"; -- 1
                    when 2 => sseg <= "0010010"; -- 2
                    when 3 => sseg <= "0000110"; -- 3
                    when 4 => sseg <= "1001100"; -- 4
                    when 5 => sseg <= "0100100"; -- 5
                    when 6 => sseg <= "0100000"; -- 6
                    when 7 => sseg <= "0001111"; -- 7
                    when 8 => sseg <= "0000000"; -- 8
                    when 9 => sseg <= "0000100"; -- 9
                end case;
            when 2 => case count_tens is
                                          --abcdefg
                    when 0 => sseg <= "0000001"; -- 0
                    when 1 => sseg <= "1001111"; -- 1
                    when 2 => sseg <= "0010010"; -- 2
                    when 3 => sseg <= "0000110"; -- 3
                    when 4 => sseg <= "1001100"; -- 4
                    when 5 => sseg <= "0100100"; -- 5
                    when 6 => sseg <= "0100000"; -- 6
                    when 7 => sseg <= "0001111"; -- 7
                    when 8 => sseg <= "0000000"; -- 8
                    when 9 => sseg <= "0000100"; -- 9
                end case;
            when 3 => case count_hundreds is
                                          --abcdefg
                    when 0 => sseg <= "0000001"; -- 0
                    when 1 => sseg <= "1001111"; -- 1
                    when 2 => sseg <= "0010010"; -- 2
                    when 3 => sseg <= "0000110"; -- 3
                    when 4 => sseg <= "1001100"; -- 4
                    when 5 => sseg <= "0100100"; -- 5
                    when 6 => sseg <= "0100000"; -- 6
                    when 7 => sseg <= "0001111"; -- 7
                    when 8 => sseg <= "0000000"; -- 8
                    when 9 => sseg <= "0000100"; -- 9
                end case;
            when 4 =>  case count_thousands is
                                          --abcdefg
                    when 0 => sseg <= "0000001"; -- 0
                    when 1 => sseg <= "1001111"; -- 1
                    when 2 => sseg <= "0010010"; -- 2
                    when 3 => sseg <= "0000110"; -- 3
                    when 4 => sseg <= "1001100"; -- 4
                    when 5 => sseg <= "0100100"; -- 5
                    when 6 => sseg <= "0100000"; -- 6
                    when 7 => sseg <= "0001111"; -- 7
                    when 8 => sseg <= "0000000"; -- 8
                    when 9 => sseg <= "0000100"; -- 9
                end case;
        end case;
    end process;

    process (anode)
    begin
        case anode is
            when 1 => digit <= "1110";
            when 2 => digit <= "1101";
            when 3 => digit <= "1011";
            when 4 => digit <= "0111";
        end case;
    end process;

    segmentselect <= digit;
    LED_OUT <= INPUT;
end Behavioral;

My idea is, I store the binary value (looking aside 1's and 2's complement) in the variable countings (which works fine in a simulation). The next part is, where I actually find the value of countings, and store it's rightmost digit in the signal count_ones (ones), and the leftmost digit (tens) in the signal count_tens.
For some unknown reason, my way of finding the ones and tens does not work well with those loops. Maybe I totally misunderstood how to use for loops.

Could any of you maybe help me out? I would really appreciate it.


Loops are tricky indeed.
The thing is, a 4-bit input is only the beginning, I'd like to be able to read more, so if I can learn the basic method with just 4 bits, that'd be awesome.

Well, the count_ones signal is for the ones, and the count_tens is for the tens of the input, so I am not quite sure I get, how to_integer(unsigned(INPUT)); is gonna work out, so I get a decimal value from 0 to 9 in count_ones or count_tens.

The subtraction method you are referencing to, I believe, I have tried to implement that in my loops, which do not work out as expected.

Best Answer

Loops in HDL are a tricky thing to use in a synthesizable manner. I would recommend simply reading in the input bits as a binary number, compare with 9, if it is greater subtract 10.