前面已經(jīng)學(xué)習(xí)了時(shí)序邏輯電路中的基本單元:觸發(fā)器,這次就用其來(lái)整點(diǎn)活,實(shí)現(xiàn)計(jì)數(shù)器的設(shè)計(jì),計(jì)數(shù)器可以說(shuō)是任何和時(shí)序有關(guān)的設(shè)計(jì)都會(huì)用到他。
一. 計(jì)數(shù)器原理
計(jì)數(shù)器的功能主要就是計(jì)數(shù),在數(shù)字系統(tǒng)中主要對(duì)脈沖的個(gè)數(shù)進(jìn)行計(jì)數(shù),以實(shí)現(xiàn)測(cè)量,計(jì)數(shù)和控制的功能,同時(shí)也可以做到分頻等功能。 同時(shí),其也是FPGA設(shè)計(jì)中最常用的一種時(shí)序邏輯電路,根據(jù)計(jì)數(shù)器的計(jì)數(shù)值可以精確控制各個(gè)信號(hào)的狀態(tài)。
二. 實(shí)用
用計(jì)數(shù)器計(jì)數(shù)1s間隔,實(shí)現(xiàn)led燈每隔1s閃爍的結(jié)果。
本設(shè)計(jì)十分簡(jiǎn)單,用一個(gè)模塊附帶簡(jiǎn)單的輸入輸出便可以完成。 如下所示:
sys_clk:輸入時(shí)鐘,為系統(tǒng)時(shí)鐘
sys_rst_n:復(fù)位信號(hào),低電平有效
led_out:輸出信號(hào),控制LED燈的亮滅
我們的邏輯是這樣:計(jì)數(shù)器進(jìn)行計(jì)數(shù),計(jì)數(shù)到1s便給LED燈賦值,讓其發(fā)亮,就可以達(dá)到1s亮滅的結(jié)果。 所以需要計(jì)算一下,計(jì)1s需要計(jì)數(shù)多少次,如果時(shí)鐘是50MHz,也就是0.000_000_02s,計(jì)數(shù)一秒需要計(jì)數(shù)50_000_000個(gè)數(shù)才可以,不過(guò)在設(shè)計(jì)時(shí)刻視為從0開(kāi)始計(jì)數(shù),所以是49_999_999個(gè)。
接下來(lái)的設(shè)計(jì)時(shí),為了節(jié)省寄存器資源,只計(jì)數(shù)24_999_999個(gè),也就是1s內(nèi)閃爍一次(0.5秒一次)。 這需要25位寬的計(jì)數(shù)器。
下面介紹兩種方式的計(jì)數(shù)器; 帶標(biāo)志位和不帶標(biāo)志位。
不帶標(biāo)志位 :設(shè)置一個(gè)cnt信號(hào)位,時(shí)鐘的每個(gè)上升沿到來(lái)時(shí)刻,cnt便自動(dòng)+1,當(dāng)計(jì)數(shù)器計(jì)到24_999_999的時(shí)候,清0,led_out信號(hào)取反,只要不復(fù)位,變一直計(jì)數(shù)下去。
帶標(biāo)志位: 在上面方案的基礎(chǔ)上,添加一個(gè)cnt_flag信號(hào),當(dāng)計(jì)數(shù)器計(jì)數(shù)到24_999_999的時(shí)候先不取反,而是讓cnt_flag產(chǎn)生一個(gè)高脈沖,當(dāng)led_out 的信號(hào)檢測(cè)到cnt_flag拉高的時(shí)候取反。
關(guān)于標(biāo)志位有什么用,先挖個(gè)坑,以后說(shuō)。
圖1
圖2
注意一下上面兩個(gè)圖(取自野火教材),標(biāo)志位拉高的時(shí)刻并不一樣,下面的圖在N-1時(shí)刻拉高,led_out的狀態(tài)是剛剛好在0時(shí)刻轉(zhuǎn)換(慢一拍),上面的圖實(shí)際上到后來(lái)是計(jì)數(shù)計(jì)多了。 對(duì)于這種簡(jiǎn)單的設(shè)計(jì)這個(gè)問(wèn)題不痛不癢,但是對(duì)于一些要求比較高的設(shè)計(jì)來(lái)說(shuō),一秒也不能差,所以這個(gè)地方需要注意。
下面給出代碼(帶信號(hào)標(biāo)志位)
module counter
#(
parameter CNT_MAX = 25'd24_999_999
)
(
input wire sys_clk , //系統(tǒng)時(shí)鐘 50Mh
input wire sys_rst_n , //全局復(fù)位
output reg led_out //輸出控制 led 燈
);
//reg define
reg [24:0] cnt ; //經(jīng)計(jì)算得需要 25 位寬的寄存器才夠 500ms
reg cnt_flag;
//cnt:計(jì)數(shù)器計(jì)數(shù),當(dāng)計(jì)數(shù)到 CNT_MAX 的值時(shí)清零
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 25'b0;
else if(cnt == CNT_MAX)
cnt <= 25'b0;
else
cnt <= cnt + 1'b1;
//cnt_flag:計(jì)數(shù)到最大值產(chǎn)生的標(biāo)志信號(hào),每當(dāng)計(jì)數(shù)滿標(biāo)志信號(hào)有效時(shí)取反
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_flag <= 1'b0;
else if(cnt == CNT_MAX – 25'b1)
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
//led_out:輸出控制一個(gè) LED 燈
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
led_out <= 1'b0;
else if(cnt_flag == 1'b1)
led_out <= ~led_out;
endmodule
測(cè)試平臺(tái):
module tb_counter(
);
reg sys_clk;
reg sys_rst_n;
wire led_out;
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
always #10 sys_clk = ~sys_clk;
counter
#(
.CNT_MAX (25'd24) //實(shí)例化帶參數(shù)的模塊時(shí)候,當(dāng)我們想要修改常數(shù)在此模塊的值的時(shí)候,直接實(shí)例化參數(shù)名后面的括號(hào)中修改即可
)
counter_inst(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.led_out(led_out)
);
endmodule
仿真波形:
到這里,問(wèn)題還沒(méi)解決,在7系列的FPGA的板上,并不輸出單端口的時(shí)鐘,其是200MHz的差分時(shí)鐘。
AD11和AD12差分時(shí)鐘輸出
經(jīng)過(guò)查閱,調(diào)用PLL鎖相環(huán)的IP核進(jìn)行差分時(shí)鐘的單端口時(shí)鐘輸出。
調(diào)用時(shí)鐘IP核,并且選擇PLL,在下面選擇差分時(shí)鐘接口。 output時(shí)鐘設(shè)置50MHz。
重新寫(xiě)頂層代碼,例化時(shí)鐘。
module counter
(
//input wire sys_clk,
input wire sys_rst_n,
input clk_p,
input clk_n,
output reg led_out
);
reg [24:0] cnt;
reg cnt_flag;
parameter CNT_MAX = 25'd24_999_999;
wire locked;
wire sys_clk;
clk_wiz_0 diff_2_single
(
.clk_out1(sys_clk),
.reset(1'b0),
.locked(locked),
.clk_in1_p(clk_p),
.clk_in1_n(clk_n)
);
//cnt:計(jì)數(shù)器計(jì)數(shù),當(dāng)計(jì)數(shù)到cnt_max的時(shí)候值清0
always @(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt <= 25'b0;
else if(cnt == CNT_MAX)
cnt <= 25'b0;
else
cnt <= cnt+1'b1;
//cnt_flag:計(jì)數(shù)到最大值產(chǎn)生的標(biāo)志位信號(hào),每當(dāng)計(jì)數(shù)滿標(biāo)志信號(hào)有效時(shí)取反
always @(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_flag <= 1'b0;
else if (cnt == CNT_MAX - 25'b1)
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
always @(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
led_out <= 1'b0;
else if (cnt_flag == 1'b1)
led_out <= ~led_out;
endmodule
RTL電路如下所示:
關(guān)于kintex7差分時(shí)鐘引腳約束的問(wèn)題需要注意:
這個(gè)地方只需要約束其中之一即可,另外一個(gè)不用管,如果是不清楚電平標(biāo)準(zhǔn)可以在Tcl控制臺(tái)輸入指令查詢:
-
FPGA
+關(guān)注
關(guān)注
1629文章
21738瀏覽量
603459 -
led
+關(guān)注
關(guān)注
242文章
23278瀏覽量
660939 -
計(jì)數(shù)器
+關(guān)注
關(guān)注
32文章
2256瀏覽量
94581 -
觸發(fā)器
+關(guān)注
關(guān)注
14文章
2000瀏覽量
61159 -
時(shí)序邏輯電路
+關(guān)注
關(guān)注
2文章
94瀏覽量
16546
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論