【FPGA基础学习】状态机思想实现流水灯

目录

一、用状态机实现LED流水灯

1.状态机思想简介

1. 1基本概念

​ 状态机(Finite State Machine, FSM)是一种用于描述系统行为及其状态转换的数学模型。它将系统抽象为有限个状态 ,并通过事件触发 实现状态间的迁移,同时可能伴随特定的动作 。其核心思想是"基于状态的逻辑控制",适用于具有明确阶段性和条件依赖性的系统

1.2.核心要素

​ 现态(Current State):系统当前所处的状态。

​ 事件(Event):触发状态迁移的条件(如用户输入、传感器信号等)

​ 动作(Action):状态迁移时执行的操作(如开启设备、发送数据等)

​ 次态(Next State):事件触发后系统将进入的新状态

1.3分类与模型

​ Moore型:输出仅由当前状态决定(如交通信号灯的红绿灯切换)

​ Mealy型:输出由当前状态和输入共同决定(如网络协议中的应答机制)

​ 确定型(DFA):每个状态对同一事件有唯一迁移路径

​ 非确定型(NFA):同一事件可能触发多个迁移路径,需额外逻辑处理

2.LED流水灯

核心代码如下:

verilog 复制代码
module led_flow(
    input clk,          // 50MHz时钟
    input rst_n,        // 复位信号(低有效)
    output reg [7:0] led
);
    // 状态定义(8个状态)
    localparam [2:0] S0=0, S1=1, S2=2, S3=3, S4=4, S5=5, S6=6, S7=7;
    reg [2:0] state;
    reg [24:0] cnt;
    wire en = (cnt == 25'd24_999_999); // 分频使能

    // 分频计数器
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) cnt <= 0;
        else if (en) cnt <= 0;
        else cnt <= cnt + 1;
    end

    // 状态机主逻辑
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= S0;
            led <= 8'b00000001; // 初始状态S0点亮LED0
        end
        else if (en) begin
            case(state)
              S0: begin led <= 8'b00000010; state <= S1; end  //S0→S1(第2个LED亮)
   			 S1: begin led <= 8'b00000100; state <= S2; end  //S1→S2(第3个LED亮)
              S2: begin led <= 8'b00001000; state <= S3; end  //S2→S3(第4个LED亮)
    		 S3: begin led <= 8'b00010000; state <= S4; end  //S3→S4(第5个LED亮)
   			 S4: begin led <= 8'b00100000; state <= S5; end  //S4→S5(第6个LED亮)
   			 S5: begin led <= 8'b01000000; state <= S6; end  //S5→S6(第7个LED亮)
    		 S6: begin led <= 8'b10000000; state <= S7; end  //S6→S7(第8个LED亮)
   			 S7: begin led <= 8'b00000001; state <= S0; end  //S7→S0(第1个LED亮,循环)
    		default: state <= S0;                          // 默认回到初始状态
            endcase
        end
    end
endmodule

仿真文件编写:

verilog 复制代码
`timescale 1ns / 1ps
module led_flow_tb;
    // 输入信号
    reg clk;          // 50MHz时钟
    reg rst_n;        // 复位信号(低有效)
    // 输出信号
    wire [7:0] led;   // LED输出
    
    // 实例化被测模块
    led_flow uut (
        .clk(clk),
        .rst_n(rst_n),
        .led(led)
    );
    
    // 1. 生成50MHz时钟
    initial begin
        clk = 0;
        forever #10 clk = ~clk; // 周期20ns(50MHz)
    end
    
    // 2. 控制复位信号
    initial begin
        rst_n = 0;    // 初始复位有效
        #100;         // 保持100ns复位
        rst_n = 1;    // 释放复位
        #2000000000;  // 仿真运行2秒(覆盖多个状态循环)
        $finish;      // 结束仿真
    end
    
    // 3. 监视信号变化
    initial begin
        $monitor("Time=%tns | State=%d | LED=%b", $time, uut.state, led);
    end
endmodule

仿真:

因为我流水灯的周期太长了,没有办法显示全,所以调整分频

verilog 复制代码
  wire en = (cnt == 25'd4_999_999); // 分频使能

可以看到仿真结果符合预期

引脚绑定:

实现效果:

led 流水灯状态机思想

二、CPLD与FPGA

1.技术区别
特性 CPLD FPGA
架构 基于乘积项(Product Term)结构,逻辑块较大 基于查找表(LUT)结构,逻辑单元粒度小
资源规模 较小(通常<10万门) 较大(可达数百万门)
时序特性 延时均匀,可预测性强 延时依赖布局布线,需时序约束优化**7
编程方式 非易失性(EEPROM/Flash),无需外部配置 易失性(SRAM),需外部存储器加载配置
功耗 静态功耗低,适合低功耗场景 动态功耗高,适合高性能计算
重构灵活性 配置固定,不支持动态重构 支持实时动态重构
2.应用场景
  • CPLD

    • 控制密集型系统:如接口转换(UART转SPI)、简单状态机、工业控制逻辑
    • 低功耗场景:电池供电设备,需长期稳定运行
    • 快速原型验证:中小规模逻辑的快速实现
  • FPGA

    • 数据密集型系统:图像处理、高速通信(如PCIe)、数字信号处理(DSP)

    • 复杂算法加速:深度学习推理、加密解密算法

    • 可重构计算:航天电子设备需在轨更新功能

3.设计选择建议
  • 若需简单逻辑控制且对成本敏感,选CPLD

  • 若需高性能并行处理或动态重构,选FPGA

三、HDLbits组合逻辑题目

HDLBits(点击进入练习) 是一个专注于 Verilog硬件描述语言(HDL)学习和实践 的在线平台,由多伦多大学开发,旨在通过小型电路设计习题帮助用户:夯实Verilog基础、理解数字电路设计思想(例如状态机设计、时序约束优化等关键概念)、衔接实际项目(平台题目与FPGA开发中的常见模块,如FIFO、接口控制器,高度相关)

题目1:简单电路B

verilog 复制代码
module top_module ( input x, input y, output z );
	assign z = ~(x ^ y);
endmodule

题目2:Two gates

verilog 复制代码
module top_module (
    input in1,
    input in2,
    input in3,
    output out);
    assign out=(~(in1^in2))^in3;
endmodule

题目3:7420chip

verilog 复制代码
module top_module ( 
    input p1a, p1b, p1c, p1d,
    output p1y,
    input p2a, p2b, p2c, p2d,
    output p2y );
	assign p1y=~(p1a&p1b&p1c&p1d);
    assign p2y=~(p2a&p2b&p2c&p2d);
endmodule

题目4:真值表

verilog 复制代码
module top_module( 
    input x3,
    input x2,
    input x1,  // three inputs
    output f   // one output
);
    wire and1 = (~x3 & x2 & ~x1);
    wire and2 = (~x3 & x2 & x1);
    wire and3 = (x3 & ~x2 & x1);
    wire and4 = (x3 & x2 & x1);

	assign f = and1 | and2 | and3 | and4;
endmodule

题目5:加法器

verilog 复制代码
 module top_module (
    input [3:0] x, 
    input [3:0] y, 
    output [4:0] sum);
    assign sum = x + y;
endmodule

参考链接:

百度词条CPLD与FPGA

CPLD与FPGA的用途及其区别

百度百科状态机

聊一聊状态机

相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
ZPC82106 天前
docker 镜像备份
人工智能·算法·fpga开发·机器人
ZPC82106 天前
docker 使用GUI ROS2
人工智能·算法·fpga开发·机器人
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛6 天前
计算机系统概论——校验码
学习
babe小鑫6 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms6 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下6 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。6 天前
2026.2.25监控学习
学习