FPGA开发入门:盘古1K按键控制LED实验详解
1. 盘古1K开发板按键控制LED实验概述
盘古1K开发板作为国产FPGA学习的热门平台,其板载资源设计充分考虑了初学者的实操需求。本次实验聚焦最基础的GPIO控制场景——通过按键控制LED灯状态变化,这是嵌入式开发入门的"Hello World"级实验,但其中蕴含着硬件设计的关键思维模式。
开发板上的LED和按键通常采用共阳极或共阴极设计。根据紫光同创PGC系列开发套件的设计惯例,盘古1K很可能采用共阳极连接(LED阳极通过限流电阻接VCC,阴极接IO口)。这意味着当IO口输出低电平时LED点亮,高电平时熄灭。按键则通常采用上拉设计,未按下时IO口检测到高电平,按下时通过接地变为低电平。
注意:实际操作前务必查阅开发板原理图确认具体电路设计,错误的电平假设会导致实验失败。部分开发板可能设计有防反接保护电路,这会影响IO口的驱动能力计算。
2. 实验环境搭建与工程创建
2.1 开发工具链准备
使用Pango Design Suite(PDS)进行开发,这是紫光同创官方推出的FPGA开发环境。建议安装最新稳定版本(当前为PDS 2022.1),安装时需注意:
- 选择完整安装以获取所有器件支持
- 安装USB驱动以保证开发板识别
- 配置License文件(社区版有功能限制)
2.2 新建工程关键步骤
- 创建新工程时选择正确的器件型号:PGC1KG-LPG100
- 设置顶层模块名为
key_led_ctrl - 添加约束文件时选择"Create File Later",后续需手动编写IO约束
// 示例:顶层模块框架代码 module key_led_ctrl( input wire clk, // 系统时钟 input wire rst_n, // 复位信号(低有效) input wire key_in, // 按键输入 output reg led_out // LED输出 ); // 功能代码将在此添加 endmodule3. 硬件电路设计与信号处理
3.1 按键消抖实现方案
机械按键存在5-10ms的抖动现象,必须进行消抖处理。推荐两种实现方式:
方案一:硬件消抖
按键 -- 10k上拉电阻 --+-- 100nF电容 -- GND | IO口成本低但占用PCB面积,适合固定电路设计。
方案二:软件消抖(推荐)采用状态机实现,Verilog代码示例:
localparam DEBOUNCE_CNT = 20'd500000; // 10ms@50MHz always @(posedge clk or negedge rst_n) begin if(!rst_n) begin key_stable <= 1'b1; key_cnt <= 20'd0; end else begin if(key_raw != key_stable) begin key_cnt <= key_cnt + 1; if(key_cnt == DEBOUNCE_CNT) begin key_stable <= key_raw; key_cnt <= 20'd0; end end else begin key_cnt <= 20'd0; end end end3.2 LED驱动电路设计
典型LED驱动参数计算:
- 红色LED正向压降:≈2V
- 工作电流:5-10mA
- 限流电阻计算:(VCC - Vf)/I = (3.3V-2V)/0.01A = 130Ω
实测技巧:使用万用表测量实际LED压降,不同颜色LED的Vf差异较大。蓝色/白色LED通常需要3V以上驱动电压。
4. Verilog代码实现与优化
4.1 基础功能实现
实现按键按下时LED亮,松开时灭:
always @(posedge clk or negedge rst_n) begin if(!rst_n) led_out <= 1'b1; // 初始熄灭 else led_out <= ~key_stable; // 按键低有效,LED低电平点亮 end4.2 状态切换进阶实现
增加状态切换功能(按一次亮,再按一次灭):
reg led_state; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin led_state <= 1'b0; led_out <= 1'b1; end else if(key_stable_fall) begin // 检测按键下降沿 led_state <= ~led_state; led_out <= ~led_state; end end4.3 边缘检测技巧
可靠的状态切换需要精确的边缘检测:
reg [1:0] key_sync; always @(posedge clk) key_sync <= {key_sync[0], key_stable}; wire key_stable_rise = (key_sync == 2'b01); wire key_stable_fall = (key_sync == 2'b10);5. 约束文件编写与下载验证
5.1 IO约束文件示例
创建.pdc约束文件,根据原理图分配管脚:
# 系统时钟 50MHz set_pin_assignment { clk } { LOCATION = R7; IOSTANDARD = LVCMOS33; } # 复位按键(开发板已带上拉) set_pin_assignment { rst_n } { LOCATION = T7; IOSTANDARD = LVCMOS33; PULLTYPE = PULLUP; } # 用户按键K1 set_pin_assignment { key_in } { LOCATION = M5; IOSTANDARD = LVCMOS33; PULLTYPE = PULLUP; } # LED D1 set_pin_assignment { led_out } { LOCATION = E5; IOSTANDARD = LVCMOS33; DRIVESTRENGTH = 8; }5.2 下载调试常见问题
编程器无法识别:
- 检查USB驱动安装
- 尝试更换USB线(需支持数据传输)
- 确认开发板供电正常(电源指示灯亮)
LED不响应按键:
- 用示波器检查按键信号是否到达FPGA管脚
- 验证约束文件中的管脚编号是否正确
- 检查代码中信号名是否与约束文件一致
LED亮度异常:
- 测量LED两端电压确认驱动能力
- 检查约束文件中DRIVESTRENGTH设置
- 确认没有多个输出信号短路到同一LED
6. 扩展实验与进阶思考
6.1 多按键组合控制
实现两个按键控制LED的不同模式:
- K1:切换开关状态
- K2:长按调节亮度(PWM控制)
PWM生成代码片段:
reg [7:0] pwm_cnt; reg [7:0] duty_cycle; always @(posedge clk) pwm_cnt <= pwm_cnt + 1; always @(posedge clk) begin if(key2_pressed_long) begin if(duty_cycle < 8'd255) duty_cycle <= duty_cycle + 1; end end assign led_out = (pwm_cnt < duty_cycle) ? 1'b0 : 1'b1;6.2 状态机设计优化
使用Moore型状态机实现复杂控制逻辑:
typedef enum logic [1:0] { LED_OFF, LED_ON, LED_BLINK_SLOW, LED_BLINK_FAST } led_state_t; led_state_t current_state, next_state; // 状态转移逻辑 always @(posedge clk) begin case(current_state) LED_OFF: if(key_press) next_state = LED_ON; LED_ON: if(key_press) next_state = LED_BLINK_SLOW; // ...其他状态转移 endcase end6.3 时序约束分析
添加时序约束保证可靠性:
create_clock -name clk -period 20 [get_ports clk] set_input_delay -clock clk 2 [get_ports key_in] set_output_delay -clock clk 1 [get_ports led_out]在完成基础实验后,可以尝试将工程移植到其他兼容开发板(如粤嵌GEC6818),注意不同平台的时钟频率、IO电压等参数差异。实际项目中,这种按键LED控制逻辑可扩展为设备状态指示、用户输入检测等实用功能。
