數(shù)電基礎(chǔ)
關(guān)于時(shí)序邏輯設(shè)計(jì)的部分依然強(qiáng)烈推薦mooc上華科的數(shù)字電路與邏輯設(shè)計(jì)。
計(jì)數(shù)器可以分為同步和異步計(jì)數(shù)器,2進(jìn)制、10進(jìn)制和任意進(jìn)制計(jì)數(shù)器,加法和減法計(jì)數(shù)器。同步和異步是指觸發(fā)器是否都由同一個(gè)時(shí)鐘信號控制。一個(gè)觸發(fā)器能存儲1位二進(jìn)制數(shù),所以由N個(gè)觸發(fā)器構(gòu)成N位寄存器。例如3個(gè)JK觸發(fā)器可以存儲000-111種狀態(tài)。在數(shù)電的原理方面,mooc上講解的很清晰,可以自行學(xué)習(xí)同步或異步的二進(jìn)制寄存器、使用復(fù)位清零和反饋置數(shù)將M進(jìn)制構(gòu)成N進(jìn)制(N
設(shè)計(jì)規(guī)劃
本例將采用一個(gè)外部時(shí)鐘信號,一個(gè)復(fù)位鍵和一個(gè)LED燈來實(shí)現(xiàn)1s內(nèi)LED閃爍(亮0.5s滅0.5s)。這種計(jì)時(shí)的功能在FPGA中是通過計(jì)數(shù)器完成的: 經(jīng)歷一個(gè)時(shí)鐘周期,計(jì)數(shù)器+1 ,我們只需要計(jì)算出計(jì)數(shù)截止的值,就可以完成計(jì)時(shí)。由于采用的50MHz時(shí)鐘頻率,也就是1s產(chǎn)生510e7個(gè)時(shí)鐘。那么亮滅0.5s就是需要計(jì)2.510e7個(gè)數(shù)。計(jì)數(shù)器從0-24999999,2^24<24999999<2^25,因此需要25個(gè)觸發(fā)器,即25位寄存器。這個(gè)計(jì)數(shù)過程是:復(fù)位鍵生效時(shí)計(jì)數(shù)器歸零,釋放后的第一個(gè)時(shí)鐘上升沿開始計(jì)數(shù),從0計(jì)到2499999時(shí)LED燈改變狀態(tài),計(jì)數(shù)器歸零重新開始計(jì)數(shù),到2499999時(shí)LED燈改變狀態(tài)...
編寫代碼
module counter
#(
parameter CNT_MAX = 25'd24_999_999
)
(
input wire sys_clk , //系統(tǒng)時(shí)鐘50MHz
input wire sys_rst_n , //全局復(fù)位
output reg led_out
);
reg [24:0] cnt; //經(jīng)計(jì)算得需要25位寬的寄存器才夠500ms
//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;
//led_out:輸出控制一個(gè)LED燈,每當(dāng)計(jì)數(shù)滿標(biāo)志信號有效時(shí)取反
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
led_out <= 1'b0;
else if(cnt == CNT_MAX)
led_out <= ~led_out;
endmodule
代碼注釋:與#define 標(biāo)識符 常量類似,這里使用參數(shù)的方式定義常量。在RTL代碼中實(shí)例化該模塊時(shí),如果需要兩個(gè)不同計(jì)數(shù)值的計(jì)數(shù)器,只需要修改常數(shù)值。使用testbench仿真時(shí)也需要實(shí)例化,0.5s才能看到led_out的變化,仿真時(shí)間過長。如果我們直接修改參數(shù)縮短時(shí)間就能看到效果。parameter定義的是局部參數(shù),只在本模塊中有效,不會影響實(shí)際值。
我們觀察cnt和led_out的變化條件:計(jì)數(shù)器發(fā)生改變的條件有兩個(gè),一個(gè)是時(shí)鐘上升沿,一個(gè)是復(fù)位有效(復(fù)位下降沿)。計(jì)數(shù)器發(fā)生的改變有兩個(gè),要么+1要么清零。清零條件有兩個(gè):復(fù)位和溢出。因此第一個(gè)always塊中有三個(gè)判斷條件:復(fù)位和溢出時(shí)清零,其他的時(shí)候+1。
led_out的變化條件:時(shí)鐘上升沿和復(fù)位有效(復(fù)位下降沿)。LED燈狀態(tài)的變化有兩個(gè),當(dāng)復(fù)位時(shí)LED燈為低電平,溢出時(shí)取反。
編寫testbench
`timescale 1ns/1ns
module tb_counter();
//reg define
reg sys_clk;
reg sys_rst_n;
//wire define
wire led_out;
//初始化輸入信號
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
//sys_clk:每10ns電平翻轉(zhuǎn)一次,產(chǎn)生一個(gè)50MHz的時(shí)鐘信號
always #10 sys_clk = ~sys_clk;
//---------------------flip_flop_inst----------------------
counter
#(
.CNT_MAX (25'd24 )
)
counter_inst(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.led_out (led_out )
);
endmodule
初始化:時(shí)鐘高電平,復(fù)位低電平,20s延遲后復(fù)位高電平。
實(shí)例化:此處的參數(shù)只對該模塊有效,想要改變這個(gè)模塊里的參數(shù)數(shù)值,只需要在這里改變即可。這里設(shè)置成24是為了方便觀察,節(jié)省時(shí)間。
對比波形
24個(gè)時(shí)鐘脈沖輸出就會取反,同理trl文件中24999999個(gè)脈沖(0.5s)之后LED燈會改變狀態(tài),實(shí)現(xiàn)1s內(nèi)閃爍。
分配管腳
全編譯后上板驗(yàn)證
LED燈在1s內(nèi)閃爍,且S1一直按LED燈會一直亮(S1按下去為低電平,復(fù)位有效,led_out=0,LED燈亮,和預(yù)期一致。
-
FPGA
+關(guān)注
關(guān)注
1630文章
21783瀏覽量
605006 -
計(jì)數(shù)器
+關(guān)注
關(guān)注
32文章
2259瀏覽量
94849 -
數(shù)字電路
+關(guān)注
關(guān)注
193文章
1620瀏覽量
80741 -
觸發(fā)器
+關(guān)注
關(guān)注
14文章
2002瀏覽量
61279 -
時(shí)鐘信號
+關(guān)注
關(guān)注
4文章
451瀏覽量
28627
發(fā)布評論請先 登錄
相關(guān)推薦
評論