-- Seven segment bubble LED, HP QDSP 6064
-- Steven J. Merrifield, June 2016

library ieee;
use ieee.std_logic_1164.all;

entity LED_driver is
    port (clk : in std_logic;
            data : in std_logic_vector(15 downto 0);
            segments : out std_logic_vector(6 downto 0); -- 'g' downto 'a'
            cathodes : out std_logic_vector(3 downto 0)
        );
end LED_driver;

architecture arch of LED_driver is

function dec2seg(num : std_logic_vector(3 downto 0)) return std_logic_vector is
begin
    case num is
        when "0000" => return("0111111"); -- 0
        when "0001" => return("0000110"); -- 1
        when "0010" => return("1011011"); -- 2
        when "0011" => return("1001111"); -- 3
        when "0100" => return("1100110"); -- 4
        when "0101" => return("1101101"); -- 5
        when "0110" => return("1111101"); -- 6
        when "0111" => return("0000111"); -- 7
        when "1000" => return("1111111"); -- 8
        when "1001" => return("1101111"); -- 9
        when "1010" => return("1110111"); -- A
        when "1011" => return("1111100"); -- b
        when "1100" => return("1011000"); -- c
        when "1101" => return("1011110"); -- d
        when "1110" => return("1111001"); -- E
        when "1111" => return("1110001"); -- F
        when others => return("0000000");
    end case;
end dec2seg;

constant refresh_max : integer := 10000;

begin
    process
        variable refresh_counter : integer := 0;
        variable cathode_num : integer range 0 to 3 := 0;
    begin
        wait until rising_edge(clk);
        if (refresh_counter < refresh_max) then
            refresh_counter := refresh_counter + 1;
        else
            refresh_counter := 0;
            if (cathode_num /= 3) then
                cathode_num := cathode_num + 1;
            else
                cathode_num := 0;
            end if;
            case cathode_num is
                when 0 => segments <= dec2seg(data(3 downto 0)); cathodes <= "1110";
                when 1 => segments <= dec2seg(data(7 downto 4)); cathodes <= "1101";
                when 2 => segments <= dec2seg(data(11 downto 8)); cathodes <= "1011";
                when 3 => segments <= dec2seg(data(15 downto 12)); cathodes <= "0111";
                when others => segments <= "0000000"; cathodes <= "1111";
            end case;
        end if;
           
    end process;
end arch;

