跳到主要内容
返回模板库

Mealy 可逆计数器Mealy Up/Down Counter

经典 Mealy 型的状态机教学示例:可逆计数器控制,输出取决于状态和输入。

Mealybasicverilog
开源标注
来源仓库: https://555tools.com
许可证: MIT
Author: 555Tools Educational
Copyright (c) 2026 555Tools Educational

Key Points

  • - Mealy machine: output depends on state AND input
  • - Parameterized counter width
  • - Parallel load, up/down mode, overflow/zero flags
  • - Two-segment coding: state reg / combined logic

RTL Source

// Copyright (c) 2026 555Tools Educational
// SPDX-License-Identifier: MIT
// Source: https://555tools.com
// Mealy FSM Example: Up/Down Counter with FSM control
// Two-segment coding style (standard for FPGA synthesis)
// 中文:Mealy 型状态机教学示例——可逆计数器控制

`timescale 1ns / 1ps

// Mealy Machine: Output depends on current state AND input
// 中文:Mealy 机——输出取决于当前状态和输入,两段式编码
// 3-bit up/down counter controlled by FSM
//   mode=0: count up, mode=1: count down
//   load=1: parallel load, enable=1: count
module mealy_counter #(
    parameter WIDTH = 3           // Counter width
)(
    input  wire              clk,      // System clock
    input  wire              rst,      // Synchronous reset
    input  wire              enable,   // Count enable
    input  wire              mode,     // 0=up, 1=down
    input  wire              load,     // Parallel load
    input  wire [WIDTH-1:0]  data_in,  // Parallel load data
    output reg  [WIDTH-1:0]  count,    // Counter output
    output reg               overflow, // Count overflow/underflow flag
    output reg               zero      // Counter is zero flag
);

    // State encoding
    localparam [1:0] S_IDLE  = 2'd0,  // Waiting for enable
                     S_COUNT = 2'd1,  // Counting
                     S_LOAD  = 2'd2,  // Loading parallel data
                     S_FLAG  = 2'd3;  // Flag output cycle

    reg [1:0] state, next_state;

    // Segment 1: State register
    always @(posedge clk) begin
        if (rst)
            state <= S_IDLE;
        else
            state <= next_state;
    end

    // Segment 2: Next-state logic (Mealy: depends on inputs)
    always @(*) begin
        case (state)
            S_IDLE: begin
                if (load)
                    next_state = S_LOAD;
                else if (enable)
                    next_state = S_COUNT;
                else
                    next_state = S_IDLE;
            end
            S_COUNT: begin
                if (load)
                    next_state = S_LOAD;
                else if (!enable)
                    next_state = S_IDLE;
                else if (overflow || zero)
                    next_state = S_FLAG;
                else
                    next_state = S_COUNT;
            end
            S_LOAD: begin
                next_state = S_IDLE;
            end
            S_FLAG: begin
                next_state = S_IDLE;
            end
            default: next_state = S_IDLE;
        endcase
    end

    // Counter and output logic
    always @(posedge clk) begin
        if (rst) begin
            count    <= 0;
            overflow <= 0;
            zero     <= 0;
        end else begin
            case (state)
                S_IDLE: begin
                    overflow <= 0;
                    zero     <= 0;
                end
                S_COUNT: begin
                    if (enable) begin
                        if (!mode) begin
                            // Count up
                            count <= count + 1;
                            if (count == {WIDTH{1'b1}})
                                overflow <= 1;
                        end else begin
                            // Count down
                            count <= count - 1;
                            if (count == 0)
                                zero <= 1;
                        end
                    end
                end
                S_LOAD: begin
                    count    <= data_in;
                    overflow <= 0;
                    zero     <= (data_in == 0);
                end
                S_FLAG: begin
                    // Mealy output: flag held for one cycle
                    overflow <= 0;
                    zero     <= 0;
                end
                default: begin
                    count    <= 0;
                    overflow <= 0;
                    zero     <= 0;
                end
            endcase
        end
    end

endmodule