1. 实验目标与硬件准备
这次我们要在Quartus 13.1环境下,用FPGA实现一个带速度调节功能的LED流水灯。相比基础流水灯实验,这次增加了外部按键控制功能,让LED流动速度可以实时调整。这个实验特别适合刚接触FPGA的朋友,既能巩固Verilog基础语法,又能学习人机交互设计。
我用的是黑金AX4010开发板(主控芯片EP4CE10F17C8N),你需要准备:
- 安装好Quartus 13.1的电脑(建议D盘新建英文路径文件夹存放工程)
- USB-Blaster下载器
- 开发板配套的电源线
- 杜邦线(用于连接按键引脚)
注意:不同开发板的LED电路可能不同,我的板子是共阴接法,高电平点亮LED。记得先查看你的原理图确认电路结构。
2. 工程创建与模块设计
2.1 新建Quartus工程
打开Quartus点击File→New Project Wizard:
- 工程路径选择之前创建的英文文件夹
- 芯片型号选择EP4CE10F17C8N
- 取消勾选"Add Files"(我们后续手动添加)
2.2 设计关键模块
这次需要两个核心模块:
- 分频计数器:将50MHz系统时钟分频为可调节的低频信号
- 按键检测:识别外部按键动作并调整分频系数
新建Verilog文件时,建议使用有意义的命名,比如led_flow_speed.v。我见过新手直接命名为"test.v",结果后期找文件时特别混乱。
3. Verilog代码实现
3.1 顶层模块设计
module led_flow_speed ( input clk, // 50MHz系统时钟 input rst_n, // 复位信号(低有效) input key_speed, // 速度调节按键 output reg [3:0] led // LED输出 ); // 参数定义 parameter FAST_SPEED = 24_999_999; // 快节奏计数上限 parameter SLOW_SPEED = 49_999_999; // 慢节奏计数上限 // 内部信号 reg [31:0] counter; reg [31:0] speed_set = FAST_SPEED; // 默认快速 wire key_pressed;3.2 按键消抖模块
机械按键会有抖动问题,需要做消抖处理:
// 按键消抖逻辑(20ms延时) reg [19:0] key_delay; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin key_delay <= 20'd0; end else begin key_delay <= {key_delay[18:0], key_speed}; end end assign key_pressed = (key_delay == 20'hFFFFF);3.3 速度调节逻辑
通过按键切换两种速度模式:
always @(posedge clk or negedge rst_n) begin if (!rst_n) begin speed_set <= FAST_SPEED; end else if (key_pressed) begin speed_set <= (speed_set == FAST_SPEED) ? SLOW_SPEED : FAST_SPEED; end end3.4 LED流水控制
always @(posedge clk or negedge rst_n) begin if (!rst_n) begin counter <= 32'd0; led <= 4'b0001; end else begin if (counter >= speed_set) begin counter <= 32'd0; led <= {led[2:0], led[3]}; // 循环左移 end else begin counter <= counter + 1; end end end4. 引脚分配与下载
4.1 引脚约束
根据原理图分配引脚:
| 信号名 | 引脚号 | 说明 |
|---|---|---|
| clk | E1 | 50MHz时钟输入 |
| rst_n | M15 | 复位按键 |
| key_speed | P11 | 速度调节按键 |
| led[0] | N3 | LED0 |
| led[1] | P3 | LED1 |
| led[2] | M6 | LED2 |
| led[3] | L7 | LED3 |
在Pin Planner中分配完成后,建议导出.qsf文件备份,避免下次打开工程需要重新分配。
4.2 程序下载
- 编译工程(Processing → Start Compilation)
- 连接USB-Blaster到JTAG口
- 点击Programmer添加生成的.sof文件
- 勾选Program/Configure后点击Start
如果遇到驱动问题,可以尝试:
- 右键"我的电脑"→管理→设备管理器,更新USB-Blaster驱动
- 换USB接口或重新插拔下载器
5. 功能验证与调试技巧
上电后你应该能看到:
- LED默认快速流动(约0.5秒切换一次)
- 按下按键后变为慢速(约1秒切换一次)
- 再次按键恢复快速
常见问题排查:
- LED不亮:检查引脚分配是否正确,测量LED两端电压
- 按键无反应:用示波器检测按键信号是否正常传入FPGA
- 速度异常:在SignalTap中观察counter计数情况
如果想增加更多速度档位,可以修改代码:
// 增加中速档 parameter MID_SPEED = 39_999_999; // 修改速度切换逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin speed_set <= FAST_SPEED; end else if (key_pressed) begin case(speed_set) FAST_SPEED: speed_set <= MID_SPEED; MID_SPEED: speed_set <= SLOW_SPEED; default: speed_set <= FAST_SPEED; endcase end end6. 进阶优化建议
6.1 使用PLL精确分频
直接计数分频会有误差,可以调用Quartus的PLL IP核:
- Tools → MegaWizard Plug-In Manager
- 选择ALTPLL
- 设置输入50MHz,输出1Hz和2Hz两个时钟
6.2 添加LED渐变效果
通过PWM调节亮度实现呼吸灯效果:
reg [7:0] pwm_cnt; always @(posedge clk) pwm_cnt <= pwm_cnt + 1; assign led_out = (led_reg & (pwm_cnt < 8'd128));6.3 增加速度显示
可以用数码管显示当前速度档位,需要增加:
- 七段译码模块
- 数码管扫描电路
这个实验最让我印象深刻的是按键消抖的处理。刚开始做FPGA时,我直接检测按键信号,结果经常误触发。后来用移位寄存器实现消抖后,稳定性大幅提升。建议大家在开发板上多尝试不同的消抖时间参数,比如改成15ms或25ms,观察实际效果差异。