按键

注意前后消抖

module module_button
(
CLK,RSTn,Pin_In,LED_Out
);
input CLK;
input RSTn;
input [1:0]Pin_In;
output [9:0]LED_Out;
/*************************/
wire [1:0]HL_Sig;
wire [1:0]LH_Sig;
module_detect U1
(
.CLK(CLK),
.RSTn(RSTn),
.Pin_In(Pin_In),
.HL_Sig(HL_Sig),
.LH_Sig(LH_Sig)
);
module_delay U2
(
.CLK(CLK),
.RSTn(RSTn),
.HL_Sig(HL_Sig),
.LH_Sig(LH_Sig),
.LED_Out(LED_Out)      
);

endmodule

module module_detect
(
CLK,RSTn,Pin_In,HL_Sig,LH_Sig
);
input [1:0]Pin_In;//按键输入//pin_In[1] key[2],pin[0]key[3]
input CLK;
input RSTn;
output [1:0]HL_Sig;//输出信号
output [1:0]LH_Sig;//输出信号

/*************************************/

reg [3:0]HL_Sig1;
reg [3:0]HL_Sig2;
reg [3:0]LH_Sig1;
reg [3:0]LH_Sig2;
always@(posedge CLK or negedge RSTn)
if(!RSTn)
    begin
        HL_Sig1<=2'b11;//高电平到低电平
        HL_Sig2<=2'b11;
        LH_Sig1<=2'b00;
        LH_Sig2<=2'b00;//低电平到高电平
      end
else
    begin
        HL_Sig1[1:0]<=Pin_In[1:0];
        HL_Sig2[1:0]<=HL_Sig1[1:0];
        LH_Sig1[1:0]<=Pin_In[1:0];
        LH_Sig2[1:0]<=LH_Sig1[1:0];
 end
assign HL_Sig[0]=(HL_Sig1[0]^HL_Sig2[0]);
assign HL_Sig[1]=(HL_Sig1[1]^HL_Sig2[1]);
assign LH_Sig[0]=(LH_Sig2[0]^LH_Sig1[0]);
assign LH_Sig[1]=(LH_Sig2[1]^LH_Sig1[1]);
endmodule

module module_delay
(
CLK,RSTn,LED_Out,HL_Sig,LH_Sig
);
input CLK;
input RSTn;
input [1:0]HL_Sig;//高到低跳变沿
input [1:0]LH_Sig;//低到高跳变沿
output [9:0]LED_Out;
/******************************/
//计数器 延时10ms
parameter T10MS=20'd499_999;
reg [19:0] Count;
reg isCount;//是否计数
reg isCount1;//
always@(posedge CLK or negedge RSTn)
if(!RSTn)
     Count<=20'd0;
else if(Count==T10MS)
    Count<=20'd0;
else if(!isCount&&!isCount1)//当一个计数的时候,另一个标志位必定为0,所以当全为0的时候才清0
    Count<=20'd0;
else if(isCount||isCount1)//有一个为一则开始计数
    Count<=Count+1'b1;
/******************************/
//单独用该模块不好用
/******************************/
reg [1:0]rPin_Out;
reg [2:0]i1;
/*always@(posedge CLK or negedge RSTn)
if(!RSTn)
 begin
  i1<=2'd0;
  rPin_Out[1]<=1'b0;
  isCount1<=1'd0;
 end
else
 case(i)
 2'd0: if(HL_Sig[1])i1<=2'd1; else if(LH_Sig[1]) i1<=2'd2;
 2'd1: if(Count==T10MS)
      begin
       i1<=2'd0;
       isCount1<=1'd0;
       rPin_Out[1]<=1'b1;
      end
   else isCount1<=1'd1;
 2'd2:if(Count==T10MS)
    begin 
     i1<=2'd0;
     isCount1<=1'd0;
     rPin_Out[1]<=1'b0;
    end
   else isCount1<=1'd1;
 endcase
*/
//按键key【2】
always@(posedge CLK or negedge RSTn)
if(!RSTn)
   begin
        i1<=3'd0;
        rPin_Out[1]<=1'b0;//输出置0
    isCount1<=1'b0;    //停止计数
    end
else
        case(i1)
        3'd0:
             if(HL_Sig[1])i1<=3'd1;else if(LH_Sig[1])i1<=3'd2;
        3'd1:begin
                    if(Count==T10MS) //如果延时结束
                        begin
                            isCount1<=1'b0; //停止计数
                           rPin_Out[1]<=1'd1;//电平拉高
                            i1<=3'd2;          //
                        end
        else isCount1<=1'b1; //不满足延时条件,计数
    end
        3'd2:begin
                   rPin_Out[1]<=1'd0;//拉低电平
                   i1<=3'd0;
                end
        3'd3:begin
                  if(Count==T10MS)  
                        begin
                            isCount1<=1'b0;
                            i1<=3'd0;
                        end
                   else isCount1<=1'b1;
    end
      
        endcase
/*************************************/
//单独用这个模块好用
reg[2:0]i;
always@(posedge CLK or negedge RSTn)
if(!RSTn)
   begin
        i<=3'd0;
        rPin_Out[0]<=1'b0;//输出置0
    isCount<=1'b0;    //停止计数
    end
else
        case(i)
        3'd0:
             if(HL_Sig[0])i<=3'd1;else if(LH_Sig[0])i<=3'd3;
        3'd1:begin
                    if(Count==T10MS) //如果延时结束
                        begin
                            isCount<=1'b0; //停止计数
                            rPin_Out[0]<=1'd1;//电平拉高
                            i<=3'd2;          //
                        end
        else isCount<=1'b1; //不满足延时条件,计数
    end
        3'd2:begin
                    rPin_Out[0]<=1'd0;//拉低电平
                    i<=3'd0;
                end
        3'd3:begin
                  if(Count==T10MS)  
                        begin
                            isCount<=1'b0;
                            i<=3'd0;
                        end
                   else isCount<=1'b1;
    end
      
        endcase
/*******************************************/
reg[9:0]rLED_Out;
always@(posedge CLK or negedge RSTn)
if(!RSTn)
    rLED_Out<=10'b0000010000;
else if(rPin_Out[0]) rLED_Out<=rLED_Out<<1;
else if(rPin_Out[1]) rLED_Out<=rLED_Out>>1;
else if(rLED_Out==10'b0) rLED_Out<=10'b0000001000;
/****************************************/
assign LED_Out=rLED_Out;
endmodule

原文地址:https://www.cnblogs.com/bixiaopengblog/p/5930158.html