2024年6月14日发(作者:)
前几天看了特权同学用Verilog写的按键消抖程序,感觉很经典。在这里将程序贴出
来分享一下。
module lcd_button2(clk,rst,seg,wei,sw1,sw2,sw3,sw4);//按键按下,数码管依次显
示0-9
input clk;
input rst;
input sw1,sw2,sw3,sw4;
output [3:0] wei;
output[7:0] seg;
reg [7:0] seg;
reg [3:0] wei;
integer num;
initial begin
num = 0;
end
reg[3:0] key_rst;
always @(posedge clk or negedge rst)
if(!rst)
key_rst <= 4'b1111;
else
key_rst <= {sw4,sw3,sw2,sw1};
reg[3:0] key_rst_r;
always @(posedge clk or negedge rst)
if(!rst)
key_rst_r <= 4'b111;
else
key_rst_r <= key_rst;
wire[3:0] key_an = key_rst_r & (~key_rst);
reg[19:0] cnt;
always @(posedge clk or negedge rst)
if(!rst)
cnt <= 0;
else if(key_an) cnt <= 0;
else cnt <= cnt+1'b1;
reg [3:0] low_sw;
always @(posedge clk or negedge rst)
if(!rst)
low_sw <= 4'b1111;
else if(cnt==10'hfffff)
low_sw <= {sw4,sw3,sw2,sw1};
reg[3:0] low_sw_r;
always @(posedge clk or negedge rst)
if(!rst)
low_sw_r <= 4'b1111;
else
low_sw_r <= low_sw;
wire [3:0] led_ctrl = low_sw_r[3:0] & (~low_sw[3:0]);
reg d1,d2,d3,d4;
always @(posedge clk or negedge rst)
if(!rst) begin
d1 <= 0;
d2 <= 0;
d3 <= 0;
d4 <= 0;
end
else begin
if(led_ctrl[0]) begin
num <= num+1;
if(num==9)
num <= 0;
end
end
always @(posedge clk ) begin
wei <= 4'b1111;
case(num)
0: seg <= 8'hfc;
1: seg <= 8'h60;
2: seg <= 8'hda;
3: seg <= 8'hf2;
4: seg <= 8'h66;
5: seg <= 8'hb6;
6: seg <= 8'hbe;
7: seg <= 8'he0;
8: seg <= 8'hfe;
9: seg <= 8'hf6;
default: seg <= 8'h02;
endcase
end
endmodule
参考了特权的代码。/1375/
-------------------------------------------------
module key_debounce(
input i_clk,
input i_rst_n,
input [4:1] i_key, // 按下为0,松开为1
output reg [4:1] o_key_val // 键值
);
//++++++++++++++++++++++++++++++++++++++
reg [4:1] key_samp1, key_samp1_locked;
// 将i_key采集至key_samp1
always @ (posedge i_clk, negedge i_rst_n)
begin
if(!i_rst_n)
key_samp1 <= 4'hF;
else
key_samp1 <= i_key;
end
// 将key_samp1锁存至key_samp1_locked
always @ (posedge i_clk, negedge i_rst_n)
begin
if(!i_rst_n)
key_samp1_locked <= 4'hF;
else
key_samp1_locked <= key_samp1;
end
//--------------------------------------
//++++++++++++++++++++++++++++++++++++++
wire [4:1] key_changed1;
// 当key_samp1由1变为0时
// key_changed1由0变为1,且维持一个时钟周期
assign key_changed1 = key_samp1_locked & (~key_samp1);
//--------------------------------------
//++++++++++++++++++++++++++++++++++++++
reg [19:0] cnt;
// 一旦有按键按下,cnt立即被清零
always @ (posedge i_clk, negedge i_rst_n)
begin
if(!i_rst_n)
cnt <= 20'h0;
else if(key_changed1)
cnt <= 20'h0;
else
cnt <= cnt + 1'b1;
end
//--------------------------------------
//++++++++++++++++++++++++++++++++++++++
reg [4:1] key_samp2, key_samp2_locked;
// 只有当按键不变化(不抖动),且维持20ms以上时
// 才将i_key采集至key_samp2
always @ (posedge i_clk, negedge i_rst_n)
begin
if(!i_rst_n)
key_samp2 <= 4'hF;
else if(cnt == 20'hF_FFFF) // 0xFFFFF/50M = 20.9715ms
key_samp2 <= i_key;
end
// 将key_samp2锁存至key_samp2_locked
always @ (posedge i_clk, negedge i_rst_n)
begin
if(!i_rst_n)
key_samp2_locked <= 4'hF;
else
key_samp2_locked <= key_samp2;
end
//--------------------------------------
//++++++++++++++++++++++++++++++++++++++
wire [4:1] key_changed2;
// 当key_samp2由1变为0时
// key_changed2由0变为1,且维持一个时钟周期
assign key_changed2 = key_samp2_locked & (~key_samp2);
//--------------------------------------
//++++++++++++++++++++++++++++++++++++++
// 每次按键稳定后,都将键值取反
always @ (posedge i_clk, negedge i_rst_n)
begin
if(!i_rst_n)
o_key_val <= 4'hF;
else
begin
if(key_changed2[1])
o_key_val[1] <= ~o_key_val[1];
if(key_changed2[2])
o_key_val[2] <= ~o_key_val[2];
if(key_changed2[3])
o_key_val[3] <= ~o_key_val[3];
if(key_changed2[4])
o_key_val[4] <= ~o_key_val[4];
end
end
//--------------------------------------
endmodule
module debounce(
clk,
rst_n,
key_i,
key_o
);
input clk;
input rst_n;
input key_i;
output key_o;
reg key_o;
wire key;
wire clk_slow;
//分频电路
reg [22:0] cnt;
reg [25:0] cnt_out;
wire key_o_reg ;
always @ ( posedge clk or negedge rst_n )
if ( !rst_n )
cnt <= 23'd0;
else
cnt <= cnt + 1'b1;
assign clk_slow = cnt[22];
//防反跳电路
reg temp_r [2:0];
reg key_r;
integer i;
always @ ( posedge clk_slow or negedge rst_n )
if ( !rst_n )
begin
for ( i = 0 ; i < 3; i = i+ 1)
temp_r[i] <= 'd0;
end
else
begin
temp_r[0] <= key_i;
temp_r[1] <= temp_r[0];
temp_r[2] <= temp_r[1];
end
assign key = (~temp_r[0]) & temp_r[1] & temp_r[2];
always @ ( posedge clk or negedge rst_n )
if ( !rst_n )
key_r <= 1'b0;
else
key_r <= key;
assign key_o_reg = key & (~key_r);
/*
always @ ( posedge clk or negedge rst_n )
// 防抖动电路
if( !rst_n )
key_o <= 1'b0 ;
else
begin
if( cnt_out<='d33554432 )
begin
if( cnt_out=='d0 )
begin
if( key_o_reg )
begin
cnt_out <= 'd1 ;
key_o <= 1'b1 ;
end
else
begin
cnt_out <= 'd0 ;
key_o <= 1'b0 ;
end
end
else
cnt_out <= cnt_out + 'd1 ;
end
else
cnt_out <= 'd0 ;
end
*/
endmodule
/bbs/bbs_?bbs_sn=3870307&bbs_id=1029


发布评论