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  : ________|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____|‾‾‾‾|____
相关推荐
keyipatience3 小时前
JS学习笔记(2)数组,函数,作用域,对象
前端·javascript·笔记·学习·html
你想知道什么?3 小时前
词向量总结-学习笔记
人工智能·笔记·学习
yangmu32034 小时前
开发网站的完整流程:从0到1上线指南
运维·学习
hackchen4 小时前
LangChain 学习第 2 课 - 提示词模板(Prompt Template)
学习·langchain·prompt
Awh-5 小时前
ARM 裸机开发 DAY10 学习笔记
arm开发·笔记·学习
我命由我123455 小时前
动火作业极简理解
学习·职场和发展·产品运营·求职招聘·职场发展·产品经理·学习方法
andrsted6 小时前
练题簿助学教学:在线刷题、随堂考试,让一门课拥有自己的题库
学习·微信小程序·小程序·学习方法·刷题
apple_692658856 小时前
GitHub fqapp 番茄开源魔改版:小短剧+漫剧+听书聚合工具 安装指南使用
学习·开源
云半S一7 小时前
Agent 学习总结一
经验分享·笔记·学习·agent
chde2Wang7 小时前
Matplotlib数据可视化学习1
学习·matplotlib