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  : ________|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____
相关推荐
一隅论数智4 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
XiHongShi20164 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
爱吃苹果的日记本4 天前
离散数学第六课
学习·离散数学
AI职业加油站4 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
奇思妙想聪明勤奋的小羊4 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
霍霍的袁4 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
彧azz4 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
我爱cope4 天前
【操作系统 | 计算机硬件:CPU、内存与 I/O 如何支撑操作系统?】
学习·操作系统