FPGA实现LED流水灯

一、在VsCode中写代码

1、建立工程项目文件water_led.v文件

2、打开项目文件,创建三个目录

3、打开文件trl,创建water_led.v文件

4、打开文件tb,创建water_led_tb.v文件

5、用VsCode打开water_led.v文件,编写源代码

复制代码
module water_led (
    input                  clk,       // 输入时钟(50 MHz)
    input                  rst_n,     // 复位信号(低电平有效)
    input                  pause_sw,  // 暂停开关(高电平暂停,低电平运行)
    output reg [5:0]       led        // 输出 6 个 LED
);
​
parameter T = 50_000_000;             // 计数器最大值,用于生成 1 秒定时
​
reg [2:0] cstate;                     // 现态
reg [2:0] nstate;                     // 次态
​
// 状态划分
localparam state_led0 = 0;            // LED0 亮
localparam state_led1 = 1;           // LED1 亮
localparam state_led2 = 2;           // LED2 亮
localparam state_led3 = 3;           // LED3 亮
localparam state_led4 = 4;           // LED4 亮
localparam state_led5 = 5;           // LED5 亮
​
reg [25:0] cnt = 0;                   // 计时器赋初值为 0
​
// 计数器模块
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        cnt <= 0;                     // 按下复位键,清零
    else if (cnt == T - 1)            // 计时器达到最大值,清零重新计数
        cnt <= 0;
    else if (!pause_sw)               // 如果未暂停,计数器继续计数
        cnt <= cnt + 1;
end
​
// 第一段:现态跟随次态,时序逻辑,非阻塞赋值
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        cstate <= state_led0;         // 复位键被按下,当前状态设置为 LED0 亮
    else if (!pause_sw)               // 如果未暂停,更新状态
        cstate <= nstate;
end
​
// 第二段:组合逻辑,阻塞赋值
always @(*) begin
    if (!rst_n)
        nstate = state_led0;          // 复位时回到初始状态
    else
        case (cstate)
            state_led0: begin
                if (cnt == T - 1)      // 该状态持续时间为 1 秒,1 秒后跳转到下一个状态
                    nstate = state_led1;
                else
                    nstate = state_led0;
            end
            state_led1: begin
                if (cnt == T - 1)
                    nstate = state_led2;
                else
                    nstate = state_led1;
            end
            state_led2: begin
                if (cnt == T - 1)
                    nstate = state_led3;
                else
                    nstate = state_led2;
            end
            state_led3: begin
                if (cnt == T - 1)
                    nstate = state_led4;
                else
                    nstate = state_led3;
            end
            state_led4: begin
                if (cnt == T - 1)
                    nstate = state_led5;
                else
                    nstate = state_led4;
            end
            state_led5: begin
                if (cnt == T - 1)
                    nstate = state_led0;
                else
                    nstate = state_led5;
            end
            default: nstate = state_led0; // 默认状态
        endcase
end
​
// 第三段:跟随状态输出
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        led <= 6'b000001;              // 复位时点亮第一个 LED
    else
        case (cstate)
            state_led0: led <= 6'b000001;
            state_led1: led <= 6'b000010;
            state_led2: led <= 6'b000100;
            state_led3: led <= 6'b001000;
            state_led4: led <= 6'b010000;
            state_led5: led <= 6'b100000;
            default: led <= 6'b000001; // 默认状态
        endcase
end
​
endmodule

6、用VsCode打开water_led_tb.v文件,编写仿真代码

复制代码
`timescale 1ns / 1ps
​
module fsm3_led_tb;
​
    // 输入信号
    reg clk;         // 输入时钟(50 MHz)
    reg rst_n;       // 复位信号(低电平有效)
    reg pause_sw;    // 暂停开关(高电平暂停,低电平运行)
​
    // 输出信号
    wire [5:0] led;  // 6 个 LED 输出
​
    // 实例化被测模块
    fsm3_led uut (
        .clk(clk),
        .rst_n(rst_n),
        .pause_sw(pause_sw),
        .led(led)
    );
​
    // 生成时钟信号
    initial begin
        clk = 0;
        forever #10 clk = ~clk; // 50 MHz 时钟周期 = 20 ns
    end
​
    // 测试过程
    initial begin
        // 初始化信号
        rst_n = 0;      // 初始复位
        pause_sw = 0;   // 初始不暂停
        #20;            // 等待 20 ns
​
        // 释放复位信号
        rst_n = 1;
        #200;           // 等待一段时间观察初始状态
​
        // 测试正常流水灯效果
        pause_sw = 0;   // 不暂停
        #2_000_000;     // 运行 2 秒,观察 LED 变化
​
        // 测试暂停功能
        pause_sw = 1;   // 暂停
        #1_000_000;     // 停留 1 秒,观察 LED 是否保持不变
        pause_sw = 0;   // 恢复
        #2_000_000;     // 再次运行 2 秒,观察 LED 变化
​
        // 测试复位功能
        rst_n = 0;      // 触发复位
        #20;            // 等待复位完成
        rst_n = 1;      // 释放复位
        #200;           // 观察复位后的初始状态
​
        // 结束仿真
        $stop;
    end
​
endmodule

二、在Quartus中创建工程与仿真

1、打开Quartus,点击New Project Wizard

2、把工程保存在之前创造的prj文件里

3、添加之前在VsCode中写好的源码和仿真源码

4、选择芯片

5、选择仿真必要选项

其余为展示页面,均点击Next即可。

6、将源码设为顶层文件

7、分析与综合

8、设置water_led_tb.v文件

添加完后,一直点OK,完成设置。

9、仿真

10、点击最下方的sim,然后右键u_water_led,在选项中选择Add Wave

11、点击最下方的Wave,根据图片点击左下角的黑点消除文件前缀,这样看着舒服点。然后选中一个参数,再CTRL+A全选中参数,最后CTRL+G分组

12、重新开始

13、运行所有

分析仿真可知,结果大差不差,嘿嘿

14、完整编译运行一次,发现未报错,然后配置引脚,配置完成后再次编译

15、下载

16、演示

FPGA-状态机+分层次+流水灯

17、参考链接

【FPGA入门二】状态机+LED流水灯_状态机加一-CSDN博客

相关推荐
双料毒狼_s7 小时前
【FPGA实战】基于DE2-115实现数字秒表
fpga开发
Cynthia的梦13 小时前
FPGA学习-基于 DE2-115 板的 Verilog 分秒计数器设计与按键功能实现
fpga开发
9527华安21 小时前
Xilinx系列FPGA实现HDMI2.1视频收发,支持8K@60Hz分辨率,提供2套工程源码和技术支持
fpga开发·音视频·8k·hdmi2.1
泪水打湿三角裤1 天前
fpga:分秒计时器
fpga开发
奋斗的牛马1 天前
FPGA_AXI仿真回环(一)
fpga开发
LeeConstantine1 天前
FPGA FLASH烧写遇到的问题
fpga开发
禾川兴 132424006881 天前
国产芯片解析:龙讯HDMI Splitter系列:多屏共享高清
单片机·fpga开发·适配器模式
威视锐科技2 天前
软件定义无线电36
网络·网络协议·算法·fpga开发·架构·信息与通信
JINX的诅咒2 天前
CORDIC算法:三角函数的硬件加速革命——从数学原理到FPGA实现的超高效计算方案
算法·数学建模·fpga开发·架构·信号处理·硬件加速器