Vending Machine Accumulator FSM
Automated retail systems rely on control logic to manage transactions and track deposited funds. A vending machine must maintain a running total of inserted coins, trigger a dispense operation once the required price is met, and calculate the appropriate change to return to the user.
The module receives a 2-bit coin_in signal representing the coin deposited. It maintains an internal accumulator for the total value. When the accumulated value reaches or exceeds the target price of 50 cents, the system transitions to a vending state for exactly one clock cycle. During this cycle, it asserts the dispense signal, outputs the excess amount on the change port, and resets the internal accumulator to zero. Any coins inserted during the vending cycle are ignored.
The machine evaluates inputs on the positive edge of clk. It uses an asynchronous, active-low reset rst_n.
The coin_in mapping is as follows: • 2'b00: 0 cents (no coin) • 2'b01: 5 cents • 2'b10: 10 cents • 2'b11: 25 cents
Cycle-by-cycle trace: Cycle 1: rst_n=0 → internal total=0, dispense=0, change=0 Cycle 2: rst_n=1, coin_in=2'b11 (25c) → internal total=25, dispense=0, change=0 Cycle 3: rst_n=1, coin_in=2'b11 (25c) → internal total=50, dispense=1, change=0 (vend triggered) Cycle 4: rst_n=1, coin_in=2'b01 (5c) → internal total=0, dispense=0, change=0 (5c ignored during vend) Cycle 5: rst_n=1, coin_in=2'b10 (10c) → internal total=10, dispense=0, change=0
flowchart LR
RESET(( )) -->|reset| IDLE
IDLE((IDLE)) -->|total + coin < 50| IDLE
IDLE -->|total + coin >= 50| VEND
VEND(["VEND ★"]):::out -->|unconditional| IDLE
classDef out fill:#6C5CE7,stroke:#5B4FE8,color:#fff{ "signal": [
{ "name": "clk", "wave": "p......" },
{ "name": "rst_n", "wave": "01....." },
{ "name": "coin_in", "wave": "=.=.=.=.=.=.", "data": ["0", "3", "3", "1", "2", "0"] },
{ "name": "dispense", "wave": "0..10.." },
{ "name": "change", "wave": "=......", "data": ["0"] }
], "head": { "text": "Two 25c coins trigger vend. The 5c coin during vend is ignored." } }| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset; all outputs go to 0 when asserted | | coin_in | input | 2 | Value of the deposited coin | | dispense | output | 1 | Registered output; asserts to 1 for one cycle when total >= 50c | | change | output | 6 | Registered output; outputs (total - 50) during the dispense cycle, otherwise 0 |
Constraints
- The design must use a positive-edge triggered clock and an asynchronous active-low reset.
dispenseandchangemust be registered outputs (driven directly by flip-flops, not combinational logic).- During the cycle where
dispenseis 1, any non-zerocoin_invalue must be ignored and not added to the next transaction. - The internal accumulator must reset to 0 in the cycle following the vend.
- The maximum possible accumulated value before a vend triggers is 70 cents (45 cents + 25 cents). Ensure internal registers are appropriately sized.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.