?
眾所周知,軟件如ARM、DSP、單片機等是按照代碼的順序,一步一步串行執行的,通過使用斷點、打印LOG等方法,順序地檢查每步的執行結果,就能找到問題,因此定位起來非常簡單。
而FPGA代碼是并行的,意味著在同一時刻,多個ALWAYS同時執行,需要檢查每時每刻所有的信號的正確性。如何從眾多的信號(幾千幾萬幾十萬個信號)、以及眾多的時鐘周期中,找到出現錯誤的時刻以及信號,非常有挑戰性。這就像檢查跳舞的姿勢,您不僅要檢查腳步的正確性,還要檢查此時此刻手勢等部位的正確性,這是面的檢查,而不是線的檢查。
正是串行和并行的差異,導致FPGA的調試難度,遠遠大于軟件。
同時,更具挑戰性的是,并行檢查就意味著設計師要對所有的信號有深刻的理解,知道每個信號的作用,以及此時此刻每個信號的值是多少,容不得有任何模糊的空間。
綜上,FPGA相對軟件,調試難度巨大,是一項艱苦的工作。調試、查找定位問題,是FPGA工程師的一項基本技術,而且是必備的技能,掌握好FPGA調試技巧,意義重大。
明德揚MDY計劃推出一系列文章,探討FPGA的調試技巧,以及如何定位問題和解決問題。本文是第一篇文章,概述性地講解錯誤類型及定位思路。
?
第1節 錯誤類型概述
明德揚可以將FPGA的錯誤類型分成三種:軟件工具錯誤、語法編譯錯誤以及功能錯誤。
軟件工具錯誤,是指錯誤使用如VIVADO、QUARTUS等軟件,,或者軟件檢查出的非代碼性的錯誤。例如軟件的license問題、管腳配置問題、缺少文件問題、缺少庫文件問題等。
語法編譯錯誤,是指不符合VERILOG語法規則而引出的錯誤,例如忘了加分號,信號未定義等。
功能錯誤,是指不符合設計目標,與預期不一致的邏輯性、邏輯性錯誤。
對于初學者,大部分時間花在解決軟件工具錯誤以及語法編譯錯誤上,這是由于不熟悉而導致的;而專業的FPGA工程師,大部分時間都花在定位功能錯誤上了,可以說FPGA工程師,一半的時間都花在功能錯誤的定位及修正上。
下面,筆者將逐個討論每種錯誤的解決思路。
?
第2節 軟件工具錯誤
2.1 分辨問題類型
軟件工具錯誤,是指錯誤使用軟件,如VIVADO、QUARTUS,或者由軟件檢查出的非代碼性的錯誤。例如軟件的license問題、管腳配置問題、缺少文件問題、缺少庫文件問題等。
?
?
如上圖是QUARTUS軟件發出的錯誤提示。對于錯誤提示,我們必須認真閱讀,抓關鍵字,不要依賴翻譯軟件,因為這些錯誤提示通常來說不會很難的,看多幾遍就熟悉了。
其次,學會分辨是軟件工具問題,還是語法問題。通常來說,語法問題一般會提示您的哪一份代碼以及哪一行出錯。如果錯誤提示里,沒有跟哪一份代碼關聯起來,一般就是軟件工具錯誤了。
?
遇到軟件錯誤的問題,可以通過搜索問題或者咨詢老師來解決。
2.2 方法1:搜索
對于軟件問題,要相信您肯定不是第一個吃螃蟹,大概率網上會有人咨詢過該問題,熱心的網友會留有詳細的答案,所以最好的方式就是去搜索了。
把錯誤提示復制后去百度搜索(軟件都會提供有復制功能,多試試右鍵),一般都能找到答案。
當然,搜索也有技巧。
??去除掉“個性詞”,例如跟您電腦名有關的、您自己的電腦路徑、您自己的文件名等。
??錯誤提示很長時,刪減一些不必要的語句,保留關鍵詞等。多試試不同的組合,萬一有人問的方式不同呢。
??搜索時,把軟件名帶上,否則會搜索出很多非本軟件的問題。
?
最后,筆者精心整理并收集了多種工具遇到的問題,并整理成一個帖子,讀者如果遇到軟件的問題,可以先從下面找找答案。
QUARTUS問題匯總貼:http://www.mdy-edu.com/plus/view.php?aid=1191
VIVADO問題匯總貼:http://www.mdy-edu.com/wentijieda/20210409/1208.html
MODELSIM問題匯總貼:http://www.mdy-edu.com/wentijieda/20210409/1215.html
在線調試工具問題貼:http://www.mdy-edu.com/wentijieda/20210409/1217.html
GVIM問題匯總貼:http://www.mdy-edu.com/wentijieda/20210409/1219.html
?
2.3 方法2:咨詢
如果搜索不到答案,讀者可以咨詢技術支持老師。老師們會打包好常用的軟件工具,提供下載路徑、使用說明和注意事項等。
?
第3節 語法編譯錯誤
語法編譯錯誤,是指不符合VERILOG/VHDL語法規則而引出的錯誤,例如忘了加分號,信號未定義等。
上面是MODELSIM提示的錯誤,上面錯誤提示里,指明了代碼led_learn_tb.v文件的第23行有問題,像這種指明了哪份代碼的,一般就是語法編譯錯誤。
語法編譯錯誤很覺見,初學者由于不熟悉VERILOG,寫出不符合語法規則的代碼;而對于專業的FPGA工程師,也經常會由于粗心,或者想讓軟件幫忙檢查等原因,出現語法編譯錯誤。
出現問題很正常,,根據錯誤提示,打開代碼文件,定位到那一行,去檢查就是了。
3.1 認識:軟件不會有毛病
首先要樹立明確的認識:軟件不會有毛病的!
軟件指出某個代碼有問題時,那肯定是代碼有問題,不用懷疑!不要認為自己遇到了很“奇怪”、“不可能”的情況,軟件不會有毛病的,肯定是代碼有問題。
有部分讀者,一出問題,稍微檢查一下,就輕易得出“奇怪”、“不可能”的結論,滿心歡喜地跟人分享。比較盲目相信自己的代碼,不愿意深入地檢查,有一種:代碼明明沒有問題,發現了軟件有毛病的心態。
經過多年的實踐證明,軟件不會出錯的,肯定是自己代碼出問題的。支持這個信念,您才能毫無顧忌地深入檢查,一遍沒檢查出來,就檢查兩遍。筆者曾經試過盯著某行代碼足足半小時,突然間才找到問題所在。
軟件提示錯誤了,那肯定是有錯,但軟件的提示也會存在誤導。它說錯誤的那一行,不一定就是這一行出錯。它說錯誤的問題,不一定是這個問題,反而是其他問題等。如說前面一行缺少了一個逗號,一個分號的話,軟件就不會在這一行提示,而是下一行提示。因此檢查時,要前前后后地檢查。
3.2 強烈推薦:代替法
對于不熟悉VERILOG語法的讀者,很擔心自己定位不出語法問題。其實定位語法問題非常簡單,筆者在此強烈推薦一種定位方法:代替法。它可以在您不熟悉語法的前提下,找到問題所在。
定位問題其實就是不斷地將問題搜索范圍變小,最終定位到某一行、某一個語法的問題。讀者首先要知道VERILOG最簡單的語法,例如簡單的modelsim結構、always結構和assign結構等。例如下面的代碼要有所了解,這是最基本的要求,如果不清楚,拿本書去學學,也就半小時的事。
1 |
module test( din ???, flag_start ) input ??din ?????????; output ?flag_add_start ; ? reg ????flag_add; always @ (posedge clk or negedge rst_n)begin if(!rst_n) begin flag_add <= 1'b0; end ????else begin flag_add <= din; end end ? assign flag_start = flag_add ^din ; ? endmodule |
假設一個復雜的代碼出現了錯誤,例如下面的代碼,其使用了比較多的語法,例如有位選符號[]、拼接符{},還出現了未知的data_width。假設軟件提示該代碼有問題,而您又看不出哪里有問題時,您該如何定位該問題呢?(本例只是假設有問題,不一定是有問題)
1 |
always @ (posedge clk or negedge rst_n)begin if(!rst_n) begin ??????? dout <= 0; end else if(spi_cs_ data_ reg2=0&&spi_cs_ data_ reg1==0)begin if(spi_ up_ flag)begin dout [data_ width-1:0]<={dout [data_ width-2:0],spi _sdi}; end else begin dout [data_ width-1:0]<=dout[data_ width-1:0]: end end end |
?
定位的思路是代替法,將復雜的、您不知道的語法,換成您確定的、簡單的語法,然后編譯查看提示,以確定修改點是不是問題所在。
您可以將上面復雜代碼,換成下面簡單代碼。如果編譯沒有出錯,那說明錯誤一定在原來的ALWAYS處。如果編譯還是出錯,說明錯誤在這個ALWAYS之外。
1 |
always @ (posedge clk or negedge rst_n)begin if(!rst_n) begin ??????? dout <= 0; end else begin dout <= 1 end end |
假設編譯沒有錯誤,推理是這個ALWAYS問題。您可以在上面基礎上補充稍復雜的內容,例如下面情況。
1 |
always @ (posedge clk or negedge rst_n)begin if(!rst_n) begin ??????? dout <= 0; end else if(spi_cs_ data_ reg2=0&&spi_cs_ data_ reg1==0)begin dout <= 1 end end |
如果編譯沒有錯誤,您可以再增加一些,例如把位選語法[]加上,例如下面代碼。
1 |
always @ (posedge clk or negedge rst_n)begin if(!rst_n) begin ??????? dout <= 0; end else if(spi_cs_ data_ reg2=0&&spi_cs_ data_ reg1==0)begin if(spi_ up_ flag)begin dout [data_ width-1:0]<=1; end else begin dout [data_ width-1:0]<=0: end end end |
?
如果有編譯錯誤,說明增加的部分有問題;如果沒有錯誤,就說明錯誤還在其他地方。
按此方法繼續補充內容,直至將所有內容填完,總之一定能找出問題所在。
假設定位到是拼接符{}有問題。此時完全可以搜索“verilog 拼接符”,學習相關內容,進而掌握正確的使用方法。
代替法是一種萬試萬靈的方法,只要不斷去實踐和嘗試,就肯定能找到問題所的,強烈推薦大家使用。
?
3.3 找不到XXX的問題
如果遇到找不到xxx,沒有xxx這類問題,例如上圖,MODELSIM提示,找不到“model_name”。
遇到這類問題,一定要清楚QUARTUS、MODELSIM、VIVDADO的流程,以及軟件工具與代碼、代碼與代碼之間是如何關聯起來的。
首先是確認軟件工具和代碼文件的關聯方法。每個軟件如QUARTUS、MODELSIM和VIVADO,都需要將代碼添加進來,即添加文件的操作。添加后的文件,就將軟件工具和代碼文件聯系起來了。注意的是,這里關聯的是“代碼文件”,而非“模塊名”,有些代碼,其代碼文件名與模塊名是不一致的。
其次是確認文件名和模塊的關聯。軟件工具會對關聯的“代碼文件”進行編譯,編譯后會產生可供使用的“模塊”,該模塊是以“模塊名”來命名的,即module name,而不是文件名。例如文件名為a.v,而里面的模塊名是module b,則會生成模塊b。還要注意,一個文件可以包含多個模塊,對該文件編譯,會生成多個模塊。如果找不到模塊,不要只檢查文件名,還要看模塊名,要檢查文件名和模塊名是不是一致。
最后是確認模塊與模塊之間的關聯。每個軟件都會要求設置一個頂層模塊,QUARTUS和VIVADO的頂層模塊,就是設計的頂層文件;MODELSIM的頂層文件是測試文件。設置了頂層文件后,軟件工具會從頂層文件開始,逐級找到其他模塊,線索就是例化。例如設置了頂層模塊為模塊a;模塊a例化了模塊b和模塊c;模塊b例化了模塊d和e。那么軟件工具首先找到頂層模塊a;根據例化,找到模塊b和模塊c;根據模塊b找到模塊d和e。通過這種方法,就把所有使用到的模塊關聯起來了。
需要注意的是,某些模塊是官方自帶的,例如VIVADO的原語、XMP等,以及某些IP核調用的庫。這些模塊在官方軟件使用時,不需要添加到工程,官方軟件是能夠自動識別的。但這些模塊在第三方軟件例如MODELSIM使用時,MODELSIM是不清楚這些模塊的,那么就要添加這些仿真庫,把這些模塊的文件添加進來,從而讓MODELSIM能識別。當發現某模塊找不到時,要辨別該模塊是在哪個文件中被調用了,是不是被IP核調用的,如果答案是肯定的話,那就要注意軟件是否缺少庫的問題了。
綜上,當提示某模塊找不到的時候,檢查代碼文件有沒有加到工程;檢查文件名和模塊名是否一致;檢查是否IP核調用了該模塊,是的話添加庫文件等。
?
第4節 功能錯誤
功能錯誤,是指不符合設計目標,與預期不一致的錯誤。
軟件是順序串行的,是按照代碼的順序,一步一步執行的,使用斷點、打印LOG等方法,順序去檢查每步的執行結果,就能找到問題,因此定位起來非常簡單。
而FPGA代碼是并行的,意味著在同一時刻,多個ALWAYS同時執行,您需要檢查每時每刻所有的信號的正確性,如何從眾多的信號(幾千幾萬幾十萬個信號)、以及眾多的時鐘周期中,發現那個出現錯誤的時刻以及信號,非常有挑戰性。
正是上面所說的差異,FPGA的定位錯誤的方法完全不同于軟件。FPGA更加考驗工程師的細心程度。
?
4.1 認識1:放穩心態
首先要認識到,出現邏輯錯誤是很正常的,沒有驗證過的代碼,一定是有問題的代碼。寫完代碼,仿真驗證,發現問題修改;再次仿真驗證,這是FPGA工程師的日常工作。
定位問題解決問題是正常工作,要放穩心態,不要著急。那種以為一寫代碼就邏輯正確的情況,是不存在的。
4.2 認識2:粗心大意
其次我們要樹立一個認識,軟件是不會有毛病的,一定是自己代碼問題;如果沒找到問題,那肯定是不夠細心;還沒找到,那就要更細心再找!
總之,沒找到問題,就更加細心就對了!
4.3 認識3:自己行動
除非有好心人,愿意犧牲時間來幫您遠程定位,否則邏輯功能錯誤是沒辦法求助的。在不熟知您代碼、不清楚設計信號的含義、不知道設計意圖時,沒有人能夠一眼看出問題所在,即使是老師也不行。這個問題只能靠工程師自己去定位去解決。
?
?
下一篇文章,我們將介紹定位功能邏輯錯誤的方法,歡迎關注。
審核編輯:湯梓紅
評論
查看更多