作者:李西銳??校對:陸輝
大俠好,歡迎來到FPGA技術(shù)江湖。本系列將帶來FPGA的系統(tǒng)性學(xué)習(xí),從最基本的數(shù)字電路基礎(chǔ)開始,最詳細(xì)操作步驟,最直白的言語描述,手把手的“傻瓜式”講解,讓電子、信息、通信類專業(yè)學(xué)生、初入職場小白及打算進(jìn)階提升的職業(yè)開發(fā)者都可以有系統(tǒng)性學(xué)習(xí)的機(jī)會。
系統(tǒng)性的掌握技術(shù)開發(fā)以及相關(guān)要求,對個人就業(yè)以及職業(yè)發(fā)展都有著潛在的幫助,希望對大家有所幫助。本次帶來Vivado系列,按鍵的使用教程。話不多說,上貨。
按鍵的使用教程
按鍵是我們使用比較多的器件之一,其結(jié)構(gòu)簡單,使用方便。在玩具、家電等方面有廣泛的應(yīng)用。
按鍵是一種應(yīng)用比較多的一種電子開關(guān),在我們開發(fā)板上有兩種按鍵開關(guān):第一種是本章節(jié)需要講解的輕觸開關(guān),第二種是自鎖按鍵,按鍵按下后保持自鎖狀態(tài),整個按鍵處于一直連通狀態(tài),再次按下,開關(guān)斷開,同時開關(guān)按鈕彈出。
本次我們實(shí)驗(yàn)任務(wù),將使用按鍵控制LED燈點(diǎn)亮,當(dāng)按鍵按下時,LED燈亮,松開熄滅。
分析電路可知,當(dāng)我們的按鍵沒有按下時,F(xiàn)PGA管腳為高電平,按鍵按下,F(xiàn)PGA管腳被短路,電平為低電平。所以我們的按鍵按下為低松開為高。那么在我們設(shè)計(jì)實(shí)驗(yàn)邏輯時,可以用按鍵的低電平控制LED燈點(diǎn)亮。
對應(yīng)的XDC約束語句如下:
我們按鍵信號作為控制信號來使用,但是我們不能直接去使用,因?yàn)檩p觸按鍵在按下或者松開時,信號非常不穩(wěn)定,會導(dǎo)致在按鍵沒有完全按下或者松開時,信號出現(xiàn)很多的毛刺,這樣的信號不能作為我們的控制信號,所以我們在寫控制邏輯之前,我們首先需要對按鍵做一下消抖處理,實(shí)現(xiàn)信號穩(wěn)定。我們處理的原理是,當(dāng)信號一直處于低電平或者高電平一段時間后,我們默認(rèn)信號處于穩(wěn)定狀態(tài),這個時間我們暫定為10ms。
接下來我們先進(jìn)行新建工程,首先點(diǎn)擊create project。
然后在打開的界面修改工程名字為key_led。
保存位置確定后,點(diǎn)擊next。
我們選擇RTL Project,點(diǎn)擊next。
我們在搜索窗口搜索我們板子的芯片型號,確定好之后點(diǎn)擊next。
點(diǎn)擊Finish完成新建工程。新建完成之后,我們開始根據(jù)前面我們所講的理論開始寫代碼。
點(diǎn)擊上圖紅色方框的加號開始新建代碼文件。
點(diǎn)擊next。選擇創(chuàng)建文件。
比如我們新建頂層文件,名字為key_led。
點(diǎn)擊OK之后開始寫代碼,代碼內(nèi)容如下:
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的邏輯,當(dāng)按鍵為低電平時,LED燈點(diǎn)亮。代碼如下:
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
邏輯控制寫好之后,我們做一下仿真,在仿真中,我們?yōu)榱丝焖倏吹浆F(xiàn)象,我們將參數(shù)修改的小一些。代碼如下:
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燈為高電平,此時燈亮。