列表

详情


VL61. 自动售卖机

描述

请设计状态机电路,实现自动售卖机功能,A饮料5元钱,B饮料10元钱,售卖机可接收投币5元钱和10元钱,每次投币只可买一种饮料,考虑找零的情况。

电路的接口如下图所示。sel信号会先于din信号有效,且在购买一种饮料时值不变。

接口电路图如下:

输入描述

   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,
   output    reg        change_out   

原站题解

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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   
);
    
    parameter idle=0;
    parameter s1=1;
    reg [1:0] c_state,n_state;
    wire [2:0] a;
    assign a={sel,din};
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            c_state<=idle;
        else
            c_state<=n_state;
    end
    
    always @(*) begin
        case(c_state)
            idle:begin
                case(a)
                    3'b101:n_state=s1;
                    default:n_state=idle;
                endcase
            end
                
            s1:begin 
                case(din)
                    2'b00:n_state=s1;
                    default:n_state=idle;
                endcase
            end
            
            default:n_state=idle;
        endcase
    end
    
     
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            drinks_out<=0;
            change_out<=0;
        end
        else if(!sel) begin
            drinks_out<=(c_state==idle&din!=0);
            change_out<=(c_state==idle&din==2);
        end
        else begin
            change_out<=(c_state==s1&din==2);
            if(c_state==s1&din!=0)
                drinks_out<=2;
            else if(c_state==idle&&din==2)
                drinks_out<=2;
            else
                drinks_out<=0;
        end
    end
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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   
);
    reg [2:0]state,next_state;
    parameter IDLE = 3'd0;//0元
    parameter FIVE = 3'd1;//5元
    
    
    always@(*)begin
        case(state)
            IDLE:if(din == 2'b0)begin
                    next_state = IDLE;
            end else if(din == 2'b01)begin
                if(sel == 0)begin
                    next_state = IDLE;
                end
                else begin
                    next_state = FIVE;
                end
            end
            else if(din == 2'b10)begin
                next_state = IDLE;
            end
            else begin
                next_state = IDLE;
            end
            FIVE:if(din == 2'b0)begin
                next_state = FIVE;
            end
            else if(din == 2'b01)begin
                next_state = IDLE;
            end
            else if(din == 2'b10)begin
                next_state = IDLE;
            end
            else begin
                next_state = FIVE;
            end
            default:next_state = IDLE;
        endcase
    end
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            state <= IDLE;
        end
        else
            state <= next_state;
    end
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            drinks_out <= 2'b0;
        end
        else begin
            case(next_state)
                IDLE:if( (din == 2'b01 || din == 2'b10) && sel == 1'b0)begin
                    drinks_out <= 2'b01;
                end else if((din == 2'b10 || din == 2'b01) && sel == 1) begin
                    drinks_out <= 2'b10;
                end else
                    drinks_out <= 2'b00;
                FIVE:
                    drinks_out <= 2'b00;
            endcase
        end
    end
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            change_out  <= 1'b0;
        end
        else begin
            case(next_state)
                IDLE:if(din == 2'b10 && sel == 0|| state == FIVE && din == 2'b10)begin
                    change_out  <= 1'b1;
                end else
                    change_out  <= 1'b0;
                FIVE:change_out  <= 1'b0;
            endcase
        end
    end
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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   
);
    
    parameter   IDLE = 3'd0,
                S0_D0= 3'd1,
                S0_D1= 3'd2,
                S0_D2= 3'd3,
                S1_D0= 3'd4,
                S1_D1= 3'd5,
                S1_D2= 3'd6,
                S1_D3= 3'd7;
    
    reg [2:0]   state       ,
                next_state  ;
    
    always@(posedge clk or negedge rst_n)
        if(!rst_n)
            state <= IDLE;
        else
            state <= next_state;
    
    always@(*)
        case(state)
            IDLE,S0_D0,S0_D1,S0_D2,S1_D0,S1_D2,S1_D3: 
                case({sel,din})
                    3'b000 :  next_state = S0_D0;
                    3'b001 :  next_state = S0_D1;
                    3'b010 :  next_state = S0_D2;
                    3'b100 :  next_state = S1_D0;
                    3'b101 :  next_state = S1_D1;
                    3'b110 :  next_state = S1_D2;
                    default :  next_state = IDLE;
                endcase
            S1_D1 : 
                if(din == 2'd0)
                    next_state = S1_D1;
                else if(din == 2'd1)
                    next_state = S1_D2;
                else if(din == 2'd2)
                    next_state = S1_D3;
                else
                    next_state = IDLE;
            default: next_state = IDLE;
        endcase
    
    always@(*)
            case(state)
                S0_D1: begin
                    drinks_out <= 2'd1;
                    change_out <= 1'b0;
                end
                S0_D2: begin
                    drinks_out <= 2'd1;
                    change_out <= 1'b1;
                end
                S1_D2: begin
                    drinks_out <= 2'd2;
                    change_out <= 1'b0;
                end
                S1_D3 : begin
                    drinks_out <= 2'd2;
                    change_out <= 1'b1;
                end
                default: begin
                    drinks_out <= 2'b0;
                    change_out <= 1'b0;
                end
            endcase
    
endmodule
            
            
            
            

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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   
);
    parameter S0 = 1'b0;
    parameter S1 = 1'b1;
    
    reg cstate, nstate;
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            cstate <= 1'b0;
        end
        else begin
            cstate <= nstate;
        end
    end
    
    always@(*) begin
        case(cstate)
            S0: begin
                nstate = (sel&(din=='d1))?S1:S0;
            end
            S1: begin
                nstate = (din=='d0)?S1:S0;
            end
            default: begin
                nstate = S0;
            end
        endcase
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            drinks_out <= 2'd0;
        end
        else if((!sel) & (cstate==S0) & (din!='d0)) begin
                drinks_out <= 2'd1;
            end
        else if(sel & (((cstate==S0) & (din=='d2)) | ((cstate==S1) & (din!='d0)))) begin
                    drinks_out <= 2'd2;
        end
        else begin
            drinks_out <= 2'd0;
        end
    end    
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            change_out <= 1'b0;
        end
        else if(((!sel) & (cstate==S0) & (din=='d2)) | (sel & (cstate==S1) & (din=='d2))) begin
            change_out <= 1'b1;
        end
        else begin
            change_out <= 1'b0;
        end
    end

endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`timescale 1ns/1ns

module sale(input clk,
            input rst_n,
            input sel,
            input [1:0] din,
            output reg [1:0] drinks_out,
            output    reg change_out);
    parameter idle = 3'b000;
    parameter s05  = 3'b001;
    parameter s10  = 3'b010;
    parameter s15  = 3'b100;
    reg [2:0] cs,ns;
    always@(posedge clk or negedge rst_n)
        cs <= ~rst_n?idle:ns;
    always@(*) begin
        ns = idle;
        case(cs)
            idle: ns    = din == 0?idle:din == 1?s05:din == 2?s10:idle;
            s05:  ns    = sel?(din == 0?s05:din == 1?s10:din == 2?s15:idle):(din == 0?idle:din == 1?s05:din == 2?s10:idle);
            s10:  ns    = din == 0?idle:din == 1?s05:din == 2?s10:idle;
            s15:  ns    = din == 0?idle:din == 1?s05:din == 2?s10:idle;
            default: ns = idle;
        endcase
    end
    always@(posedge clk or negedge rst_n) begin
        if (!rst_n)
            drinks_out <= 0;
        else
            drinks_out <= sel?((ns == s10 || ns == s15)?2:0):((ns == s05 || ns == s10 | cs == s15)?1:0);
    end
    always@(posedge clk or negedge rst_n) begin
        if (!rst_n)
            change_out <= 0;
        else
            change_out <= sel?((ns == s15)?1:0):((ns == s10 || ns == s15)?1:0);
    end
endmodule

上一题