12.21 Vending machine, single item, multiple items

vending machine 

if naive method

 One idea is to use the register cnt to record the existing smallest unit currency amount, here it is 0.5

When d1, cnt+1; when d2, cnt+2; when d3, cnt+4;

`timescale 1ns/1ns
module seller1(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,
	input wire d2 ,
	input wire d3 ,
	
	output reg out1,
	output reg [1:0]out2
);
reg[2:0]cnt;
always@(posedge clk,negedge rst)begin
	if(!rst)begin
		cnt<=0;
		out1<=0;
		out2<=0;
	end
	else begin
	if(d1)cnt<=cnt+1;
	else if(d2)cnt<=cnt+2;
	else if(d3)cnt<=cnt+4;
	else if(cnt>=3)begin
		out1<=1;
		out2<=cnt-3;
		cnt<=0;//记得复位为0,表示一个过程的结束
	end
	else begin
		out1<=0;
		out2<=0;
	end//这里需要注意一定需要这一步,不然在不复位时,将保持一直输出1的状态
	end
end
endmodule

Note here that d1, d2, and d3 are all in the form of pulses, that is, they will only be accepted in one time step, and the detection is also

`timescale 1ns/1ns


module seller1(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,
	input wire d2 ,
	input wire d3 ,
	
	output reg out1,
	output reg [1:0]out2
);

    parameter S0 = 'd0, S1 = 'd1, S2 = 'd2, S3 = 'd3 , S4 = 'd4, S5 = 'd5 , S6 = 'd6;
    reg  [2:0]	current_state;
    reg  [2:0]	next_state;
	wire [2:0]   input_state;//将输入组合起来
	assign input_state = {d1,d2,d3};
	
    always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
            current_state <= S0;
        end
        else begin
            current_state <= next_state;
        end
    end   
    
    always@(*)begin
        case(current_state)
            S0:begin
				case(input_state)
					3'b100:next_state = S1 ;
					3'b010:next_state = S2 ;
					3'b001:next_state = S4 ;
					default:next_state = next_state;
				endcase	
            end
            S1:begin
            	case(input_state)
					3'b100:next_state = S2 ;
					3'b010:next_state = S3 ;
					3'b001:next_state = S5 ;
					default:next_state = next_state; 
				endcase
            end
            S2:begin
			    case(input_state)
					3'b100:next_state = S3 ;
					3'b010:next_state = S4 ;
					3'b001:next_state = S6 ;
					default:next_state = next_state;
				endcase				
            end
			
            default:begin
                next_state = S0;
            end
        endcase
    end
    
    always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
            out1 <= 1'b0;
			out2 <= 2'b0;
        end
        else begin
			case(next_state)
					S3:		   begin out1 <= 1'b1;out2 <= 2'b0; end 
					S4:		   begin out1 <= 1'b1;out2 <= 2'b1; end 
					S5:		   begin out1 <= 1'b1;out2 <= 2'b10; end 
					S6:		   begin out1 <= 1'b1;out2 <= 2'b11; end 
					default:   begin out1 <= 1'b0;out2 <= 2'b0; end 
			endcase	
        end
    end
 
endmodule

State machine method

Using MOORE state machine, that is, the output is only related to the state and has nothing to do with the current input signal

The state machine method can support inserting multiple coins at one time

MOORE three sections

The first paragraph: signal declaration, state definition, state transition

Second paragraph: From the current state, determine the next state based on the input signal

It can be seen here that if multiple coins are invested at one time, transfer and judgment can be performed. Just add judgment in the case.

Section 3: Determine the output signal based on the secondary state

Vending machine (supports multi-item vending)

When sel is 0, buy one dollar and a half, which is the fourth state, s3; when sel is 1, buy two yuan and a half, which is the sixth state, s5.

state machine

`timescale 1ns/1ns

module seller2(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,
	input wire d2 ,
	input wire sel ,
	
	output reg out1,
	output reg out2,
	output reg out3
);
//*************code***********//

    parameter S0=0, S0_5=1, S1=2, S1_5=3, S2=4, S2_5=5, S3=6;
    reg[2:0] state, nstate;
    
    always@(posedge clk or negedge rst) begin
        if(~rst)
            state <= 0;
        else
            state <= nstate;
    end
    
    always@(*) begin
        case(state)
            S0     : nstate = d1? S0_5:
                              d2? S1:
                              nstate;
            S0_5   : nstate = d1? S1:
                              d2? S1_5:
                              nstate;
            S1     : nstate = d1? S1_5:
                              d2? S2:
                              nstate;
            S1_5   : nstate = ~sel? S0:
                              d1? S2:
                              d2? S2_5:
                              nstate;
            S2     : nstate = ~sel? S0:
                              d1? S2_5:
                              d2? S3:
                              nstate;
            default: nstate = S0;
        endcase
    end
    
    always@(*) begin
        if(~rst) begin
            {out1, out2, out3} = 3'b000;
        end
        else begin
            case(state)
                S0, S0_5, S1: {out1, out2, out3} = 0;
                S1_5        : {out1, out2, out3} = ~sel? 3'b100: 3'b000;
                S2          : {out1, out2, out3} = ~sel? 3'b101: 3'b000;
                S2_5        : {out1, out2, out3} = ~sel? 3'b101: 3'b010;
                S3          : {out1, out2, out3} = ~sel? 3'b101: 3'b011;
                default     : {out1, out2, out3} = 3'b000;
            endcase
        end
    end
//*************code***********//
endmodule

The above is a mealy state machine, that is, the output depends on the current state and the input signal 

`timescale 1ns/1ns


module seller2(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,
	input wire d2 ,
	input wire sel ,
	
	output reg out1,
	output reg out2,
	output reg out3
);

    parameter S0 = 'd0, S1 = 'd1, S2 = 'd2, S3 = 'd3 , S4 = 'd4, S5 = 'd5, S6 = 'd6;
    reg [2:0]	current_state;
    reg [2:0]	next_state;
    wire [1:0]  input_state;
	assign input_state = {d1,d2};
	
    always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
            current_state <= S0;
        end
        else begin
            current_state <= next_state;
        end
    end   
    
    always@(*)begin
		if (!sel) begin
			case(current_state)
			    S0:begin
					case(input_state)
						2'b10 :next_state = S1 ;
						2'b01 :next_state = S2 ;
						default:next_state = next_state;
					endcase	
			    end
			    S1:begin
			    	case(input_state)
						2'b10 :next_state = S2 ;
						2'b01 :next_state = S3 ;
						default:next_state = next_state;
					endcase	 
			    end
			    S2:begin
				    case(input_state)
						2'b10 :next_state = S3 ;
						2'b01 :next_state = S4 ;
						default:next_state = next_state;
					endcase	
			    end
			    default:  next_state = S0;  
			endcase
		end
		else begin
			case(current_state)
			    S0:begin
					case(input_state)
						2'b10 :next_state = S1 ;
						2'b01 :next_state = S2 ;
						default:next_state = next_state;
					endcase	
			    end
			    S1:begin
			    	case(input_state)
						2'b10 :next_state = S2 ;
						2'b01 :next_state = S3 ;
						default:next_state = next_state;
					endcase	 
			    end
			    S2:begin
				    case(input_state)
						2'b10 :next_state = S3 ;
						2'b01 :next_state = S4 ;
						default:next_state = next_state;
					endcase	
			    end
				S3:begin
				    case(input_state)
						2'b10 :next_state = S4 ;
						2'b01 :next_state = S5 ;
						default:next_state = next_state;
					endcase	
				end
				S4:begin
				    case(input_state)
						2'b10 :next_state = S5 ;
						2'b01 :next_state = S6 ;
						default:next_state = next_state;
					endcase	
				end
			    default:  next_state = S0;  
			endcase
			
		
		end
    end
    
    always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
            out1 <= 1'b0;
			out2 <= 1'b0;
			out3 <= 1'b0;
        end
        else begin
			if(!sel)begin
				case (next_state)
					S3:		begin out1 <= 1'b1;out2 <= 1'b0;out3 <= 1'b0;end 
					S4:		begin out1 <= 1'b1;out2 <= 1'b0;out3 <= 1'b1;end 
					default:begin out1 <= 1'b0;out2 <= 1'b0;out3 <= 1'b0;end 
				endcase
			end
			else begin
				case (next_state)	
					S5:		begin out1 <= 1'b0;out2 <= 1'b1;out3 <= 1'b0;end 	
					S6:		begin out1 <= 1'b0;out2 <= 1'b1;out3 <= 1'b1;end 	
					default:begin out1 <= 1'b0;out2 <= 1'b0;out3 <= 1'b0;end 	
				endcase	
			end
        end
    end
 
endmodule

The above is the standard MOORE state machine code, that is, the output is only related to the secondary state.

During state transition, be sure to remember to write

That is equivalent to  the subsequent reset, otherwise there is no way to reset

Guess you like

Origin blog.csdn.net/m0_73553411/article/details/135130144