需求:
- 博宸電子的ZYNQ7020DEV開(kāi)發(fā)板
- Vivado 2018.3
- 一定的verilog語(yǔ)言基礎(chǔ)
一.任務(wù)剖析
1.1 實(shí)驗(yàn)?zāi)康?/h3>
在1s內(nèi)實(shí)現(xiàn)開(kāi)發(fā)板上四個(gè)led燈的輪流閃爍,每個(gè)燈亮起0.25s.
1.2原理圖及其分析
在1s內(nèi)實(shí)現(xiàn)開(kāi)發(fā)板上四個(gè)led燈的輪流閃爍,每個(gè)燈亮起0.25s.
博主目前學(xué)習(xí)的是博宸電子的ZYNQ7020DEV開(kāi)發(fā)板,下面是關(guān)于本次分享led流水燈的原理圖
圖1 涉及本次led流水燈的電路
首先,從圖1來(lái)看,每個(gè)led端口都和一個(gè)阻值為4.7k的電阻和一個(gè)發(fā)光二極管相連,并且發(fā)光二極管負(fù)端接地。要使得led發(fā)光,那么就要令發(fā)光二極管導(dǎo)通,即led端口應(yīng)拉高。在編寫(xiě)代碼中,當(dāng)led輸入端口輸入為“1”時(shí),代表拉高。
圖2 涉及本次led流水燈的引腳
開(kāi)發(fā)板上共有六個(gè)led燈。LED1,LED2上電即點(diǎn)亮,故不考慮。
對(duì)于剩下的四個(gè)led燈,其引腳分配如下:
燈號(hào) | 引腳 |
---|---|
LED3 | Y14 |
LED4 | AA13 |
LED5 | AB14 |
LED6 | AB15 |
清楚了上述背景知識(shí),接下來(lái)我們就可以編寫(xiě)代碼啦。
二.總代碼
2.1 敲寫(xiě)代碼
2.1.1 代碼內(nèi)容
module led_stream(
input clk,
input rst_n,
output reg [3:0] led //設(shè)置為寄存器類型,否則第二個(gè)always模塊會(huì)報(bào)錯(cuò)
);
//定義一個(gè)1s的計(jì)時(shí)器,時(shí)鐘頻率為50MHz
reg [25:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt <= 26'd0;
else if(cnt < 26'd5000_0000)
cnt <= cnt + 1'b1;
else cnt <= 26'd0;
end
//通過(guò)計(jì)時(shí)器控制led交替閃爍,1s內(nèi)閃爍4個(gè)燈
always @(cnt) begin
if(cnt<26'd1250_0000) led <= 4'b0001;
if(cnt<26'd2500_0000 && cnt >= 26'd1250_0000) led <= 4'b0010;
if(cnt<26'd3750_0000 && cnt >= 26'd2500_0000) led <= 4'b0100;
if(cnt<26'd5000_0000 && cnt >= 26'd3750_0000) led <= 4'b1000;
end
endmodule
2.1.2 代碼分析
-
時(shí)間:
開(kāi)發(fā)板內(nèi)部自帶有一個(gè)50M赫茲的晶振,即系統(tǒng)時(shí)鐘clk為50M赫茲,也就是1s內(nèi)時(shí)鐘clk有50*10的6次方個(gè)上升沿。為了能夠?qū)崿F(xiàn)計(jì)時(shí)1s(實(shí)驗(yàn)?zāi)康模?,所以需要定義一個(gè)計(jì)數(shù)器cnt。時(shí)鐘clk每達(dá)到一次上升沿,計(jì)數(shù)器cnt計(jì)數(shù)一次。所以當(dāng)計(jì)數(shù)器cnt等于50000000(50M)時(shí),時(shí)間等于1s。
0.25s也就是50000000(50M)的四分之一,即12500000. -
計(jì)數(shù):
當(dāng)系統(tǒng)復(fù)位時(shí),cnt賦值為0,準(zhǔn)備開(kāi)始計(jì)數(shù)計(jì)時(shí)。
clk每上升一次,cnt的數(shù)值加一。
當(dāng)cnt值等于50M時(shí),cnt賦值為0,重新開(kāi)始計(jì)數(shù)。
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt <= 26'd0;
else if(cnt < 26'd5000_0000)
cnt <= cnt + 1'b1;
else cnt <= 26'd0;
end
- 點(diǎn)亮:
本實(shí)驗(yàn)先令LED3亮起0.25s,再讓LED4亮起0.25s,隨后是LED5,最后是LED6。 所以:
當(dāng)cnt的值處于0~12500000時(shí),LED3端口賦值1,其余端口賦值為0.
當(dāng)cnt的值處于12500000~25000000時(shí),LED4端口賦值1,其余端口賦值為0.
當(dāng)cnt的值處于25000000~37500000時(shí),LED5端口賦值1,其余端口賦值為0.
當(dāng)cnt的值處于37500000~5000000時(shí),LED6端口賦值1,其余端口賦值為0.
always @(cnt) begin
if(cnt<26'd1250_0000) led <= 4'b0001;
if(cnt<26'd2500_0000 && cnt >= 26'd1250_0000) led <= 4'b0010;
if(cnt<26'd3750_0000 && cnt >= 26'd2500_0000) led <= 4'b0100;
if(cnt<26'd5000_0000 && cnt >= 26'd3750_0000) led <= 4'b1000;
end
- module:
定義兩個(gè)輸入:clk,rst-n。
定義一個(gè)的輸出:reg [3:0] led
因?yàn)橛兴膫€(gè)led燈,所以led應(yīng)該有四位,即[3:0],從3數(shù)到0
并且led在always語(yǔ)句進(jìn)行賦值,所以應(yīng)該是reg寄存器類型
module led_stream(
input clk,
input rst_n,
output reg [3:0] led //設(shè)置為寄存器類型,否則第二個(gè)always模塊會(huì)報(bào)錯(cuò)
);
2.2 引腳與電壓分配
- 方式一
按照上圖箭頭所指的四個(gè)部分,依次完成分配。最終結(jié)果應(yīng)與上圖一致。
- 方式二
點(diǎn)任選兩個(gè)個(gè)方框中任意一個(gè),左鍵點(diǎn)擊
選擇第一項(xiàng),加入一個(gè)新的約束文檔
進(jìn)行命名,這里與項(xiàng)目名保持一致
點(diǎn)擊方框,直到看見(jiàn)xdc文件,在右側(cè)屏幕進(jìn)行手動(dòng)引腳即電壓分配
這里為了大家編寫(xiě)方便,我將代碼復(fù)制到下邊了
set_property PACKAGE_PIN Y14 [get_ports {led[0]}]
set_property PACKAGE_PIN AA13 [get_ports {led[1]}]
set_property PACKAGE_PIN AB14 [get_ports {led[2]}]
set_property PACKAGE_PIN AB15 [get_ports {led[3]}]
set_property PACKAGE_PIN W17 [get_ports clk]
set_property PACKAGE_PIN V4 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
當(dāng)然大家也不必?fù)?dān)心,代碼這么多自己該如何編寫(xiě)。它的格式都很固定,只需要根據(jù)引腳及電壓更改一些參數(shù)而已。并且,當(dāng)你采用方式一進(jìn)行引腳分配后,Vivado會(huì)自動(dòng)為你生成你的分配代碼。
三. 仿真
因?yàn)橛械耐瑢W(xué)手上可能沒(méi)有板子,不過(guò)沒(méi)有關(guān)系,Vivado上自帶有仿真系統(tǒng),為了讓大家不受板子限制,博主在此也是做出了本次實(shí)驗(yàn)的相應(yīng)仿真部分,供大家參考。仿真所涉及到的知識(shí)點(diǎn)會(huì)在以后詳細(xì)講解,這里大家先看看最后效果就好。
3.1 建立仿真
老樣子,二選一
按照?qǐng)D片,選擇第三個(gè),建立仿真文件,下一步
命名,這里多加入一個(gè)tb下劃線,用來(lái)警醒自己這應(yīng)該作為頭部文件
然后就可以開(kāi)始編寫(xiě)代碼啦
3.2 仿真代碼
大家直接復(fù)制粘貼到代碼編寫(xiě)區(qū)域即可
`timescale 1ns / 1ps
module tb_led_stream();
reg sys_clk;
reg sys_rst_n;
wire [3:0] led;
initial begin //初始化
sys_clk = 1'b0;
sys_rst_n = 1'b0;
#1 sys_rst_n = 1'b1;
end
always #10 sys_clk = ~sys_clk; //定義一個(gè)50M赫茲的時(shí)鐘
led_stream u_led_stream( //例化
.clk (sys_clk),
.rst_n (sys_rst_n),
.led (led)
);
endmodule
然后點(diǎn)擊下圖
:
進(jìn)行仿真,仿真結(jié)果如下:
可以看見(jiàn),每隔0.25s(250ms)不同的led燈依次點(diǎn)亮,滿足實(shí)驗(yàn)要求。所以本次實(shí)驗(yàn)成功!
四.知識(shí)點(diǎn)
4.1 Verilog語(yǔ)法
- 時(shí)序always模塊
此模塊的代碼框架基本如下:
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
//初始化你的參數(shù)
end
else
//編寫(xiě)代碼邏輯
end
并且大多數(shù)采用阻塞賦值,即“<=”文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-767606.html
- 電平always模塊
此模塊的代碼框架基本如下:
always @(*) begin
//代碼邏輯部分
end
并且大多數(shù)采用非阻塞賦值,即“=”文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-767606.html
- 數(shù)值的定義
對(duì)寄存器類型的變量而言,其賦值需要根據(jù)參數(shù)的位數(shù)進(jìn)行。
reg [4:0] num; //5位,所以num最大是 2*2*2*2*2 - 1 = 31
num = 5'd30; //十進(jìn)制d下賦值30;
num = 5'b01011; //二進(jìn)制b下賦值01011;
//同理,還有八進(jìn)制,十六進(jìn)制賦值,但最大不能超過(guò)十進(jìn)制下的31;
到了這里,關(guān)于FPGA學(xué)習(xí)分享--01 led流水燈的實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!