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博客

相关推荐
Terasic友晶科技1 小时前
【教程】Agilex 5 SoC 的两种启动模式的开发演示(一)(FPGA Configuration First)
fpga开发·agilex 5 soc
ALINX技术博客1 小时前
【黑金云课堂】FPGA技术教程Vitis开发:SD卡WAV文件读取音频播放实验
fpga开发·音视频
仲南音2 天前
Xilinx FPGA——时钟IP核MMCM、PLL
fpga开发
I'm a winner3 天前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper20203 天前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
Eloudy3 天前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia3 天前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper20203 天前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
你是我的解忧王子4 天前
嵌入式 ADC采样 原始数据分析上层(平均值 波动率 正态分布 线性补偿 系统误差)
fpga开发·数据挖掘·数据分析
9527华安4 天前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi