马上注册,看完整文章,学更多FPGA知识。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
作者:潘文明
众所周知,软件如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:搜索对于软件问题,要相信您肯定不是第一个吃螃蟹,大概率网上会有人咨询过该问题,热心的网友会留有详细的答案,所以最好的方式就是去搜索了。 把错误提示复制后去百度搜索(软件都会提供有复制功能,多试试右键),一般都能找到答案。 当然,搜索也有技巧。 Ø 去除掉“个性词”,例如跟您电脑名有关的、您自己的电脑路径、您自己的文件名等。 Ø 错误提示很长时,删减一些不必要的语句,保留关键词等。多试试不同的组合,万一有人问的方式不同呢。 Ø 搜索时,把软件名带上,否则会搜索出很多非本软件的问题。
最后,笔者精心整理并收集了多种工具遇到的问题,并整理成一个帖子,读者如果遇到软件的问题,可以先从下面找找答案。
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:自己行动除非有好心人,愿意牺牲时间来帮您远程定位,否则逻辑功能错误是没办法求助的。在不熟知您代码、不清楚设计信号的含义、不知道设计意图时,没有人能够一眼看出问题所在,即使是老师也不行。这个问题只能靠工程师自己去定位去解决。
下一篇文章,我们将介绍定位功能逻辑错误的方法,欢迎关注。
|