?
眾所周知,軟件如ARM、DSP、單片機(jī)等是按照代碼的順序,一步一步串行執(zhí)行的,通過使用斷點(diǎn)、打印LOG等方法,順序地檢查每步的執(zhí)行結(jié)果,就能找到問題,因此定位起來非常簡(jiǎn)單。
而FPGA代碼是并行的,意味著在同一時(shí)刻,多個(gè)ALWAYS同時(shí)執(zhí)行,需要檢查每時(shí)每刻所有的信號(hào)的正確性。如何從眾多的信號(hào)(幾千幾萬幾十萬個(gè)信號(hào))、以及眾多的時(shí)鐘周期中,找到出現(xiàn)錯(cuò)誤的時(shí)刻以及信號(hào),非常有挑戰(zhàn)性。這就像檢查跳舞的姿勢(shì),您不僅要檢查腳步的正確性,還要檢查此時(shí)此刻手勢(shì)等部位的正確性,這是面的檢查,而不是線的檢查。
正是串行和并行的差異,導(dǎo)致FPGA的調(diào)試難度,遠(yuǎn)遠(yuǎn)大于軟件。
同時(shí),更具挑戰(zhàn)性的是,并行檢查就意味著設(shè)計(jì)師要對(duì)所有的信號(hào)有深刻的理解,知道每個(gè)信號(hào)的作用,以及此時(shí)此刻每個(gè)信號(hào)的值是多少,容不得有任何模糊的空間。
綜上,F(xiàn)PGA相對(duì)軟件,調(diào)試難度巨大,是一項(xiàng)艱苦的工作。調(diào)試、查找定位問題,是FPGA工程師的一項(xiàng)基本技術(shù),而且是必備的技能,掌握好FPGA調(diào)試技巧,意義重大。
明德?lián)PMDY計(jì)劃推出一系列文章,探討FPGA的調(diào)試技巧,以及如何定位問題和解決問題。本文是第一篇文章,概述性地講解錯(cuò)誤類型及定位思路。
?
第1節(jié) 錯(cuò)誤類型概述
明德?lián)P可以將FPGA的錯(cuò)誤類型分成三種:軟件工具錯(cuò)誤、語法編譯錯(cuò)誤以及功能錯(cuò)誤。
軟件工具錯(cuò)誤,是指錯(cuò)誤使用如VIVADO、QUARTUS等軟件,,或者軟件檢查出的非代碼性的錯(cuò)誤。例如軟件的license問題、管腳配置問題、缺少文件問題、缺少庫文件問題等。
語法編譯錯(cuò)誤,是指不符合VERILOG語法規(guī)則而引出的錯(cuò)誤,例如忘了加分號(hào),信號(hào)未定義等。
功能錯(cuò)誤,是指不符合設(shè)計(jì)目標(biāo),與預(yù)期不一致的邏輯性、邏輯性錯(cuò)誤。
對(duì)于初學(xué)者,大部分時(shí)間花在解決軟件工具錯(cuò)誤以及語法編譯錯(cuò)誤上,這是由于不熟悉而導(dǎo)致的;而專業(yè)的FPGA工程師,大部分時(shí)間都花在定位功能錯(cuò)誤上了,可以說FPGA工程師,一半的時(shí)間都花在功能錯(cuò)誤的定位及修正上。
下面,筆者將逐個(gè)討論每種錯(cuò)誤的解決思路。
?
第2節(jié) 軟件工具錯(cuò)誤
2.1 分辨問題類型
軟件工具錯(cuò)誤,是指錯(cuò)誤使用軟件,如VIVADO、QUARTUS,或者由軟件檢查出的非代碼性的錯(cuò)誤。例如軟件的license問題、管腳配置問題、缺少文件問題、缺少庫文件問題等。
?

?
如上圖是QUARTUS軟件發(fā)出的錯(cuò)誤提示。對(duì)于錯(cuò)誤提示,我們必須認(rèn)真閱讀,抓關(guān)鍵字,不要依賴翻譯軟件,因?yàn)檫@些錯(cuò)誤提示通常來說不會(huì)很難的,看多幾遍就熟悉了。
其次,學(xué)會(huì)分辨是軟件工具問題,還是語法問題。通常來說,語法問題一般會(huì)提示您的哪一份代碼以及哪一行出錯(cuò)。如果錯(cuò)誤提示里,沒有跟哪一份代碼關(guān)聯(lián)起來,一般就是軟件工具錯(cuò)誤了。
?
遇到軟件錯(cuò)誤的問題,可以通過搜索問題或者咨詢老師來解決。
2.2 方法1:搜索
對(duì)于軟件問題,要相信您肯定不是第一個(gè)吃螃蟹,大概率網(wǎng)上會(huì)有人咨詢過該問題,熱心的網(wǎng)友會(huì)留有詳細(xì)的答案,所以最好的方式就是去搜索了。
把錯(cuò)誤提示復(fù)制后去百度搜索(軟件都會(huì)提供有復(fù)制功能,多試試右鍵),一般都能找到答案。
當(dāng)然,搜索也有技巧。
??去除掉“個(gè)性詞”,例如跟您電腦名有關(guān)的、您自己的電腦路徑、您自己的文件名等。
??錯(cuò)誤提示很長(zhǎng)時(shí),刪減一些不必要的語句,保留關(guān)鍵詞等。多試試不同的組合,萬一有人問的方式不同呢。
??搜索時(shí),把軟件名帶上,否則會(huì)搜索出很多非本軟件的問題。
?
最后,筆者精心整理并收集了多種工具遇到的問題,并整理成一個(gè)帖子,讀者如果遇到軟件的問題,可以先從下面找找答案。
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
在線調(diào)試工具問題貼:http://www.mdy-edu.com/wentijieda/20210409/1217.html
GVIM問題匯總貼:http://www.mdy-edu.com/wentijieda/20210409/1219.html
?
2.3 方法2:咨詢
如果搜索不到答案,讀者可以咨詢技術(shù)支持老師。老師們會(huì)打包好常用的軟件工具,提供下載路徑、使用說明和注意事項(xiàng)等。
?
第3節(jié) 語法編譯錯(cuò)誤
語法編譯錯(cuò)誤,是指不符合VERILOG/VHDL語法規(guī)則而引出的錯(cuò)誤,例如忘了加分號(hào),信號(hào)未定義等。

上面是MODELSIM提示的錯(cuò)誤,上面錯(cuò)誤提示里,指明了代碼led_learn_tb.v文件的第23行有問題,像這種指明了哪份代碼的,一般就是語法編譯錯(cuò)誤。
語法編譯錯(cuò)誤很覺見,初學(xué)者由于不熟悉VERILOG,寫出不符合語法規(guī)則的代碼;而對(duì)于專業(yè)的FPGA工程師,也經(jīng)常會(huì)由于粗心,或者想讓軟件幫忙檢查等原因,出現(xiàn)語法編譯錯(cuò)誤。
出現(xiàn)問題很正常,,根據(jù)錯(cuò)誤提示,打開代碼文件,定位到那一行,去檢查就是了。
3.1 認(rèn)識(shí):軟件不會(huì)有毛病
首先要樹立明確的認(rèn)識(shí):軟件不會(huì)有毛病的!
軟件指出某個(gè)代碼有問題時(shí),那肯定是代碼有問題,不用懷疑!不要認(rèn)為自己遇到了很“奇怪”、“不可能”的情況,軟件不會(huì)有毛病的,肯定是代碼有問題。
有部分讀者,一出問題,稍微檢查一下,就輕易得出“奇怪”、“不可能”的結(jié)論,滿心歡喜地跟人分享。比較盲目相信自己的代碼,不愿意深入地檢查,有一種:代碼明明沒有問題,發(fā)現(xiàn)了軟件有毛病的心態(tài)。
經(jīng)過多年的實(shí)踐證明,軟件不會(huì)出錯(cuò)的,肯定是自己代碼出問題的。支持這個(gè)信念,您才能毫無顧忌地深入檢查,一遍沒檢查出來,就檢查兩遍。筆者曾經(jīng)試過盯著某行代碼足足半小時(shí),突然間才找到問題所在。
軟件提示錯(cuò)誤了,那肯定是有錯(cuò),但軟件的提示也會(huì)存在誤導(dǎo)。它說錯(cuò)誤的那一行,不一定就是這一行出錯(cuò)。它說錯(cuò)誤的問題,不一定是這個(gè)問題,反而是其他問題等。如說前面一行缺少了一個(gè)逗號(hào),一個(gè)分號(hào)的話,軟件就不會(huì)在這一行提示,而是下一行提示。因此檢查時(shí),要前前后后地檢查。
3.2 強(qiáng)烈推薦:代替法
對(duì)于不熟悉VERILOG語法的讀者,很擔(dān)心自己定位不出語法問題。其實(shí)定位語法問題非常簡(jiǎn)單,筆者在此強(qiáng)烈推薦一種定位方法:代替法。它可以在您不熟悉語法的前提下,找到問題所在。
定位問題其實(shí)就是不斷地將問題搜索范圍變小,最終定位到某一行、某一個(gè)語法的問題。讀者首先要知道VERILOG最簡(jiǎn)單的語法,例如簡(jiǎn)單的modelsim結(jié)構(gòu)、always結(jié)構(gòu)和assign結(jié)構(gòu)等。例如下面的代碼要有所了解,這是最基本的要求,如果不清楚,拿本書去學(xué)學(xué),也就半小時(shí)的事。
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 |
假設(shè)一個(gè)復(fù)雜的代碼出現(xiàn)了錯(cuò)誤,例如下面的代碼,其使用了比較多的語法,例如有位選符號(hào)[]、拼接符{},還出現(xiàn)了未知的data_width。假設(shè)軟件提示該代碼有問題,而您又看不出哪里有問題時(shí),您該如何定位該問題呢?(本例只是假設(shè)有問題,不一定是有問題)
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 |
?
定位的思路是代替法,將復(fù)雜的、您不知道的語法,換成您確定的、簡(jiǎn)單的語法,然后編譯查看提示,以確定修改點(diǎn)是不是問題所在。
您可以將上面復(fù)雜代碼,換成下面簡(jiǎn)單代碼。如果編譯沒有出錯(cuò),那說明錯(cuò)誤一定在原來的ALWAYS處。如果編譯還是出錯(cuò),說明錯(cuò)誤在這個(gè)ALWAYS之外。
1 |
always @ (posedge clk or negedge rst_n)begin if(!rst_n) begin ??????? dout <= 0; end else begin dout <= 1 end end |
假設(shè)編譯沒有錯(cuò)誤,推理是這個(gè)ALWAYS問題。您可以在上面基礎(chǔ)上補(bǔ)充稍復(fù)雜的內(nèi)容,例如下面情況。
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 |
如果編譯沒有錯(cuò)誤,您可以再增加一些,例如把位選語法[]加上,例如下面代碼。
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 |
?
如果有編譯錯(cuò)誤,說明增加的部分有問題;如果沒有錯(cuò)誤,就說明錯(cuò)誤還在其他地方。
按此方法繼續(xù)補(bǔ)充內(nèi)容,直至將所有內(nèi)容填完,總之一定能找出問題所在。
假設(shè)定位到是拼接符{}有問題。此時(shí)完全可以搜索“verilog 拼接符”,學(xué)習(xí)相關(guān)內(nèi)容,進(jìn)而掌握正確的使用方法。
代替法是一種萬試萬靈的方法,只要不斷去實(shí)踐和嘗試,就肯定能找到問題所的,強(qiáng)烈推薦大家使用。
?
3.3 找不到XXX的問題

如果遇到找不到xxx,沒有xxx這類問題,例如上圖,MODELSIM提示,找不到“model_name”。
遇到這類問題,一定要清楚QUARTUS、MODELSIM、VIVDADO的流程,以及軟件工具與代碼、代碼與代碼之間是如何關(guān)聯(lián)起來的。
首先是確認(rèn)軟件工具和代碼文件的關(guān)聯(lián)方法。每個(gè)軟件如QUARTUS、MODELSIM和VIVADO,都需要將代碼添加進(jìn)來,即添加文件的操作。添加后的文件,就將軟件工具和代碼文件聯(lián)系起來了。注意的是,這里關(guān)聯(lián)的是“代碼文件”,而非“模塊名”,有些代碼,其代碼文件名與模塊名是不一致的。
其次是確認(rèn)文件名和模塊的關(guān)聯(lián)。軟件工具會(huì)對(duì)關(guān)聯(lián)的“代碼文件”進(jìn)行編譯,編譯后會(huì)產(chǎn)生可供使用的“模塊”,該模塊是以“模塊名”來命名的,即module name,而不是文件名。例如文件名為a.v,而里面的模塊名是module b,則會(huì)生成模塊b。還要注意,一個(gè)文件可以包含多個(gè)模塊,對(duì)該文件編譯,會(huì)生成多個(gè)模塊。如果找不到模塊,不要只檢查文件名,還要看模塊名,要檢查文件名和模塊名是不是一致。
最后是確認(rèn)模塊與模塊之間的關(guān)聯(lián)。每個(gè)軟件都會(huì)要求設(shè)置一個(gè)頂層模塊,QUARTUS和VIVADO的頂層模塊,就是設(shè)計(jì)的頂層文件;MODELSIM的頂層文件是測(cè)試文件。設(shè)置了頂層文件后,軟件工具會(huì)從頂層文件開始,逐級(jí)找到其他模塊,線索就是例化。例如設(shè)置了頂層模塊為模塊a;模塊a例化了模塊b和模塊c;模塊b例化了模塊d和e。那么軟件工具首先找到頂層模塊a;根據(jù)例化,找到模塊b和模塊c;根據(jù)模塊b找到模塊d和e。通過這種方法,就把所有使用到的模塊關(guān)聯(lián)起來了。
需要注意的是,某些模塊是官方自帶的,例如VIVADO的原語、XMP等,以及某些IP核調(diào)用的庫。這些模塊在官方軟件使用時(shí),不需要添加到工程,官方軟件是能夠自動(dòng)識(shí)別的。但這些模塊在第三方軟件例如MODELSIM使用時(shí),MODELSIM是不清楚這些模塊的,那么就要添加這些仿真庫,把這些模塊的文件添加進(jìn)來,從而讓MODELSIM能識(shí)別。當(dāng)發(fā)現(xiàn)某模塊找不到時(shí),要辨別該模塊是在哪個(gè)文件中被調(diào)用了,是不是被IP核調(diào)用的,如果答案是肯定的話,那就要注意軟件是否缺少庫的問題了。
綜上,當(dāng)提示某模塊找不到的時(shí)候,檢查代碼文件有沒有加到工程;檢查文件名和模塊名是否一致;檢查是否IP核調(diào)用了該模塊,是的話添加庫文件等。
?
第4節(jié) 功能錯(cuò)誤
功能錯(cuò)誤,是指不符合設(shè)計(jì)目標(biāo),與預(yù)期不一致的錯(cuò)誤。
軟件是順序串行的,是按照代碼的順序,一步一步執(zhí)行的,使用斷點(diǎn)、打印LOG等方法,順序去檢查每步的執(zhí)行結(jié)果,就能找到問題,因此定位起來非常簡(jiǎn)單。
而FPGA代碼是并行的,意味著在同一時(shí)刻,多個(gè)ALWAYS同時(shí)執(zhí)行,您需要檢查每時(shí)每刻所有的信號(hào)的正確性,如何從眾多的信號(hào)(幾千幾萬幾十萬個(gè)信號(hào))、以及眾多的時(shí)鐘周期中,發(fā)現(xiàn)那個(gè)出現(xiàn)錯(cuò)誤的時(shí)刻以及信號(hào),非常有挑戰(zhàn)性。
正是上面所說的差異,F(xiàn)PGA的定位錯(cuò)誤的方法完全不同于軟件。FPGA更加考驗(yàn)工程師的細(xì)心程度。
?
4.1 認(rèn)識(shí)1:放穩(wěn)心態(tài)
首先要認(rèn)識(shí)到,出現(xiàn)邏輯錯(cuò)誤是很正常的,沒有驗(yàn)證過的代碼,一定是有問題的代碼。寫完代碼,仿真驗(yàn)證,發(fā)現(xiàn)問題修改;再次仿真驗(yàn)證,這是FPGA工程師的日常工作。
定位問題解決問題是正常工作,要放穩(wěn)心態(tài),不要著急。那種以為一寫代碼就邏輯正確的情況,是不存在的。
4.2 認(rèn)識(shí)2:粗心大意
其次我們要樹立一個(gè)認(rèn)識(shí),軟件是不會(huì)有毛病的,一定是自己代碼問題;如果沒找到問題,那肯定是不夠細(xì)心;還沒找到,那就要更細(xì)心再找!
總之,沒找到問題,就更加細(xì)心就對(duì)了!
4.3 認(rèn)識(shí)3:自己行動(dòng)
除非有好心人,愿意犧牲時(shí)間來幫您遠(yuǎn)程定位,否則邏輯功能錯(cuò)誤是沒辦法求助的。在不熟知您代碼、不清楚設(shè)計(jì)信號(hào)的含義、不知道設(shè)計(jì)意圖時(shí),沒有人能夠一眼看出問題所在,即使是老師也不行。這個(gè)問題只能靠工程師自己去定位去解決。
?
?
下一篇文章,我們將介紹定位功能邏輯錯(cuò)誤的方法,歡迎關(guān)注。
審核編輯:湯梓紅
評(píng)論