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

FPGA实现LED流水灯

1.vscode的安装和使用

vscode下载

Visual Studio Code - Code Editing. Redefined

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

image-20250315124141272

quartus绑定vscode

image-20250315122510088

image-20250315122531803

image-20250315122646581

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

流水灯模块设计

时钟输入

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

时钟周期

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

image-20250312171741312

对于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引脚配置说明如下:

image-20250312163700788

管脚绑定如下:

image-20250315122405289

效果展示

flow_led

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

使用按钮开关

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

image-20250312164218485

我选择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
管脚绑定

按钮开关配置说明如下:

image-20250312164415043

管脚绑定如下:

image-20250315140622394

效果展示

flow

参考链接:

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

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

FPGA点亮led

led流水灯

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值