verilog 售卖机 三段式状态机

本文介绍了一种基于Mealy状态机的自动售卖机设计。该设计使用三段式状态机,能够处理不同面额的硬币投入,并实现找零与出货功能。通过具体的Verilog代码实现,展示了如何根据当前状态和输入来决定下一状态及输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

状态机类型

Moore 状态机

Moore 型状态机的输出只与当前状态有关,与当前输入无关。输入对输出的影响要到下一个时钟周期才能反映出来。

Mealy 状态机。

Mealy 型状态机的输出,不仅与当前状态有关,还取决于当前的输入信号。输入变化可能出现在任何状态的时钟周期内


Mealy型3段式状态机 自动售卖机:

状态转移图:
在这里插入图片描述
自动售卖机的功能描述如下:

饮料单价 2 元,该售卖机只能接受 0.5 元、1 元的硬币。考虑找零和出货。投币和出货过程都是一次一次的进行,不会出现一次性投入多币或一次性出货多瓶饮料的现象。每一轮售卖机接受投币、出货、找零完成后,才能进入到新的自动售卖状态。

其中,coin = 1 代表投入了 0.5 元硬币,coin = 2 代表投入了 1 元硬币。

// 售卖机  三段式状态机

module  vending_machine_p3  (
    input           clk,   
    input           rstn,   
    input   [1:0]   coin,    // 投入硬币  01 for 0.5 jiao, 10 for 1 yuan
    output  [1:0]   change,  // 找零
    output          sell     // 出货
    );

    // 状态码
    parameter   IDLE    =   3'd0;
    parameter   GET05   =   3'd1;  // 收了5毛
    parameter   GET10   =   3'd2;  // 收了1元
    parameter   GET15   =   3'd3;  // 收了1.5元

    reg [2:0]   next_state;
    reg [2:0]   current_state;

    // 状态机第一段,时序逻辑,非阻塞赋值,传递寄存器的状态
    always @(posedge clk or negedge rstn) begin
        if(~rstn) begin
            next_state <= 3'b0;
            current_state <= 3'b0;
        end 
        else begin
            current_state <= next_state;
        end
    end

    // 状态机第二段,组合逻辑,阻塞赋值,根据当前状态和当前输入,确定下一个状态机的状态。
    always @(*) begin
        case(current_state)
            IDLE:
                case(coin)
                    2'b01:  next_state = GET05; // 收了5毛
                    2'b10:  next_state = GET10; // 收了1元
                    default:next_state = IDLE;  // 原地不动
                endcase 
            GET05:
                case(coin)
                    2'b01:  next_state = GET10; // 收了1元
                    2'b10:  next_state = GET15; // 收了1.5元
                    default:next_state = GET05; // 原地不动
                endcase 
            GET10:
                case(coin)
                    2'b01:  next_state = GET15; // 收了1.5元
                    2'b10:  next_state = IDLE;  // 收了2元,达到单价,返回
                    default:next_state = GET10; // 原地不动
                endcase 
            GET15:
                case(coin)
                    2'b01:  next_state = IDLE; // 收了2元,达到单价,返回
                    2'b10:  next_state = IDLE; // 收了2.5元,超过单价,找零,返回
                    default:next_state = GET15; // 原地不动
                endcase 
            default:
                next_state = IDLE;                                                                  
        endcase // current_state
    end

    // 状态机第三段,时序逻辑,非阻塞赋值,因为是 Mealy 型状态机,根据当前状态和当前输入,确定输出信号
    reg [1:0]   change_r;
    reg         sell_r;
    always @(posedge clk or negedge rstn) begin 
        if(~rstn) begin
            change_r <= 2'b0 ;
            sell_r <= 1'b0;
        end 
        else if ((current_state == GET15 && coin == 2'd1 ) 
                    || (current_state == GET10 && coin == 2'd2 ))begin
            change_r <=  2'b0 ;
            sell_r <= 1'b1;  // 出货
        end
        else if (current_state == GET15 && coin == 2'd2 )begin
            change_r <=  2'b1 ;  // 找零
            sell_r <= 1'b1;    // 出货
        end
        else begin  // default
            change_r <= 2'b0 ;
            sell_r <= 1'b0;         
        end
    end

    assign sell = sell_r;
    assign change  = change_r;

endmodule

`timescale 1ns/1ps

module vending_machine_p3_tb ;
    reg             clk;  
    reg             rstn;    
    reg     [1:0]   coin;     // 投入硬币  01 for 0.5 jiao, 10 for 1 yuan
    wire    [1:0]   change;   // 找零
    wire            sell;      // 出货

   //(1) mealy state with 3-stage
    vending_machine_p3    u_mealy_p3     (
        .clk(clk),
        .rstn(rstn),
        .coin(coin),
        .change(change),
        .sell(sell)
        );

    // 仿真停止
    always begin
      #100;
      if ($time >= 10000)  $finish ;
    end


    parameter CYCLE_200MHz = 10;  // 1/200*10^6 = 5*10^-9 = 5ns 半周期
    always begin
        clk = 0 ; #(CYCLE_200MHz/2) ;  // 半周期翻转#(CYCLE_200MHz/2)
        clk = 1 ; #(CYCLE_200MHz/2) ;
    end

    reg [9:0]   buy_oper;  // 操作状态
    initial begin
        buy_oper    =   10'd0;
        coin        =   2'd0;   
        rstn        =   1'd0;
        #8 rstn     =   1'b1;  // (即仿真开始后的第8ns,第一个周期内)(一个周期10ns)

        @(negedge clk);  // 从下降沿开始(即仿真开始后的第10ns)

        //case(1) 0.5 -> 0.5 -> 0.5 -> 0.5
        #16;    // 等待16ns  (即仿真开始后的第26ns,第3个周期内)
        buy_oper  = 10'b00_0101_0101 ;
        repeat(5) begin
            @(negedge clk);   // 再过4ns到下降沿 (即仿真开始后的第30ns)
            coin        =   buy_oper[1:0];
            buy_oper    =   buy_oper >> 2;  // 右移两位 (每次都给5毛)
        end

        //case(2)  1 -> 0.5 -> 1
        #16;  // 再过16ns (即仿真开始后的第46ns,clk=1在45ns-50ns之间)
        buy_oper  = 10'b00_0010_0110 ;
        repeat(5) begin
            @(negedge clk);  // 再过4ns到下降沿 (即仿真开始后的第50ns)
            coin        =   buy_oper[1:0];
            buy_oper    =   buy_oper >> 2;  // 右移两位 (每次都给5毛)
        end

        //case(3) 0.5 -> 1 -> 0.5
        #16 ;
        buy_oper  = 10'b00_0001_1001 ;
        repeat(5) begin
            @(negedge clk) ;
            coin      = buy_oper[1:0] ;
            buy_oper  = buy_oper >> 2 ;
        end

        //case(4) 0.5 -> 0.5 -> 0.5 -> 1
        #16 ;
        buy_oper  = 10'b00_1001_0101 ;
        repeat(5) begin
            @(negedge clk) ;
            coin      = buy_oper[1:0] ;
            buy_oper  = buy_oper >> 2 ;
        end        
    end


endmodule // test

在这里插入图片描述


<think>好的,用户想要查找有限状态机Verilog中的实现示例,特别是具体的代码。我需要先回忆一下相关知识,然后结合提供的引用内容来组织回答。 首先,根据引用[1],有限状态机(FSM)由状态寄存器和组合逻辑构成,用于处理复杂的状态转移,比如IIC协议。引用[2]提到Moore和Mealy状态机的区别,Moore的输出仅与当前状态有关,而Mealy还和输入有关,且Mealy状态更少。引用[3]给出了一个序列检测器的Verilog代码示例,采用三段式设计,使用one-hot编码,并且有状态转移的组合逻辑部分。 用户需要的是实现示例,所以应该提供一个清晰的代码示例,并解释各部分的结构。可能需要选择常见的例子,比如自动售货机或者交通灯控制,但根据引用中的例子,序列检测器和自动饮料售卖机比较适合。引用[3]已经有序列检测器的代码,所以可能需要再补充另一个例子,比如自动饮料售卖机,或者交通灯控制,但引用[2]提到了自动饮料售卖机,所以可能用这个作为第二个例子。 需要注意的是,用户可能需要三段式状态机的实现方式,因为引用[3]的代码分成了时序逻辑的状态转移、组合逻辑的状态转移条件、时序逻辑的输出。这样结构清晰,符合最佳实践。同时,需要解释Moore和Mealy的区别,并给出对应的代码结构。 另外,用户可能需要代码的详细解释,比如状态编码方式(one-hot、二进制等),状态转移的条件,以及输出逻辑。同时,要确保代码语法正确,使用中文注释还是英文?根据用户的问题,回答使用中文,所以注释可能需要用中文,但原引用中的代码是英文,可能需要调整。 还需要生成相关问题,可能涉及状态机类型选择、三段式优点、状态编码方式、应用场景等。确保问题与内容相关,并帮助用户深入理解。 总结回答结构:首先介绍有限状态机Verilog中的两种类型(Moore和Mealy),然后给出两个示例,一个是序列检测器(来自引用3),另一个是自动饮料售卖机(引用2提到的),并分别说明三段式的结构。然后列出相关问题。</think>### 有限状态机 Verilog 实现示例 有限状态机(FSM)在Verilog中通常采用**三段式结构**实现,分为**状态寄存器**、**组合逻辑状态转移**和**输出逻辑**三部分。以下提供两种典型示例:序列检测器和自动饮料售卖机。 --- #### 示例1:序列检测器(检测"1101") ```verilog module fsm_sequence_detection( input clk, input rst_n, input din, output reg dout ); // 状态编码:One-Hot方式 parameter IDLE = 4'b0001; parameter S1 = 4'b0010; parameter S2 = 4'b0100; parameter S3 = 4'b1000; reg [3:0] CS, NS; // 当前状态和次态 // 第一段:时序逻辑更新状态 always @(posedge clk or negedge rst_n) begin if (!rst_n) CS <= IDLE; else CS <= NS; end // 第二段:组合逻辑判断状态转移 always @(*) begin case (CS) IDLE: NS = (din == 1) ? S1 : IDLE; S1 : NS = (din == 1) ? S2 : IDLE; S2 : NS = (din == 0) ? S3 : S2; S3 : NS = (din == 1) ? IDLE : IDLE; // 检测到完整序列后复位 default: NS = IDLE; endcase end // 第三段:时序逻辑输出(Moore型) always @(posedge clk) begin if (!rst_n) dout <= 0; else dout <= (CS == S3 && din == 1); end endmodule ``` **功能说明**:检测输入序列"1101",检测成功时输出高电平。此设计为**Moore型状态机**,输出仅依赖当前状态[^2]。 --- #### 示例2:自动饮料售卖机(价格3元) ```verilog module vending_machine( input clk, input rst_n, input [1:0] coin, // 0:无 1:1元 2:2元 output reg drink ); // 状态定义:二进制编码 parameter S0 = 2'b00; // 0元 parameter S1 = 2'b01; // 1元 parameter S2 = 2'b10; // 2元 reg [1:0] CS, NS; // 第一段:状态寄存器 always @(posedge clk) begin if (!rst_n) CS <= S0; else CS <= NS; end // 第二段:状态转移(Mealy型) always @(*) begin case (CS) S0: NS = (coin == 1) ? S1 : (coin == 2) ? S2 : S0; S1: NS = (coin == 1) ? S2 : (coin == 2) ? S0 : S1; S2: NS = (coin == 1) ? S0 : (coin == 2) ? S0 : S2; default: NS = S0; endcase end // 第三段:输出逻辑(Mealy型) always @(*) begin drink = ((CS == S1 && coin == 2) || (CS == S2 && coin >= 1)); // 输入直接参与输出 end endmodule ``` **功能说明**:当累计投入≥3元时输出饮料。此设计为**Mealy型状态机**,输出依赖当前状态和输入[^2]。 --- ### 关键设计要点 1. **状态编码选择** - One-Hot:每个状态用1bit表示,适合状态数少的情况(如示例1) - 二进制:节省寄存器资源,适合状态数多的情况(如示例2) 2. **三段式优势** - 时序与组合逻辑分离,避免冒险竞争 - 输出寄存器化提升时序性能[^3] 3. **Moore vs Mealy** | 类型 | 输出依赖 | 状态数 | 时序要求 | |-------|---------------|------|-------| | Moore | 仅当前状态 | 较多 | 严格 | | Mealy | 当前状态 + 输入 | 较少 | 需防毛刺 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值