Verilog 每日一题(VL14 自动贩售机1--FSM常见题型)

 自动贩售机

题目描述:    

设计一个自动贩售机,输入货币有三种,为0.5/1/2元,饮料价格是1.5元,要求进行找零,找零只会支付0.5元。

ps:投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号

注意rst为低电平复位

信号示意图:

d1   0.5元

d2   1元

d3   2元

out1 饮料

out2 零钱


这一题第一眼就想到的是状态机,所以先把状态图画出来:

看上去好像有点复杂了。。。 根据状态图写代码就简单很多了。

编译成功的代码详解如下:(但在状态变化那一段有疑惑)

//A:nstate <= (d1)? B:(d2)?C:(d3)?E:nstate; 
//这里是不理解的一点,如果把末尾的nstate写成A会报错,out1会丢失一些值,但明明d1d2d3都为0时,就是保持A不变吧,nstate=A也没有问题啊应该。(看到答案才改成的nstate)

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
);
//*************code***********//
//这一题应该用FSM来做
//声明7个状态
    parameter A=0,B=1,C=2,D=3,E=4,F=5,G=6;
    reg [2:0] state,nstate;
    
//逻辑变化
    always @(*) begin
        case(state)  
            A:nstate <= (d1)? B:(d2)?C:(d3)?E:nstate; 
//这里是不理解的一点,如果把末尾的nstate写成A会报错,但明明d1d2d3都为0时,就是保持A不变吧,nstate=A也没有问题啊应该
            B:nstate <= (d1)? C:(d2)?D:(d3)?F:nstate;
            C:nstate <= (d1)? D:(d2)?E:(d3)?G:nstate;
            D:nstate <= A;
            E:nstate <= A;
            F:nstate <= A;
            G:nstate <= A;
            default: nstate <= A;
        endcase
    end
  //时序变化          
    always @(posedge clk or negedge rst)begin
        if(!rst) state<=A;
        else state<=nstate;
     end
            //输出判定
            always @(*)begin 
                case(state)  //有答案写的上升沿时才输出,并按nstate来进行输出判断
                    D: begin out1<=1;out2<=0; end
                    E: begin out1<=1;out2<=1; end
                    F: begin out1<=1;out2<=2; end
                    G: begin out1<=1;out2<=3; end
                    default: begin out1<=0;out2<=0; end
                endcase
            end     
//*************code***********//
endmodule

答案里还看到说用简单的寄存器来进行判定的,即用加法计数来判断,好像也是一种不错的思路,而且代码会简单很多。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力回答你的问题。 实现自动售货机的状态需要以下几个步骤: 1. 确定状态 自动售货机的状态可以分为以下几个: - 等待状态(Wait):等待用户投入硬币或选择商品。 - 接收硬币状态(Coin):接收用户投入的硬币。 - 选择商品状态(Select):用户选择商品。 - 出货状态(Dispense):出货并找零。 2. 确定输入 自动售货机的输入可以分为以下几个: - 投入硬币(Coin_In):用户投入硬币。 - 选择商品(Select_Item):用户选择商品。 - 出货(Dispense_Item):出货并找零。 3. 确定输出 自动售货机的输出可以分为以下几个: - 显示(Display):显示用户当前的状态和余额。 - 出货(Dispense_Item):出货并找零。 4. 确定状态转移条件 根据自动售货机的状态和输入,我们可以确定状态转移条件。例如,在等待状态下,如果用户投入了硬币,那么转移到接收硬币状态;如果用户选择了商品,那么转移到选择商品状态。 5. 实现状态 根据上述步骤,我们可以实现自动售货机的状态。下面是一个Verilog代码片段,用于实现自动售货机的状态: ``` // 定义状态 typedef enum logic [1:0] { Wait, Coin, Select, Dispense } state; // 定义输入 input Coin_In; input Select_Item; input Dispense_Item; // 定义输出 output reg Dispense_Item; output reg [7:0] Display; // 定义状态寄存器和下一个状态变量 reg [1:0] current_state; reg [1:0] next_state; // 确定状态转移条件 always @(*) begin case(current_state) Wait: begin if (Coin_In) next_state = Coin; else if (Select_Item) next_state = Select; else next_state = Wait; end Coin: begin if (Coin_In) next_state = Coin; else if (Select_Item) next_state = Select; else next_state = Wait; end Select: begin if (Coin_In) next_state = Coin; else if (Select_Item) next_state = Select; else next_state = Dispense; end Dispense: begin next_state = Wait; end default: next_state = Wait; endcase end // 实现状态 always @(posedge clk) begin current_state <= next_state; case(current_state) Wait: begin Display <= "00000000"; end Coin: begin Display <= Display + 1; end Select: begin Display <= Display + 2; end Dispense: begin Display <= Display - 2; Dispense_Item <= 1; end default: begin Display <= "00000000"; end endcase end ``` 这段代码使用了Verilog语言实现了自动售货机的状态。在此代码中,我们使用了一个状态寄存器和一个下一个状态变量来实现状态转移。同时,我们使用了一个时钟信号(clk)来控制状态的运行。在状态运行的过程中,我们可以根据当前状态和输入来确定下一个状态,并根据当前状态来实现相应的输出。 以上就是Verilog实现自动售货机状态的基本步骤和代码实现。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值