`timescale 1ns/1ns

module sale(
   input                clk   ,
   input                rst_n ,
   input                sel   ,//sel=0,5$dranks,sel=1,10&=$drinks
   input          [1:0] din   ,//din=1,input 5$,din=2,input 10$
 
   output   reg  [1:0] drinks_out,//drinks_out=1,output 5$ drinks,drinks_out=2,output 10$ drinks
   output    reg        change_out   
);
    //------------------------//
    //这个题目有个坑,就是当sel=1,din=1时,即选择购买B饮料且投币5元时,正常输出应该是
    //drinks_out=0,change_out=1;即无饮料输出且找零5元(退钱)。
    //但是,这个题目要求钱不够时,必须要继续投币,继续购买饮料。
    //因此当sel=1,din=1时,输出drinks_out=0,change_out=0;注意此时售卖机内还有5元,
    //那么就有可能出现输出B饮料同时找零5元这种情况
    //我的思路时按输出结果,划分成6种状态,分别是:
    //A:没有饮料输出且没有找零,这个状态也可以作为默认初始状态;
    //B:输出A饮料且没有找零;
    //C: 输出A饮料且找零;
    //D: 输出B饮料且没有找零;
    //E: 没有饮料输出且没有找零,但是售卖机内还有5元;
    //F: 输出B饮料且找零。
    //------------------------//
    reg [2:0] state, next_state;
    parameter A = 0, B = 1,C = 2, D = 3, E = 4, F = 5; 
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n) begin
            state <= A;
        end else begin
            state <= next_state;
        end
    end
    
    always @(*) begin
        case(state)
            A: begin
                case({sel,din})
                    3'b000: next_state <= A;
                    3'b001: next_state <= B;
                    3'b010: next_state <= C;
                    3'b100: next_state <= A;
                    3'b101: next_state <= E;
                    3'b110: next_state <= D;
                    default: next_state <= A;
                endcase
            end
            B: begin
                case({sel,din})
                    3'b000: next_state <= A;
                    3'b001: next_state <= B;
                    3'b010: next_state <= C;
                    3'b100: next_state <= A;
                    3'b101: next_state <= E;
                    3'b110: next_state <= D;
                    default: next_state <= A;
                endcase
            end
            C: begin
                case({sel,din})
                    3'b000: next_state <= A;
                    3'b001: next_state <= B;
                    3'b010: next_state <= C;
                    3'b100: next_state <= A;
                    3'b101: next_state <= E;
                    3'b110: next_state <= D;
                    default: next_state <= A;
                endcase
            end
            D: begin
                case({sel,din})
                    3'b000: next_state <= A;
                    3'b001: next_state <= B;
                    3'b010: next_state <= C;
                    3'b100: next_state <= A;
                    3'b101: next_state <= E;
                    3'b110: next_state <= D;
                    default: next_state <= A;
                endcase
            end
            E: begin
                case({sel,din})
                    3'b100: next_state <= E;
                    3'b101: next_state <= D;
                    3'b110: next_state <= F;
                    default: next_state <= A;
                endcase
            end
            
            F: begin
                case({sel,din})
                    3'b000: next_state <= A;
                    3'b001: next_state <= B;
                    3'b010: next_state <= C;
                    3'b100: next_state <= A;
                    3'b101: next_state <= E;
                    3'b110: next_state <= D;
                    default: next_state <= A;
                endcase
            end
        endcase
    end
    
    always @(*) begin
        case(state)
            A: drinks_out <= 2'd0;
            B: drinks_out <= 2'd1;
            C: drinks_out <= 2'd1;
            D: drinks_out <= 2'd2;
            E: drinks_out <= 2'd0;
            F: drinks_out <= 2'd2;
            default: drinks_out <= 2'd0;
        endcase
    end
    always @(*) begin
        case(state)
            A: change_out <= 1'b0;
            B: change_out <= 1'b0;
            C: change_out <= 1'b1;
            D: change_out <= 1'b0;
            E: change_out <= 1'b0;
            F: change_out <= 1'b1;
            default: change_out <= 1'b0;
        endcase
    end
endmodule