[FPGA基础学习]实现流水灯与按键暂停

FPGA实现LED流水灯

1.vscode的安装和使用

vscode下载

Visual Studio Code - Code Editing. Redefined

vscode插件(Verilog-HDL/SystemVerilog)下载
quartus绑定vscode

2.用6个LED完成周期为1秒的跑马灯效果

流水灯模块设计

时钟输入

DE2-115开发板配备了一个固定的时钟源。该开发板内置了一个50MHz的晶振,这意味着开发板上有一个能够产生每秒50百万个周期信号的振荡器或时钟发生器,用于驱动FPGA(现场可编程门阵列)芯片

时钟周期

时钟周期是时钟信号的一个完整波形(从上升沿到下一个上升沿或下降沿到下一个下降沿)所需的时间,可以通过下面的公式计算:

对于50MHz的时钟频率,时钟周期为20纳秒。

1s内点亮6个led,即等待前一个灯熄灭后1/6s=0.167s点亮下一个灯,所以代码编写如下

代码编写(计数器版本)
复制代码
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

我需要将现有的代码拆分为至少两个模块:一个计数器模块和一个LED控制模块,然后创建一个顶层模块来连接这两个模块

顶层模块

复制代码
module led_test(
    input wire clk,
    input wire rst_n,
    output wire [5:0] led
);
// 连接计数器与LED控制器
wire [25:0] cnt_net;
​
counter counter_inst (
    .clk(clk),
    .rst_n(rst_n),
    .cnt(cnt_net)
);
​
led_controller led_ctrl_inst (
    .clk(clk),
    .rst_n(rst_n),
    .cnt_value(cnt_net),
    .led(led)
);
​
endmodule

LED控制模块 (led_controller.v)

复制代码
module led_controller(
    input wire clk,
    input wire rst_n,
    input wire [25:0] cnt_value,
    output reg [5:0] led
);
// LED状态更新逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        led <= 6'b000000;
    end else begin
        led <= led; // 默认保持当前状态
        // 顺序点亮LED(每个LED间隔约1/6秒)
        case (1'b1)
            (cnt_value == 26'd8_333_332): led <= 6'b000001;
            (cnt_value == 26'd16_666_665): led <= 6'b000010;
            (cnt_value == 26'd24_999_998): led <= 6'b000100;
            (cnt_value == 26'd33_333_331): led <= 6'b001000;
            (cnt_value == 26'd41_666_664): led <= 6'b010000;
            (cnt_value == 26'd49_999_997): led <= 6'b100000;
            default: ;
        endcase
    end
end
endmodule

计数器模块

复制代码
module counter(
    input wire clk,
    input wire rst_n,
    output reg [25:0] cnt
);
// 计数1秒(50MHz时钟)
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        cnt <= 26'd0;
    else if (cnt == 26'd49_999_999) // 50M-1
        cnt <= 26'd0;
    else
        cnt <= cnt + 1'b1;
end
endmodule
管脚绑定

使用的LEDR[0]~[5]这六个led灯来进行实验,LED引脚配置说明如下:

管脚绑定如下:

效果展示

2.(选做)增加流水灯的按键暂停、按键恢复功能

使用按钮开关

DE2-115 提供了四个按钮开关,每个按钮开关都通过一个施 密特触发器进行了去抖动处理。四个施密特触发器的输出信 号,分别为KEY0、KEY1、KEY2、KEY3,直接连接到了Cyclone IV E FPGA。当按钮没有 被按下的时候,它的输出是高电平,按下去则给出一个低电平

我选择KEY0做为复位按钮,KEY1作为控制led流水灯暂停的按钮

代码编写
复制代码
module flow_led_pause(
    input         clk,       // 50MHz时钟
    input         rst_n,     // 异步复位(低有效)
    input         key_pause, // 暂停/继续按键(低有效)
    output reg [5:0] led     // 6位LED输出
);
​
// 参数定义
parameter CLK_FREQ = 50_000_000; // 50MHz时钟
parameter LED_INTERVAL = CLK_FREQ / 6; // 每个LED亮0.1667秒
​
// 主计数器(1秒周期)
reg [25:0] cnt;
wire cnt_max = (cnt == LED_INTERVAL - 1);
​
// 按键消抖(两级寄存器同步)
reg [1:0] key_sync;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) key_sync <= 2'b11;
    else key_sync <= {key_sync[0], key_pause};
end
wire pause_trig = (key_sync == 2'b10); // 下降沿检测
​
// 暂停标志
reg pause_flag;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) pause_flag <= 1'b0;
    else if (pause_trig) pause_flag <= ~pause_flag; // 按键切换状态
end
​
// LED状态计数器(0~5循环)
reg [2:0] led_state;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt <= 0;
        led_state <= 0;
    end
    else if (!pause_flag) begin
        if (cnt_max) begin
            cnt <= 0;
            led_state <= (led_state == 3'd5) ? 0 : led_state + 1;
        end
        else cnt <= cnt + 1;
    end
end
​
// LED输出逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) led <= 6'b000001; // 复位后LED0亮
    else if (!pause_flag) begin
        case (led_state)
            3'd0: led <= 6'b000001; // LED0
            3'd1: led <= 6'b000010; // LED1
            3'd2: led <= 6'b000100; // LED2
            3'd3: led <= 6'b001000; // LED3
            3'd4: led <= 6'b010000; // LED4
            3'd5: led <= 6'b100000; // LED5
            default: led <= led;
        endcase
    end
end
​
endmodule
管脚绑定

按钮开关配置说明如下:

管脚绑定如下:

效果展示

flow

参考链接:

vscode安装+配置+使用+调试【保姆级教程】

VSCode配置Verilog/SystemVerilog环境(二)插件安装

FPGA点亮led

led流水灯

FPGA学习------按键控制LED流水灯(附源码 无按键消抖版本)

相关推荐
bnsarocket4 小时前
Verilog和FPGA的自学笔记2——点亮LED
笔记·fpga开发·verilog·自学
易享电子9 小时前
基于单片机智能台灯(调光,时钟)系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
电子凉冰10 小时前
FPGA强化-串口RS485
fpga开发
ShiMetaPi11 小时前
操作【GM3568JHF】FPGA+ARM异构开发板 使用指南:音频接口
arm开发·嵌入式硬件·fpga开发·rk3568
码不停蹄Zzz12 小时前
xdma IP使用教程1-xdma ip核配置
网络协议·tcp/ip·fpga开发
易享电子20 小时前
基于单片机电器断路器保护器系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
璞致电子1 天前
fpga开发板ZYNQ 璞致 PZ7010/7020 邮票孔核心板简介-ZYNQ7000系列小系统学习板
linux·嵌入式硬件·学习·fpga开发·fpga·fpga开发板·xilinx开发板
greatofdream1 天前
HDLBit 个人记录
fpga开发
ARM+FPGA+AI工业主板定制专家1 天前
基于JETSON/RK3588机器人高动态双目视觉系统方案
人工智能·机器学习·fpga开发·机器人·自动驾驶
li星野2 天前
打工人日报#20251010
笔记·程序人生·fpga开发·学习方法