module Button(Clk,Rst,Sw1,Sw2,Led);// 模块接口 
        input Clk; // 时钟信号 
        input Rst; // 复位信号 
        input Sw1; // 按钮SW1输入,0表示按下,1表示抬起 
        input Sw2; // 按钮SW2输入 
        output [1 : 0] Led; // led 输出 
         
        /* 
        教程中的开发板是4 个LED,本开发板2 个LED 稍作修改 
        */ 
        reg [20 : 0]C1; //去抖动延时计时器C1 
        reg [20 : 0]C2; //去抖动延时计时器C2 
        reg [0 :0 ]Ledn; // 指示那个LED 输出 
        reg [1 :0 ]Led; //Led 输出 
        reg Sw1D,Sw1D1,Sw2D,Sw2D1; //同步延时中间信号 
        wire Sw1_IsDwon,Sw2_IsDwon;//标示按钮按下的信号 
         
        // 通过同步电路,实现判断按钮按下一次 
        // 当按钮按下前一个时钟Sw1D1=0,Sw1D=0,Sw1_IsDwon=0 
        // 挡按钮按下第一个时钟Sw1D1=0,Sw1D=1,Sw1_IsDwon=1 
        // 挡按钮按下第二个时钟Sw1D1=1,Sw1D=1,Sw1_IsDwon=0 
        assign Sw1_IsDwon = !Sw1D1 && Sw1D; 
        //按钮SW2 的同步信号和SW1 一样 
        assign Sw2_IsDwon = !Sw2D1 && Sw2D; 
         
        // 此模块把按钮按下的判断信号延时1个时钟 
        always @(posedge Clk ) begin 
                if( !Rst )begin // 
                        Sw1D1 <= 1'b0; 
                        Sw2D1 <= 1'b0; 
                end 
                else begin 
                        Sw1D1 <= Sw1D; 
                        Sw2D1 <= Sw2D; 
                end 
        end 
         
        always @(posedge Clk ) 
                if( !Rst )begin 
                        Sw1D <= 1'b0; 
                        Sw2D <= 1'b0; 
                end 
                else begin 
                        //如果C1[20] 为1 则Sw1D 置1 表示按钮按下 
                        // 如果按钮按下,则必须等到C1=0 才置Sw1D 为0 表示按钮抬起 
                        if( C1[ 20 ] ) Sw1D <= 1'b1; 
                        else if( Sw1D && C1==0 ) Sw1D <=1'b0; 
                        //按钮SW2 和SW1 一样 
                        if( C2[ 20 ] ) Sw2D <= 1'b1; 
                        else if( Sw2D && C2==0 ) Sw2D <=1'b0; 
                end 
                 
        always @(posedge Clk ) 
                if( !Rst )begin 
                        C1 <= 21'd0; 
                        C2 <= 21'd0; 
                end 
                else begin 
                        // 如果按钮SW1 按下,则C1 开始计数,否则减计数,实现去抖动 
                        if( !Sw1 ) begin  
                                if( !C1[ 20 ] ) C1 <= C1 + 1'b1;  
                                end 
                        else if( C1 > 0 ) C1 <= C1 - 1'b1; 
                        // 如果按钮SW2 按下,则C2 开始计数,否则减计数,实现去抖动 
                        if( !Sw2 ) begin  
                                if( !C2[ 20 ] ) C2 <= C2 + 1'b1;  
                                end 
                        else if( C2 > 0 ) C2 <= C2 - 1'b1; 
                end 
                 
        //控制LED 的输出模块 
        //每次按下LED 后,LED 移动移位 
        //移动方向由按钮控制 
        always @( posedge Clk ) 
                if(!Rst)begin 
                        Ledn <= 1'd0; 
                        Led <= 2'h0; 
                end  
                else begin 
                if( Sw1_IsDwon ) Ledn <= Ledn + 1'b1; 
                else if( Sw2_IsDwon ) Ledn <= Ledn - 1'b1; 
                Led <= 2'h0; //LED 0 灭掉 
                Led[Ledn] <= 1'b1; //LED 1 点亮 
                //有些开发板是0 点亮,1 灭掉 
                end 
endmodule 
上面是教程里的按键去抖程序,有点不理解,求大神帮忙介绍下这个去抖原理。 
另外, 
always @(posedge Clk ) 
                if( !Rst )begin 
                        C1 <= 21'd0; 
                        C2 <= 21'd0; 
                end 
                else begin 
                        // 如果按钮SW1 按下,则C1 开始计数,否则减计数,实现去抖动 
                        if( !Sw1 ) begin  
                                if( !C1[ 20 ] ) C1 <= C1 + 1'b1;  
                                end 
                        else if( C1 > 0 ) C1 <= C1 - 1'b1; 
                        // 如果按钮SW2 按下,则C2 开始计数,否则减计数,实现去抖动 
                        if( !Sw2 ) begin  
                                if( !C2[ 20 ] ) C2 <= C2 + 1'b1;  
                                end 
                        else if( C2 > 0 ) C2 <= C2 - 1'b1; 
                end 
这个always块里面,减计数,去抖是怎么实现的,为什么减计数就可以去抖,还有就是C1 >0,和上面!c2[20]有重合的部分,不理解。 
 
 |