小梅哥课程学习——基于verilog系统函数语法的按键抖动模拟与仿真(C)

发布时间 2023-03-28 11:45:20作者: 无情的造轮子
  1 //源代码,因为在返回到空闲状态时没有清零
  2 module key_filter(
  3     clk,
  4     reset_n,
  5     key,
  6 //    key_p_flag,
  7 //    key_r_flag,
  8     key_flag,
  9     key_state
 10     );
 11     input clk;
 12     input reset_n;
 13     input key;
 14 //    output reg key_p_flag;
 15 //    output reg key_r_flag;
 16     output key_flag;
 17     output reg key_state;
 18     
 19     reg key_p_flag;
 20     reg key_r_flag;
 21     assign key_flag = (key_p_flag | key_r_flag);
 22     
 23     //定义两个寄存器来产生上升沿和下降沿。
 24    
 25     reg [1:0] r_key;
 26     always@(posedge clk)//利用位拼接来完成。
 27         r_key <= {r_key[0],key};
 28 //    always@(posedge clk)begin
 29 //        r_key[0] <= key;
 30 //        r_key[1] <= r_key[0];
 31 //    end
 32     
 33     //上升沿
 34     wire pedge_key;
 35     assign pedge_key = (r_key == 2'b01);
 36     
 37     //下降沿
 38     wire nedge_key;
 39     assign nedge_key = (r_key == 2'b10);
 40     
 41     //定义计数器
 42     reg [19:0] cnt;
 43     
 44      
 45     reg [1:0] state;
 46     always@(posedge clk or negedge reset_n)
 47     if(!reset_n)begin
 48         state <= 0;
 49         key_r_flag <= 0;
 50         key_p_flag <= 0;
 51         cnt <= 0;
 52         key_state <= 1;
 53     end
 54     else begin
 55         case(state)
 56             0: 
 57                 begin
 58                     key_r_flag <= 0;
 59                     if(nedge_key)
 60                         state <= 1;
 61                     else
 62                         state <= 0;
 63                 end
 64             1:  
 65                 if((pedge_key) &&(cnt < 1000000-1))begin
 66                     cnt <= 0;
 67                     state <= 0;
 68                 end
 69                 else if(cnt >= 1000000-1)begin
 70                     state <= 2;
 71                     cnt<=0;
 72                     key_p_flag <= 1;
 73                     key_state <= 0;
 74                 end
 75                 else begin
 76                     cnt <= cnt +1'b1;
 77                     state <= 1;
 78                 end
 79             2:
 80                 begin
 81                     key_p_flag <= 0;
 82                     
 83                     if(pedge_key)
 84                         state <= 3;
 85                     else
 86                         state <= 2;
 87                 end
 88             3:
 89                 if((nedge_key) &&(cnt < 1000000-1))begin
 90                     state <= 2;
 91                     cnt <= 0;
 92                 end
 93                 else if(cnt >= 1000000-1)begin
 94                     state <= 0;
 95                     cnt <= 0;
 96                     key_r_flag <= 1;
 97                     key_state <= 1;
 98                 end
 99                 else begin
100                     cnt <= cnt +1'b1;
101                     state <= 3;
102                 end
103             default:;
104         endcase
105     end
106         
107 endmodule
108 
109 //仿真代码tb2引入了随机数种子
110 `timescale 1ns / 1ps
111 module key_filter_tb2();
112     reg clk;
113     reg reset_n;
114     reg key;
115 //    wire key_p_flag;
116 //    wire key_r_flag;
117     wire key_flag;
118     wire key_state;
119     key_filter  key_filter_inst0(
120     clk,
121     reset_n,
122     key,
123 //    key_p_flag,
124 //    key_r_flag,
125     key_flag,
126     key_state
127     );
128     
129     initial clk = 1;
130     always #10 clk =! clk;
131     //按键抖动优化
132     initial begin
133         reset_n = 0;
134         key = 1;
135         #201;
136         reset_n =1;
137         #3000;
138         press_key(2);
139         $stop;
140         //模拟抖动
141 //        key = 0;
142 //        #20000;
143 //        key = 1;
144 //        #30000;
145 //        key = 0;
146 //        #20000;
147 //        key = 1;
148 //        #30000;
149 //        key = 0;
150 //        #50000000;
151         
152 //        key = 1;
153 //        #30000;
154 //        key = 0;
155 //        #20000;
156 //        key = 1;
157 //        #30000;
158 //        key = 0;
159 //        #20000;
160 //        key = 1;
161 //        #50000000;
162     end
163     
164     reg [31:0] rand;
165 //    initial begin
166 //        rand = {$random} %10000000;
167 //        #rand key = ~key;
168         
169 //    end
170   
171     task press_key;
172         input [3:0] seed;
173         begin
174             key = 1;
175             #20000000;
176             //按下按键
177             repeat(5)begin
178                 rand = {$random(seed)} %10000000;
179                 #rand key = ~key;
180             end
181             key = 0;
182             #40000000;
183             //释放按键
184             repeat(5)begin
185                 rand = {$random(seed)} %10000000;
186                 #rand key = ~key;
187             end
188             key = 1;
189             #40000000;
190             
191         end
192     endtask
193 endmodule

2023-03-28 11:34:55