基于状态机的按键抖动消除和状态转移图

按键抖动情况:
在这里插入图片描述
实际情况与要求:
在这里插入图片描述
分析状态:
在这里插入图片描述
状态转移图:
在这里插入图片描述
IDLE:空闲 P_FILTER:按下滤波 WAIT_R:等待释放 R_FILTER:释放滤波

首次设计:

module key_filter(
   Clk,
  Reset_n,
  Key,
  Key_P_Flag,
  Key_R_Flag
    );
   input   Clk;
   input  Reset_n;
   input   Key;
 output reg  Key_P_Flag;
 output reg Key_R_Flag;
    
 reg [1:0] r_Key;   
    always@(posedge Clk)
     r_Key <= {r_Key[0],Key};
     //    always@(posedge Clk)begin
//        r_Key[0] <= Key;  
//        r_Key[1] <= r_Key[0];  
//    end 

     
   wire pedge_key ;
   assign pedge_key = r_Key == 2'b01;
   wire nedge_key;
   assign nedge_key = r_Key == 2'b10;
    
    reg [19:0] cnt;
    reg [1:0] state;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
    state <= 0;
    Key_P_Flag <= 1'b0;
    Key_R_Flag <= 1'b0;
    cnt <= 0;
    end
 else begin
     case(state) 
      0 : 
         begin
           Key_R_Flag <= 1'b0;
           if(nedge_key)
             state <= 1;
             else
              state <= 0;
     end
     1: 
         if((pedge_key)&&(cnt<=1000000-1))begin
            state <= 0;
            cnt <=0;
            end
          else  if(cnt>=1000000-1)
          begin
             state <= 2;
             Key_P_Flag <= 1'b1;
             cnt<=0;
         end
         else 
            begin
             state <= 1;
             cnt <= cnt +1'b01;          
            end      
   
      
      
      2:
         begin
            Key_P_Flag <= 0;
         if(pedge_key)
            state <=  3;
          else
          state <= 2;   
  end
  
     3:
       
        if((nedge_key)&&(cnt <= 1000000 - 1))begin
        state<=2;
        cnt <= 0;
        end
       else if(cnt>=1000000-1)begin
         Key_R_Flag <= 1'b1;
         state <= 0;
         cnt <= 0;
         end
         else begin
            cnt <= cnt + 1'b1;
            state <= 3;
   end

 endcase   
end
endmodule
`timescale 1ns / 1ps

module key_filter_tb( );

   reg  Clk;
   reg  Reset_n;
  reg   Key;
wire  Key_P_Flag;
wire Key_R_Flag;

 key_filter key_filter(
     .Clk(Clk),
  .Reset_n(Reset_n),
  .Key_P_Flag(Key_P_Flag),
  .Key_R_Flag(Key_R_Flag),
   .Key(Key)
);

 initial Clk = 1;
 always#10 Clk = ~Clk;
 
 initial begin
   Reset_n = 0;
   Key = 1;
   #201;
   Reset_n = 1;
   #20000;
   Key=1;
   #30000;
   Key = 0;
   #20000;
   Key = 1;
   #30000;
   Key = 0;
   #50000000;
   
   Key = 1;
   #30000;
   Key = 0;
   #20000;
   Key = 1;
   #30000;
   Key = 0;
   #20000;
   Key = 1;
   #50000000;   
   $stop; 
 end
endmodule


最终期望得到信号为:消除掉了滤波的信号

修改设计: 消除掉滤波 且可以根据   Key_Flag 和  Key_State 信号判断到底是按下还是释放。

```c
module key_filter(
    Clk,
    Reset_n,
    Key,
    Key_Flag,
    Key_State
);
    input Clk;
    input Reset_n;
    input Key;
    output Key_Flag;
    output reg Key_State;
    
    reg Key_P_Flag;
    reg Key_R_Flag;
    
    assign Key_Flag = Key_P_Flag | Key_R_Flag;
    
    reg [1:0] r_Key;
    always@(posedge Clk)
        r_Key <= {r_Key[0],Key};
        
//    always@(posedge Clk)begin
//        r_Key[0] <= Key;  
//        r_Key[1] <= r_Key[0];  
//    end 

    wire pedge_key;
    assign pedge_key = r_Key == 2'b01;
    wire nedge_key;
    assign nedge_key = r_Key == 2'b10;
    
    reg [19:0]cnt;
    
    reg [1:0]state;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
        state <= 0;
        Key_R_Flag <= 1'b0;
        Key_P_Flag <= 1'b0;
        cnt <= 0;
        Key_State <= 1;
    end
    else begin
        case(state)
            0:
                begin
                    Key_R_Flag <= 1'b0;
                    if(nedge_key)
                        state <= 1;
                    else
                        state <= 0;
                end
            
            1:
                if((pedge_key)&&(cnt <1000000 -1))begin
                    state <= 0;
                    cnt <= 0;
                end
                else if(cnt >= 1000000 -1)begin
                    state <= 2;
                    cnt <= 0;
                    Key_P_Flag <= 1;
                    Key_State <= 0;
                end
                else begin
                    cnt <= cnt + 1'b1;
                    state <= 1;
                end
                
            2:
                begin
                    Key_P_Flag <= 0;
                    if(pedge_key)
                        state <= 3;
                    else
                        state <= 2;
                 end
                    
            3:
                if((nedge_key)&&(cnt <1000000 -1))begin
                    state <= 2;
                    cnt <= 0;
                end
                else if(cnt >= 1000000 -1)begin
                    state <= 0;
                    cnt <= 0;
                    Key_R_Flag <= 1'b1;
                    Key_State <= 1;
                end
                else begin
                    cnt <= cnt + 1'b1;
                    state <= 3;               
                end
        endcase   
    end
endmodule
`timescale 1ns / 1ps
module key_filter_tb();
    reg Clk;
    reg Reset_n;
    reg Key;
    wire Key_Flag;
    wire Key_State;    
    
    key_filter key_filter(
        Clk,
        Reset_n,
        Key,
        Key_Flag,
        Key_State
    );
    
    initial Clk = 1;
    always#10 Clk = ~Clk;
    
    initial begin
        Reset_n = 0;
        Key = 1;
        #201;
        Reset_n = 1;
        #3000;
        Key = 0;
        #20000;
        Key = 1;
        #30000;  
        Key = 0;
        #20000;
        Key = 1;
        #30000;
        Key = 0;
        #50000000;
        
        Key = 1;
        #30000;  
        Key = 0;
        #20000;
        Key = 1;
        #30000;
        Key = 0;
        #20000;
        Key = 1;               
        #50000000;
        $stop;   
    end
    
endmodule

修改TB文件:

`timescale 1ns / 1ps
module key_filter_tb2(  );
 reg  clk;
 reg Reset_n;
 reg Key;
 wire Key_Flag;
 wire Key_State;
 
 key_filter key_filter(
    Clk,
    Reset_n,
    Key,
//    Key_P_Flag,
//    Key_R_Flag,
    Key_Flag,
    Key_State
 );

initial clk = 1;
always#10 clk = ~clk;

initial begin
 Reset_n = 0;
 Key = 1;
 #201;
 Reset_n = 1;
 #3000;
 press_key(2);  //调用task,seed赋值为2
 $stop;
end

reg [31: 0] rand;  //协议规定产生一个32位的有符号随机数
 
 task press_key;
   input [3:0] seed;
    begin
    Key = 1;
    #20000000;
    repeat(5)begin          // 重复五次
      rand = {$random(seed)} %10000000;  //随机一个从0——9999999的数 
      #rand Key = ~ Key;
    end
    Key = 0;
    #40000000;
    
     repeat(5)begin
      rand = {$random(seed)} %10000000;
      #rand Key = ~ Key;
    end
    Key = 1;
    #40000000;
    end
endtask
endmodule

关于$random(seed)

r a n d o m 根 据 s e e d 来 产 生 随 机 数 。 s e e d 不 同 , 产 生 的 随 机 数 的 序 列 也 不 同 。 而 且 , 每 执 行 一 次 random根据seed来产生随机数。seed不同,产生的随机数的序列也不同。而且,每执行一次 randomseedseedrandom(seed)产生一个随机数,seed也自动更新一次。

在上面代码中,seed初始值被赋为2(也可以是1或其它数),在第一个时钟上升沿,rand_num取得的第一个随机数就是 r a n d o m ( 0 ) 产 生 的 , s e e d 也 随 即 更 新 ; 在 第 二 个 时 钟 上 升 沿 时 , r a n d n u m 取 得 第 二 个 随 机 数 , 是 random(0)产生的,seed也随即更新;在第二个时钟上升沿时,rand_num取得第二个随机数,是 random(0)seed沿randnumrandom(更新后的seed)产生的,seed又随即更新;如此下去。

`timescale 1ns / 1ps
module key_filter(
   Clk,
  Reset_n,
  Key,
  Key_P_Flag,
  Key_R_Flag
    );
   input   Clk;
   input  Reset_n;
   input   Key;
 output reg  Key_P_Flag;
 output reg Key_R_Flag;
    
    reg [1:0] sync_key;
    always@(posedge Clk)
    r_Key <={sync_key[0],Key};     //防止亚稳态

 reg [1:0] r_Key;   
    always@(posedge Clk)
     r_Key <= {r_Key[0],Key};
     //    always@(posedge Clk)begin
//        r_Key[0] <= Key;  
//        r_Key[1] <= r_Key[0];  
//    end 

   wire pedge_key ;
   assign pedge_key = r_Key == 2'b01;
   wire nedge_key;
   assign nedge_key = r_Key == 2'b10;
    
    reg [19:0] cnt;
    reg [1:0] state;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
    state <= 0;
    Key_P_Flag <= 1'b0;
    Key_R_Flag <= 1'b0;
    cnt <= 0;
    end
 else begin
     case(state) 
      0 : 
         begin
           Key_R_Flag <= 1'b0;
           if(nedge_key)
             state <= 1;
             else
              state <= 0;
     end
     1: 
         if((pedge_key)&&(cnt<=1000000-1))begin
            state <= 0;
            cnt <=0;
          end
          else  if(cnt>=1000000-1)
          begin
             state <= 2;
             Key_P_Flag <= 1;
             cnt<=0;
         end
         else 
            begin
             state <= 1;
             cnt <= cnt +1'b1;          
            end      
      
      2:
         begin
            Key_P_Flag <= 0;
         if(pedge_key)
            state <=  3;
          else
          state <= 2;   
  end
  
     3:
        if((nedge_key)&&(cnt <= 1000000 - 1))begin
        state<=2;
        cnt <= 0;
        end
       else if(cnt>=1000000-1)begin
         Key_R_Flag <= 1'b1;
         state <= 0;
         cnt <= 0;
         end
         else begin
            cnt <= cnt + 1'b1;
            state <= 3;
   end

 endcase   
end
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值