参考

verilog状态机.csdn
有限状态机的九元组定义.csdn
状态机顺序化描述——串口与 AXI4 协议流程建模.csdn

目标

时钟状态LED
ResetS00 灭
第1拍S11 亮
第2拍S20 灭
第3拍S31 亮
第4拍S00 灭
第5拍S11 亮
第6拍S20 灭
第7拍S31 亮

一段式

`timescale 1ns/1ps

module fsm_one_block (
    input  wire i_clk,
    input  wire i_rst_n,
    output reg  o_led
);

    // 状态定义
    localparam S0 = 2'd0;
    localparam S1 = 2'd1;
    localparam S2 = 2'd2;
    localparam S3 = 2'd3;

    reg [1:0] r_state;

    // 一段式状态机
    // 状态跳转和输出逻辑全部写在一个 always 块中
    always @(posedge i_clk or negedge i_rst_n) begin
        if (!i_rst_n) begin
            r_state <= S0;
            o_led   <= 1'b0;
        end
        else begin
            case (r_state)

                S0: begin
                    o_led   <= 1'b0;
                    r_state <= S1;
                end

                S1: begin
                    o_led   <= 1'b1;
                    r_state <= S2;
                end

                S2: begin
                    o_led   <= 1'b0;
                    r_state <= S3;
                end

                S3: begin
                    o_led   <= 1'b1;
                    r_state <= S0;
                end

                default: begin
                    o_led   <= 1'b0;
                    r_state <= S0;
                end

            endcase
        end
    end

endmodule

三段式

`timescale 1ns/1ps

module fsm_three_block (
    input  wire i_clk,
    input  wire i_rst_n,
    output reg  o_led
);

    //============================================================
    // 状态定义
    //============================================================
    localparam S0 = 2'd0;
    localparam S1 = 2'd1;
    localparam S2 = 2'd2;
    localparam S3 = 2'd3;

    //============================================================
    // 状态寄存器
    //============================================================
    reg [1:0] r_state;
    reg [1:0] r_next_state;

    //============================================================
    // 第一段:状态寄存器
    //============================================================
    always @(posedge i_clk or negedge i_rst_n) begin
        if (!i_rst_n)
            r_state <= S0;
        else
            r_state <= r_next_state;
    end

    //============================================================
    // 第二段:次态逻辑
    //============================================================
    always @(*) begin

        // 默认保持当前状态
        r_next_state = r_state;

        case (r_state)

            S0: begin
                r_next_state = S1;
            end

            S1: begin
                r_next_state = S2;
            end

            S2: begin
                r_next_state = S3;
            end

            S3: begin
                r_next_state = S0;
            end

            default: begin
                r_next_state = S0;
            end

        endcase
    end

    //============================================================
    // 第三段:输出逻辑
    //============================================================
    always @(*) begin

        // 默认灭
        o_led = 1'b0;

        case (r_state)

            S0: begin
                o_led = 1'b0;
            end

            S1: begin
                o_led = 1'b1;
            end

            S2: begin
                o_led = 1'b0;
            end

            S3: begin
                o_led = 1'b1;
            end

            default: begin
                o_led = 1'b0;
            end

        endcase
    end

endmodule

tb.v

`timescale 1ns/1ps

module tb;

    //============================================================
    // Clock
    //============================================================
    reg i_clk;

    initial begin
        i_clk = 1'b0;

        forever #5 i_clk = ~i_clk;
    end


    //============================================================
    // Reset
    //============================================================
    reg i_rst_n;

    initial begin

        // 初始复位
        i_rst_n = 1'b0;

        // 保持复位 20ns
        #20;

        // 释放复位
        i_rst_n = 1'b1;

    end


    //============================================================
    // DUT 输出
    //============================================================
    wire w_led_one;
    wire w_led_three;


    //============================================================
    // 一段式状态机
    //============================================================
    fsm_one_block u_fsm_one_block (
        .i_clk   (i_clk),
        .i_rst_n (i_rst_n),
        .o_led   (w_led_one)
    );


    //============================================================
    // 三段式状态机
    //============================================================
    fsm_three_block u_fsm_three_block (
        .i_clk   (i_clk),
        .i_rst_n (i_rst_n),
        .o_led   (w_led_three)
    );


    //============================================================
    // 仿真监视
    //============================================================
    initial begin

        $display("================================================");
        $display(" Time   Reset   OneBlock   ThreeBlock");
        $display("================================================");

        $monitor(
            "%5t    %b        %b           %b",
            $time,
            i_rst_n,
            w_led_one,
            w_led_three
        );

    end


    //============================================================
    // 自动检查两个状态机输出
    //============================================================
    always @(posedge i_clk) begin

        if (i_rst_n) begin

            if (w_led_one !== w_led_three) begin

                $display(
                    "ERROR: time=%0t, one_block=%b, three_block=%b",
                    $time,
                    w_led_one,
                    w_led_three
                );

            end

        end

    end


    //============================================================
    // 仿真结束
    //============================================================
    initial begin

        #120;

        $display("================================================");
        $display("Simulation finished.");
        $display("================================================");

        $finish;

    end

endmodule

测试

在这里插入图片描述

一段式:
STATE : S0  S1   S2   S3   S0   S1  S2  
LED :____________|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾
 
三段式:
STATE :   S0   S1   S2   S3   S0   S1   S2   S3
STATE':   S1   S2   S3   S0   S1   S2   S3   S0
LED  : ________|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐