FPGA按键消抖设计与紫光同创开发板实践

FPGA按键消抖设计与紫光同创开发板实践
1. 盘古PGX-Nano开发板硬件概览PG2L50H_MBG324这颗FPGA芯片是紫光同创Logos2系列的主力型号采用28nm工艺制程内部包含50K逻辑单元。开发板在设计上充分考虑了教学和原型验证需求板载资源包括集成USB-Blaster下载器省去外接下载器的麻烦通过Type-C接口即可完成程序烧录2MB SRAM型号通常为IS61WV102416BLL可作为高速数据缓存使用8位DAC芯片用于模拟信号生成测试ESP32-WROOM模组提供WiFi/蓝牙无线通信能力40pin扩展接口包含通用IO、电源和地线可连接各种外设模块开发板上的基础输入输出设备包括4个机械按键、8位拨码开关和4个LED指示灯这些将成为我们按键消抖实验的主要操作对象。特别需要注意的是按键电路采用典型的上拉电阻设计常态为高电平按下时接地变为低电平。2. 按键抖动现象的本质分析当机械按键的金属触点闭合或断开时由于弹性作用和空气电离等因素会在毫秒级时间内产生多次快速跳变的电信号。我用示波器实测过常见的6x6mm贴片按键抖动时间通常在5-20ms之间抖动次数可能达到十余次。这种抖动对数字电路会产生严重影响FPGA的时钟频率通常在MHz级别一个20ms的抖动窗口可能包含数万个时钟周期如果不处理抖动信号单次按键操作会被误判为多次触发在状态机设计中可能导致不可预测的状态跳转传统单片机常用软件延时消抖法但在FPGA中我们有更专业的解决方案。这里需要理解两个关键参数抖动时间Tbounce实测最大值约20ms稳定时间Tstable按键保持稳定状态的最小时间建议取50ms3. 基于状态机的硬件消抖设计3.1 状态转移图设计我们采用三段式状态机实现消抖IDLE - (下降沿触发) - CHECK_LOW - (持续低电平超过20ms) - STABLE_LOW STABLE_LOW - (上升沿触发) - CHECK_HIGH - (持续高电平超过20ms) - IDLE3.2 Verilog核心代码实现module debounce ( input clk, // 50MHz时钟 input key_in, // 原始按键输入 output reg key_out // 消抖后输出 ); parameter DEBOUNCE_TIME 1_000_000; // 20ms50MHz reg [19:0] counter; reg [1:0] state; always (posedge clk) begin case(state) 2b00: begin // IDLE if(!key_in) begin state 2b01; counter 0; end key_out 1b1; end 2b01: begin // CHECK_LOW if(!key_in) begin if(counter DEBOUNCE_TIME) begin state 2b10; key_out 1b0; end else counter counter 1; end else state 2b00; end 2b10: begin // STABLE_LOW if(key_in) begin state 2b11; counter 0; end end 2b11: begin // CHECK_HIGH if(key_in) begin if(counter DEBOUNCE_TIME) state 2b00; else counter counter 1; end else state 2b10; end endcase end endmodule3.3 时钟频率适配技巧开发板默认晶振为50MHz计算20ms需要的计数值为 50,000,000 Hz × 0.02 s 1,000,000 cycles如果使用其他频率时钟需要重新计算这个参数。建议在模块中增加参数化设计parameter CLK_FREQ 50_000_000; // 单位Hz localparam DEBOUNCE_CYCLES CLK_FREQ * 20 / 1000;4. 紫光PDS开发环境实操指南4.1 工程创建步骤打开PDS 2022.1开发环境选择File - New Project器件选择PG2L50H_MBG324封装为MBG324添加新建的Verilog源文件配置约束文件create_clock -name clk -period 20 [get_ports clk] set_property PACKAGE_PIN M5 [get_ports clk] set_property PACKAGE_PIN A3 [get_ports key_in] set_property PACKAGE_PIN B4 [get_ports key_out]4.2 常见编译错误处理Error: Cant place 50% of IOs检查约束文件中的引脚分配是否正确Warning: Clock net has no load确认时钟信号确实驱动了寄存器Critical Warning: No clocks defined检查create_clock约束是否添加4.3 在线调试技巧连接开发板后识别到USB-Blaster点击Programmer中的Auto Detect选择生成的bitstream文件勾选Verify和Program/Verify选项点击Start开始烧录5. 实验现象验证与进阶测试5.1 基础功能验证使用SignalTap II逻辑分析仪抓取波形时应该观察到原始按键信号(key_in)会有密集的抖动脉冲消抖后输出(key_out)是干净的方波每次按键只产生一个完整的高低电平变化5.2 性能极限测试逐步减小DEBOUNCE_TIME参数找到能稳定工作的最小值测试快速连续按键的响应延迟验证多个按键同时操作的相互影响5.3 实际应用扩展将消抖模块封装成IP核通过以下方式增强实用性module multi_debounce #( parameter WIDTH 4, parameter CLK_FREQ 50_000_000 )( input clk, input [WIDTH-1:0] keys_in, output [WIDTH-1:0] keys_out ); genvar i; generate for(i0; iWIDTH; ii1) begin: debounce_gen debounce #(.CLK_FREQ(CLK_FREQ)) u_debounce( .clk(clk), .key_in(keys_in[i]), .key_out(keys_out[i]) ); end endgenerate endmodule6. 工程经验与避坑指南时序约束必须完整即使简单设计也要添加基本的时钟约束否则PDS可能无法正确优化布局布线按键采样时钟选择不建议直接用50MHz时钟采样按键最佳实践是先通过时钟分频产生1kHz左右的采样时钟代码示例reg [15:0] clk_div; always (posedge clk) clk_div clk_div 1; wire sample_clk (clk_div 0);板级问题排查流程先确认电源指示灯正常测量晶振输出是否稳定检查JTAG连接是否可靠用万用表测量按键电路通断PDS工具使用技巧综合前执行Check Syntax提前发现语法错误布局布线后查看Floorplan确认资源利用率时序报告重点关注Worst Negative Slack数值这个设计经过实际验证在PGX-Nano开发板上能稳定工作。需要注意的是不同批次的按键机械特性可能有差异建议在实际应用中预留调节消抖时间的接口。对于更高要求的场景可以考虑采用窗口滤波法等更复杂的算法。