Nanfeng

Notes on software development, code, and curious ideas

Designing a Vending Machine Controller in VHDL

A vending-machine course project is a practical finite-state and datapath design. The controller accepts validated coin pulses, accumulates credit, checks a selected product price, emits a dispense pulse, returns change, and updates a display.

Partition the design

  • An input conditioner synchronizes and debounces mechanical coin and button signals.
  • A credit register adds accepted denominations and enforces a maximum.
  • Selection logic looks up price and availability.
  • Transaction control emits one-cycle dispense and change events.
  • A BCD/display block drives the visible credit or status.

Represent money as integer units rather than a floating-point value.

Controller skeleton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
credit <= 0;
dispense <= '0';
change <= 0;
else
dispense <= '0';
change <= 0;

if coin_valid = '1' then
credit <= credit + coin_value;
end if;

if cancel = '1' then
change <= credit;
credit <= 0;
elsif select_valid = '1' and stock_available = '1' then
if credit >= selected_price then
dispense <= '1';
change <= credit - selected_price;
credit <= 0;
end if;
end if;
end if;
end if;
end process;

Production VHDL needs explicit types and ranges, and simultaneous events need a defined priority. For example, decide whether a coin arriving in the same cycle as selection contributes to that purchase.

Verification

The testbench should cover reset, every denomination, exact payment, excess payment, insufficient credit, cancellation, unavailable stock, repeated button pulses, simultaneous inputs, and maximum credit. Assertions should verify that dispense lasts exactly one cycle, credit never leaves its legal range, and value is conserved across credit, product price, and change.

Inspect waveforms for the controller, BCD conversion, display output, and top-level integration. A clean simulation separates clocked state from combinational next-state logic and initializes every output on every combinational path to prevent unintended latches.

+