library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity soda_dispenser is
    Port (
        clk     : in  STD_LOGIC;
        reset   : in  STD_LOGIC;
        nickel  : in  STD_LOGIC;
        dime    : in  STD_LOGIC;
        quarter : in  STD_LOGIC;
        price   : in  STD_LOGIC_VECTOR(7 downto 0);  -- 8-bit price input
        d       : out STD_LOGIC                     -- dispense output
    );
end soda_dispenser;

architecture Behavioral of soda_dispenser is
    type STATE_TYPE is (Init, Check, Add, Disp);
    signal state : STATE_TYPE := Init;

    signal sum     : unsigned(7 downto 0) := (others => '0'); -- total inserted
    signal coin    : unsigned(7 downto 0) := (others => '0'); -- current coin value
    signal p       : unsigned(7 downto 0);                    -- converted price input
begin

    p <= unsigned(price);  -- Convert STD_LOGIC_VECTOR to unsigned

    process(clk, reset)
    begin
        if reset = '1' then
            state <= Init;
            sum   <= (others => '0');
            coin  <= (others => '0');
            d     <= '0';

        elsif rising_edge(clk) then
            case state is

                when Init =>
                    sum <= (others => '0');
                    d   <= '0';
                    state <= Check;

                when Check =>
                    if (nickel = '1' or dime = '1' or quarter = '1') then
                        if nickel = '1' then
                            coin <= to_unsigned(5, 8);
                        elsif dime = '1' then
                            coin <= to_unsigned(10, 8);
                        elsif quarter = '1' then
                            coin <= to_unsigned(25, 8);
                        end if;
                        state <= Add;
                    end if;

                when Add =>
                    sum <= sum + coin;
                    if sum + coin >= p then
                        state <= Disp;
                    else
                        state <= Check;
                    end if;

                when Disp =>
                    d <= '1';
                    sum <= (others => '0');
                    state <= Check;

            end case;
        end if;
    end process;
end Behavioral;
