Washing Machine FSM Fix
Washing Machine FSM Fix
reg t ;
reg [2:0] timerOut;
reg [2:0] presentState, nextState;
if(presentState == start)
begin
t <= 1'b0;
timerOut <= 3'd0;
end
else begin
presentState <= nextState;
while (timerOut <= 3'd5) begin
timerOut <= timerOut + 1;
end
if (timerOut == 3'd5)
begin
timerOut <= 3'b111;
t <= 1;
end else
t <= 0;
end
1/81
end
end
case(presentState)
start : nextState = coin ? soak : start;
soak : nextState = t ? wash : soak;
wash : nextState = t ? rinse : wash;
rinse : nextState = t ? (doubleWash ? wash : spin ) :
rinse;
spin : nextState = t ? (lid ? stop : start) : spin;
stop : nextState = lid ? stop : spin;
default: nextState = start;
endcase
end
endmodule
2/81
wire complete;
reg coin , doubleWash , lid , clk ;
initial begin
$dumpfile("5_WashingMachine.vcd");
$dumpvars();
end
initial begin
$monitor ("time=%3t clk=%b coin=%b doubleWash=%b
lid=%b | complete = %b ", $time,clk,coin, doubleWash,
lid,complete);
end
initial begin
clk=0;coin=0;lid=0;doubleWash=0;#10;
coin=1;lid=0;doubleWash=0;#10;
doubleWash=1;#10;
lid=1 ;#10;
lid=0; #10;
$finish;
end
Below is one corrected version of your design. In this revision, I made the following key
changes:
Module Names: Renamed the modules so they start with a letter (avoiding names like
“5_WashingMachine”).
Clock & Timer Handling: Removed the non‐synthesizable while loop and instead use a
counter (with a parameterized maximum count) that increments on every clock cycle.
3/81
When the counter reaches the timer maximum, the “t” signal is asserted and the state
machine transitions.
State Updates: Combined the coin‐triggered start and regular state transitions in a
synchronous always block. Next‑state and output logic are handled in separate
combinational always blocks.
Testbench Clock Generation: Fixed the clock generation (using an initial block with a
forever loop rather than an “always” assignment).
You may adjust the timer period (set by TIMER_MAX ) to suit your design. Review the state
transitions and output logic to ensure they match your intended washing-machine behavior.
verilog
module WashingMachine (
input clk,
input coin,
input lid,
input doubleWash,
output reg complete
);
// FSM States
parameter START = 3'b000,
SOAK = 3'b001,
WASH = 3'b010,
RINSE = 3'b011,
SPIN = 3'b100,
STOP = 3'b101;
reg t;
reg [2:0] timerOut;
reg [2:0] presentState, nextState;
4/81
// Synchronous state and timer update
always @(posedge clk) begin
// On coin insertion at START, immediately move to SOAK
if (presentState == START && coin) begin
presentState <= SOAK;
timerOut <= 0;
t <= 0;
end
else begin
// Increment timer until it reaches TIMER_MAX
if (timerOut < TIMER_MAX) begin
timerOut <= timerOut + 1;
t <= 0;
end
else begin
// Timer expired: reset timer, signal expiration, and update state
timerOut <= 0;
t <= 1;
presentState <= nextState;
end
end
end
5/81
default: complete = 0;
endcase
end
endmodule
verilog
module WashingMachine_tb;
// Monitor signals
initial begin
$monitor("time=%3t clk=%b coin=%b doubleWash=%b lid=%b complete=%b",
$time, clk, coin, doubleWash, lid, complete);
6/81
end
// Test stimulus
initial begin
// Initial values
coin = 0;
doubleWash = 0;
lid = 0;
#10;
// Simulate lid open then close (as needed by SPIN state logic)
lid = 1;
#10;
lid = 0;
#20;
$finish;
end
endmodule
This version corrects the syntactic issues and makes the FSM and timer logic synthesizable.
Adjust the timing and state conditions as necessary for your intended simulation behavior.
remove comments
verilog
7/81
module WashingMachine (
input clk,
input coin,
input lid,
input doubleWash,
output reg complete
);
reg t;
reg [2:0] timerOut;
reg [2:0] presentState, nextState;
parameter TIMER_MAX = 5;
8/81
SOAK: nextState = t ? WASH : SOAK;
WASH: nextState = t ? RINSE : WASH;
RINSE: nextState = t ? (doubleWash ? WASH : SPIN) : RINSE;
SPIN: nextState = t ? (lid ? STOP : START) : SPIN;
STOP: nextState = lid ? STOP : SPIN;
default: nextState = START;
endcase
end
endmodule
verilog
module WashingMachine_tb;
WashingMachine dut (
.clk(clk),
.coin(coin),
.lid(lid),
.doubleWash(doubleWash),
.complete(complete)
);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("WashingMachine.vcd");
9/81
$dumpvars;
end
initial begin
$monitor("time=%3t clk=%b coin=%b doubleWash=%b lid=%b complete=%b",
$time, clk, coin, doubleWash, lid, complete);
end
initial begin
coin = 0;
doubleWash = 0;
lid = 0;
#10;
coin = 1;
#10;
coin = 0;
doubleWash = 1;
#10;
lid = 1;
#10;
lid = 0;
#20;
$finish;
end
endmodule
verilog
module WashingMachine (
input clk,
input coin,
input lid,
input doubleWash,
output reg complete
);
parameter START = 3'b000,
SOAK = 3'b001,
WASH = 3'b010,
10/81
RINSE = 3'b011,
SPIN = 3'b100,
STOP = 3'b101;
initial begin
presentState = START;
timerOut = 0;
complete = 0;
end
11/81
SOAK: nextState = WASH;
WASH: nextState = RINSE;
RINSE: nextState = doubleWash ? WASH : SPIN;
SPIN: nextState = lid ? STOP : SPIN;
STOP: nextState = lid ? STOP : SPIN;
default: nextState = START;
endcase
end
endmodule
verilog
module WashingMachine_tb;
reg clk, coin, lid, doubleWash;
wire complete;
WashingMachine dut (
.clk(clk),
.coin(coin),
.lid(lid),
.doubleWash(doubleWash),
.complete(complete)
);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("WashingMachine.vcd");
$dumpvars;
end
initial begin
$monitor("time=%3t clk=%b coin=%b doubleWash=%b lid=%b complete=%b",
$time, clk, coin, doubleWash, lid, complete);
end
initial begin
coin = 0;
doubleWash = 0;
12/81
lid = 0;
#10;
coin = 1;
#10;
coin = 0;
doubleWash = 0;
#30;
lid = 1;
#10;
lid = 0;
#30;
$finish;
end
endmodule
13/81
time= 70 clk=0 coin=0 doubleWash=0 lid=0 complete=0
time= 75 clk=1 coin=0 doubleWash=0 lid=0 complete=0
time= 80 clk=0 coin=0 doubleWash=0 lid=0 complete=0
time= 85 clk=1 coin=0 doubleWash=0 lid=0 complete=0
q1.v:103: $finish called at 90 (1s)
time= 90 clk=0 coin=0 doubleWash=0 lid=0 complete=0
siddharthdoshi06@DESKTOP-
7RLTNAI:~/Verilog2/assignment2.1/question5$
verilog
module WashingMachine (
input clk,
input coin,
input lid,
input doubleWash,
output reg complete
);
parameter START = 3'b000,
SOAK = 3'b001,
WASH = 3'b010,
RINSE = 3'b011,
SPIN = 3'b100,
STOP = 3'b101;
initial begin
presentState = START;
timerOut = 0;
complete = 0;
end
14/81
timerOut <= timerOut + 1;
complete <= 0;
end else begin
timerOut <= 0;
if (presentState == SPIN && ~lid) begin
complete <= 1;
presentState <= START;
end else begin
complete <= 0;
presentState <= nextState;
end
end
end
end
verilog
module WashingMachine_tb;
reg clk, coin, lid, doubleWash;
wire complete;
WashingMachine dut (
.clk(clk),
.coin(coin),
.lid(lid),
.doubleWash(doubleWash),
.complete(complete)
);
15/81
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("WashingMachine.vcd");
$dumpvars;
end
initial begin
$monitor("time=%3t clk=%b coin=%b doubleWash=%b lid=%b complete=%b",
$time, clk, coin, doubleWash, lid, complete);
end
initial begin
coin = 0;
doubleWash = 0;
lid = 0;
#10;
coin = 1;
#10;
coin = 0;
#180;
$finish;
end
endmodule
16/81
b) Write verilog code to simulate the state machine.
Inputs:
• coin: A pulse that starts the machine.
• doubleWash: When high, causes the machine to repeat the wash/rinse sequence.
• lid: Indicates if the lid is raised. (During spin, if high the timer is suspended.)
Output:
• complete: A one‐cycle pulse (or level) indicating the process has finished (when the spin
cycle completes with the lid lowered).
State Diagram:
pgsql
+----------------+
| |<--(after spin timer T & lid low)--+
| Idle | |
| (waiting coin) | |
+----------------+ |
| coin=1 complete
v
+----------------+
| |
| Soak | <-- Timer T (after period)
| |
+----------------+
|
v Timer T
+----------------+
| |
| Wash | <-- Timer T (after period)
| |
+----------------+
|
v Timer T
+----------------+
| |--- if doubleWash=1 --> (back to Wash)
| Rinse |
| |--- if doubleWash=0 --> (proceed to Spin)
17/81
+----------------+
|
v Timer T (only if lid is low)
+----------------+
| |
| Spin |
| | (if lid is raised, hold in Spin; timer halted)
+----------------+
Verilog Code:
Below is one possible Verilog simulation that implements the described state machine. In
this code the internal timer counter simulates the fixed time period for each stage. During
the spin state, if the lid is raised the timer does not increment. When the timer expires in spin
with the lid lowered, the machine outputs a complete signal and returns to the idle state.
verilog
module WashingMachine (
input clk,
input coin,
input doubleWash,
input lid,
output reg complete
);
// State encoding
parameter IDLE = 3'b000,
SOAK = 3'b001,
WASH = 3'b010,
RINSE = 3'b011,
SPIN = 3'b100;
initial begin
state = IDLE;
timer = 0;
18/81
complete = 0;
end
// State transitions occur when the timer expires (except in spin if lid is
raised)
if (timer == TIMER_MAX) begin
// For spin, only allow transition if lid is low
if (state == SPIN && ~lid)
state <= next_state;
else if (state != SPIN)
state <= next_state;
end
end
// Next-state logic
always @(*) begin
case (state)
IDLE: begin
if (coin)
next_state = SOAK;
else
next_state = IDLE;
end
SOAK: next_state = WASH; // after timer T in soak
WASH: next_state = RINSE; // after timer T in wash
RINSE: begin
if (doubleWash)
next_state = WASH; // second wash if doubleWash is on
else
next_state = SPIN;
end
SPIN: begin
19/81
// During spin, if lid is raised, remain in SPIN.
if (lid)
next_state = SPIN;
else
next_state = IDLE; // complete the cycle when lid is
lowered
end
default: next_state = IDLE;
endcase
end
// Output logic: complete is asserted in the spin state when timer expires and
lid is low.
always @(*) begin
if (state == SPIN && timer == TIMER_MAX && ~lid)
complete = 1;
else
complete = 0;
end
endmodule
verilog
module WashingMachine_tb;
reg clk, coin, doubleWash, lid;
wire complete;
WashingMachine dut (
.clk(clk),
.coin(coin),
.doubleWash(doubleWash),
.lid(lid),
.complete(complete)
);
20/81
initial begin
$dumpfile("WashingMachine.vcd");
$dumpvars;
end
initial begin
$monitor("time=%3t | clk=%b coin=%b doubleWash=%b lid=%b complete=%b",
$time, clk, coin, doubleWash, lid, complete);
end
initial begin
// Start in Idle
coin = 0; doubleWash = 0; lid = 0;
#10;
// Insert coin to start cycle; process enters Soak.
coin = 1;
#10;
coin = 0;
// For this test, you can adjust doubleWash and lid to check different
paths.
// Let doubleWash = 1 for a double wash scenario (optional)
doubleWash = 1;
// Wait long enough for several timer cycles to pass
#100;
// Now simulate lid being raised during spin (this should freeze the timer)
lid = 1;
#30;
// Lower the lid so spin can complete and machine resets.
lid = 0;
#50;
$finish;
end
endmodule
Explanation:
1. Idle: The machine waits for a coin. Once a coin is inserted, it moves to Soak.
21/81
2. Soak, Wash, and Rinse: Each state waits for the timer to count to its maximum
(TIMER_MAX). In Rinse, if the doubleWash input is high, the machine goes back to Wash;
otherwise it proceeds to Spin.
3. Spin: The timer runs only if the lid is not raised. If the lid is raised, the timer is suspended
(the machine holds in the SPIN state). Once the lid is lowered and the timer expires, the
machine outputs a complete signal and returns to Idle.
verilog
module WashingMachine (
input clk,
input coin,
input doubleWash,
input lid,
output reg complete
);
parameter IDLE = 3'b000,
SOAK = 3'b001,
WASH = 3'b010,
RINSE = 3'b011,
SPIN = 3'b100;
initial begin
state = IDLE;
timer = 0;
complete = 0;
end
22/81
state : next_state;
end
verilog
module WashingMachine_tb;
reg clk, coin, doubleWash, lid;
wire complete;
WashingMachine dut (
.clk(clk),
.coin(coin),
.doubleWash(doubleWash),
.lid(lid),
.complete(complete)
);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("WashingMachine.vcd");
$dumpvars;
end
initial begin
$monitor("time=%3t | clk=%b coin=%b doubleWash=%b lid=%b complete=%b",
23/81
$time, clk, coin, doubleWash, lid, complete);
end
initial begin
coin = 0; doubleWash = 0; lid = 0; #10;
coin = 1; #10;
coin = 0; doubleWash = 1; #100;
lid = 1; #30;
lid = 0; #50;
$finish;
end
endmodule
24/81
if (!rst) present_state <= IDLE;
else present_state <= next_state;
case (present_state)
IDLE: begin
// total_amount <= 0; total_cost<=0;
remaining_change<=0;change <= 0; notes_100 <= 0;
notes_50 <= 0; notes_20 <= 0; notes_10 <= 0; notes_5 <= 0;
money_in = (money_5 * 5) + (money_10 * 10) +
(money_20 * 20) + (money_50 * 50) + (money_100 * 100);
end
ACCEPT: begin total_amount <= money_in; end
endcase
end
$display($time,1111,remaining_change,change,total_cost);
25/81
end
if(remaining_change<total_cost) begin
$display($time,222,remaining_change,change,total_cost);
notes_100 = remaining_change / 100;
remaining_change = remaining_change %
100;
$display($time,222,remaining_change,change,total_cost,no
tes_100);
notes_50 = remaining_change / 50;
remaining_change = remaining_change %
50;
$display($time,222,remaining_change,change,total_cost,no
tes_50);
notes_20 = remaining_change / 20;
remaining_change = remaining_change %
20;
$display($time,222,remaining_change,change,total_cost,no
tes_20);
notes_10 = remaining_change / 10;
remaining_change = remaining_change %
10;
$display($time,222,remaining_change,change,total_cost,no
tes_10);
notes_5 = remaining_change / 5;
remaining_change = remaining_change % 5;
$display($time,222,remaining_change,change,total_amoun
t,total_cost,notes_5);
change = total_amount - total_cost;
$display($time,222,remaining_change,change,total_cost,no
26/81
tes_5);
next_state=DISPENSE;
end
end
else begin
$display($time,444,remaining_change,total_cost);
next_state = ASK_MORE;
end
end
ASK_MORE:begin
if(remaining_change > 0 && add_more) begin
$display($time,555,remaining_change,total_cost);
//change = 0;
//notes_100 = 0;
//notes_50 = 0;
//notes_20 = 0;
//notes_10 = 0;
//notes_5 = 0;
//total_cost=0;
next_state=SELECT;
end
else begin
$display($time,666,remaining_change,change,total_cost,no
tes_5);
notes_100 = remaining_change / 100;
remaining_change = remaining_change %
100;
$display($time,666,remaining_change,change,total_cost,no
tes_5);
notes_50 = remaining_change / 50;
remaining_change = remaining_change %
50;
$display($time,666,remaining_change,change,total_cost,no
27/81
tes_5);
notes_20 = remaining_change / 20;
remaining_change = remaining_change %
20;
$display($time,666,remaining_change,change,total_cost,no
tes_5);
notes_10 = remaining_change / 10;
remaining_change = remaining_change %
10;
$display($time,666,remaining_change,change,total_cost,no
tes_5);
notes_5 = remaining_change / 5;
remaining_change = remaining_change % 5;
$display($time,666,remaining_change,change,total_cost,no
tes_5);
change = total_amount - total_cost;
$display($time,666,remaining_change,change,total_cost,no
tes_5);
next_state=DISPENSE;
end
end
DISPENSE: begin next_state = IDLE; end
default: next_state = IDLE;
endcase
end
endmodule
verilog
module q7(
input clk, rst,
input [3:0] money_5, money_10, money_20, money_50, money_100,
input [3:0] quantity_cold_drink, quantity_dairy_milk, quantity_biscuits,
28/81
quantity_red_bull, quantity_imported_chocolate,
input add_more,
output dispense,
output reg [9:0] change, refund,
output reg [3:0] notes_100, notes_50, notes_20, notes_10, notes_5
);
localparam IDLE = 4'h0, ACCEPT = 4'h1, SELECT = 4'h2, CHANGE = 4'h3, ASK_MORE =
4'h4, DISPENSE = 4'h5;
reg [3:0] present_state, next_state;
reg [9:0] total_amount, total_cost, remaining_change, money_in,
remaining_refund;
parameter COLD_DRINK = 10, DAIRY_MILK = 45, BISCUITS = 5, RED_BULL = 75,
IMPORTED_CHOCOLATE = 135;
initial begin
present_state = IDLE;
change = 0;
notes_100 = 0;
notes_50 = 0;
notes_20 = 0;
notes_10 = 0;
notes_5 = 0;
total_amount = 0;
total_cost = 0;
remaining_change = 0;
money_in = 0;
end
29/81
assign dispense = (present_state == DISPENSE);
30/81
remaining_change <= remaining_change % 20;
notes_10 <= remaining_change / 10;
remaining_change <= remaining_change % 10;
notes_5 <= remaining_change / 5;
remaining_change <= remaining_change % 5;
change <= total_amount - total_cost;
end
else if (present_state == ASK_MORE && !((remaining_change > 0) &&
add_more)) begin
notes_100 <= (total_amount - total_cost) / 100;
remaining_change <= (total_amount - total_cost) % 100;
notes_50 <= remaining_change / 50;
remaining_change <= remaining_change % 50;
notes_20 <= remaining_change / 20;
remaining_change <= remaining_change % 20;
notes_10 <= remaining_change / 10;
remaining_change <= remaining_change % 10;
notes_5 <= remaining_change / 5;
remaining_change <= remaining_change % 5;
change <= total_amount - total_cost;
end
end
end
endmodule
verilog
module q7(
input clk,
input rst,
input [3:0] money5, money10, money20, money50, money100,
input [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull,
qtyImportedChoco,
input add_more,
output dispense,
output reg [9:0] change,
output reg [9:0] refund,
output reg [3:0] note100, note50, note20, note10, note5
31/81
);
localparam IDLE = 4'h0,
ACCEPT = 4'h1,
SELECT = 4'h2,
CHANGE = 4'h3,
ASK_MORE = 4'h4,
DISPENSE = 4'h5;
initial begin
state_reg = IDLE;
change = 0;
note100 = 0;
note50 = 0;
note20 = 0;
note10 = 0;
note5 = 0;
inserted_money = 0;
total_money = 0;
total_price = 0;
rem_change = 0;
end
32/81
rem_change <= 0;
end
else begin
state_reg <= state_next;
state_reg == IDLE ? inserted_money <= (money5 * 5) + (money10 * 10) +
(money20 * 20) + (money50 * 50) + (money100 * 100)
: state_reg == ACCEPT ? total_money <=
inserted_money : 1'b0;
end
end
33/81
rem_change <= total_money - total_price;
note100 <= (total_money - total_price) / 100;
temp <= (total_money - total_price) % 100;
note50 <= temp / 50;
temp <= temp % 50;
note20 <= temp / 20;
temp <= temp % 20;
note10 <= temp / 10;
temp <= temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
change <= total_money - total_price;
end
else if (state_reg == ASK_MORE && !((rem_change > 0) && add_more)) begin
note100 <= (total_money - total_price) / 100;
temp <= (total_money - total_price) % 100;
note50 <= temp / 50;
temp <= temp % 50;
note20 <= temp / 20;
temp <= temp % 20;
note10 <= temp / 10;
temp <= temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
change <= total_money - total_price;
end
end
endmodule
Below is a much‐simplified version of a vending machine FSM that uses a single request
signal (rs) as input and produces a single output (dispense). In this design, when rs is high
the machine moves from IDLE to an ACCEPT state and then to a DISPENSE state, where the
output is asserted for one cycle before returning to IDLE.
verilog
module simple_vending_machine(
input clk,
input rs,
34/81
output reg dispense
);
localparam IDLE = 2'b00,
ACCEPT = 2'b01,
DISPENSE= 2'b10;
verilog
module tb_simple_vending_machine;
reg clk, rs;
wire dispense;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("simple_vending_machine.vcd");
$dumpvars;
end
35/81
initial begin
rs = 0;
#10;
rs = 1;
#10;
rs = 0;
#50;
$finish;
end
endmodule
This design meets the request for simplicity by having only one input (rs) and one output
(dispense) while still following an FSM approach using ternary operators for state transitions.
module q7(
input clk,
input rst,
input [3:0] money5, money10, money20, money50,
money100,
input [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits,
qtyRedBull, qtyImportedChoco,
input add_more,
output dispense,
output reg [9:0] change,
output reg [9:0] refund,
output reg [3:0] note100, note50, note20, note10, note5
);
localparam IDLE = 4'h0,
ACCEPT = 4'h1,
SELECT = 4'h2,
CHANGE = 4'h3,
ASK_MORE = 4'h4,
DISPENSE = 4'h5;
36/81
initial begin
state_reg = IDLE;
change = 0;
note100 = 0;
note50 = 0;
note20 = 0;
note10 = 0;
note5 = 0;
inserted_money = 0;
total_money = 0;
total_price = 0;
rem_change = 0;
end
37/81
state_next = (state_reg == IDLE) ? ((|{money5,
money10, money20, money50, money100}) ? ACCEPT : IDLE)
: (state_reg == ACCEPT) ? ((total_money != 0) ?
SELECT : ACCEPT)
: (state_reg == SELECT) ? (((total_price =
(PRICE_COLD_DRINK * qtyColdDrink) + (PRICE_DAIRY_MILK
* qtyDairyMilk) +
(PRICE_BISCUITS *
qtyBiscuits) + (PRICE_RED_BULL * qtyRedBull) +
(PRICE_IMPORTED_CHOCOLATE * qtyImportedChoco)) != 0)
? CHANGE : SELECT)
: (state_reg == CHANGE) ? ((total_money >=
total_price) ? DISPENSE : ASK_MORE)
: (state_reg == ASK_MORE) ? (((rem_change > 0)
&& add_more) ? SELECT : DISPENSE)
: (state_reg == DISPENSE) ? IDLE : IDLE;
end
38/81
rem_change <= temp % 5;
change <= total_money - total_price;
end
else if (state_reg == ASK_MORE && !((rem_change > 0)
&& add_more)) begin
note100 <= (total_money - total_price) / 100;
temp <= (total_money - total_price) % 100;
note50 <= temp / 50;
temp <= temp % 50;
note20 <= temp / 20;
temp <= temp % 20;
note10 <= temp / 10;
temp <= temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
change <= total_money - total_price;
end
end
endmodule USE IF ELSE AND GIVE TESTBENCH
Below is one simplified version of your module using explicit if–else statements instead of
ternary operators along with a testbench.
verilog
module q7(
input clk,
input rst,
input [3:0] money5, money10, money20, money50, money100,
input [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull,
qtyImportedChoco,
input add_more,
output dispense,
output reg [9:0] change,
output reg [9:0] refund,
output reg [3:0] note100, note50, note20, note10, note5
);
localparam IDLE = 4'h0,
ACCEPT = 4'h1,
39/81
SELECT = 4'h2,
CHANGE = 4'h3,
ASK_MORE= 4'h4,
DISPENSE= 4'h5;
// Initial values
initial begin
state_reg = IDLE;
change = 0;
note100 = 0;
note50 = 0;
note20 = 0;
note10 = 0;
note5 = 0;
inserted_money = 0;
total_money = 0;
total_price = 0;
rem_change = 0;
end
40/81
note5 <= 0;
rem_change <= 0;
end else begin
state_reg <= state_next;
if(state_reg == IDLE) begin
inserted_money <= (money5 * 5) + (money10 * 10) + (money20 * 20) +
(money50 * 50) + (money100 * 100);
end else if(state_reg == ACCEPT) begin
total_money <= inserted_money;
end
end
end
41/81
else
state_next = ASK_MORE;
end else if(state_reg == ASK_MORE) begin
if((rem_change > 0) && add_more)
state_next = SELECT;
else
state_next = DISPENSE;
end else if(state_reg == DISPENSE) begin
state_next = IDLE;
end else begin
state_next = IDLE;
end
end
42/81
temp = temp % 100;
note50 <= temp / 50;
temp = temp % 50;
note20 <= temp / 20;
temp = temp % 20;
note10 <= temp / 10;
temp = temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
end
end
endmodule
Testbench
verilog
module q7_tb;
reg clk, rst;
reg [3:0] money5, money10, money20, money50, money100;
reg [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull, qtyImportedChoco;
reg add_more;
wire dispense;
wire [9:0] change, refund;
wire [3:0] note100, note50, note20, note10, note5;
q7 uut (
.clk(clk),
.rst(rst),
.money5(money5),
.money10(money10),
.money20(money20),
.money50(money50),
.money100(money100),
.qtyColdDrink(qtyColdDrink),
.qtyDairyMilk(qtyDairyMilk),
.qtyBiscuits(qtyBiscuits),
.qtyRedBull(qtyRedBull),
.qtyImportedChoco(qtyImportedChoco),
43/81
.add_more(add_more),
.dispense(dispense),
.change(change),
.refund(refund),
.note100(note100),
.note50(note50),
.note20(note20),
.note10(note10),
.note5(note5)
);
// Dump waves
initial begin
$dumpfile("q7_tb.vcd");
$dumpvars(0, q7_tb);
end
// Test stimulus
initial begin
// Initialize inputs
rst = 0;
money5 = 0; money10 = 0; money20 = 0; money50 = 0; money100 = 0;
qtyColdDrink = 0; qtyDairyMilk = 0; qtyBiscuits = 0; qtyRedBull = 0;
qtyImportedChoco = 0;
add_more = 0;
#10;
rst = 1;
#10;
44/81
qtyColdDrink = 1;
qtyDairyMilk = 1;
qtyBiscuits = 2;
qtyRedBull = 0;
qtyImportedChoco = 1;
#10;
// Wait for state transitions to process change and dispense
#50;
$finish;
end
endmodule
Explanation
1. Module q7:
Uses if–else statements in the state register update, next-state logic, and change
calculation.
In the IDLE state, money is captured. In the ACCEPT state, the inserted money is
transferred to the total.
In the SELECT state, the total price is computed from the quantities and unit prices.
45/81
In the CHANGE state, if sufficient funds exist the machine computes the change and
breaks it into note denominations.
In the ASK_MORE state, if additional money is not added, it similarly computes the
note breakdown before dispensing.
2. Testbench:
Stimulates two scenarios: one where sufficient funds are provided and one with
lower funds.
This version uses explicit if–else constructs and provides a complete testbench for
simulation.
Below is one complete solution that implements the described vending machine. In this
design, the machine goes through a sequence of states using if–else statements. It accepts
various denominations, computes the total inserted money, then in the SELECT state
calculates the total price of the chosen items (cold drink, dairy milk, biscuits, red-bull,
imported chocolate). Finally, in the CHANGE state the machine computes the change (broken
into Rs. 100, 50, 20, 10, and 5 notes) and only then asserts the dispense output. The item is
released (dispense asserted) only when the entire purchase procedure is complete.
46/81
verilog
module q7(
input clk,
input rst,
input [3:0] money5, money10, money20, money50, money100,
input [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull,
qtyImportedChoco,
input add_more, // when true, allows additional selection
output dispense,
output reg [9:0] change,
output reg [9:0] refund,
output reg [3:0] note100, note50, note20, note10, note5
);
// State definitions
localparam IDLE = 4'h0,
ACCEPT = 4'h1,
SELECT = 4'h2,
CHANGE = 4'h3,
ASK_MORE= 4'h4,
DISPENSE= 4'h5;
// Initialize registers
initial begin
state_reg = IDLE;
change = 0;
note100 = 0;
note50 = 0;
note20 = 0;
note10 = 0;
note5 = 0;
47/81
inserted_money = 0;
total_money = 0;
total_price = 0;
rem_change = 0;
end
48/81
state_next = ACCEPT;
else
state_next = IDLE;
end
else if(state_reg == ACCEPT) begin
if(total_money != 0)
state_next = SELECT;
else
state_next = ACCEPT;
end
else if(state_reg == SELECT) begin
// Compute total price based on item quantities
total_price = (PRICE_COLD_DRINK * qtyColdDrink) +
(PRICE_DAIRY_MILK * qtyDairyMilk) +
(PRICE_BISCUITS * qtyBiscuits) +
(PRICE_RED_BULL * qtyRedBull) +
(PRICE_IMPORTED_CHOCOLATE * qtyImportedChoco);
if(total_price != 0)
state_next = CHANGE;
else
state_next = SELECT;
end
else if(state_reg == CHANGE) begin
if(total_money >= total_price)
state_next = DISPENSE;
else
state_next = ASK_MORE;
end
else if(state_reg == ASK_MORE) begin
if((rem_change > 0) && add_more)
state_next = SELECT;
else
state_next = DISPENSE;
end
else if(state_reg == DISPENSE) begin
state_next = IDLE;
end
else begin
state_next = IDLE;
end
end
49/81
// Calculate change and note breakdown using if-else
always @(posedge clk) begin
if (rst == 0) begin
change <= 0;
refund <= 0;
note100 <= 0;
note50 <= 0;
note20 <= 0;
note10 <= 0;
note5 <= 0;
rem_change <= 0;
end else if(state_reg == CHANGE && (total_money >= total_price)) begin
temp = total_money - total_price;
change <= temp;
note100 <= temp / 100;
temp = temp % 100;
note50 <= temp / 50;
temp = temp % 50;
note20 <= temp / 20;
temp = temp % 20;
note10 <= temp / 10;
temp = temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
end else if(state_reg == ASK_MORE && !((rem_change > 0) && add_more)) begin
temp = total_money - total_price;
change <= temp;
note100 <= temp / 100;
temp = temp % 100;
note50 <= temp / 50;
temp = temp % 50;
note20 <= temp / 20;
temp = temp % 20;
note10 <= temp / 10;
temp = temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
end
end
endmodule
50/81
Testbench
verilog
module q7_tb;
reg clk, rst;
reg [3:0] money5, money10, money20, money50, money100;
reg [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull, qtyImportedChoco;
reg add_more;
wire dispense;
wire [9:0] change, refund;
wire [3:0] note100, note50, note20, note10, note5;
q7 uut (
.clk(clk),
.rst(rst),
.money5(money5),
.money10(money10),
.money20(money20),
.money50(money50),
.money100(money100),
.qtyColdDrink(qtyColdDrink),
.qtyDairyMilk(qtyDairyMilk),
.qtyBiscuits(qtyBiscuits),
.qtyRedBull(qtyRedBull),
.qtyImportedChoco(qtyImportedChoco),
.add_more(add_more),
.dispense(dispense),
.change(change),
.refund(refund),
.note100(note100),
.note50(note50),
.note20(note20),
.note10(note10),
.note5(note5)
);
51/81
// Dump waveform for inspection
initial begin
$dumpfile("q7_tb.vcd");
$dumpvars(0, q7_tb);
end
// Test stimulus
initial begin
// Reset the machine
rst = 0;
money5 = 0; money10 = 0; money20 = 0; money50 = 0; money100 = 0;
qtyColdDrink = 0; qtyDairyMilk = 0; qtyBiscuits = 0; qtyRedBull = 0;
qtyImportedChoco = 0;
add_more = 0;
#10;
rst = 1;
#10;
52/81
#10;
// Select item costing Rs.10 (1 cold drink)
qtyColdDrink = 1; qtyDairyMilk = 0; qtyBiscuits = 0; qtyRedBull = 0;
qtyImportedChoco = 0;
#10;
// In this case total_money (20) is greater than total_price (10), so it
should directly dispense with Rs.10 change.
#50;
$finish;
end
endmodule
Explanation
1. Module q7:
Uses explicit if–else constructs to update the state register, capture inserted money,
compute total price, and calculate change.
The machine transitions from IDLE (waiting for money) to ACCEPT (capturing money)
to SELECT (item selection) to CHANGE (checking if funds cover cost) to ASK_MORE (if
insufficient funds and more money is needed) and finally to DISPENSE (releasing the
items and providing change).
2. Testbench (q7_tb):
Stimulates two scenarios: one with sufficient funds (with a detailed breakdown) and
one with insufficient funds.
This solution meets the problem requirements where multiple denominations are accepted,
various items can be purchased in any combination, change is provided when needed, and
the item is released only after the entire purchase is complete.
WITHOUT COMMENT
verilog
53/81
module q7(
input clk,
input rst,
input [3:0] money5, money10, money20, money50, money100,
input [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull,
qtyImportedChoco,
input add_more,
output dispense,
output reg [9:0] change,
output reg [9:0] refund,
output reg [3:0] note100, note50, note20, note10, note5
);
localparam IDLE = 4'h0,
ACCEPT = 4'h1,
SELECT = 4'h2,
CHANGE = 4'h3,
ASK_MORE= 4'h4,
DISPENSE= 4'h5;
initial begin
state_reg = IDLE;
change = 0;
note100 = 0;
note50 = 0;
note20 = 0;
note10 = 0;
note5 = 0;
inserted_money = 0;
total_money = 0;
total_price = 0;
rem_change = 0;
end
54/81
always @(posedge clk) begin
if (rst == 0) begin
state_reg <= IDLE;
inserted_money <= 0;
total_money <= 0;
total_price <= 0;
change <= 0;
note100 <= 0;
note50 <= 0;
note20 <= 0;
note10 <= 0;
note5 <= 0;
rem_change <= 0;
end else begin
state_reg <= state_next;
if(state_reg == IDLE)
inserted_money <= (money5 * 5) + (money10 * 10) + (money20 * 20) +
(money50 * 50) + (money100 * 100);
else if(state_reg == ACCEPT)
total_money <= inserted_money;
end
end
55/81
(PRICE_IMPORTED_CHOCOLATE * qtyImportedChoco);
if(total_price != 0)
state_next = CHANGE;
else
state_next = SELECT;
end else if(state_reg == CHANGE)
if(total_money >= total_price)
state_next = DISPENSE;
else
state_next = ASK_MORE;
else if(state_reg == ASK_MORE)
if((rem_change > 0) && add_more)
state_next = SELECT;
else
state_next = DISPENSE;
else if(state_reg == DISPENSE)
state_next = IDLE;
else
state_next = IDLE;
end
56/81
note5 <= temp / 5;
rem_change <= temp % 5;
end else if(state_reg == ASK_MORE && !((rem_change > 0) && add_more)) begin
temp = total_money - total_price;
change <= temp;
note100 <= temp / 100;
temp = temp % 100;
note50 <= temp / 50;
temp = temp % 50;
note20 <= temp / 20;
temp = temp % 20;
note10 <= temp / 10;
temp = temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
end
end
endmodule
verilog
module q7_tb;
reg clk, rst;
reg [3:0] money5, money10, money20, money50, money100;
reg [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull, qtyImportedChoco;
reg add_more;
wire dispense;
wire [9:0] change, refund;
wire [3:0] note100, note50, note20, note10, note5;
q7 uut (
.clk(clk),
.rst(rst),
.money5(money5),
.money10(money10),
.money20(money20),
.money50(money50),
.money100(money100),
.qtyColdDrink(qtyColdDrink),
.qtyDairyMilk(qtyDairyMilk),
.qtyBiscuits(qtyBiscuits),
.qtyRedBull(qtyRedBull),
57/81
.qtyImportedChoco(qtyImportedChoco),
.add_more(add_more),
.dispense(dispense),
.change(change),
.refund(refund),
.note100(note100),
.note50(note50),
.note20(note20),
.note10(note10),
.note5(note5)
);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("q7_tb.vcd");
$dumpvars(0, q7_tb);
end
initial begin
rst = 0;
money5 = 0; money10 = 0; money20 = 0; money50 = 0; money100 = 0;
qtyColdDrink = 0; qtyDairyMilk = 0; qtyBiscuits = 0; qtyRedBull = 0;
qtyImportedChoco = 0;
add_more = 0;
#10;
rst = 1;
#10;
money5 = 4; money10 = 2; money20 = 3; money50 = 1; money100 = 2;
#10;
qtyColdDrink = 1;
qtyDairyMilk = 1;
qtyBiscuits = 2;
qtyRedBull = 0;
qtyImportedChoco = 1;
#10;
#50;
rst = 0;
#10; rst = 1;
58/81
money5 = 0; money10 = 0; money20 = 1; money50 = 0; money100 = 0;
#10;
qtyColdDrink = 1; qtyDairyMilk = 0; qtyBiscuits = 0; qtyRedBull = 0;
qtyImportedChoco = 0;
#10;
#50;
$finish;
end
endmodule
verilog
module q7(
input clk,
input rst,
input [3:0] money5, money10, money20, money50, money100,
input [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull,
qtyImportedChoco,
input add_more,
output dispense,
output reg [9:0] change,
output reg [9:0] refund,
output reg [3:0] note100, note50, note20, note10, note5
);
localparam IDLE = 4'h0,
ACCEPT = 4'h1,
SELECT = 4'h2,
CHANGE = 4'h3,
ASK_MORE= 4'h4,
DISPENSE= 4'h5;
reg [3:0] state_reg, state_next;
reg [9:0] inserted_money, total_money, total_price, rem_change;
reg [9:0] temp;
parameter PRICE_COLD_DRINK = 10,
PRICE_DAIRY_MILK = 45,
PRICE_BISCUITS = 5,
PRICE_RED_BULL = 75,
PRICE_IMPORTED_CHOCOLATE = 135;
initial begin
59/81
state_reg = IDLE;
change = 0;
note100 = 0;
note50 = 0;
note20 = 0;
note10 = 0;
note5 = 0;
inserted_money = 0;
total_money = 0;
total_price = 0;
rem_change = 0;
end
always @(posedge clk) begin
if (rst == 0) begin
state_reg <= IDLE;
inserted_money <= 0;
total_money <= 0;
total_price <= 0;
change <= 0;
note100 <= 0;
note50 <= 0;
note20 <= 0;
note10 <= 0;
note5 <= 0;
rem_change <= 0;
end else begin
state_reg <= state_next;
if(state_reg == IDLE)
inserted_money <= (money5 * 5) + (money10 * 10) + (money20 * 20) +
(money50 * 50) + (money100 * 100);
else if(state_reg == ACCEPT)
total_money <= inserted_money;
end
end
assign dispense = (state_reg == DISPENSE);
always @(*) begin
if(state_reg == IDLE)
if((money5 != 0) || (money10 != 0) || (money20 != 0) || (money50 != 0)
|| (money100 != 0))
state_next = ACCEPT;
else
state_next = IDLE;
60/81
else if(state_reg == ACCEPT)
if(total_money != 0)
state_next = SELECT;
else
state_next = ACCEPT;
else if(state_reg == SELECT) begin
total_price = (PRICE_COLD_DRINK * qtyColdDrink) +
(PRICE_DAIRY_MILK * qtyDairyMilk) +
(PRICE_BISCUITS * qtyBiscuits) +
(PRICE_RED_BULL * qtyRedBull) +
(PRICE_IMPORTED_CHOCOLATE * qtyImportedChoco);
if(total_price != 0)
state_next = CHANGE;
else
state_next = SELECT;
end else if(state_reg == CHANGE)
if(total_money >= total_price)
state_next = DISPENSE;
else
state_next = ASK_MORE;
else if(state_reg == ASK_MORE)
if((rem_change > 0) && add_more)
state_next = SELECT;
else
state_next = DISPENSE;
else if(state_reg == DISPENSE)
state_next = IDLE;
else
state_next = IDLE;
end
always @(posedge clk) begin
if (rst == 0) begin
change <= 0;
refund <= 0;
note100 <= 0;
note50 <= 0;
note20 <= 0;
note10 <= 0;
note5 <= 0;
rem_change <= 0;
end else if(state_reg == CHANGE && (total_money >= total_price)) begin
temp = total_money - total_price;
61/81
change <= temp;
note100 <= temp / 100;
temp = temp % 100;
note50 <= temp / 50;
temp = temp % 50;
note20 <= temp / 20;
temp = temp % 20;
note10 <= temp / 10;
temp = temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
end else if(state_reg == ASK_MORE && !((rem_change > 0) && add_more)) begin
temp = total_money - total_price;
change <= temp;
note100 <= temp / 100;
temp = temp % 100;
note50 <= temp / 50;
temp = temp % 50;
note20 <= temp / 20;
temp = temp % 20;
note10 <= temp / 10;
temp = temp % 10;
note5 <= temp / 5;
rem_change <= temp % 5;
end
end
endmodule
verilog
module q7_tb;
reg clk, rst;
reg [3:0] money5, money10, money20, money50, money100;
reg [3:0] qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull, qtyImportedChoco;
reg add_more;
wire dispense;
wire [9:0] change, refund;
wire [3:0] note100, note50, note20, note10, note5;
q7 uut (
.clk(clk),
.rst(rst),
62/81
.money5(money5),
.money10(money10),
.money20(money20),
.money50(money50),
.money100(money100),
.qtyColdDrink(qtyColdDrink),
.qtyDairyMilk(qtyDairyMilk),
.qtyBiscuits(qtyBiscuits),
.qtyRedBull(qtyRedBull),
.qtyImportedChoco(qtyImportedChoco),
.add_more(add_more),
.dispense(dispense),
.change(change),
.refund(refund),
.note100(note100),
.note50(note50),
.note20(note20),
.note10(note10),
.note5(note5)
);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("q7_tb.vcd");
$dumpvars(0, q7_tb);
end
initial begin
$monitor("time=%t, rst=%b, money5=%d, money10=%d, money20=%d, money50=%d,
money100=%d, qtyCD=%d, qtyDM=%d, qtyB=%d, qtyRB=%d, qtyIC=%d, add_more=%b, state=%d,
total_money=%d, total_price=%d, dispense=%b, change=%d, note100=%d, note50=%d,
note20=%d, note10=%d, note5=%d",
$time, rst, money5, money10, money20, money50, money100,
qtyColdDrink, qtyDairyMilk, qtyBiscuits, qtyRedBull,
qtyImportedChoco,
add_more, uut.state_reg, uut.total_money, uut.total_price,
dispense, change, note100, note50, note20, note10, note5);
63/81
rst = 0;
money5 = 0; money10 = 0; money20 = 0; money50 = 0; money100 = 0;
qtyColdDrink = 0; qtyDairyMilk = 0; qtyBiscuits = 0; qtyRedBull = 0;
qtyImportedChoco = 0;
add_more = 0;
#10;
rst = 1;
#10;
money5 = 4; money10 = 2; money20 = 3; money50 = 1; money100 = 2;
#10;
qtyColdDrink = 1;
qtyDairyMilk = 1;
qtyBiscuits = 2;
qtyRedBull = 0;
qtyImportedChoco = 1;
#10;
#50;
rst = 0;
#10;
rst = 1;
money5 = 0; money10 = 0; money20 = 1; money50 = 0; money100 = 0;
#10;
qtyColdDrink = 1; qtyDairyMilk = 0; qtyBiscuits = 0; qtyRedBull = 0;
qtyImportedChoco = 0;
#10;
#50;
$finish;
end
endmodule
64/81
money20= 3, money50= 1, money100= 2, qtyCD= 0, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 0,
total_money= 0, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 25, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 0, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 1,
total_money= 0, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 30, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 1,
total_money= 0, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 35, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 1,
total_money= 350, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 45, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 2,
total_money= 350, total_price= 200, dispense=0, change=
0, note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 55, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 3,
total_money= 350, total_price= 200, dispense=0, change=
0, note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 65, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 5,
total_money= 350, total_price= 200, dispense=1, change=
150, note100= 1, note50= 1, note20= 0, note10= 0, note5= 0
time= 75, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 0,
total_money= 350, total_price= 200, dispense=0, change=
150, note100= 1, note50= 1, note20= 0, note10= 0, note5= 0
time= 85, rst=1, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 1,
65/81
total_money= 350, total_price= 200, dispense=0, change=
150, note100= 1, note50= 1, note20= 0, note10= 0, note5= 0
time= 90, rst=0, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 1,
total_money= 350, total_price= 200, dispense=0, change=
150, note100= 1, note50= 1, note20= 0, note10= 0, note5= 0
time= 95, rst=0, money5= 4, money10= 2,
money20= 3, money50= 1, money100= 2, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 0,
total_money= 0, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 100, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 0,
total_money= 0, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 105, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
1, qtyB= 2, qtyRB= 0, qtyIC= 1, add_more=0, state= 1,
total_money= 0, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 110, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 1,
total_money= 0, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 115, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 1,
total_money= 20, total_price= 0, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 125, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 2,
total_money= 20, total_price= 10, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
time= 135, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 3,
total_money= 20, total_price= 10, dispense=0, change= 0,
note100= 0, note50= 0, note20= 0, note10= 0, note5= 0
66/81
time= 145, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 5,
total_money= 20, total_price= 10, dispense=1, change= 10,
note100= 0, note50= 0, note20= 0, note10= 1, note5= 0
time= 155, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 0,
total_money= 20, total_price= 10, dispense=0, change= 10,
note100= 0, note50= 0, note20= 0, note10= 1, note5= 0
time= 165, rst=1, money5= 0, money10= 0,
money20= 1, money50= 0, money100= 0, qtyCD= 1, qtyDM=
0, qtyB= 0, qtyRB= 0, qtyIC= 0, add_more=0, state= 1,
total_money= 20, total_price= 10, dispense=0, change= 10,
note100= 0, note50= 0, note20= 0, note10= 1, note5= 0
VedingMachine2.v:216: $finish called at 170 (1s) it is right
?
The simulation output is correct. It shows that in the first scenario, after inserting money
totaling 350, selecting items costing 200, the machine moves to DISPENSE (state 5) with a
change of 150 (with one Rs.100 note and one Rs.50 note). In the second scenario, with a total
of 20 and an item costing 10, the machine dispenses with a change of 10 (broken as one
Rs.10 note). The state transitions and computed values match the design requirements.
67/81
conditions cause state and output changes. Everything may
not have been specified, so write down any assumptions
you make. module digitalLock (input A ,B , clk , output reg
Open , Ring );
if (pstate == ideal)
pstate <=ideal ;
else
pstate <= nstate;
end
always @ ( A or B or pstate)
begin
case(pstate)
ideal : nstate = A ? seqtrue1 : ( B ? resetB1 : ideal ) ;
seqtrue1 : nstate = A ? seqtrue2 : ( B ? resetB1 :
seqtrue1 ) ;
seqtrue2 : nstate = A ? ideal : ( B ? seqtrue3 : seqtrue2
);
seqtrue3 : nstate = A ? seqtrue4 : ( B ? resetB2 :
seqtrue3 ) ;
seqtrue4 : nstate = A ? ideal : ( B ? seqtrue5 : seqtrue4
);
seqtrue5 : nstate = A ? lockOpen : ( B ? resetB2 :
seqtrue5 ) ;
lockOpen : nstate = A ? ideal : ( B ? resetB1 : lockOpen )
;
resetB1 : nstate = A ? ideal : ( B ? resetB2 : resetB1 ) ;
68/81
resetB2 : nstate = A ? ideal : ( B ? ideal : resetB2 ) ;
default: nstate = ideal ;
endcase
end
always @ (A or B or pstate)
begin
case(pstate)
ideal : begin Open = 0 ; Ring = 0 ; end
seqtrue1 : begin Open = 0 ; Ring = 0; end
seqtrue2 : begin Open = 0 ; Ring = A ? 1 : 0; end
seqtrue3 : begin Open = 0 ; Ring = 0; end
seqtrue4 : begin Open = 0 ; Ring = A ? 1 : 0; end
seqtrue5 : begin Open = A ? 1 : 0 ; Ring = 0 ; end
lockOpen : begin Open = 1 ; Ring = 0 ; end
resetB1 : begin Open = 0 ; Ring = A ? 1 : 0; end
resetB2 : begin Open = 0 ; Ring = A ? 1 : 0; end
endcase
end
endmodule
reg A ,B,clk;
wire Open , Ring;
initial begin
$dumpfile("digitalLock.vcd");
$dumpvars();
end
initial begin
69/81
Ring=%b",$time,clk,A,B,Open,clk );
end
initial begin
A=0;B=0;clk=0;#10;
A=1;B=0;#10;
A=1;B=0;#10;
A=0;B=1;#10;
A=1;B=0;#10;
A=0;B=1;#10;
A=1;B=0;#10;
A=1;B=0;#10;
A=0;B=1;#10;
A=0;B=1;#10;
A=1;B=0;#10;
A=0;B=0;#10;
A=1;B=1;#10;
A=1;B=1;#10;
A=0;B=0;#10;
A=1;B=1;#10;
A=0;B=1;#10;
A=1;B=0;#10;
A=1;B=0;#10;
A=1;B=0;#10;
A=0;B=1;#10;
A=1;B=0;#10;
$finish;
end
endmodule correct it
verilog
module digitalLock(
input A, B, clk, rst,
output reg Open, Ring
);
parameter ideal = 4'b0000, seqtrue1 = 4'b0001, seqtrue2 = 4'b0010, seqtrue3 =
4'b0011,
seqtrue4 = 4'b0100, seqtrue5 = 4'b0101, lockOpen = 4'b0110, resetB1 =
4'b0111, resetB2 = 4'b1000;
reg [3:0] pstate, nstate;
70/81
always @(posedge clk or negedge rst) begin
if (!rst)
pstate <= ideal;
else
pstate <= nstate;
end
module digitalLocktb;
reg A, B, clk, rst;
wire Open, Ring;
71/81
digitalLock uut (.A(A), .B(B), .clk(clk), .rst(rst), .Open(Open), .Ring(Ring));
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("digitalLock.vcd");
$dumpvars(0, digitalLocktb);
end
initial begin
$monitor("time=%t, clk=%b, rst=%b, A=%b, B=%b, pstate=%b, Open=%b, Ring=%b",
$time, clk, rst, A, B, uut.pstate, Open, Ring);
rst = 0; A = 0; B = 0; #10;
rst = 1; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 0; B = 0; #10;
A = 1; B = 1; #10;
A = 1; B = 1; #10;
A = 0; B = 0; #10;
A = 1; B = 1; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
$finish;
end
endmodule
72/81
so give me list and also say all changes of all codes in
structure way
Below is a structured summary of all changes and modifications made to the digital lock
design and testbench code:
Reset Handling:
Added an asynchronous reset in the state update always block using negedge rst
so that on reset the machine immediately goes to the initial state ( ideal ).
Rewrote the state transition (next state) always block using a case statement with an
always @(*) block (combinational logic).
Incorporated transitions so that once the lock is open, any button press (A or B) will
reset the machine (close the lock).
Separated the output logic (which produces the Open and Ring signals) into its
own always block.
State Definitions:
Defined all states with 4-bit parameters for clarity (e.g., ideal , seqtrue1 ,
seqtrue2 , …, lockOpen , resetB1 , resetB2 ).
Clock Generation:
73/81
Corrected the initialization of signals including reset ( rst ) and the push-button
inputs ( A and B ).
$monitor Statement:
Added a detailed $monitor call that displays simulation time, clock, reset,
pushbutton inputs, the current state ( pstate from the DUT), and the outputs ( Open
and Ring ).
Waveform Dumping:
Included $dumpfile and $dumpvars calls for viewing waveforms in a VCD file.
Sensitivity Lists:
Changed all combinational always blocks to use always @(*) for clarity and proper
simulation.
Organized the code into clear sections: state update, next-state logic, and output
logic.
──────────────────────────────
Below is the final updated code (without comments) that reflects these changes:
verilog
module digitalLock(
input A, B, clk, rst,
output reg Open, Ring
);
parameter ideal = 4'b0000, seqtrue1 = 4'b0001, seqtrue2 = 4'b0010, seqtrue3 =
4'b0011,
74/81
seqtrue4 = 4'b0100, seqtrue5 = 4'b0101, lockOpen = 4'b0110, resetB1 =
4'b0111, resetB2 = 4'b1000;
reg [3:0] pstate, nstate;
75/81
module digitalLocktb;
reg A, B, clk, rst;
wire Open, Ring;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
$dumpfile("digitalLock.vcd");
$dumpvars(0, digitalLocktb);
end
initial begin
$monitor("time=%t, clk=%b, rst=%b, A=%b, B=%b, pstate=%b, Open=%b, Ring=%b",
$time, clk, rst, A, B, uut.pstate, Open, Ring);
rst = 0; A = 0; B = 0; #10;
rst = 1; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 0; B = 0; #10;
A = 1; B = 1; #10;
A = 1; B = 1; #10;
A = 0; B = 0; #10;
A = 1; B = 1; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 1; B = 0; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
76/81
$finish;
end
endmodule
──────────────────────────────
This structured list explains all modifications made to both the digital lock module and its
testbench.
2/2
2/2
77/81
Here are the state diagrams for the three designs:
78/81
Vending Machine State Diagram Description:
1. IDLE:
2. ACCEPT:
3. SELECT:
4. CHANGE:
Checks if the total money is greater than or equal to the total price.
5. ASK_MORE:
6. DISPENSE:
Selected items: Cold drink, Dairy Milk, Biscuits, Red Bull, Imported Chocolate.
User choice: Add more money or proceed with the current selection.
Outputs:
79/81
Change in Rs.100, Rs.50, Rs.20, Rs.10, and Rs.5 notes.
python
import networkx as nx
def draw_vending_machine_state_diagram():
G = nx.DiGraph()
G.add_edges_from([
("IDLE", "ACCEPT", {'label': 'Insert Money'}),
("ACCEPT", "SELECT", {'label': 'Total Money > 0'}),
("SELECT", "CHANGE", {'label': 'Items Selected'}),
("CHANGE", "DISPENSE", {'label': 'Sufficient Funds'}),
("CHANGE", "ASK_MORE", {'label': 'Insufficient Funds'}),
("ASK_MORE", "SELECT", {'label': 'Add More Money'}),
("ASK_MORE", "DISPENSE", {'label': 'No Additional Money'}),
("DISPENSE", "IDLE", {'label': 'Complete'}),
])
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_size=3000, node_color="lightblue",
font_size=10, font_weight="bold", arrows=True, edge_color="black")
edge_labels = nx.get_edge_attributes(G, 'label')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=8,
font_color='darkred')
plt.title("Vending Machine State Diagram")
plt.show()
draw_vending_machine_state_diagram()
80/81
Here is the state diagram for the vending machine design:
3. SELECT: Allows the user to select one or more items and calculates the total cost.
4. CHANGE: Checks if there are sufficient funds to cover the total cost.
5. ASK_MORE: If there are insufficient funds, prompts the user to add more money.
81/81