FPGA知识基础之--500ms计数器,边沿检测,按键消抖


前言


一、边沿检测

1.1 使用背景

在我们设计电路时,经常会遇到需要继续检测上升沿和下降沿的电路,因此需要对边沿继续检测

1.2 方法:打拍法

1.2.1 背景

data数据信号不是时钟信号,不稳定,有许多毛刺,不能直接利用always语句中的posedge和nesedge来检测,因此需要通过其他办法来对边沿进行检测
有关毛刺,在数字电路的竞争与冒险中有讲解,是一个很重要的概念,希望读者先行掌握

在这里插入图片描述

1.2.2 原理

采用两个寄存器,对data数据信号进行打两拍处理,来消除数据不稳定产生的毛刺
在这里插入图片描述

1.2.3 上升沿

在这里插入图片描述由上述波形图可知:上升沿脉冲即为data_0为0 ,data_1为1时所取的信号
代码

module pos_data(
input 			sys_clk,
input 			sys_rst_n,
input 			data,
			
output			pos_data
);

reg 			data_0;
reg 			data_1;

always @(posedge sys_clk or negedge sys_rst_n) begin
	if(!sys_rst_n)
		begin 
			data_0 <= 1'd0;
			data_1 <= 1'd0;
		end
	else 
		begin
			data_0 <= data;
			data_1 <= data_0;
		end 
end 

assign pos_data = data_0 && ~data_1; //若是下降沿,则改为~data_0 && data_1;若是边缘,则改为 data_0 ^ data_1
endmodule

tb代码



`timescale 1ns / 1ns        

module tb_pos_data();

//parameter define
parameter  CLK_PERIOD = 20;           
      

//reg define
reg           sys_clk;
reg           sys_rst_n;
reg           data;

//wire define
wire         pos_data;


initial begin
    sys_clk <= 1'b0;
    sys_rst_n <= 1'b0;
    data <= 1'b0;
    #200
    sys_rst_n <= 1'b1;

    #200
    data <= 1'b1;
    #200
    data <= 1'b0;
    #200
    data <= 1'b1;

end


always #(CLK_PERIOD/2) sys_clk = ~sys_clk;


pos_data  u_pos_data(
    .sys_clk      (sys_clk),
    .sys_rst_n    (sys_rst_n),
    .data          (data),
    .pos_data        (pos_data)
    );

endmodule


波形

在这里插入图片描述

需要注意的是,在编写Testbench时,要将data改变的时间间隔延长一些,否则结果不明显

二、计数器

2.1 原理

计时500ms用寄存器cnt_500;因为晶振为50MHZ,即20ns,所以需要cnt记到25000时清零,25000转化为二进制为0110 0001 1010 1000,有15位,所以cnt需要定义为15位
在这里插入图片描述

2.2 RTL代码

module cnt_500(
input                   sys_clk,
input                   sys_rst_n,

output  reg  [14:0]      cnt

);

parameter  CNT_MAX = 25000 ;

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) 
        cnt <= 15'd0;
    else if (cnt < (CNT_MAX - 1'd1))
        cnt <= cnt + 1'd1;
    else 
        cnt <= 1'd0;
    
end

endmodule

Testbench代码


`timescale 1ns / 1ns   
module tb_cnt_500();

parameter CLK_PERIOD = 20;


reg            sys_clk;
reg           sys_rst_n;

wire   [14:0]     cnt ;






always #(CLK_PERIOD/2) sys_clk = ~sys_clk;

initial begin
    sys_clk <= 1'd0;
    sys_rst_n <= 1'd0;
    #200
    sys_rst_n <= 1'd1;


    
end

cnt_500 u_cnt_500(
    .sys_clk     (sys_clk),
    .sys_rst_n   (sys_rst_n),
    .cnt          (cnt)
);

endmodule

波形

在这里插入图片描述
符合预期

三、按键消抖

RTL代码

module key_debounce(  
input       sys_clk,
input       sys_rst_n,
input       key,

output   reg   key_filter
);

parameter CNT_MAX = 1000; //延时20ms


reg key_0;
reg key_1;
reg   [9:0] cnt;

always @(posedge sys_clk or negedge sys_rst_n) begin 
    if(!sys_rst_n) begin
        key_0 <= 1'b0;
        key_1 <= 1'b0;
    end
    else
    begin
        key_0    <= key;
        key_1   <= key_0;
    end 
end

always @(posedge sys_clk or negedge sys_rst_n) begin 
    if(!sys_rst_n) 
        cnt <= 0;
    else if  ( key_0 !=  key_1 | cnt == (CNT_MAX - 1)) 
        cnt <= 0;
    else if (cnt < (CNT_MAX - 1) )
        cnt <= cnt + 1;
    
    
   
end

always @(posedge sys_clk or negedge sys_rst_n) begin 
    if(!sys_rst_n) 
        key_filter <= 1;
    else if  (cnt == (CNT_MAX-1))
        key_filter <= key_1;
end 


endmodule

Testbench代码

`timescale 1ns/1ns 
module tb_key_debounce();


reg key;
reg sys_clk;
reg sys_rst_n;

wire key_filter;

parameter CLK_PERIOD = 20;
parameter CNT_MAX = 10;//延时200ns


initial begin
    sys_clk <= 1'd0;
    sys_rst_n <= 1'd0;
    key <= 1'd1;
    #10
    sys_rst_n <= 1'd1;
    key <= 1'd0;
    #20
    key <= 1'd1;
    #30
    key <= 1'd0;
    #300
    key <= 1'd1;
    #20
    key <= 1'd0;
    #10
    key <= 1'd1;
    #30
    key <= 1'd0;

end


always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
key_debounce #(
        .CNT_MAX    (CNT_MAX)
)
    u_key_debounce(
        .sys_clk    (sys_clk),
        .sys_rst_n  (sys_rst_n),
        .key        (key),

        .key_filter (key_filter)
);


endmodule

波形展示
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值