【FPGA学习】DE2-115实现LED流水灯

目录

一、引言

二、开发环境搭建

[1. 安装VSCode](#1. 安装VSCode)

三、模块化设计

[1. 顶层模块(LedBlink.v)](#1. 顶层模块(LedBlink.v))

[2. 分频模块(fenpin.v)](#2. 分频模块(fenpin.v))

[3. 显示模块(display.v)](#3. 显示模块(display.v))

四、代码实现

五、功能测试与验证

[1. 测试环境搭建](#1. 测试环境搭建)

[2. 测试过程](#2. 测试过程)

六、扩展功能(选做)

[1. 按键暂停与恢复功能](#1. 按键暂停与恢复功能)

​编辑

结果演示:

七、总结

八、参考链接


一、引言

又到了最常规的流水灯环节!通过在DE2-115开发板上实现一个LED流水灯实验,加深对Verilog HDL的理解,还能培养模块化设计的习惯。本文将详细介绍如何在DE2-115开发板上设计一个周期为1秒的6个LED跑马灯效果,并提供规范化的代码实现。

二、开发环境搭建

1. 安装VSCode

  • 在VSCode中安装Verilog-HDL/SystemVerilog插件,实现Verilog代码的语法高亮和自动补全功能。(安装这个功能的话在VScode中编程就不容易出错,很简单就可以实现修改、报错、提示等等!)亲测!!好用!!!

  • 文件芯片:EP4CE115F29C7

三、模块化设计

任务要求:

1)采用层次化设计,分别在VScdoe编程各代码文件,如top顶层模块(比如LedBlink.v)、分频模块(fenpin.v)、显示模块(display.v);

2)尽量采用计数器、状态机思想;

题目分析:

DE2-115 开发板搭载了一个50MHz 固定频率晶振,作为 FPGA 系统的核心时钟源。该晶振可产生稳定的周期性电信号,每秒震荡 50×10⁶次,为整个电路提供时序基准。

时钟周期(Clock Period)指时钟信号完成一个完整周期(如上升沿到下一个上升沿)的时间,计算公式为:

时钟周期=时钟频率1​

对于 50MHz 时钟:

周期=50×106Hz1​=20×10−9秒=20纳秒(ns)

功能目标 :1 秒内依次点亮 6 个 LED,即每个 LED 的点亮间隔为 1/6 秒(约 0.167 秒)

整体代码:

复制代码
module led_test(
    input wire clk,     // 50MHz时钟输入
    input wire rst_n,   // 复位信号,低电平有效
    
    output reg [5:0] led // 6个LED灯的状态
);
​
// 计数器,计数1s需要50_000_000个时钟周期
reg [25:0] cnt; 
​
// 计数器模块
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt <= 26'd0; // 复位时计数器归零
    end 
    else if (cnt == 50_000_000 - 1) begin // 计满1秒后复位
        cnt <= 26'd0;
    end 
    else begin
        cnt <= cnt + 1'd1; // 使用非阻塞赋值
    end 
end 
​
// LED状态更新逻辑:每次触发时先清零所有LED
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        led <= 6'b000000; // 复位时关闭所有LED
    end 
    else begin
        // 默认保持当前状态(非阻塞赋值)
        led <= led;
        
        if (cnt == 8_333_333 - 1) begin
            led <= 6'b000001; // 点亮第一个LED
        end
        else if (cnt == 16_666_666 - 1) begin
            led <= 6'b000010; // 点亮第二个LED
        end
        else if (cnt == 25_000_000 - 1) begin
            led <= 6'b000100; // 点亮第三个LED
        end
        else if (cnt == 33_333_333 - 1) begin
            led <= 6'b001000; // 点亮第四个LED
        end
        else if (cnt == 41_666_666 - 1) begin
            led <= 6'b010000; // 点亮第五个LED
        end
        else if (cnt == 50_000_000 - 1) begin
            led <= 6'b100000; // 点亮第六个LED
        end
    end 
end 
​
endmodule

1. 顶层模块(LedBlink.v)

  • 定义顶层模块,整合各个子模块,实现整体功能。

  • 顶层模块负责初始化和连接各个子模块,确保整个系统协调工作。

复制代码
  module LedBlink (
      input clk,        // 系统时钟信号
      input rst,        // 复位信号
      output [5:0] led  // 6个LED的输出信号
  );
      wire clk_1hz; // 1Hz的时钟信号

      // 实例化分频模块
      fenpin u_fenpin (
          .clk(clk),
          .rst(rst),
          .clk_out(clk_1hz)
      );

      // 实例化显示模块
      display u_display (
          .clk(clk_1hz),
          .rst(rst),
          .led(led)
      );
  endmodule

2. 分频模块(fenpin.v)

  • 设计分频模块,将系统时钟信号分频为1秒的时钟信号。

  • 使用计数器实现分频功能,确保时钟信号的稳定性和准确性。

复制代码
  module fenpin (
      input clk,          // 系统时钟信号
      input rst,          // 复位信号
      output reg clk_out  // 分频后的时钟信号
  );
      reg [24:0] counter; // 25位计数器,用于分频

      always @(posedge clk or posedge rst) begin
          if (rst) begin
              counter <= 0;   // 复位计数器
              clk_out <= 0;   // 复位输出时钟
          end else begin
              if (counter == 25'd49999999) begin
                  counter <= 0;       // 计数器溢出,重置计数器
                  clk_out <= ~clk_out; // 翻转输出时钟
              end else begin
                  counter <= counter + 1; // 计数器加1
              end
          end
      end
  endmodule

3. 显示模块(display.v)

  • 设计显示模块,控制6个LED的动态显示效果。

  • 使用状态机思想,实现LED的跑马灯效果。

    复制代码
    module display (
        input clk,        // 时钟信号
        input rst,        // 复位信号
        output reg [5:0] led // 6个LED的输出信号
    );
        reg [2:0] state; // 3位状态寄存器,用于状态机
    
        always @(posedge clk or posedge rst) begin
            if (rst) begin
                state <= 3'b000; // 复位状态
                led <= 6'b000001; // 初始状态,点亮第一个LED
            end else begin
                case (state)
                    3'b000: led <= 6'b000010; // 状态0,点亮第二个LED
                    3'b001: led <= 6'b000100; // 状态1,点亮第三个LED
                    3'b010: led <= 6'b001000; // 状态2,点亮第四个LED
                    3'b011: led <= 6'b010000; // 状态3,点亮第五个LED
                    3'b100: led <= 6'b100000; // 状态4,点亮第六个LED
                    3'b101: led <= 6'b000001; // 状态5,回到第一个LED
                    default: led <= 6'b000001; // 默认状态
                endcase
                state <= state + 1; // 状态机状态更新
            end
        end
    endmodule

四、代码实现

    • 使用一个25位计数器 counter,将50MHz的系统时钟分频为1Hz的时钟信号 clk_1hz

    • 每当计数器计数到49999999时,输出时钟信号翻转一次,实现1秒的周期。

  1. 显示模块

    • 使用一个3位状态寄存器 state,通过状态机控制6个LED的动态显示效果。

    • 每个状态对应一个LED的点亮,状态机在每个1Hz时钟周期更新状态。

    module FLED (
    input clk, // 系统时钟信号,通常为50MHz
    input rst, // 复位信号
    output reg [5:0] led // 6个LED的输出信号
    );
    // 分频模块:将50MHz的系统时钟分频为1Hz
    reg [24:0] counter; // 25位计数器,用于分频
    reg clk_1hz; // 1Hz的时钟信号,定义为reg类型

    复制代码
     always @(posedge clk or posedge rst) begin
         if (rst) begin
             counter <= 0;   // 复位计数器
             clk_1hz <= 0;   // 复位输出时钟
         end else begin
             if (counter == 25'd49999999) begin
                 counter <= 0;       // 计数器溢出,重置计数器
                 clk_1hz <= ~clk_1hz; // 翻转输出时钟
             end else begin
                 counter <= counter + 1; // 计数器加1
             end
         end
     end
    
     // 显示模块:控制6个LED的动态显示效果
     reg [2:0] state; // 3位状态寄存器,用于状态机
    
     always @(posedge clk_1hz or posedge rst) begin
         if (rst) begin
             state <= 3'b000; // 复位状态
             led <= 6'b000001; // 初始状态,点亮第一个LED
         end else begin
             case (state)
                 3'b000: led <= 6'b000010; // 状态0,点亮第二个LED
                 3'b001: led <= 6'b000100; // 状态1,点亮第三个LED
                 3'b010: led <= 6'b001000; // 状态2,点亮第四个LED
                 3'b011: led <= 6'b010000; // 状态3,点亮第五个LED
                 3'b100: led <= 6'b100000; // 状态4,点亮第六个LED
                 3'b101: led <= 6'b000001; // 状态5,回到第一个LED
                 default: led <= 6'b000001; // 默认状态
             endcase
             state <= state + 1; // 状态机状态更新
         end
     end

    endmodule
    //博主这个代码有点小瑕疵还待完善

代码成功跑通啦!!!

五、功能测试与验证

1. 测试环境搭建

  • 介绍如何在DE2-115开发板上搭建测试环境,包括硬件连接和软件配置。

  • 文件芯片:EP4CE115F29C7

  • 说明如何将编译后的代码下载到开发板上进行测试。

  • 配置芯片:

烧录,运行:

2. 测试过程

1s周期流水灯

运行视频

六、扩展功能(选做)

1. 按键暂停与恢复功能

  • 介绍如何在流水灯实验中增加按键暂停和恢复功能。

  • 提供扩展功能的代码实现,解释按键功能的逻辑和实现方法。

  • DE2-115 提供了四个按钮开关,每个按钮开关都通过一个施 密特触发器进行了去抖动处理。四个施密特触发器的输出信 号,分别为KEY0、KEY1、KEY2、KEY3,直接连接到了Cyclone

  • IV E FPGA。当按钮没有 被按下的时候,它的输出是高电平,按下去则给出一个低电平

KEY0:复位

KEY1:按下暂停

代码实现如下:

复制代码
module LedBlink(
    input wire clk,       // 50MHz时钟输入
    input wire rst_n,     // 复位信号,低电平有效
    input wire stop_n,      //停止信号
    output reg [5:0] led  // 6个LED灯输出
);
    reg [25:0] cnt;       // 26位计数器,用于计数1秒周期
    // 计数器模块
    always @(posedge clk or negedge rst_n or negedge stop_n) begin // posedge是指clk的上升沿 negedge是指rst_n的下降沿
        if (!rst_n) begin
            cnt <= 26'd0; // 复位时,计数器从0开始计数
            led <= 6'b000001; // 复位时,第一个LED亮
			end
		  else if (!stop_n) begin
				cnt <= cnt;
				led <= led;
			end 
		  else if (cnt == 50_000_000 - 1) begin // 计数到50,000,000 - 1
            cnt <= 26'd0; // 重置计数器
            led <= {led[4:0], led[5]}; // 循环右移一位,保持流水灯效果
        end 
		  else begin
            cnt <= cnt + 1; // 增加计数器
        end
    end 
endmodule

结果演示:

运行结果如视频:

按键控制流水灯暂停

七、总结

在本次流水灯模块设计实践中,我们系统掌握了从硬件资源分析到软件代码实现的全流程开发方法,深度理解了数字电路中时序控制与逻辑设计的核心原理。学习到很多内容,掌握了多种方式点亮LED,实现LED灯光管理和控制,按键控制。

八、参考链接

FPGA学习(二)------实现LED流水灯_de2-115引脚分配-CSDN博客

[FPGA基础学习]实现流水灯与按键暂停_上升沿fpga使用按键控制暂停与启动-CSDN博客

相关推荐
西岭千秋雪_4 小时前
计算机网络学习笔记:TCP可靠传输实现、超时重传时间选择
网络·笔记·学习·tcp/ip·计算机网络
小开心大王4 小时前
嵌入式学习笔记——day36-多路IO复用
笔记·学习
炽天使3285 小时前
Git 日常操作流程(备查)
git·学习
唐人街都是苦瓜脸5 小时前
学习Oracle------高可用架构解析
学习·oracle·架构
FPGA_ADDA7 小时前
宽带中频10.4G采集卡
fpga开发·信号处理·高速数据采集·10g采集卡
全栈小57 小时前
【数据库】在线体验KingbaseES平台,零门槛学习,并快速体验Oracle增改查全基础功能
数据库·学习·oracle
来两个炸鸡腿7 小时前
【Datawhale组队学习202506】YOLO-Master task02 YOLO系列发展线
python·深度学习·学习·yolo
ehiway8 小时前
中科亿海微SoM模组——FPGA+DSP核心板
fpga开发
点灯大师李9 小时前
PL端软核FIFO读写
fpga开发