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

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

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

1、按键的特点

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

2、软件如何解决

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

复制代码
while(1)
{
    // read gpio value
    gpio_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 signal

always @(posedge clk or negedge rst)
	if(!rst) begin
		in1 <= 1'b1;
		in2 <= 1'b1;
	end 
	else begin
		in1 <= in;
		in2 <= in1;
	end

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

复制代码
// state machine

always @(posedge clk or negedge rst) // state machine defined here
	if(!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 counter

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

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

复制代码
// out signal

always@(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;
	else
		out2 <= out1;

// final result

always @(*)
	if(!rst)
		out = 1'b0;
	else if(!out1 & out2)
		out = 1'b1;
	else // or out1&!out2
		out = 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));
 
initial
    begin
        rst = 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;
    end
 
 
initial
begin
    while(1)
    clk = #5 !clk;
end
 
initial
begin
    $dumpfile("hello.vcd");
    $dumpvars(0, test);
end
 
endmodule

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

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

复制代码
module key(input clk, //50M clk
		input rst,
		input in,
		output reg out);

`define TIME_DELAY 16'h20

reg in1;
reg in2;
reg out1;
reg out2;
reg state;
reg[15:0] count;

// input signal

always @(posedge clk or negedge rst)
	if(!rst) begin
		in1 <= 1'b1;
		in2 <= 1'b1;
	end 
	else begin
		in1 <= in;
		in2 <= in1;
	end

// state machine

always @(posedge clk or negedge rst) // state machine defined here
	if(!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 counter

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

// out signal

always@(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;
	else
		out2 <= out1;

// final result

always @(*)
	if(!rst)
		out = 1'b0;
	else if(!out1 & out2)
		out = 1'b1;
	else // or out1&!out2
		out = 1'b0;

endmodule
相关推荐
风已经起了18 分钟前
FPGA学习笔记——图像处理之对比度调节(直方图均衡化)
图像处理·笔记·学习·fpga开发·fpga
szxinmai主板定制专家3 小时前
基于ZYNQ的ARM+FPGA+yolo AI火灾实时监测与识别系统
arm开发·yolo·fpga开发
li星野4 小时前
打工人日报#20250925
程序人生·fpga开发
hahaha60166 小时前
PS_PL设计
fpga开发
ARM+FPGA+AI工业主板定制专家6 小时前
基于RK3576+MCU+FPGA的工业自动化控制板解决方案
fpga开发
9527华安8 小时前
FPGA实现双目摄像头红蓝3D融合,提供6套工程源码和技术支持
图像处理·3d·fpga开发·3d融合
#include<菜鸡>1 天前
AXI_CAN IP 简单使用。(仿真、microblaze)
网络协议·tcp/ip·fpga开发
风已经起了1 天前
FPGA学习笔记——图像处理之亮度调节(乘法型)
图像处理·笔记·学习·fpga开发·fpga
文火冰糖的硅基工坊1 天前
[硬件电路-320]:模拟电路与数字电路,两者均使用晶体管(如BJT、MOSFET),但模拟电路利用其线性区,数字电路利用其开关特性。
单片机·嵌入式硬件·数学建模·fpga开发·系统架构·信号处理
FPGA小c鸡2 天前
FPGA流水线除法器/加法器/乘法器_设计详解
fpga开发