作者:李西锐 校对:陆辉
大侠好,欢迎来到FPGA技术江湖。本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
系统性的掌握技术开发以及相关要求,对个人就业以及职业发展都有着潜在的帮助,希望对大家有所帮助。本次带来Vivado系列,按键的使用教程。话不多说,上货。
按键的使用教程
按键是我们使用比较多的器件之一,其结构简单,使用方便。在玩具、家电等方面有广泛的应用。
按键是一种应用比较多的一种电子开关,在我们开发板上有两种按键开关:第一种是本章节需要讲解的轻触开关,第二种是自锁按键,按键按下后保持自锁状态,整个按键处于一直连通状态,再次按下,开关断开,同时开关按钮弹出。
本次我们实验任务,将使用按键控制LED灯点亮,当按键按下时,LED灯亮,松开熄灭。
分析电路可知,当我们的按键没有按下时,FPGA管脚为高电平,按键按下,FPGA管脚被短路,电平为低电平。所以我们的按键按下为低松开为高。那么在我们设计实验逻辑时,可以用按键的低电平控制LED灯点亮。
对应的XDC约束语句如下:
我们按键信号作为控制信号来使用,但是我们不能直接去使用,因为轻触按键在按下或者松开时,信号非常不稳定,会导致在按键没有完全按下或者松开时,信号出现很多的毛刺,这样的信号不能作为我们的控制信号,所以我们在写控制逻辑之前,我们首先需要对按键做一下消抖处理,实现信号稳定。我们处理的原理是,当信号一直处于低电平或者高电平一段时间后,我们默认信号处于稳定状态,这个时间我们暂定为10ms。
接下来我们先进行新建工程,首先点击create project。
然后在打开的界面修改工程名字为key_led。
保存位置确定后,点击next。
我们选择RTL Project,点击next。
我们在搜索窗口搜索我们板子的芯片型号,确定好之后点击next。
点击Finish完成新建工程。新建完成之后,我们开始根据前面我们所讲的理论开始写代码。
点击上图红色方框的加号开始新建代码文件。
点击next。选择创建文件。
比如我们新建顶层文件,名字为key_led。
点击OK之后开始写代码,代码内容如下:
01 module jitter(
02
03 input wire clk,
04 input wire rst_n,
05 input wire key,
06
07 output reg flag
08 );
09
10 parameter t = 500_000;
11
12 reg [18:0] cnt;
13 reg state;
14
15 always @ (posedge clk, negedge rst_n)
16 begin
17 if(rst_n == 1'b0)
18 begin
19 cnt <= 19'd0;
20 state <= 1'd0;
21 flag <= 1'd1;
22 end
23 else
24 case(state)
25 1'd0 : begin
26 if(key == 1'b0)
27 begin
28 if(cnt == t - 1)
29 begin
30 cnt <= 19'd0;
31 state <= 1'd1;
32 flag <= 1'b0;
33 end
34 else
35 begin
36 cnt <= cnt + 1'b1;
37 state <= 1'd0;
38 flag <= 1'b1;
39 end
40 end
41 else
42 begin
43 cnt <= 19'd0;
44 state <= 1'd0;
45 flag <= 1'b1;
46 end
47 end
48 1'd1 : begin
49 if(key == 1'b1)
50 begin
51 if(cnt == t - 1)
52 begin
53 cnt <= 19'd0;
54 state <= 1'd0;
55 flag <= 1'b1;
56 end
57 else
58 begin
59 cnt <= cnt + 1'b1;
60 state <= 1'b1;
61 flag <= 1'b0;
62 end
63 end
64 else
65 begin
66 cnt <= 19'd0;
67 state <= 1'b1;
68 flag <= 1'b0;
69 end
70 end
71 endcase
72 end
73 endmodule
74
接下来是按键控制LED的逻辑,当按键为低电平时,LED灯点亮。代码如下:
01 module key_ctrl(
02
03 input wire clk,
04 input wire rst_n,
05 input wire flag,
06
07 output reg led
08 );
09
10 always @ (posedge clk, negedge rst_n)
11 begin
12 if(rst_n == 1'b0)
13 led <= 1'b0;
14 else if(flag == 1'b0)
15 led <= 1'b1;
16 else
17 led <= 1'b0;
18 end
19 endmodule
两个模块做好之后,我们在顶层文件中例化子模块:
01 module key_led(
02
03 input wire clk,
04 input wire rst_n,
05 input wire key,
06
07 output wire led
08 );
09
10 wire flag;
11
12 jitter jitter_inst(
13
14 .clk (clk),
15 .rst_n (rst_n),
16 .key (key),
17
18 .flag (flag)
19 );
20
21 key_ctrl key_ctrl_inst(
22
23 .clk (clk),
24 .rst_n (rst_n),
25 .flag (flag),
26
27 .led (led)
28 );
29
30 endmodule
逻辑控制写好之后,我们做一下仿真,在仿真中,我们为了快速看到现象,我们将参数修改的小一些。代码如下:
01 `timescale 1ns / 1ps
02
03 module key_led_tb;
04
05 reg clk;
06 reg rst_n;
07 reg key;
08
09 wire led;
10
11 defparam key_led_inst.jitter_inst.t = 100;
12
13 initial begin
14 clk = 0;
15 rst_n = 0;
16 key = 1;
17 #105;
18 rst_n = 1;
19 #1000;
20
21 //模拟按键按下时的抖动
22 key = 0;
23 #20;
24 key = 1;
25 #30;
26 key = 0;
27 #30;
28 key = 1;
29 #10;
30 key = 0;
31
32 #5000;
33
34 //模拟按键松开时的抖动
35 key = 1;
36 #30;
37 key = 0;
38 #30;
39 key = 1;
40 #10;
41 key = 0;
42 #50;
43 key = 1;
44
45 #1000;
46 $stop;
47 end
48
49 always #10 clk = ~clk;
50
51 key_led key_led_inst(
52
53 .clk (clk ),
54 .rst_n (rst_n ),
55 .key (key ),
56
57 .led (led )
58 );
59
60 endmodule
仿真波形:
Flag信号等效按键,flag拉低时,LED灯为高电平,此时灯亮。