本節我們通過驅動流水燈的不同方式來體現Fpga中的一個重要思想—層次化設計。 首先介紹一下我所使用開發板的硬件資源,50MHZ時鐘輸入、4個低電平點亮的流水燈。然后通過兩種不同驅動方式的對比使讀者更加深層次的了解層次化設計 下圖提供了一段流水燈代碼,請問能夠實現流水現象嗎?
![]() ![]() ![]()
![]()
FPGA的時鐘是50M,周期20ns,上述代碼每隔20ns,流水燈的狀態發生改變,即每個燈亮的狀態是20ns,時間非常短,人的肉眼觀察不到燈亮的狀態。 由于周期特別短導致無法觀察到燈亮,因此只要通過計數器將周期延長一定的時間,就可以看到“流水”現象。以下代碼通過設計一個計數器count將周期延長到兩秒,代碼如下 代碼經過編譯以后得到RTL圖如下 下面提供相對應的 仿真代碼,通過參數傳遞的方式將led_fsm1 中的NUM賦值為50,代替NUM=28'd100000000,提高仿真效率
具體解釋如下,在led_fsm1中NUM 達到28'd100000000-1(NUM-1)時,才會產生時鐘的跳轉,但是在波形仿真中仿真時間長,效率低,通過參數傳遞將50傳給NUM,這樣在仿真中,NUM-1=49時,時鐘發生翻轉,提高仿真效率,參數傳遞時,將參數定義為parameter 類型,并且在文件中凡是能夠用到參數的地方,盡量要用參數表示,比如用到28'd100000000-1,可以用NUM-1代替,否則會導致參數傳遞失敗。具體參考給出的波形文件 仿真結果如下 從上面的波形看出當count==50-1,led_out 發生改變,而不是count==28'd100000000-1 ,由此可知參數傳遞成功 那么,請問一下,在一個模塊里面既要寫count分頻模塊,又要寫led_out的輸出,有沒有簡單的思路呢? 下面我們介紹一種更簡單的思考方式,層次化設計 所謂層次設計就是將一個整體項目劃分成多個模塊,就像電腦由鍵盤、鼠標、 顯示器構成一樣。分好模塊以后,我們就必須要一個頂層文件,將多個模塊連接起來。 下面依然用一個50MHz的晶振點亮一個流水燈進行層次化設計為例進行講解。 首先考慮流水燈由哪幾個模塊構成。如果用50MHz驅動流水燈的話,50MHz頻率過快,會導致點亮流水燈的效果看不到,所以我們需要一個分頻模塊,將時鐘頻率降低。為了實現流水燈則需要一個邏輯控制模塊,最后將這兩個模塊在頂層中進行連接 系統框圖如下: 接下來,設計具體 電路描述代碼,實現各模塊功能,首先,新建工程如下 然后建立起頂層文件 建立時鐘分頻模塊 led_freq 在這里不建議調用鎖相環(PLL),鎖相環分頻是有限制的,我試了一下如果用鎖相環來點燈的話,時鐘太快還是看不到流水的現象,所以需要獨立編寫一個led_freq模塊 在寫完分頻模塊以后,就要寫如何讓流水燈實現,以下是流水燈控制模塊的代碼,在控制模塊(led_ctrl)中 注意信號clk, 此時鐘不是50M時鐘,是經過分頻模塊分頻以后的時鐘,這點是如何實現的呢?可以看后面提供的RTL圖,看模塊的連接關系,和頂層模塊講解 下面先提供一個led_ctrl 控制的仿真代碼,用來測試單獨的流水燈控制模塊,具體代碼如下 led_ctrl模塊仿真波形如下 有以上波形可以看出,復位結束以后,流水燈的驅動端口led_out和狀態機的狀態寄存器state在時鐘上升沿的驅動下有效配合,實現了數據的滾動賦值,可以正確實現流水燈設計。
下面編輯頂層模塊,頂層模塊的主要功能是將分頻模塊和流水燈控制模塊連接起來,我們要求在頂層中只做端口連線,不做任何邏輯。頂層具體代碼如下: 進行全編譯,結果如下: 編譯通過,我們可以首先查看一下RTL級視圖,點擊Tools->Netlist Viewers->RTL Viewer 查看結果如下 由上圖可以說明,最終綜合出來的電路和我們所設想的是完全一致的。
通過對比以上兩種方法,可以很明顯的發現層次化設計的RTL視圖能夠清晰的反映出模塊之間的連接關系,在設計中可以獨立的對每個模塊進行設計,降低設計的復雜度,尤其是大規模的設計,也便于代碼的調試,將一個復雜的系統轉換為對每個獨立模塊的調試,所以層次化設計是一項非常重要的設計技巧
| 傳奇
本主題由 夢翼師兄 于 2015-3-21 09:56 限時高亮
4.png (35.9 KB, 下載次數: 0)
[url=] [/url]
|