4*4按键消抖(野火升腾拓展)

解释:

1、扫描控制:

• scan_cnt 从 0 计数到 49999(共 50000 个周期)

• 每 1ms(1kHz)产生一个 valid_tick 脉冲

2、行切换:

• valid_tick 触发 row_sel 状态机,依次激活 4 行

3、消抖与缓存:

• 每列信号独立消抖( col_flag )

• 在 valid_tick 上升沿将消抖结果写入 key_state 对应行

代码

// 按键消抖模块(单路)

module key_filter #(

parameter CNT_MAX = 20'd999_999 // 约20ms@50MHz

)(

input wire sys_clk,

input wire sys_rst_n,

input wire key_in,

output reg key_flag

);

reg [19:0] cnt_20ms;

always @(posedge sys_clk or negedge sys_rst_n) begin

if (!sys_rst_n)

cnt_20ms <= 20'd0;

else if (key_in)

cnt_20ms <= 20'd0;

else if (cnt_20ms == CNT_MAX)

cnt_20ms <= cnt_20ms;

else

cnt_20ms <= cnt_20ms + 1'b1;

end

always @(posedge sys_clk or negedge sys_rst_n) begin

if (!sys_rst_n)

key_flag <= 1'b0;

else

key_flag <= (cnt_20ms == CNT_MAX - 1'b1);

end

endmodule

// 4x4矩阵键盘扫描与消抖顶层模块

module matrix_keypad #(

parameter CNT_MAX = 20'd999_999, // 消抖计数最大值

parameter SCAN_DIV = 16'd50000 // 扫描分频系数 (50MHz -> 1kHz)

)(

input wire sys_clk, // 50MHz系统时钟

input wire sys_rst_n, // 复位,低有效

input wire [3:0] col_in, // 4列输入(外部上拉)

output wire [3:0] row_out, // 4行输出

output reg [15:0] key_state // 按键状态:1表示按下

);

// 扫描控制信号

reg [15:0] scan_cnt; // 扫描分频计数器 (16位)

reg valid_tick; // 采样有效脉冲

reg [3:0] row_sel; // 当前行选择

// 消抖后列信号

wire [3:0] col_flag;

//===== 扫描控制器 =====//

// 生成1kHz扫描时钟 (50MHz / 50000 = 1kHz)

always @(posedge sys_clk or negedge sys_rst_n) begin

if (!sys_rst_n) begin

scan_cnt <= 16'd0;

valid_tick <= 1'b0;

end else if (scan_cnt == SCAN_DIV - 1) begin

scan_cnt <= 16'd0;

valid_tick <= 1'b1;

end else begin

scan_cnt <= scan_cnt + 1'b1;

valid_tick <= 1'b0;

end

end

//===== 行选择状态机 =====//

always @(posedge sys_clk or negedge sys_rst_n) begin

if (!sys_rst_n)

row_sel <= 4'b1110; // 默认选中第0行

else if (valid_tick) begin // 每1ms切换一行

case (row_sel)

4'b1110: row_sel <= 4'b1101; // 第0行 → 第1行

4'b1101: row_sel <= 4'b1011; // 第1行 → 第2行

4'b1011: row_sel <= 4'b0111; // 第2行 → 第3行

4'b0111: row_sel <= 4'b1110; // 第3行 → 第0行

default: row_sel <= 4'b1110;

endcase

end

end

assign row_out = row_sel;

//===== 列消抖(复用4个单路消抖模块)=====//

genvar i;

generate

for (i=0; i<4; i=i+1) begin : debounce_inst

key_filter #(.CNT_MAX(CNT_MAX))

u_debounce (

.sys_clk(sys_clk),

.sys_rst_n(sys_rst_n),

.key_in(col_in[i]),

.key_flag(col_flag[i])

);

end

endgenerate

//===== 状态缓存 =====//

always @(posedge sys_clk or negedge sys_rst_n) begin

if (!sys_rst_n)

key_state <= 16'd0;

else if (valid_tick) begin // 仅在行切换时更新状态

case (row_sel)

4'b1110: key_state[3:0] <= col_flag; // 第0行状态

4'b1101: key_state[7:4] <= col_flag; // 第1行状态

4'b1011: key_state[11:8] <= col_flag; // 第2行状态

4'b0111: key_state[15:12] <= col_flag; // 第3行状态

endcase

end

end

endmodule

相关推荐
黄埔数据分析15 小时前
QDMA把描述符当数据搬移, 不用desc engine
fpga开发
南檐巷上学21 小时前
基于FPGA的正弦信号发生器、滤波器的设计(DAC输出点数受限条件下的完整正弦波产生器)
fpga开发·数字信号处理·dsp·dds
嵌入式-老费1 天前
Linux Camera驱动开发(fpga + csi rx/csi tx)
fpga开发
ALINX技术博客2 天前
【202601芯动态】全球 FPGA 异构热潮,ALINX 高性能异构新品预告
人工智能·fpga开发·gpu算力·fpga
JJRainbow2 天前
SN75176 芯片设计RS-232 转 RS-485 通信模块设计原理图
stm32·单片机·嵌入式硬件·fpga开发·硬件工程
s9123601012 天前
FPGA眼图
fpga开发
北京青翼科技2 天前
【PCIe732】青翼PCIe采集卡-优质光纤卡- PCIe接口-万兆光纤卡
图像处理·人工智能·fpga开发·智能硬件·嵌入式实时数据库
minglie12 天前
verilog信号命名规范
fpga开发
XINVRY-FPGA2 天前
中阶FPGA效能红线重新划定! AMD第2代Kintex UltraScale+登场,记忆体频宽跃升5倍
嵌入式硬件·fpga开发·硬件工程·dsp开发·fpga
南檐巷上学2 天前
基于FPGA的音频信号监测识别系统
fpga开发·音频·verilog·fpga·傅立叶分析·fft·快速傅里叶变换