0 實驗環境
0.1 軟件環境
- ISE 14.7
- win10
- vivado 2017.4
0.2 硬件設備
- ISE適用的FPGA開發板:ALINK AX309
1 需求
能夠靈活控制4個LED燈
2 Verilog實現
`timescale 1ns / 1ps
//
// Create Date: 14:18:20 08/08/2020
// Module Name: led
// Revision 0.01 - File Created
//
module led(input clk,input rst,output reg led);//define the time counterreg [31:0] timer;// cycle counter:from 0 to 4 secalways@(posedge clk or negedge rst)beginif (rst == 1'b0)timer <= 32'd0; //when the reset signal valid,time counter clearingelse if (timer == 32'd39_999_999) //4 seconds count(50M*4-1=199999999)timer <= 32'd0; //count done,clearing the time counterelsetimer <= timer + 32'd1; //timer counter = timer counter + 1end// LED controlalways@(posedge clk or negedge rst)begin if (rst == 1'b0) led <= 1'b0; //when the reset signal activeelse if (timer == 32'd49_999_999) //time counter count to 1st sec,LED1 lightenled <= 1'b1;else if(timer == 32'd99_999_999)led <= 1'b0;endendmodule
功能說明:
- 輸入:時鐘clk和復位鍵rst信號(clk是50MHz)
- 輸出:發出控制一個led燈的信號
- 對于led信號,初始為0,間隔1秒,變成1,再間隔1秒,變成0,循環往復
時間說明:
50MHz對應的時鐘周期是0.02μs,因此,1s需要 50 * 10^6
個時鐘周期。
初始的timer = 0
,因此,實際的1s,對應timer = 32'd_49_999_999
,也就是50_000_000
個時鐘周期。
3 仿真測試(略)
不是本次實驗的重點,略。
4 綜合測試
直接在ISE軟件執行綜合即可。
5 管腳分配
這是本文的重點。 需要理解
- Verilog代碼(
.v
文件)如何與ucf
文件建立關聯 - 代碼如何與實際的硬件平臺管腳建立關聯
5.1 建立.ucf
文件
我們先在ISE建立一個.ucf
文件,然后分配管腳。
關于具體的管腳分配信息,需要參照開發板使用說明書。
NET "clk" LOC = T8 | TNM_NET = sys_clk_pin;
TIMESPEC TS_sys_clk_pin = PERIOD sys_clk_pin 50000 kHz;##
NET rst LOC = L3 | IOSTANDARD = "LVCMOS33"; ## reset pushbutton
##########LED Pin define#####################
NET led LOC = P5 | IOSTANDARD = "LVCMOS33"; ## LED1
重要的說明
- 以上代碼直接被開發板說明給出,不需要自己改,除非你有特定需求
- 需要注意的是自己編寫的Verilog代碼的信號名稱,必須與上述代碼的
NET
后面的信號保持一致。例如
- 時鐘信號必須是
clk
- 復位信號必須是
rst
- LED燈信號必須是
led
NET
后面的內容,是與Verilog代碼信號建立關聯,而LOC
后面的內容,則是與硬件設備的引腳建立關聯,之后的部分是電壓,可以先不管。
重要的公式:NET “端口名稱” LOC = 引腳編號 | IOSTANDARD = “電壓” ;
這是非常重要的,我們在進行管腳分配的時候,就是按照這樣的方式分配的。
- 代碼模擬的硬件設備,突出的就是輸入輸出端口,與Verilog設計有關
- 硬件設備,突出的就是引腳,與硬件有關
- 紅色的雙箭頭,就是二者的關聯,與
.ucf
文件有關,它的NET端口名
必須和Verilog端口名一樣,LOC管腳編號
以及電壓,必須和硬件設備一樣
對于以下ucf
內容
########LED Pin define#####################
NET led<0> LOC = P4 | IOSTANDARD = "LVCMOS33"; ## LED1
NET led<1> LOC = N5 | IOSTANDARD = "LVCMOS33"; ## LED2
NET led<2> LOC = P5 | IOSTANDARD = "LVCMOS33"; ## LED3
NET led<3> LOC = M6 | IOSTANDARD = "LVCMOS33"; ## LED4
值得注意的是<0>
這部分。
首先,led引腳的位寬是1,嗯,通常引腳是1位,這樣靈活性高(還是得參考對應的說明文檔)。
LED的說明如下
你很容易知道LED燈引腳位寬是1,為0的時候不亮,為1的時候點亮。
########LED Pin define#####################
NET led<0> LOC = P4 | IOSTANDARD = "LVCMOS33"; ## LED1
NET led<1> LOC = N5 | IOSTANDARD = "LVCMOS33"; ## LED2
NET led<2> LOC = P5 | IOSTANDARD = "LVCMOS33"; ## LED3
NET led<3> LOC = M6 | IOSTANDARD = "LVCMOS33"; ## LED4
但是這與<>
無關,引腳的事情,是LOC
后面內容的事情,<>
是端口的事情,那么,尖括號對應端口究竟是怎么回事?
猜想,然后試一下就好了!
我們之前的led輸出信號是1位,現在我們改一下
output reg[1:0] led
然后再把LED control改改
// LED controlalways@(posedge clk or negedge rst)begin if (rst == 1'b0) led <= 1'b0; else if (timer == 32'd19_999_999) led <= 2'b01;else if(timer == 32'd39_999_999)led <= 2'b10;end
注意變化,關注led <= 2'b01;
,
然后我們再改改.ucf
文件
########LED Pin define#####################
NET led<0> LOC = P4 | IOSTANDARD = "LVCMOS33"; ## LED1
NET led<1> LOC = N5 | IOSTANDARD = "LVCMOS33"; ## LED2
之后上板測試,很容易得到結論。
如果你還沒有得到,不妨試一下3位寬,4位寬的led信號。
結論是:led<0>
的0
對應的是output reg[1:0] led
信號的led[0]
,而led<1>
對應的是led[1]
。
分治思想:區分端口名與管腳編號
對于.ucf
文件
NET
的值是端口名,與Verilog中的端口名稱完全一致,如果是多位寬,則按照上面的結論寫上<number>
LOC
的值是管腳編號,根據你的需求,你需要將合適的管腳(對應的器件)與合適的端口建立連接
對于同樣一個led<0>
,它可以分配的引腳有多種選擇,不過,需要遵循的是
- 引腳對應的器件必須是LED燈
- 引腳不能發生沖突(例如2個端口接到了同一個引腳,并且端口信號同一時間發出不同信息)
需要注意:
對于沒有的端口號,不能分配管腳!
這是顯而易見的,不過還是得多提示一下。
實驗思維
很多時候,不管是書籍還是說明文檔,都不可能詳細描述所有細節,但是,你依然可以通過試驗程序,猜測得出結論,然后你需要多次驗證(通過實驗,資料等)。
信息 = 位 + 上下文
以往,我們對于二進制數字1000
和0001
的反應可能是對應十進制8
和1
,但是對于本實驗(假設用了4個LED燈),它的含義就是只有LED4亮
和只有LED1亮
。
這也充分詮釋了二進制信息含義 = 位 + 上下文
的含義。