FPGA学习记录——牛客网刷题(一)

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

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

  • sel为选择信号,用来选择购买饮料的种类,sel=0,表示购买A饮料,sel=1,表示购买B饮料;
  • din表示投币输入,din=0表示未投币,din=1表示投币5元,din=2表示投币10元,不会出现din=3的情况;
  • drinks_out表示饮料输出,drinks_out=0表示没有饮料输出,drinks_out=1表示输出A饮料,drinks_out=2表示输出B饮料,不出现drinks_out =3的情况,输出有效仅保持一个时钟周期;
  • change_out表示找零输出,change_out=0表示没有找零,change_out=1表示找零5元,输出有效仅保持一个时钟周期。

接口电路图如下:

输入描述:

   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   

问题分析:

整个过程可以分为6个状态,sel先选,din次选,接着00、01、10三个状态跳转。值得注意的是买十块的可以先投5块、再投十块。

`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] c_state,n_state;
    parameter idle = 3'd0,
    S1 = 3'd1,//5元买5元饮料
    S2 = 3'd2,//10元买5元饮料找5块
    S3 = 3'd3,//5元买十元饮料
    S4 = 3'd4,//加了5块,不找
    S5 = 3'd5;//加了10块,找5块


always@(posedge clk or negedge rst_n)
    if(!rst_n)
    c_state<=idle;
    else
    c_state <= n_state;


always@(*)
    if(sel== 1'b0)begin
    case(c_state)
        idle:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= S1;
            2'b10: n_state <= S2;
          endcase
          end
        S1:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= S1;
            2'b10: n_state <= S2;
          endcase
          end
        S2:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= S1;
            2'b10: n_state <= S2;
          endcase
          end
        S3:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= idle;
            2'b10: n_state <= idle;
          endcase
          end
        S4:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= idle;
            2'b10: n_state <= idle;
          endcase
          end
        S5:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= idle;
            2'b10: n_state <= idle;
          endcase
          end
    endcase
    end
else begin
case(c_state)
        idle:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= S3;
            2'b10: n_state <= S4;
          endcase
          end
        S1:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= idle;
            2'b10: n_state <= idle;
          endcase
          end
        S2:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= idle;
            2'b10: n_state <= idle;
          endcase
          end
        S3:begin
        case(din)
            2'b00: n_state <= S3;
            2'b01:  n_state <= S4;
            2'b10: n_state <= S5;
          endcase
          end
        S4:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= S3;
            2'b10: n_state <= S4;
          endcase
          end
        S5:begin
        case(din)
            2'b00: n_state <= idle;
            2'b01:  n_state <= S3;
            2'b10: n_state <= S4;
          endcase
          end
    endcase
end

always@(*)
if(!rst_n)begin
drinks_out <= 0;
change_out <=0;
end
else begin
case(c_state)
idle:begin
drinks_out <= 0;
change_out <=0;
end
S1:begin
drinks_out <= 2'd1;
change_out <=1'd0;
end
S2:begin
drinks_out <= 2'd1;
change_out <=1'd1;
end
S3:begin
drinks_out <= 0;
change_out <=0;
end
S4:begin
drinks_out <=2'd2;
change_out <=0;
end
S5:begin
drinks_out <= 2'd2;
change_out <=1'd1;
end


endcase
end
    endmodule

  • 30
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值