《FPGA至簡設計原理與應用》學習筆記——1位閃爍燈設計

本文爲明德揚原創及錄用文章,轉載請註明出處!
作者:一條鹹魚

個人總結及感悟:

對於學習本案例,首先要理解案例的頂層框架,再是理解框架下面的邏輯,最後纔是理解代碼。這一點對於自己動手寫代碼也很有幫助,畢竟寫代碼就是爲了實現框架。再來說說本案例中的代碼吧,本案例給出的代碼對於剛接觸FPGA的人也許會有“這代碼寫的太麻煩了吧!”“明明可以寫成49_999_999的爲啥要寫成50_000_000-1呢?”之類的想法,這也是我剛接觸明德揚的代碼時的想法。

後來接觸多了,自己也開始用明得揚的代碼規範寫了一些代碼,才慢慢覺得明德揚的代碼規範挺好用的,寫出來的代碼也通俗易懂。而且這些代碼也很方便移植與修改,對於實現某些相似的功能時也不用自己再重新寫代碼,可以直接拿過來再修改一下就行了。

總的來說,要想學好FPGA需要從三個方面着手:1、框架;2、規範;3、動手做。這三個方面做好了,那以後自己做工程就成功一半了。

設計目標:

使用一個LED燈,實現閃爍燈的功能。工作時鐘50M,也就是時鐘週期爲20ns。輸出低電平時,燈亮;輸出高電平時,燈滅。

功能要求:

隔1秒,亮N秒。N的變化是1,2,3,……,9秒。然後再次循環。

波形示意圖:

在這裏插入圖片描述

頂層信號設計:

工程共需要三個信號,時鐘clk,復位rst_n和輸出信號led。其中clk、rst_n是輸入信號,led是輸出信號,並且三個信號都是1比特的。

工程實現思路:

從功能要求及波形圖可知,需要一個計數器計數第N次,需要一個計數器計數第N次需要持續的時間。本工程設計兩個計數器cnt0,cnt1。cnt0用於計數第N次需要持續的時間,cnt1計數第N次。第1次時,持續2秒;第2次時,持續3秒;第N次時,持續N+1秒。直至第9次結束,又從第1次開始循環。輸出信號led同時滿足cnt0計數器的計數開始信號add_cnt0的出現與cnt0計數到50_000_000-1這兩個條件時變爲低電平;在end_cnt0信號出現時變爲高電平,意味着在第N次計數中第1秒內燈滅,其餘時間燈亮。

代碼實現:

計數器cnt0

always@(posedgeclkor negedgerst_n)begin
if(rst_n)begin
cnt0<=0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0<=0;
else
cnt0<=cnt0+1;
end
end
assign add_cnt0 = 1;
assign end_cnt0 = add_cnt0&&cnt0==x-1;

因爲cnt0需要不停的計數,永不停止,故計數開始信號add_cnt0一直爲1。引入了變量x,x爲要計數的個數。比較計數器cnt1的不同,從而賦予變量x不同的值。

cnt1計數器

always@(posedgeclkor negedgerst_n)begin
if(rst_n)begin
   cnt1<=0;
end
elseif(add_cnt1)begin
   if(end_cnt1)
       cnt1<=0;
   else
       cnt1<=cnt1+1;
end
end
assignadd_cnt1 = end_cnt0;
assignend_cnt1 = add_cnt1&&cnt1==9-1;

當計數器cnt0計數結束時的下一個時鐘節拍裏,使得cnt1計數加1。

led輸出信號

always@(posedgeclkor negedgerst_n)begin
if(rst_n)begin
led<= 1;
end
elseif(add_cnt0 && cnt0 ==50_000_000-1)begin
   led <= 0;
elseif(end_cnt0)begin
   led <= 1;
end
end

led信號在第N次計數時,計數1秒後燈亮。

信號定義:

always裏面的信號需要定義爲reg型;assign的信號需要定義爲wire型。另外需要重點注意每個信號的位寬。

注意事項:

具體編寫代碼過程中,需要注意以下三點。
1、要注意計數器的計數結束條件,例如工作時鐘是50M,計數1秒鐘,那麼計數範圍就是0~49_999_999,千萬要注意不能超出。
2、代碼一定要規範,不然過段時間可能連自己都看不懂。
3、要注意各個信號的位寬。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章