含两拍同步 + 消抖 + 异步复位同步释放
module top (
input sys_clk,
input sys_rst_n,
input key_n, // 按键(低有效)
output [3:0] led
);
// ── 异步复位同步释放 ──
reg rst_r1, rst_r2;
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin rst_r1 <= 0; rst_r2 <= 0; end
else begin rst_r1 <= 1; rst_r2 <= rst_r1; end
end
wire rst_n = rst_r2;
// ── 两拍同步 ──
reg key_r1, key_r2;
always @(posedge sys_clk or negedge rst_n) begin
if (!rst_n) begin key_r1 <= 1; key_r2 <= 1; end
else begin key_r1 <= key_n; key_r2 <= key_r1; end
end
// ── 消抖(20ms @ 50MHz)──
parameter CNT_MAX = 1_000_000;
reg [19:0] db_cnt;
reg key_db;
always @(posedge sys_clk or negedge rst_n) begin
if (!rst_n) begin db_cnt <= 0; key_db <= 1; end
else if (key_r2 != key_db) begin
if (db_cnt >= CNT_MAX - 1) begin db_cnt <= 0; key_db <= key_r2; end
else db_cnt <= db_cnt + 1;
end else db_cnt <= 0;
end
// ── 下降沿检测 + 翻转 ──
reg key_prev;
reg [3:0] led_r;
always @(posedge sys_clk or negedge rst_n) begin
if (!rst_n) begin key_prev <= 1; led_r <= 4'b0000; end
else begin
key_prev <= key_db;
if (key_prev && !key_db) led_r <= ~led_r;
end
end
assign led = ~led_r;
endmodule