Design ideas:
First, analyze the topic and stem in turn, and sort out the verilog code ideas.
- The system can complete its own reset. Storage of cargo information, process control, coin processing, balance calculation, display and other functions.
In the code, the control system can be designed as a finite state machine, each process is defined as a corresponding state, and conditional jumps between states are realized.
The display function can be defined with out, and the pins are subsequently defined, and the corresponding display is performed on the circuit board. - The machine only accepts 1 yuan coins and 5 cents coins.
Define two variables for the number of dollar coins and pennies. Define another variable to store the total amount of money. Because float (decimal) in verilog language will lose data and be complicated. Here we temporarily use 5 cents as a unit for calculation. All inputs and outputs are unified in multiples of 5 cents.
The coin module should be designed to be triggered by rising or falling edges, and every time the coin variable changes, the number of coins will be increased by one. - The machine provides 4 kinds of goods in total, and the prices are 2 yuan, 2 yuan, 1.5 yuan, and 1.5 yuan (the unit price of each kind of goods can be changed by adjusting the code).
You can use the parameter macro to define the unit price of the goods at the beginning of the code, and you can also change the code directly at the initial stage of the code when you change it later. - The customer first selects a desired product, and after confirming the selected product, enters the coin-inserting state. When the goods selected by the customer are sold out, when the customer confirms the goods, the customer will be prompted that the goods are sold out, and return to the initial state (when the customer confirms the goods, provide two options of confirming the selection and re-selecting).
Selecting goods is a state. You can enter the state of judging whether it is sold out by setting the confirmation variable to 1. You can also enter the initialization state by setting the reselection variable to 1. - If the customer does not insert coins after waiting for 30s, it will return to the initial state; after the customer inserts coins, the system will automatically calculate the coins. If there are enough coins, they will be shipped for change. If the coin is not enough 30s after the customer confirms the goods, the coin will be refunded and return to the initial state. You can also press the coin-input completion button to quickly enter the coin counting state and subsequent states when the coin-insertion is complete.
After entering the coin-operating state, start timing, use the clock frequency division module to count the 48MHz clock to 30s, if the time reaches 30s or set the confirmation to 1, then enter the next state: judge whether the money is enough. If the returned variable is set to 1, the next state is the initial state. - The required design is done on a circuit board capable of providing a standard 48MHz clock signal.
Due to limited hardware conditions, we are limited to the software level and do not download the board. However, the clock signal still uses the 48MHz described in the question as our standard signal.
State transition diagram:
According to the design idea, our design status is as follows:
S0: Initialize
S1: Select the goods
S2: Whether the goods are sold out
S3: Insert coins
S4: Is the money enough
S5: Give change
S6: Ship
The state transition diagram is shown in the figure:
Verilog code writing:
According to the state transition diagram and related logic,
the complete verilog code we wrote is as follows:
module machine(clk,money_in1,money_in2,select,item_confirm,money_confirm,cancel,sold_out,money_out,item_out,sta);
input clk;
//为方便计算钱数,以五角钱为一单位
input money_in1; //投入五角硬币
input money_in2; //投入一元硬币
input [1:4] select; //选择货物,只有一位有效
input item_confirm,money_confirm,cancel;
input [1:4] sold_out; //四种货物是否售空的状态,为1表示售空
output reg [2:0] money_out; //退款或找零的钱数
output reg [1:4] item_out; //出货物,只有一位有效
reg [1:4] select_sta;
output reg [2:0] sta; //状态机的状态
reg timeing; //计时状态
reg [31:0] time_cnt_s;
reg [8:0] time_cnt_l;
reg [2:0] money_sum;
reg [2:0] money_sum1;
reg [2:0] money_sum2;
parameter S_init=4'b000,S_select=4'b001,S_soldout=4'b010,S_30sec=4'b011,
S_enough=4'b100,S_change=4'b101,S_out=4'b110;
parameter item1=3'd4,item2=3'd4,item3=3'd3,item4=3'd3; //货物单价
initial
begin
sta=S_init;
money_sum1=0;
money_sum2=0;
end
always@(posedge clk) //分频模块,波形测试时需减小分频,方便看波形
begin
if(sta==S_init)
begin
time_cnt_s=0;
time_cnt_l=0;
end
if(timeing)
time_cnt_s=time_cnt_s+1;
if(time_cnt_s==32'd5_000_000)
time_cnt_l=time_cnt_l+1;
end
always@(posedge money_in1) //投币模块,上升沿为投币
begin
if(timeing)
begin
money_sum1=money_sum1+1;
end
if(sta!=S_30sec)
money_sum1=0;
end
always@(posedge money_in2) //投币模块,上升沿为投币
begin
if(timeing)
begin
money_sum2=money_sum2+2;
end
if(sta!=S_30sec)
money_sum2=0;
end
always@(posedge clk)
begin
case(sta)
S_init:
begin
select_sta=4'b0000;
timeing=0;
money_sum=0;
money_out=0;
item_out=4'b0000;
sta=S_select;
end
S_select:
begin
select_sta=select|select_sta;
if(item_confirm)
begin
sta=S_soldout;
end
if(cancel)
begin
sta=S_init;
end
end
S_soldout:
begin
if(select_sta&sold_out!=4'b0000) //若相同位同时为1
sta=S_init;
else
sta=S_30sec;
end
S_30sec:
begin
timeing=1;
if(money_confirm==1 || time_cnt_l>=288) //经计算,若时钟频率为48MHz,30s则对应288个time_cnt_l
begin
timeing=0;
money_sum=money_sum1+money_sum2;
sta=S_enough;
end
else
sta=S_30sec;
end
S_enough:
begin
case(select_sta)
4'b1000:
begin
if(money_sum>=item1)
begin
money_sum=money_sum-item1; //求出找钱数
sta=S_change;
end
else
begin
money_out=money_sum; //退钱
sta=S_init;
end
end
4'b0100:
begin
if(money_sum>=item2)
begin
money_sum=money_sum-item2;
sta=S_change;
end
else
begin
money_out=money_sum;
sta=S_init;
end
end
4'b0010:
begin
if(money_sum>=item3)
begin
money_sum=money_sum-item3;
sta=S_change;
end
else
begin
money_out=money_sum;
sta=S_init;
end
end
4'b0001:
begin
if(money_sum>=item4)
begin
money_sum=money_sum-item4;
sta=S_change;
end
else
begin
money_out=money_sum;
sta=S_init;
end
end
default:
begin
money_out=money_sum;
sta=S_init;
end
endcase
end
S_change:
begin
if(money_sum>0)
begin
money_out=money_sum;
sta=S_out;
end
else
sta=S_out;
end
S_out:
begin
item_out=select_sta;
sta=S_init;
end
endcase
end
endmodule
Notes on the definition of related variables are in the comments
Functional Verification:
We use quartus software to write stimulus files, simulate input, and observe waveforms.
The incentive file code is as follows:
`timescale 1 ps/ 1 ps
module machine_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg cancel;
reg clk;
reg item_confirm;
reg money_confirm;
reg money_in1;
reg money_in2;
reg [1:4] select;
reg [1:4] sold_out;
// wires
wire [1:4] item_out;
wire [2:0] money_out;
wire [2:0] sta;
// assign statements (if any)
machine i1 (
// port map - connection between master ports and signals/registers
.cancel(cancel),
.clk(clk),
.item_confirm(item_confirm),
.item_out(item_out),
.money_confirm(money_confirm),
.money_in1(money_in1),
.money_in2(money_in2),
.money_out(money_out),
.select(select),
.sold_out(sold_out),
.sta(sta)
);
initial
begin
// code that executes only once
// insert code here --> begin
// --> end
clk=0;
money_in1=0;
money_in2=0; //投入一元硬币
select=4'b0010; //选择货物,只有一位有效
item_confirm=1;money_confirm=0;cancel=0;
sold_out=4'b0000;
#100 money_in2=1;
#10 money_in2=0;
#10 money_in2=1;
#10 money_in2=0;
#10 money_confirm=1;
end
always
// optional sensitivity list
// @(event1 or event2 or .... eventn)
begin
// code executes for every event on sensitivity list
// insert code here --> begin
#5 clk=~clk;
// --> end
end
endmodule
The generated waveform is as follows:
After we input the third item of the selected item: 0010, and select item_confirm, the item_confirm key,
sta enters the state 011 from the initial state 000: waiting for coin insertion.
After we put in two one-yuan coins using the falling edge of the coin, and it is not yet 30s, we select the coin confirmation key money_confirm=1, and sta enters the next state 100: judging whether the money is enough.
After calculation by the system, the goods we selected are 1.5 yuan, and we invested 2 yuan, so the money is enough, and we enter the next state. At this time, money_out is 0.5 yuan, that is, we have given us 0.5 yuan in change.
The next state is the shipping state, and item_out is 0010, which just matches the goods we need.
After that, sta becomes 000, that is, it returns to the initial state, and starts the next cycle.
So far, a complete set of vending machine control system has been demonstrated. Functions exactly as expected.