学习fpga一个月了,一个月中断断续续的看书弄实验箱,中间因实验箱的芯片有点老,资料少,又买了黑金的开发板,这两天才开始系统的学习,看到黑金配套的verilog那些事 中消抖的那块,突然想起以前看特权的视频中的消抖和实验箱配套的周立功出版的书上的消抖模块,现在列出下面三种消抖的代码请教这三种的哪种最实用,各自的思想好处,或者有其他更好更实用的消抖方法么?以后用到消抖该采用哪种呢??
特权同学
module sw_debounce(
clk,rst_n,
sw1_n,sw2_n,sw3_n,
led_d1,led_d2,led_d3
);
input clk; //Ö÷ʱÖÓÐźţ¬50MHz
input rst_n; //¸´Î»Ðźţ¬µÍÓÐЧ
input sw1_n,sw2_n,sw3_n; //Èý¸ö¶ÀÁ¢°´¼ü£¬µÍ±íʾ°´ÏÂ
output led_d1,led_d2,led_d3; //·¢¹â¶þ¼«¹Ü£¬·Ö±ðÓÉ°´¼ü¿ØÖÆ
//---------------------------------------------------------------------------
reg[2:0] key_rst;
always @(posedge clk or negedge rst_n)
if (!rst_n) key_rst <= 3'b111;
else key_rst <= {sw3_n,sw2_n,sw1_n};
reg[2:0] key_rst_r; //ÿ¸öʱÖÓÖÜÆÚµÄÉÏÉýÑؽ«low_swÐźÅËø´æµ½low_sw_rÖÐ
always @ ( posedge clk or negedge rst_n )
if (!rst_n) key_rst_r <= 3'b111;
else key_rst_r <= key_rst;
//µ±¼Ä´æÆ÷key_rstÓÉ1±äΪ0ʱ£¬led_anµÄÖµ±äΪ¸ß£¬Î¬³ÖÒ»¸öʱÖÓÖÜÆÚ
wire[2:0] key_an = key_rst_r & ( ~key_rst);
//---------------------------------------------------------------------------
reg[19:0] cnt; //¼ÆÊý¼Ä´æÆ÷
always @ (posedge clk or negedge rst_n)
if (!rst_n) cnt <= 20'd0; //Òì²½¸´Î»
else if(key_an) cnt <=20'd0;
else cnt <= cnt + 1'b1;
reg[2:0] low_sw;
always @(posedge clk or negedge rst_n)
if (!rst_n) low_sw <= 3'b111;
else if (cnt == 20'hfffff) //Âú20ms£¬½«°´¼üÖµËø´æµ½¼Ä´æÆ÷low_swÖÐ cnt == 20'hfffff
low_sw <= {sw3_n,sw2_n,sw1_n};
//---------------------------------------------------------------------------
reg [2:0] low_sw_r; //ÿ¸öʱÖÓÖÜÆÚµÄÉÏÉýÑؽ«low_swÐźÅËø´æµ½low_sw_rÖÐ
always @ ( posedge clk or negedge rst_n )
if (!rst_n) low_sw_r <= 3'b111;
else low_sw_r <= low_sw;
//µ±¼Ä´æÆ÷low_swÓÉ1±äΪ0ʱ£¬led_ctrlµÄÖµ±äΪ¸ß£¬Î¬³ÖÒ»¸öʱÖÓÖÜÆÚ
wire[2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]);
reg d1;
reg d2;
reg d3;
always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
d1 <= 1'b0;
d2 <= 1'b0;
d3 <= 1'b0;
end
else begin //ij¸ö°´¼üÖµ±ä»¯Ê±£¬LED½«×öÁÁÃð· ת
if ( led_ctrl[0] ) d1 <= ~d1;
if ( led_ctrl[1] ) d2 <= ~d2;
if ( led_ctrl[2] ) d3 <= ~d3;
end
assign led_d3 = d1 ? 1'b1 : 1'b0; //LED· תÊä³ö
assign led_d2 = d2 ? 1'b1 : 1'b0;
assign led_d1 = d3 ? 1'b1 : 1'b0;
endmodule
周立功配套实验书
module debounce(clk,key_in,key_out); //按键消抖模块
input clk; //系统时钟输入
input[KEY_WIDTH-1:0] key_in; //外部按键输入
output[KEY_WIDTH-1:0]key_out; //按键消抖输出
reg[KEY_WIDTH-1:0]dout1,dout2,dout3; //寄存器
parameter KEY_WIDTH = 8; //参数
assign key_out = (dout1 | dout2 | dout3); //按键消抖输出
always @(posedge clk)
begin
dout1 <= key_in;
dout2 <= dout1;
dout3 <= dout2;
end
endmodule
黑金配套资料
分三个部分
顶层文件
module debounce_module
(
CLK, RSTn, Pin_In, Pin_Out
);
input CLK;
input RSTn;
input Pin_In;
output Pin_Out;
/**************************/
wire H2L_Sig;
wire L2H_Sig;
detect_module U1
(
.CLK( CLK ),
.RSTn( RSTn ),
.Pin_In( Pin_In ), // input - from top
.H2L_Sig( H2L_Sig ), // output - to U2
.L2H_Sig( L2H_Sig ) // output - to U2
);
/**************************/
delay_module U2
(
.CLK( CLK ),
.RSTn( RSTn ),
.H2L_Sig( H2L_Sig ), // input - from U1
.L2H_Sig( L2H_Sig ), // input - from U1
.Pin_Out( Pin_Out ) // output - to top
);
/*******************************/
endmodule
电平检测模块
module detect_module(clk,rst,pin_in,h2l_sig,l2h_sig);
input clk;
input rst;
input pin_in;
output h2l_sig;
output l2h_sig;
parameter T100US=11'd1999;
reg[10:0]cnt;
reg isen;
[email=always@(posedge]always@(posedge[/email] clk or negedge rst)
begin
if(!rst)
begin
cnt<=11'd0;
isen<=1'b0;
end
else if(cnt==T100US)
isen<=1'b1;
else
cnt<=cnt+1;
end
reg h2l_f1;
reg h2l_f2;
reg l2h_f1;
reg l2h_f2;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
h2l_f1<=1'b1;
h2l_f2<=1'b1;
l2h_f1<=1'b0;
l2h_f2<=1'b0;
end
else
begin
h2l_f1<=pin_in;
h2l_f2<=h2l_f1;
l2h_f1<=pin_in;
l2h_f2<=l2h_f1;
end
end
assign h2l_sig = isen ? ( h2l_f2 & !h2l_f1 ) : 1'b0;
assign l2h_sig = isen ? ( !l2h_f2 & l2h_f1 ) : 1'b0;
endmodule
10ms延迟模块
module delay_module
(
CLK, RSTn, H2L_Sig, L2H_Sig, Pin_Out
);
input CLK;
input RSTn;
input H2L_Sig;
input L2H_Sig;
output Pin_Out;
/****************************************/
parameter T1MS = 16'd19_999;
/***************************************/
reg [15:0]Count1;
always @ ( posedge CLK or negedge RSTn )
if( !RSTn )
Count1 <= 16'd0;
else if( isCount && Count1 == T1MS )
Count1 <= 16'd0;
else if( isCount )
Count1 <= Count1 + 1'b1;
else if( !isCount )
Count1 <= 16'd0;
/****************************************/
reg [3:0]Count_MS;
always @ ( posedge CLK or negedge RSTn )
if( !RSTn )
Count_MS <= 4'd0;
else if( isCount && Count1 == T1MS )
Count_MS <= Count_MS + 1'b1;
else if( !isCount )
Count_MS <= 4'd0;
/******************************************/
reg isCount;
reg rPin_Out;
reg [1:0]i;
always @ ( posedge CLK or negedge RSTn )
if( !RSTn )
begin
isCount <= 1'b0;
rPin_Out <= 1'b0;
i <= 2'd0;
end
else
case ( i )
2'd0 :
if( H2L_Sig ) i <= 2'd1;
else if( L2H_Sig ) i <= 2'd2;
2'd1 :
if( Count_MS == 4'd10 ) begin isCount <= 1'b0; rPin_Out <= 1'b1; i <= 2'd0; end
else isCount <= 1'b1;
2'd2 :
if( Count_MS == 4'd10 ) begin isCount <= 1'b0; rPin_Out <= 1'b0; i <= 2'd0; end
else isCount <= 1'b1;
endcase
/********************************************/
assign Pin_Out = rPin_Out;
/********************************************/
endmodule
我知道特权和黑金的代码是软件仿真就是10ms检测,而周立功的是硬件消抖,建立DFF来消抖,你们这三种方法那个最好呢? |