Digital IC design study notes
Key debounce module 1
1 原理图
2 Verilog 代码
3 Modelsim仿真
1. Schematic
(1). Key waveform diagram The
ideal key signal is between 0 and 1, which can be completed instantaneously; when the key is pressed, a jitter signal of a certain time range will be generated, and the duration of the jitter signal is set as 20ms.
(2). key_flag, key_state waveform diagram The
first waveform is the key signal key; the
second waveform is the key_flag signal, when the jitter waveform is filtered out, a single-cycle high pulse is generated; the
third waveform is the key_state signal, when filtering After removing the jitter waveform, it transforms into a waveform consistent with the key signal;
(3). State transition diagram
2 Verilog code
//----top module---------------------------------
module fsm_key_filter#(
parameter IDLE = 4'b0001,
parameter FILTER1 = 4'b0010,
parameter DOWN = 4'b0100,
parameter FILTER2 = 4'b1000
)
(
input clk, //50MHz 20us
input rst_n,
input key,
output key_flag,
output reg key_state
);
reg cnt_en;
reg cnt_full;
reg [19:0] cnt1;
//reg [19:0] cnt2;
reg [3:0] state;
reg key_syn1;
reg key_syn2;
reg key_reg1;
reg key_reg2;
wire pos_edge;
wire neg_edge;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
state <= IDLE;
cnt_en <= 1'b0;
end else
begin
case(state)
IDLE:
begin
if(neg_edge)begin
state <= FILTER1;
cnt_en <= 1'b1;
end else
begin
state <= IDLE;
cnt_en <= 1'b0;
end
end
FILTER1:
begin
if(cnt_full)//20ms
begin
state <= DOWN;
cnt_en <= 1'b0;
end
else if(pos_edge)
begin
state <= IDLE;
cnt_en <= 1'b0;
end else
begin
state <= FILTER1;
cnt_en <= cnt_en;
end
end
DOWN:
begin
if(pos_edge)begin
cnt_en <= 1'b1;
state <= FILTER2;
end else
begin
cnt_en <= 1'b0;
state <= DOWN;
end
end
FILTER2:
begin
if(cnt_full)
state <= IDLE;
else if(neg_edge)begin
cnt_en <= 1'b0;
state <= DOWN;
end
else
state <= FILTER2;
end
default: begin
state <= IDLE;
cnt_en <= 1'b0;
end
endcase
end
//----cnt--------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt1 <= 20'd0;
else if(cnt_en)
cnt1 <= cnt1 + 20'd1;
else
cnt1 <= 20'd0;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt_full <= 1'b0;
else if(cnt1 == 20'd999_999)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;
end
//----asyn_key-->syn---------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
key_syn1 <= 1'b0;
key_syn2 <= 1'b0;
end else
begin
key_syn1 <= key;
key_syn2 <= key_syn1;
end
end
//----key edge detect--------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
key_reg1 <= 1'b0;
key_reg2 <= 1'b0;
end else
begin
key_reg1 <= key_syn2;
key_reg2 <= key_reg1;
end
end
assign neg_edge = (!key_reg1) & key_reg2;
assign pos_edge = key_reg1 & (!key_reg2);
//----key_flag---------------------------------------
// always@(posedge clk or negedge rst_n)
// if(!rst_n)
// key_flag <= 0;
// else if(cnt_full)
// key_flag <= 1;
// else
// key_flag <= 0;
assign key_flag = (cnt1 == 20'd999_999)? 1'b1:1'b0;
//----key_state--------------------------------------
always@(posedge clk or negedge rst_n)
if(!rst_n)
key_state <= 1;
else if(cnt_full)
key_state <= ~key_state;
else
key_state <= key_state;
endmodule
//----------------------------------------------------
//----testbench--------------------------------------
`timescale 1ns/1ns
`define clock_period 20
module tb_fsm_key_filter;
reg clk;
reg rst_n;
reg key;
wire key_flag;
wire key_state;
fsm_key_filter uut(
.clk(clk),
.rst_n(rst_n),
.key(key),
.key_flag(key_flag),
.key_state(key_state)
);
initial clk = 1;
always #(`clock_period/2) clk = ~clk;
initial begin
rst_n = 0;
key = 1;//before press
#(`clock_period*10);
rst_n = 1;
#(`clock_period*1000000+1);
//-----------第一种testbench------------------
//-------------------------------------
//----first time-----------------------
//----press--------------------
// //---jitter------------
// key = 0;
// #1000;key = 1;
// #2000;key = 0;
// #1400;key = 1;
// #2600;key = 0;
// #1300;key = 1;
// #20; key = 0;
// //---non jitter--------
// #20000100;
// #50000100;
-----------------------------
//
----release------------------
// //---jitter------------
// #1000;key = 1;
// #2000;key = 0;
// #1400;key = 1;
// #2600;key = 0;
// #1300;key = 1;
// //---non jitter-------------
// #20000100;
-------------------------------------
----second time----------------------
----press--------------------
// //---jitter------------
// key = 0;
// #1000;key = 1;
// #2000;key = 0;
// #1400;key = 1;
// #2600;key = 0;
// #1300;key = 1;
// #20; key = 0;
// //---non jitter--------
// #20000100;
// #50000100;
-----------------------------
//
----release------------------
// //---jitter------------
// #1000;key = 1;
// #2000;key = 0;
// #1400;key = 1;
// #2600;key = 0;
// #1300;key = 1;
// //---non jitter-------------
// #20000100;
//
//-----------第二种testbench------------------
press_key;
#10000;
press_key;
#10000;
press_key;
#10000;
//#50000100;
$stop;
end
reg [15:0] myrand;
task press_key;
begin
repeat(50)begin
myrand = {
$random}%65536;//0~65535;
#myrand; key = ~key;
end
key = 0;
#50000000;
repeat(50)begin
myrand = {
$random}%65536;//0~65535;
#myrand; key = ~key;
end
key = 1;
#50000000;
end
endtask
endmodule
Testbench: The
first type lists the excitation signals in detail, which is simple but the code is verbose; the
second type uses task, which generates the function $random randomly, and the code is simple; the
third type uses a simulation model, and a single module generates the excitation signal, which is mostly used for authentic memory. Models, etc.; (simulation models are generally provided by the government)
//----------------------------------------------------
//----第三种test bench--------------------------------------
`timescale 1ns/1ns
`define clock_period 20
module tb2_fsm_key_filter;
reg clk;
reg rst_n;
wire key;
wire key_flag;
wire key_state;
fsm_key_filter uut1(
.clk(clk),
.rst_n(rst_n),
.key(key),
.key_flag(key_flag),
.key_state(key_state)
);
fsm_filter_model uut2(
.key(key)
);
initial clk = 1;
always #(`clock_period/2) clk = ~clk;
initial begin
rst_n = 0;
#(`clock_period*10);
rst_n = 1;
#(`clock_period*1000000+1);
// #50000100;
// $stop;
end
//----仿真模型-------------------------------
`timescale 1ns/1ns
module fsm_filter_model(
output reg key
);
reg [15:0] myrand;
initial begin
key = 1;//before press
press_key;
#10000;
press_key;
#10000;
press_key;
#10000;
//#50000100;
$stop;
end
task press_key;
begin
repeat(50)begin
myrand = {
$random}%65536;//{$random}%6553(0~65535);{random}%65536:(-65535~65535)
#myrand; key = ~key;
end
key = 0;
#50000000;
repeat(50)begin
myrand = {
$random}%65536;//0~65535;
#myrand; key = ~key;
end
key = 1;
#50000000;
end
endtask
endmodule
endmodule
How to load the simulation model to the testbench?
(Quartus) Since the internal logic statements of the simulation model cannot be synthesized, the simulation model needs to be added to the testbench before the simulation, and press the operation to execute:
Assignment–> setting–>simulation–>1–>2–>3–>4 ,
And then perform RTL simulation.
3 Modelsim simulation
The original content of learning comes from Xiaomei Ge FPGA self-study notes
[Note]: Personal study notes, if there are any mistakes, please feel free to enlighten me. This is polite~~~