您的位置:首页 > 财经 > 金融 > 文案素材网站_视频剪辑素材免费网站_企业培训考试_上海seo公司排名

文案素材网站_视频剪辑素材免费网站_企业培训考试_上海seo公司排名

2025/5/24 7:12:40 来源:https://blog.csdn.net/weixin_67907028/article/details/144247307  浏览:    关键词:文案素材网站_视频剪辑素材免费网站_企业培训考试_上海seo公司排名
文案素材网站_视频剪辑素材免费网站_企业培训考试_上海seo公司排名

基于ZYNQ-7000系列的FPGA学习笔记7——按键控制蜂鸣器(模块化编写)

  • 1. 实验要求
  • 2. 功能分析
  • 3. 模块设计
  • 4. 波形图
    • 4.1 按键消抖模块
    • 4.2 按键控制蜂鸣器模块
  • 5.代码编写
    • 5.1 rtl代码
    • 5.2 测试代码
  • 6. 代码仿真
  • 7. 添加约束文件并分析综合

在上期的内容中,我们通过模拟按键控制led,这一期学习的内容是:按键控制蜂鸣器

1. 实验要求

在这里插入图片描述

通过按键控制领航者底板上的蜂鸣器,要求如下:

  • 初始状态蜂鸣器响起
  • 按下一次按键,改变一次按键的状态
  • 需要对输入的按键信号进行消抖,消抖的时间为20ms
  • 按下复位按键,蜂鸣器恢复默认状态

2. 功能分析

首先我们需要看一下蜂鸣器相关的原理图:
在这里插入图片描述
可以看到蜂鸣器通过一个8050的三极管驱动,连接到FPGA芯片的Bank35 ,引脚为L23。需要让蜂鸣器叫的话,给高电平就可以。

关于按键部分的内容,可以参考本系列的前面几篇,这里不做介绍。

3. 模块设计

在这里插入图片描述
由于本次的实验内容中需要我们设计多个模块,所以我设计了上述的功能框图,可以分为下面三个子模块:

  1. 按键消抖模块:作用是对输入的按键信号进行一个20ms的消抖
  2. 按键控制蜂鸣器模块:作用是对消抖之后的数据边沿采集,通过采集到的信号沿控制蜂鸣器
  3. 按键控制蜂鸣器顶层模块:分别例化了按键消抖模块和按键控制蜂鸣器模块,完成整个实验要求。

4. 波形图

4.1 按键消抖模块

在这里插入图片描述
为了防止按键的输入信号在采集的过程中出现亚稳态,我这里进行了打两拍的操作。同时为了实现按键的消抖,我也定义了一个cnt,用来记录电平保持稳定的时间,当这个时间大于20ms时才任务是按键按下了,这样就实现了按键的消抖

4.2 按键控制蜂鸣器模块

在这里插入图片描述
由于按键控制蜂鸣器模块的按键输入是消抖的后的按键信息(已经打过两拍了),所以我这里只打一个拍,用来计算是否产生了下降沿,从而判断按键是否按下

【注】:由于顶层按键控制蜂鸣器只是例化了上述两个模块,因此这里就不绘制波形图了,之间看后面仿真结果就可以。

5.代码编写

5.1 rtl代码

  1. 按键消抖模块:key_filter.v
//模块的端口定义
module key_filter(input  sys_clk,input  sys_rst_n,input  key,output reg key_filter);reg key_d0;     // 打两拍的变量定义
reg key_d1;reg change;     //这个是用来确定的是否有电平变化的,为1表示有电平变化,为0表示没有//定义计数的变量,用来判断电平是否持续了20ms
reg [19:0] cnt;
//CNT_MAX用来确定按键消抖的时间, CNT_MAX =  20ms /  (1s / 50Mhz ) =  1000_000 ,其中20ms是消抖的时间,50Mhz是系统时钟频率
parameter CNT_MAX = 20'd1000_000;   //对输入的key信号,打两拍操作
always @(posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)   begin   //初始状态下,d0和d1都是高电平,和按键未按下时一致key_d0 <= 1'b1;key_d1 <= 1'b1;endelse begin       //运行状态下,开始打拍key_d0 <= key;key_d1 <= key_d0;end
end//检测是否有电平变化,如果有的话,把change置1,否则保持0
always @(posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)change <= 1'b0;else begin if ( key_d0 != key_d1 )change <= 1'b1;else change <= 1'b0;end
end//如果change为1,说明电平有变化,重新开始计数,否则cnt减一,减到0停止
always @(posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0) cnt <= 20'd0;else beginif(change == 1'b1)cnt <= CNT_MAX;else beginif(cnt >20'd0)cnt <= cnt - 20'd1;elsecnt <= 20'd0;endend
end//如果cnt顺利的减到了1,说明电平保持了20ms,可以输出
always @(posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0) key_filter <= 1'b1;else beginif(cnt == 20'd1)key_filter <= key_d1; elsekey_filter <= key_filter;end
endendmodule

大致流程如下:首先对输入的按键信号大量拍,判断是否按键的电平是否变化,如果变化就把cnt置为最大值,如果没有变化,cnt每个系统时钟减1,直到减到1,表示抖动结束,输出当前的按键信息,否则输出上一次的按键信息。

  1. 按键控制蜂鸣器模块:key_beep.v
    module key_beep(input sys_clk,input sys_rst_n,input key_filter, //消抖后按键值output reg beep //蜂鸣器
);reg key_filter_d0; //将消抖后的按键值延迟一个时钟周期wire neg_key_filter; //按键有效脉信号//捕获按键端口的下降沿,得到一个时钟周期的脉冲信号
assign neg_key_filter = (~key_filter) & key_filter_d0;//对按键端口的数据延迟一个时钟周期
always @ (posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_filter_d0 <= 1'b1;elsekey_filter_d0 <= key_filter;
end//每次按键按下时,就翻转蜂鸣器的状态
always @ (posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)beep <= 1'b1;else if(neg_key_filter) //有效的一次按键被按下beep <= ~beep;elsebeep <= beep;
end
endmodule

大致流程如下:对消抖之后的按键输入打一个拍,用来判断是否产生下降沿,如果产生下降沿,说明有按键按下,改变一次蜂鸣器的状态。

  1. 顶层按键控制蜂鸣器模块:top_key_beep.v
module top_key_beep(input sys_clk , //系统时钟input sys_rst_n , //系统复位,低电平有效input key , //按键output beep //蜂鸣器
);parameter CNT_MAX = 20'd100_0000; //消抖时间 20mswire key_filter ; //按键消抖后的值//例化按键消抖模块
key_filter #( .CNT_MAX (CNT_MAX) ) u_key_filter(.sys_clk        (sys_clk),.sys_rst_n      (sys_rst_n),.key            (key),.key_filter     (key_filter)
);//例化蜂鸣器控制模块
key_beep u_key_beep (.sys_clk        (sys_clk),.sys_rst_n      (sys_rst_n),.key_filter     (key_filter),.beep           (beep)
);
endmodule

5.2 测试代码

`timescale 1ns/1ns  //仿真单位/精度module tb_top_key_beep();parameter CLK_PERIOD = 20;      //时钟周期20ms
parameter CNT_MAX = 20'd10;     //消抖时间 200ns//定义输入和输出的变量
reg     sys_clk;
reg     sys_rst_n;
reg     key;wire beep;//这里用来产生按键按下的信息
initial beginsys_clk <=1'b0;sys_rst_n <=1'b0;key <= 1'b0;    #190sys_rst_n <=1'b1;key <= 1'b1;    //抖动开始#20key <= 1'b0;#30key <= 1'b1;#40key <= 1'b0;#30key <= 1'b1;#40key <= 1'b0;    //抖动结束#300key <= 1'b1;    //松开按键,抖动开始#40key <= 1'b0;#30key <= 1'b1;    //抖动结束   end//产生时钟
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;//例化测试设计
top_key_beep  #(.CNT_MAX (CNT_MAX) )  u_top_key_beep(.sys_clk    (sys_clk),.sys_rst_n  (sys_rst_n),.key        (key),.beep       (beep)
);endmodule

【注】:这里的测试代码只针对顶层文件,底层的模块测试代码,暂时不需要。

6. 代码仿真

如下是仿真的结果:
在这里插入图片描述
可以看到仿真的结果和我们话的波形图是基本一致的,并且小于200ns的抖动都已经被滤除了,很不错。

7. 添加约束文件并分析综合

首先我们添加对应的约束文件

#时序约束
create_clock -period 20.000 -name sys_clk [get_ports sys_clk]
#IO 管脚约束
set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports beep]
set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports key]
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]

完成之后,分析综合,得到如下结果:

  1. 顶层模块:
    在这里插入图片描述
    可以看到里面分别由两个子模块连接,下面是子模块的内部结构。

  2. 按键消抖模块

在这里插入图片描述

  1. 按键控制蜂鸣器模块
    在这里插入图片描述
    下一步就是生成比特流文件,然后上板调试了,这里结果我就还是不展示了。

以上就是本期的所有内容,创造不易,点个关注再走呗。

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com