芯路恒电子技术论坛

 找回密码
 立即注册
热搜: 合集
查看: 7077|回复: 0

按键消抖仿真时 计数波形显示滞后

[复制链接]

该用户从未签到

1

主题

1

帖子

6

积分

新手入门

Rank: 1

积分
6
发表于 2020-10-14 18:48:41 | 显示全部楼层 |阅读模式
     module key_shake(Rst_n,key_in,clk,key_flag,key_state);
   
  input Rst_n;
    input clk;
  input key_in;
   
  output reg key_flag;   //按键状态切换标志
  output reg key_state;  //按键状态标志

localparam
     IDEL      = 4'b0000,
   FILTER0   = 4'b0010,
   DOWN      = 4'b0100,
   FILTER1   = 4'b1000;
   
   
  reg [19:0]cnt;
    reg en_cnt;//使能计数器
  reg cnt_full;//计数满标志
   
   
   reg [3:0]state;
   
   reg key_temp0,key_temp1;
   wire pedge,nedge;
   
   always@(posedge clk or negedge Rst_n)
   if(!Rst_n)begin
   key_temp0<=1'b0;
   key_temp1<=1'b0;
               end


else begin

   key_temp0<=key_in;
   key_temp1<=key_temp0;

end
/*检测边沿信号*/
assign nedge =!key_temp0 & key_temp1;  //下降沿
assign pedge = key_temp0 & (!key_temp1);//上升沿


//*计数器模块设计*//
/*计数使能模块*/
always@(posedge clk or negedge Rst_n)     
  if(!Rst_n)
      cnt<= 20'd0;
else if(en_cnt)
    cnt<=cnt+1'b1;
else
    cnt<=20'd0;
/*计数模块*/
   always@(posedge clk or negedge Rst_n)
if(!Rst_n)
      cnt_full<= 1'b0;
else if(cnt==20'd999_999)
    cnt_full<=1'b1;
else
    cnt_full<=1'b0;

always@(posedge clk or negedge Rst_n) //所有状态的复位
  if(!Rst_n)begin
    state <= IDEL;
  en_cnt<=1'b0;
  key_flag<=1'b0;
  key_state<=1'b1;
  
end
  
  else begin
  case(state)
       IDEL:
   begin
   key_flag<=1'b0;      //按键按下标志位清零
       if(nedge)begin  //检测到下降沿,进入FILTER0 状态,计数器开始计数
      
       state<= FILTER0;
       en_cnt<=1'b1;
   
       end
    else           
      state <= IDEL;  //没有检测到下降沿,返回初始态IDEL
   
end   
     FILTER0:
   if(cnt_full)begin  //如果说计数值达到20ms 并且没有上升沿,认为按键按下
     key_flag<=1'b1;
     key_state<=1'b0;
      en_cnt<=1'b0; //进入DOWN状态,计数器清零
      state<= DOWN;
end
  else if(pedge)begin
       state <= IDEL;  //检测到上升沿,返回IDEL
    en_cnt<=1'b0;
end
    else
       state <= FILTER0;
  
      DOWN:
  begin
  key_flag<=1'b0;  //进入down状态后将状态标志位清零
  
  if(pedge)begin   //检测到上升沿,进入FILTER1,并开始计数
      state<=FILTER1;  
     en_cnt<=1'b1;

end
       else
   state <= DOWN; //保持原位
end
     FILTER1:
   if(cnt_full)begin //计数满20ms后不存在下降沿。将flag。state置1,回到IDEL态,等待下一次按键按下
   state<=IDEL;
   key_flag<=1'b1;
   key_state<=1'b1;
   end
   else if(nedge)begin// 检测到下降沿,返回到上一状态DOWN,计数器清零
   
   en_cnt<=1'b0;
   state<=DOWN;
   
end
   else  
      state<=FILTER1;

default:begin state <= IDEL;
              en_cnt<=1'b0;
      key_state <=1'b1;
      key_flag <=1'b0;
        end
    endcase

end
   
  

endmodule


//*仿真文件1*/
`timescale 1ns/1ns
`define clock_period 20
module   key_shake_tb;
reg clk;
reg Rst_n;

wire key_in;
wire key_flag;
wire key_state;

key_shake shake0 (
         .Rst_n(Rst_n),
   .key_in(key_in),
   .clk(clk),
   .key_flag(key_flag),
   .key_state(key_state)
   );
key_model key_model(.key(key_in));

initial clk=1;
  
  always #(`clock_period/2)clk =~clk;
     
   
   
   initial begin
   Rst_n=1'b0;
   #(`clock_period*10) Rst_n =1'b1;
   #(`clock_period*10+1);
  
   end
   
   
   
   
   
   
endmodule


/**仿真文件2*/
`timescale 1ns/1ns
module key_model(key);
output reg key;
reg [15:0]myrand;

initial begin
   
key= 1'b1;
   press_key;
   #10000;
   press_key;
   #10000;
   $stop;
   end

  task press_key;  //产生随机函数
   begin
   repeat(50)begin
   myrand ={$random}%65536;  //0~65536
   #myrand key =~key;
   end
   key = 0;
   #50000000;
   
   repeat(50)begin
   myrand ={$random}%65536;  //0~65536
   #myrand key =~key;
   end
   key = 1;
   #50000000;
   
   end
   endtask
   
   endmodule
    Wave2 2020_10_14 18_42_19.png





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|芯路恒电子技术论坛 |鄂ICP备2021003648号

GMT+8, 2024-11-21 19:43 , Processed in 0.185949 second(s), 33 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc. Template By 【未来科技】【 www.wekei.cn 】

快速回复 返回顶部 返回列表