按键抖动情况:
实际情况与要求:
分析状态:
状态转移图:
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不同,产生的随机数的序列也不同。而且,每执行一次 random根据seed来产生随机数。seed不同,产生的随机数的序列也不同。而且,每执行一次random(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也随即更新;在第二个时钟上升沿时,randnum取得第二个随机数,是random(更新后的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