Author Topic: Vhdl Vending Machine Question  (Read 1237 times)

0 Members and 1 Guest are viewing this topic.

Offline KaramelTopic starter

  • Regular Contributor
  • *
  • Posts: 178
  • Country: tr
Vhdl Vending Machine Question
« on: December 20, 2017, 09:45:36 pm »
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: [Select]
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)
begin
if(reset = '1') then
state_reg <= idle;
elsif(clk'event and clk = '1') then
state_reg <= state_next;
end if;
end process;


--my FSM
process(state_reg, one_tl, request, MyMoney)
begin

case state_reg is

when idle =>
digit2 <= "0000";
ready <= '0';

if(request = '1') then
state_next <= acceptMoney;
end if;

when acceptMoney =>
digit2 <= "0001";
        ready <= '0';

if(one_tl = '1') then
state_next <= calculate;
end if;

when calculate =>
digit2 <= "0010";
ready <= '0';

if(MyMoney = unsigned(MyPrize)) then
                                      state_next <= myReady;
else
                                      state_next <= acceptMoney;
end if;

when myReady =>
digit2 <= "0011";
ready <= '1';

if(take_item = '1') then
state_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");
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9886
  • Country: us
Re: Vhdl Vending Machine Question
« Reply #1 on: December 20, 2017, 11:02:20 pm »
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: [Select]
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)
begin
if(reset = '1') then
state_reg <= idle;
elsif(clk'event and clk = '1') then
state_reg <= state_next;
end if;
end process;


--my FSM
process(state_reg, one_tl, request, MyMoney)
begin

case state_reg is

when idle =>
digit2 <= "0000";
ready <= '0';

if(request = '1') then
state_next <= acceptMoney;
end if;

when acceptMoney =>
digit2 <= "0001";
        ready <= '0';

if(one_tl = '1') then
state_next <= calculate;
end if;

when calculate =>
digit2 <= "0010";
ready <= '0';

if(MyMoney = unsigned(MyPrize)) then
                                      state_next <= myReady;
else
                                      state_next <= acceptMoney;
end if;

when myReady =>
digit2 <= "0011";
ready <= '1';

if(take_item = '1') then
state_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");

Every 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: [Select]
--my FSM
process(state_reg, one_tl, request, MyMoney)
begin

                -- define default outputs
                state_next <= state_reg;
                digit2 <= (others => '0');
                ready <= '0';
                -- etc. --


case state_reg is

when idle =>
digit2 <= "0000";
ready <= '0';

if(request = '1') then
state_next <= acceptMoney;
end if;
« Last Edit: December 21, 2017, 06:02:47 am by rstofer »
 

Offline KaramelTopic starter

  • Regular Contributor
  • *
  • Posts: 178
  • Country: tr
Re: Vhdl Vending Machine Question
« Reply #2 on: December 20, 2017, 11:10:21 pm »
I didn't understand. First machine works for state_next to state_reg,

Code: [Select]
begin
  -- my state machine!!
  process(clk, reset)
  begin
   if(reset = '1') then
    state_reg <= idle;
   elsif(clk'event and clk = '1') then
    state_reg <= state_next;
   end if;
  end process;

After, I am looking of states.

Code: [Select]
  --my FSM
  process(state_reg, one_tl, request, MyMoney)
  begin
 
  case state_reg is
 
   when idle =>
    digit2 <= "0000";
    ready <= '0';
   
    if(request = '1') then
     state_next <= acceptMoney;
    end if;

   when acceptMoney =>
    digit2 <= "0001";
           ready <= '0';
   
    if(one_tl = '1') then
     state_next <= calculate;
    end if;
   
   when calculate =>
    digit2 <= "0010";
    ready <= '0';

    if(MyMoney = unsigned(MyPrize)) then
                                      state_next <= myReady;
    else
                                      state_next <= acceptMoney;
    end if;
   
   when myReady =>
    digit2 <= "0011";
    ready <= '1';
   
    if(take_item = '1') then
     state_next <= idle;
    end if;
 
  end case;
 
  end process;

Could you try to fix my problem on my code? Because I didn't understand anything.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9886
  • Country: us
Re: Vhdl Vending Machine Question
« Reply #3 on: December 21, 2017, 12:44:13 am »
Actually, you only have 3 outputs and I defined them all in my first response.
Consider the case in state 'idle' where you do
    if(request = '1') then
     state_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 is

when idle =>
     ...
    if(request = '1') then
     state_next <= acceptMoney;
    else
      state_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.

« Last Edit: December 21, 2017, 06:01:52 am by rstofer »
 

Offline stj

  • Super Contributor
  • ***
  • Posts: 2153
  • Country: gb
Re: Vhdl Vending Machine Question
« Reply #4 on: December 21, 2017, 07:52:25 pm »
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.
« Last Edit: December 21, 2017, 08:50:29 pm by stj »
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9886
  • Country: us
Re: Vhdl Vending Machine Question
« Reply #5 on: December 21, 2017, 08:20:43 pm »
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.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf