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