有一种更精妙的防抖设计方法
parent
c1859093ec
commit
430f88e7be
@ -0,0 +1,187 @@
|
||||
`timescale 1ns/1ns
|
||||
|
||||
module tb_lm();
|
||||
|
||||
|
||||
reg k_1; // 显示的图像1
|
||||
reg k_2; // 显示的图像2
|
||||
|
||||
reg key; // 物理按键 开关显示, 该按键异步的, 每次按下 等于
|
||||
|
||||
reg key_1; // 物理按键的随时钟同步变化信号
|
||||
reg key_2; //
|
||||
reg is_show; // 互斥变化的
|
||||
reg [4:0] flag_time;
|
||||
|
||||
reg flag; // 状态改变周期 现在500纳秒改变一次状态, 显示相反的图像
|
||||
|
||||
reg sys_clk;
|
||||
reg sys_rst;
|
||||
|
||||
|
||||
reg [7:0]x;
|
||||
reg [7:0]y;
|
||||
|
||||
always #10 sys_clk = ~sys_clk;
|
||||
|
||||
initial begin
|
||||
sys_clk <= 1'b0;
|
||||
sys_rst <= 1'b0;
|
||||
#200
|
||||
sys_rst <= 1'b1;
|
||||
|
||||
// 延迟2000纳秒, 现在x 应该是0
|
||||
#2000
|
||||
|
||||
|
||||
key <= 1'b1;
|
||||
#120
|
||||
key <= 1'b0;
|
||||
#20
|
||||
|
||||
key <= 1'b1;
|
||||
#80
|
||||
key <= 1'b0;
|
||||
#20
|
||||
|
||||
key <= 1'b1;
|
||||
#90
|
||||
key <= 1'b0;
|
||||
#20
|
||||
|
||||
// 延迟4000纳秒观察
|
||||
{k_2, k_1} <= 2'b10;
|
||||
#3900
|
||||
{k_2, k_1} <= 2'b01;
|
||||
#3800
|
||||
|
||||
|
||||
key <= 1'b1;
|
||||
#20
|
||||
key <= 1'b0;
|
||||
#20
|
||||
|
||||
key <= 1'b1;
|
||||
#20
|
||||
key <= 1'b0;
|
||||
#20
|
||||
|
||||
key <= 1'b1;
|
||||
#90
|
||||
key <= 1'b0;
|
||||
#200
|
||||
|
||||
key <= 1'b1;
|
||||
#120
|
||||
key <= 1'b0;
|
||||
#20
|
||||
|
||||
key <= 1'b1;
|
||||
#120
|
||||
key <= 1'b0;
|
||||
#20
|
||||
|
||||
key <= 1'b1;
|
||||
#150
|
||||
key <= 1'b0;
|
||||
|
||||
end
|
||||
|
||||
|
||||
// 显示的时候计时
|
||||
always @(posedge sys_clk or negedge sys_rst) begin
|
||||
if (sys_rst == 1'b0) begin
|
||||
flag_time <= 5'd0;
|
||||
end
|
||||
else if (flag_time < (5'd25 - 5'd1) && is_show) begin
|
||||
flag_time <= flag_time + 5'd1;
|
||||
end
|
||||
else begin
|
||||
flag_time <= 5'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge sys_clk or negedge sys_rst) begin
|
||||
if (sys_rst == 1'b0) begin
|
||||
{k_2, k_1} <= 2'b11;
|
||||
x <= 8'b00000000;
|
||||
y <= 8'b11111111; // 所有的都显示算了
|
||||
end
|
||||
else if ({k_2, k_1} == 2'b10 && is_show) begin
|
||||
case (flag)
|
||||
1'b0: x <= 8'b1010_1010;
|
||||
1'b1: x <= 8'b0101_0101;
|
||||
endcase
|
||||
end
|
||||
else if ({k_2, k_1} == 2'b01 && is_show) begin
|
||||
case (flag)
|
||||
1'b0: x <= 8'b1111_0000;
|
||||
1'b1: x <= 8'b0000_1111;
|
||||
endcase
|
||||
end
|
||||
else begin
|
||||
x <= 8'b00000000;
|
||||
end
|
||||
end
|
||||
|
||||
// 每 显示500ns 改变显示的图像
|
||||
always @(posedge sys_clk or negedge sys_rst) begin
|
||||
if (sys_rst == 1'b0) begin
|
||||
flag <= 1'b0;
|
||||
end
|
||||
else if (flag_time == (5'd25 - 5'd1)) begin
|
||||
flag <= !flag;
|
||||
end
|
||||
else begin
|
||||
end
|
||||
end
|
||||
|
||||
// 异步信号, 通过比较上次时钟周期的状态和当前时钟周期的状态得到当前是否按下了
|
||||
always @(posedge sys_clk or negedge sys_rst) begin
|
||||
if (sys_rst == 1'b0) begin
|
||||
key <= 1'b0;
|
||||
key_1 <= 1'b0;
|
||||
key_2 <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
key_1 <= key;
|
||||
key_2 <= key_1;
|
||||
end
|
||||
end
|
||||
|
||||
reg [4:0] click_time; // max: 20
|
||||
always @(posedge sys_clk or negedge sys_rst) begin
|
||||
if (sys_rst == 1'b0) begin
|
||||
is_show <= 1'b0;
|
||||
click_time <= 5'd0;
|
||||
end
|
||||
|
||||
if (key_1 != key_2) begin
|
||||
click_time <= 5'd0;
|
||||
end
|
||||
else begin
|
||||
// 如果一直相同持续时间达到20个时钟周期
|
||||
if (click_time == (5'd20 - 5'd1)) begin
|
||||
// 当前的key就是可用的
|
||||
if (key_1) begin
|
||||
is_show <= !is_show;
|
||||
end
|
||||
else begin
|
||||
end
|
||||
end
|
||||
else begin
|
||||
click_time <= click_time + 5'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
lm u_lm(
|
||||
.x (x),
|
||||
.y (y)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue