Finite State Machine VendingMachine problem & solution

apaj edited this page Sep 3, 2018 · 1 revision

Solution to the Vending Machine problem is provided and commented within this page, omitting the overhead (such as import statements, etc).

The problem is given as follows:

// Problem:
// Implement a vending machine using 'when' states.
// 'nickel' is a 5 cent coin
// 'dime'   is 10 cent coin
// 'sOk' is reached when there are coins totalling 20 cents or more in the machine.
// The vending machine should return to the 'sIdle' state from the 'sOk' state.

We first define the box and the ports, in a standard way:

class VendingMachine extends Module {
  val io = IO(new Bundle {
    val nickel = Input(Bool())
    val dime   = Input(Bool())
    val valid  = Output(Bool())

Next is bookkeeping for the states, explained in more detail in Enum, as follows:

  val sIdle :: s5 :: s10 :: s15 :: sOk :: Nil = Enum(5)

Define the beginning state, i.e. the state in which the FSM goes at reset:

  val state = RegInit(sIdle)

For each of the possible states and conditions, we use when, === and := to determine where to go next from the current state given the appropriate condition:

  when (state === sIdle) { // if we are in state sIdle, meaning "no money"
    when (io.nickel) { state := s5 } // and a nickle appears, next state is s5
    when (io.dime)   { state := s10 } // if a dime appears, next state is s10
  when (state === s5) { // if we are in state s5
    when (io.nickel) { state := s10 } // another nickle takes us to s10
    when (io.dime)   { state := s15 } // and a dime takes us to 5+10 => s15
  when (state === s10) { // if the first coin was actually a dime
    when (io.nickel) { state := s15 } // a nickle takes us to 10+5 =>s15
    when (io.dime)   { state := sOk } // another dime take us back to zero 
  when (state === s15) { // if there were a nickle and a dime,
    when (io.nickel) { state := sOk } // in both cases
    when (io.dime)   { state := sOk } // FSM is taken back to zero
  when (state === sOk) {
    state := sIdle // once zero is reached, machine goes back to idle

Finally, the output will assert if the state of zero money, i.e. sum of 20 cents is reached:

  io.valid := (state === sOk)
Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.