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
参考链接: