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