Verilog没有葵花宝典——day9(按键防抖)
题目
- 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz。
- 记录题目1中用到的工具,操作步骤,遇到的错误和提示信息。
第一题
用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz。
思路
假设按键按下时是低电平,松开时是高电平。监测按键由按下到松开整个过程,并用key_vld
信号来表示x消抖后的按键输出。进一步可以输出按下、松开的有效信号(边沿检测),甚至可以按键计时。使用状态机完成,伪状态转移图:
仿真图:
Verilog描述
module debounce
#(
parameter DELAY_TIME = 18'h3ffff
)
(
input clk,
input rst_n,
input key_in,
output reg key_vld
);
localparam IDLE = 4'b0001,
PRESS_DELAY = 4'b0010,
WAIT_RELEASE= 4'b0100,
RELEASE_DELA= 4'b1000;
reg [1:0] key_in_r;
wire key_press_edge;
wire key_release_edge;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_in_r <= 2'b11;
end else begin
key_in_r <= {key_in_r[0],key_in};
end
end
assign key_press_edge = key_in_r[1] & (~key_in_r[0]);
assign key_release_edge = (~key_in_r[1]) & key_in_r[0];
reg [17:0] cnt;
reg [3:0] cstate,nstate;
//FSM-1
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cstate <= IDLE;
end else begin
cstate <= nstate;
end
end
//FSM-2
always @(*) begin
case (cstate)
IDLE : nstate = key_press_edge ? PRESS_DELAY : IDLE;
PRESS_DELAY: begin
if (cnt==DELAY_TIME && key_in_r[0] == 0) begin
nstate = WAIT_RELEASE;//按下完成
end else if (cnt<DELAY_TIME && key_in_r[0] == 1) begin
nstate = IDLE;//抖动
end else begin
nstate = PRESS_DELAY;//计数未完成
end
end
WAIT_RELEASE: nstate = key_release_edge ? RELEASE_DELA : WAIT_RELEASE;
RELEASE_DELA: begin
if (cnt==DELAY_TIME && key_in_r[0] == 1) begin
nstate = IDLE;//松开完成
end else if (cnt<DELAY_TIME && key_in_r[0] == 0) begin
nstate = WAIT_RELEASE;//抖动
end else begin
nstate = RELEASE_DELA;//计数未完成
end
end
default: nstate = IDLE;
endcase
end
//FSM-3
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_vld <= 1'b1;
end else begin
case (nstate)
IDLE,PRESS_DELAY:key_vld <= 1'b1;
WAIT_RELEASE,RELEASE_DELA: key_vld <= 1'b0;
default: key_vld <= 1'b1;
endcase
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 18'd0;
else if (cstate==PRESS_DELAY || cstate==RELEASE_DELA) begin
if (cnt==DELAY_TIME) begin
cnt <= 18'd0;
end else begin
cnt <= cnt + 1'b1;
end
end else begin
cnt <= 18'd0;
end
end
endmodule
testbench
module tb_debounce;
reg clk ;
reg rst_n ;
reg key_in ;
wire key_vld ;
initial begin
clk = 1;
forever #10 clk = ~clk;
end
initial begin
rst_n = 1'b0;
#22 rst_n = 1'b1;
end
initial begin
key_in = 1'b1;
repeat(15) begin
@(posedge clk)
key_in = {$random};
end
repeat(25) begin
@(posedge clk)
key_in = 1'b0;
end
repeat(25) begin
@(posedge clk)
key_in = 1'b1;
end
repeat(15) begin
@(posedge clk)
key_in = {$random};
end
$finish;
end
debounce
#(
'd10
)
debounce
(
.clk (clk ),
.rst_n (rst_n ),
.key_in (key_in ),
.key_vld (key_vld)
);
endmodule
第二题
警告信息
Ignoring unknown option '-debug-all' passed to 'vcs' and continuing
原因是将-debug_all
写出了-debug-all
。
halftop
即将入行的数字IC设计工程师