Verilog implementation of vending machine control system

Design ideas:

First, analyze the topic and stem in turn, and sort out the verilog code ideas.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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:
insert image description here

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:
insert image description here
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.
insert image description here
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.
insert image description here
insert image description here
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.
insert image description here
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.

Guess you like

Origin blog.csdn.net/qq_43734019/article/details/104058539