【 聲明:版權所有,歡迎轉載,請勿用于商業用途。 聯系信箱:feixiaoxing @163.com】
? ? ? ? 我們之前在學校學習c、c++的時候,其實學校漏掉了很重要的一個教學環節,那就是調試、測試。很多時候我們代碼寫出來了,不知道怎么測試、調試。其實fpga也是一樣的。fpga本質上還是信號的處理,我們與其說是寫代碼,不如說是設計電路。這個電路以寄存器和時序電路為基礎,以組合電路為輔,通過狀態機、協議和流程共同實現一個模塊的開發。那么這個模塊寫的對不對,就需要通過調試來進行判別了。
1、做好設計
? ? ? ? 設計是我們所有工作的起點,這個設計的來源,一方面是需求,一方面是標準協議,還有一方面來自于fpga的現實接口約束。在開發之前,就要想好解決什么問題,系統的協議、交互邏輯和狀態機是什么樣的。子模塊的信號,甚至可以提前把波形設計好,這樣就可以直接轉化成verilog代碼了。后續的調試就變成對這個波形的確認。
2、仿真調試
? ? ? ? 仿真是很重要的一個環節。fpga相比較c語言編程有一個缺點,那就是綜合、編譯的速度會比較慢。在前期開發調試的時候,沒有必要直接上板子測試,這和嵌入式開發是一樣的。能仿真的部分,盡量用仿真來解決。簡單一點的iverilog+gtkwave仿真,復雜一點的modelsim仿真,都是可以去做的。仿真的部分,盡可能做成自動化測試,用類似python之類的腳本串起來,這樣效率會比較高。仿真本身解決的是邏輯層面的問題,如果邏輯層面都有問題,直接上fpga基本就是浪費時間。
3、會查看時序報告
? ? ? ? 前面說過,仿真只是解決功能層面是否正確,但是時序層面是不是正確,需要通過綜合時得到的時序報告,去進行判斷。實際fpga驗證的時候,最好把這些關鍵路徑做一個時序優化。這里面最主要的方法,就是組合邏輯拆分、case優化、做延時tap。修改后,通常需要回頭重新做一下仿真測試。測試沒問題之后,繼續修正時序,直到得到想要的結果。畢竟我們總是希望頻率越高越好,而頻率收到關鍵路徑的約束,所以只好通過識別關鍵路勁,通過優化來不斷提高處理頻率。
? ? ? ? 時序的本質,其實就在于兩個clock之間的組合邏輯,是否可以滿足時鐘約束的要求。我們編寫時序電路的時候,中間會有很多的判斷條件。這些判斷條件綜合出來,很多都是組合邏輯。這些組合邏輯如果過于復雜和冗長,其實是需要進行優化和拆分的,這就是時序分析的根本來源。
4、添加串口打印
? ? ? ? 串口本身還是非常方便的,一個fifo模塊,再加一個uart,就可以通過循環打印的方式,不停把狀態機里面的信號讀出來,非常方便。如果奢侈一點的話,可以自己準備一個軟核cpu,這樣還可以通過軟核+串口的方式,直接編程解決ip內部的調試問題。要做到這一點,就要對編譯器、鏈接器、匯編、二進制代碼有所了解。某種意義上,這就相當于一個小型的mcu開發了。
5、output pin
? ? ? ? 這里的outpin就不僅僅是串口打印,而是內部的register、wire信號查看,綁定到外部的pin而已。原理是比較簡單,就是開發效率比較低。因為想看什么信號,每次都需要通過重新綜合+外部示波器查看的辦法來解決。當然如果對cpu軟核和嵌入式軟件不算太了解,這也是很有效的一種調試方式。
6、signal tap
? ? ? ? signal tap的本意就是通過內置signal ram的方式,把一部分運行信號鎖到ram里面,再通過jtag的方式把信號送出來。因為signal tap本身是占有一定資源的,所以實際使用的時候,必須有選擇性地去挑選一些信號進行debug處理。本質上,signal tap就是一個藏在fpga里面的小示波器。挑選哪些信號,怎么觸發,都是可以通過ide進行設置的。和output pin一樣,它也需要在每次調試的時候,重新進行綜合處理。
7、其他
? ? ? ? 對fpga的調試,其實很大程度上取決于自己對于軟件的理解、對于數字電路的理解。實際開發的時候,要把自己想象成一個cpu、一個時序和組合邏輯模塊,而不是單純的verilog代碼,這樣會調試起來好很多。出現問題,優先從原理入手,原理沒問題再看電路、看信號、看打印,這樣一步步去解決,最終肯定會找到問題的所在。