verilog状态机输出方波

参考

verilog状态机.csdn

有限状态机的九元组定义.csdn

状态机顺序化描述------串口与 AXI4 协议流程建模.csdn

目标

时钟 状态 LED
Reset S0 0 灭
第1拍 S1 1 亮
第2拍 S2 0 灭
第3拍 S3 1 亮
第4拍 S0 0 灭
第5拍 S1 1 亮
第6拍 S2 0 灭
第7拍 S3 1 亮

一段式

verilog 复制代码
`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

三段式

verilog 复制代码
`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

verilog 复制代码
`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

测试

bash 复制代码
一段式:
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  : ________|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____
相关推荐
zyf1044164 小时前
暑期实践日志 Day47:复盘第七章内容,规整对应成果
学习·计算机网络·剪辑·暑期实践·课题任务
传奇开心果编程4 小时前
【Rust入门知识点学与练】第10课:Option 和 Result(错误处理入门)
开发语言·学习·rust
喵的前端路4 小时前
《EDVAC》学习记录(第二部分)
学习
lee_curry5 小时前
AI Agent 工程师完整学习路线(面向生产级项目与面试)
人工智能·学习·ai·面试·agent
小毛驴8505 小时前
前端开发学习路线可以分为几个层次
学习
star learning white5 小时前
STM32入门学习3
stm32·单片机·学习
浔溺5 小时前
al+大数据每日学习笔记31
大数据·笔记·学习
!!!!8135 小时前
AI Coding学习
学习
山岚的运维笔记5 小时前
mysql 专业笔记 -- 第 8 章:使用变量
运维·数据库·笔记·后端·学习·mysql·dba
XiHongShi20165 小时前
cpuz分享,建议保存
单片机·学习