当前位置: 首页 > backend >正文

Zynq开发实践(FPGA之按键输入)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        led显示是数字电路中的输出部分,最简单的应用场景。那输入部分的话,就是按键。这样按键和led,就是最简单的输入和输出部分。很多开发板也是会以这两个case作为范例,来进行教学处理。这样学完之后,大家有一个基本的印象,即用fpga如何来描述输入输出电路。

1、按键的特点

        其实按键最大的一个问题就是抖动。按键没有按下去的时候,一般就是一个高电平。但是按下去之后,就变成了低电平。中间呢,因为抖动的原因,还有可能恢复成高电平,这是比较麻烦的事情。后期按键恢复的时候,也会出现这个情况。

2、软件如何解决

        大家解决这个问题之前,可以试想一下,如果是软件,该怎么解决。因为嵌入式mcu、和fpga两者本质上是一样的处理思路。处理fpga,只不过是把软件处理的思路转变成fpga描述电路。所以,我们如果是软件处理按键,一般这么来做,

while(1)
{// read gpio valuegpio_value = read_gpio();if(gpio_old == gpio_value){sleep(5ms);continue;}sleep(10ms);gpio_value = read_gpio();if(gpio_old != gpio_value){report_event(gpio_value);gpio_old = gpio_value;}
}

        首先,我们需要定时轮询这个数值,如果相同,下次继续轮询。一旦发现不同,就需要sleep大约10ms。这个10ms就是去除硬件抖动的时间,再次读取gpio_value。如果发现还是发现不同,就及时上报。至于是上升沿上报,还是下降沿上报,就看自己的需求了。

3、fpga如何实现

        本质上,fpga处理的方法和软件处理的方法是一样的。只不过fpga是并发处理,可以降低cpu轮询时间。并且fpga还有一个好处,那就是不管多少个gpio,对它来说都是一样的处理速度,本来每一个端口都是并发的。同样,我们首先需要依次读入信号,

// input signalalways @(posedge clk or negedge rst)if(!rst) beginin1 <= 1'b1;in2 <= 1'b1;end else beginin1 <= in;in2 <= in1;end

        接着就是添加一个状态机。添加的目的,主要还是为了方便编写verilog,利用寄存器编写状态机可以让整个流程更加清晰。

// state machinealways @(posedge clk or negedge rst) // state machine defined hereif(!rst)state <= 1'b0;else if(in1 != in2 && state == 1'b0)state <= 1'b1;else if(count == `TIME_DELAY && state == 1'b1)state <= 1'b0;

        软件处理的时候是统一计数10ms。那么硬件处理的时候,其实也需要进行计数处理。因为硬件触发可能存在抖动,如果发生这一情况,还需要重新开始计数处理,

// about counteralways@(posedge clk or negedge rst)if(!rst)count <= 16'h0;else if(state == 1'b1) beginif(count == `TIME_DELAY || in1 != in2)count <= 16'h0;elsecount <= count + 16'h1;end

        最后就是统一输出处理。等到计数时间达到要求的时候,才开始进行统一的输出。这个时候再根据输出来判断按键事件,就会容易很多。

// out signalalways@(posedge clk or negedge rst)if(!rst)out1 <= 1'b1;else if(count == `TIME_DELAY && state == 1'b1)out1 <= in2;always @(posedge clk or negedge rst)if(!rst)out2 <= 1'b1;elseout2 <= out1;// final resultalways @(*)if(!rst)out = 1'b0;else if(!out1 & out2)out = 1'b1;else // or out1&!out2out = 1'b0;

4、验证和测试

        代码写好之后,在上板子之前一定要自己仿真测试一下。一方面效率比较高,可以去除简单的语法错误,还可以验证功能,特别是corner case。这个时候,我们写的test case是这样的,

`timescale 1ns/1ps
module test();reg rst;
reg clk;
reg in;
wire out;key key(.rst(rst),.clk(clk),.in(in),.out(out));initialbeginrst = 1;in = 1;clk = 0;#12 rst = 0;#21 rst = 1;#35 in = 0;#50 in = 1;#70 in = 0;#500 in = 1;#1000 $finish;endinitial
beginwhile(1)clk = #5 !clk;
endinitial
begin$dumpfile("hello.vcd");$dumpvars(0, test);
endendmodule

        执行之后,就是这样的逻辑图,

        最后给出完整的verilog代码,有需求的同学可以好好看下按键输入是怎么处理的,


module key(input clk, //50M clkinput rst,input in,output reg out);`define TIME_DELAY 16'h20reg in1;
reg in2;
reg out1;
reg out2;
reg state;
reg[15:0] count;// input signalalways @(posedge clk or negedge rst)if(!rst) beginin1 <= 1'b1;in2 <= 1'b1;end else beginin1 <= in;in2 <= in1;end// state machinealways @(posedge clk or negedge rst) // state machine defined hereif(!rst)state <= 1'b0;else if(in1 != in2 && state == 1'b0)state <= 1'b1;else if(count == `TIME_DELAY && state == 1'b1)state <= 1'b0;// about counteralways@(posedge clk or negedge rst)if(!rst)count <= 16'h0;else if(state == 1'b1) beginif(count == `TIME_DELAY || in1 != in2)count <= 16'h0;elsecount <= count + 16'h1;end// out signalalways@(posedge clk or negedge rst)if(!rst)out1 <= 1'b1;else if(count == `TIME_DELAY && state == 1'b1)out1 <= in2;always @(posedge clk or negedge rst)if(!rst)out2 <= 1'b1;elseout2 <= out1;// final resultalways @(*)if(!rst)out = 1'b0;else if(!out1 & out2)out = 1'b1;else // or out1&!out2out = 1'b0;endmodule

        

http://www.xdnf.cn/news/19006.html

相关文章:

  • el-select多选下拉框出现了e611
  • 参数模板优化配置指南:从基础到进阶的完整解决方案
  • 学习游戏制作记录(音频的制作和使用)8.28
  • iOS开发之苹果系统包含的所有字体库
  • Node.js汉字转拼音指南:pinyin-pro全解析
  • R 语言 + 卒中 Meta 分析
  • 神经网络|(十六)概率论基础知识-伽马函数·中
  • vant Overlay 遮罩层内元素无法滚动解决方案
  • Java 大视界 -- Java 大数据在智能安防入侵检测系统中的多模态数据融合与检测精度提升(405)
  • 手写链路追踪
  • 新手向:从零开始理解百度语音识别API的Python实现
  • 跨境物流数字化转型怎么做?集运/转运系统定制,源码交付,助力企业降本增效,抢占市场先机
  • 【前端教程】JavaScript 对象与数组操作实战:从基础到优化
  • linux安装海康工业相机MVS SDK(3.0)会导致ROS的jsk插件崩溃
  • Java IO 流-详解
  • 从零开始学习单片机16
  • 循环高级(2)
  • 血缘元数据采集开放标准:OpenLineage Integrations Manually Annotated Lineage
  • 企业级数据库管理实战(二):数据库权限最小化原则的落地方法
  • 【分治法 BFS 质因数分解】P12255 [蓝桥杯 2024 国 Java B] 园丁|普及+
  • 智慧养老建设方案(PPT)
  • 开源大语言模型(Qwen3)
  • 深入探讨可视化技术如何实现安全监测
  • 【小白笔记】Visual Studio 在 2025年7月更新的功能说明(英文单词记忆)
  • 智慧工地系统:基于Java微服务与信创国产化的建筑施工数字化管理平台
  • 171-178CSS3新增
  • NullPointerException 空指针异常,为什么老是遇到?
  • 评价指标FID/R Precision
  • vscode编辑器中设置断点,不会自动启动调试器
  • 介绍⼀下Llama的结构