Vhdl Vending Machine Question - Page 1
Forum section: electronics / beginners

author: Karamel
author_rank: Regular Contributor
timestamp: December 20, 2017, 09:45:36 pm
content: Hi,I am trying to impelement vending machine with Moore output logic. My machine has coin input and I have these states;Idle, AcceptMoney, Calculate, Ready.Machine starts at idle state. If someone has pressed to request button, machine jumps to AcceptMoney state. In this state, if someone press coin button, my coin should be increment by one but, it behaves strange, increases too much.my code is like these:Code:signal MyMoney : unsigned (3 downto 0) := x"0";signal MyPrize : std_logic_vector (3 downto 0) := x"0";begin-- my state machine!!process(clk, reset)beginif(reset = '1') thenstate_reg <= idle;elsif(clk'event and clk = '1') thenstate_reg <= state_next;end if;end process;--my FSMprocess(state_reg, one_tl, request, MyMoney)begincase state_reg iswhen idle =>digit2 <= "0000";ready <= '0';if(request = '1') thenstate_next <= acceptMoney;end if;when acceptMoney =>digit2 <= "0001";ready <= '0';if(one_tl = '1') thenstate_next <= calculate;end if;when calculate =>digit2 <= "0010";ready <= '0';if(MyMoney = unsigned(MyPrize)) thenstate_next <= myReady;elsestate_next <= acceptMoney;end if;when myReady =>digit2 <= "0011";ready <= '1';if(take_item = '1') thenstate_next <= idle;end if;end case;end process;digit1 <= std_logic_vector(MyMoney);MyPrize <= "0001" when(item_select = "00") else"0010" when(item_select = "01") else"0011" when(item_select = "10") else"0100" when(item_select = "11");

author: rstofer
author_rank: Super Contributor
timestamp: December 20, 2017, 11:02:20 pm
content: Quote from: Karamel on December 20, 2017, 09:45:36 pmEvery output of the state machine needs to be defined under all conditions in all states. This tends to be burdensome so we set some default values at the top of the combinatorial process:Code:--my FSMprocess(state_reg, one_tl, request, MyMoney)begin-- define default outputsstate_next <= state_reg;digit2 <= (others => '0');ready <= '0';-- etc. --case state_reg iswhen idle =>digit2 <= "0000";ready <= '0';if(request = '1') thenstate_next <= acceptMoney;end if;

author: Karamel
author_rank: Regular Contributor
timestamp: December 20, 2017, 11:10:21 pm
content: I didn't understand. First machine works for state_next to state_reg,Code:begin-- my state machine!!process(clk, reset)beginif(reset = '1') thenstate_reg <= idle;elsif(clk'event and clk = '1') thenstate_reg <= state_next;end if;end process;After, I am looking of states.Code:--my FSMprocess(state_reg, one_tl, request, MyMoney)begincase state_reg iswhen idle =>digit2 <= "0000";ready <= '0';if(request = '1') thenstate_next <= acceptMoney;end if;when acceptMoney =>digit2 <= "0001";ready <= '0';if(one_tl = '1') thenstate_next <= calculate;end if;when calculate =>digit2 <= "0010";ready <= '0';if(MyMoney = unsigned(MyPrize)) thenstate_next <= myReady;elsestate_next <= acceptMoney;end if;when myReady =>digit2 <= "0011";ready <= '1';if(take_item = '1') thenstate_next <= idle;end if;end case;end process;Could you try to fix my problem on my code? Because I didn't understand anything.

author: rstofer
author_rank: Super Contributor
timestamp: December 21, 2017, 12:44:13 am
content: Actually, you only have 3 outputs and I defined them all in my first response.Consider the case in state 'idle' where you doif(request = '1') thenstate_next <= acceptMoney;end if;You don't assign a value to state_next if request /= '1'.Every output must be defined under every condition in every state. OR, you assign default values at the top of the process like I did in my first response.The effect iswhen idle =>...if(request = '1') thenstate_next <= acceptMoney;elsestate_next <= idle;end if;Assigning a default value to state_next may not be a good idea. More often you want to stay in the same state by default. In that case, provide the else clause in every state and omit it at the beginning of the process. In that case, you would only default digit2 and ready.ETA: I made that too complicated. Just define the defaults as I did above and state_next will default to state_reg but will be overridden by assignments like state_next = idle. By default, unless overridden, you will always stay in the state you are in.If there is under any question about what state the FSM should transition to it will go somewhere you can't even imagine. Furthermore, latches will be inferred for the undefined outputs and that is a really bad idea.ETA: Every state has to define both digit2 and ready even if they aren't used in that state. There can be no condition under which the output isn't defined. Thus the default assignment at the top of the FSM.

author: stj
author_rank: Super Contributor
timestamp: December 21, 2017, 07:52:25 pm
content: in a real vending machine you cant do that.you need multitasking.one routine services the coinmech and note-validator and updates the value deposited,another routine reads the inputs and if you select something in stock, it compares the value to the deposited amount.if it's equal or higher it dispenses the product and deducts the amount from the deposited value.a final routine on demand, pays out the deposited ot remaining value.this one is a bit complex because it has to check what denominations of coins and notes are in the system and break down the total into the smaller units before driving the hoppers or note recycler.you cant do this type of thing with linear coding.

author: rstofer
author_rank: Super Contributor
timestamp: December 21, 2017, 08:20:43 pm
content: It is worth pointing out that your FSM (itself) is not clocked, only the state value is registered. Therefore, values for ready and digit2 are not clocked into registers and the values set only last for the duration of the state.If you want the signals to retain their values between states, you need to pull all of the combinatorial logic up into the clocked process or create some other way of registering the values. This other way usually has separate clocked processes (D-flops) enabled by signals in the FSM.