FPGA形状的调试高合 自慰,尤其是大型形状,一直都是耗时耗力的使命。领先是因为HDL谈话沿空间并发膨大的脾性不同于一般基于依时间线性叙事的计较机谈话,各个元素之间的逻辑关系愈加考究,不易贯穿和念念考,debug技艺也未几。同期,FPGA形状的详尽布线经过都比较缓缓,时时一个中等大小的形状会需要恭候数十分钟材干得到输出文献,大型接洽run隔夜是常见的事情,浮滑一个笔误都会带来很高的千里没资本。每次说到这里,都不由赢得忆起多年畴前某次出差作念实验,邂逅过一位接头所年老打趣说最爱教育指派FPGA任务,因为只须按下详尽按钮,便能省心歇息半个午后。当时候,六合初开,摸鱼这个词还莫得发明,也莫得猜想即即是当下最强最fancy的CPU也没能调停这种恭候。
长篇大套。在逻辑构念念基本正确,形状编写大致轨范的前提下,大浩繁的问题,都仅仅写代码时的一些小强项。通过实施功能仿真,其实不错把浩繁逻辑问题都找出来。关联词,本色使命中,时时没随机候或耐性作念仿真,而是径直编码后下硬件调试了。此时,通过仔细阅读详尽器给出的告诫信息,就不错在最耗时的布局布线之前把多样小问题找出来并修正,从而灵验地提升开辟成果。在调试阶段,若是际遇了难以贯穿的气候,回过火去分析告诫信息亦然一种灵验的成见。在本文中,咱们以vivado自带详尽器为例、以verilog为编程谈话,望望怎么贯穿和哄骗告诫信息放弃代码中的小bug。
(以上图片来自采集: My digital designing diary by Mandapati) 为了毛糙申诉,咱们先建一个样例工程,包含模块top和adder。
为了幸免像许多经典教科书中的 “a=(b++)+(++c)” 那样被指为“例子代码不提神软件工程”,专门把这个形状写的尽量靠近工程本色一些(除了莫得注目)。领先它具有特定的功能,对两路并发输入的数据流先相加再累加。其次,数据端口界说摄取时下常用的AXI-Stream格调。
模块top是顶层模块,其源码Top.v如下图。该模块具备时钟信号clk和异步复位信号rst。输入数据端口din_tdata[31:0],配套流控持手信号din_tvalid和din_tready。在模块里面,输入数据领先被劈成2个16bit数据,代表要相加的两路数据流,并注入加法器模块adder。加法器的输出数据是adder_out[15:0]。第31行首先的always语句则完成对加法适度的累加操作。累加适度从端口acc_tdata输出,配套数据灵验符号acc_tvalid。
再望望加法器的源码Adder.v,如下图。两路数据din1和din2,分享解除组流控持手信号din_tvalid和din_tready。加法适度从端口dout输出。在模块里面,第14行的always语句看重完成通盘逻辑处置。中枢语句在第21行:当输入数据灵验何况后级成立准备好时,进行一次加法操作。写到这里作家亦然十分感叹,三十多行代码就是为了伺候第23行的这个“+”号。
至此,例子形状搭建好了。形状比较小,按下Run Synthesis按钮恭候半分钟阁下就能看到详尽适度。底下咱们一说念一边修改代码一边望望常见的告诫信息都有哪些。 1. 常数驱动 告诫之是以是告诫,是因为详尽器分不清它是否果然有问题。许多告诫是不错忽略的。举例上述例程,看上去很完整,但详尽完成后仍然会得到如下的告诫信息:
这里,详尽器提醒咱们,top模块的端口din_tready被驱动为常数1,可能是一个潜在的问题。在top的逻辑中,din_tready的功能是提醒模块外部的前级数据源“是否准备好招揽数据”。被驱动为1则默示“长久都准备好招揽数据”。用穷追思底的形状分析代码,不错看到din_tready是被加法器实例adder1驱动的,而在加法器里面(adder.v的第31行),该信号来自于加法器输出端的tready。
成人网再看回top.v的第17行,尽然加法器的tready被置为常数1,根源在此。具体到这个例子,此逻辑自身莫得大问题,因为top模块的输入端口惟稀有据灵验信号acc_tvalid,并莫得配套的tready,诠释该端口是强行输出的,并不研讨后级莫得准备好的情况。 是以,在此例中,这个常数驱动告诫“基本上”不错被忽略。关联词,问题禁不住细琢磨,比如斯例程并莫得研讨在复位信号rst灵验时间din_tready应当拉低来进犯数据输入,不太玉成。
进一步的,咱们还能瞎猜想,在确凿的系统中,这个接口界说是否存在隐患? 即,后级模块是否果然不错无要求招揽数据? 这些都是告诫信息带来的福利。 2. 毋庸信号 底下首先折腾代码。领先把top.v line27处的端口和洽去掉,只留住空括号。这么,adder1实例的dout_tvalid输出就悬空了。
详尽之后高合 自慰,得到如下图的告诫。详尽器见知adder1中的dout_tvalid所对应的寄存器资源被移除。
澄澈,这是由于在top中断开了信号和洽,于是dout_tvalid信号在adder里面诚然被赋值,关联词在通盘这个词逻辑中莫得被任何其它方位使用,也莫得输出,于是详尽器在给出告诫后就将其删除了。从这个例子不错看到,若是一个信号被自动移除了,应当领先应当研讨它是否莫得在别处被用到。不外,鄙人一个例子里立时不错看到这并不是信号被优化掉的惟一的原因。 3. 无源信号 领先,先把源码收复,然后试着把Top.v第17行注目掉:
详尽之后,得到如下告诫信息:
第一条信息直奔主题:adder_tready信号莫得被驱动。这澄澈是前述修改带来的,源形状里零落对adder_tready的赋值操作。第二条以及随后更多的信息则会让东说念主困惑:adder1/dout[15:0]被从逻辑中移除了。这些信号明明都有被后续的累加操作用到,为什么还会被优化掉? 通过分析adder中的逻辑关系不错知说念,这仍然是因为adder_tready莫得被驱动,于是详尽器以为但凡依赖于adder_tready的后续信号都照旧莫得存在的意旨,于是一股脑全拿掉了。这就指示咱们,若是发现存大片的逻辑隐没了,不但要往后寻找看是否零落最终的输出,何况要往前寻找看是否存在不细目或者无驱动的输入。
天然,关于多样很是情况,不同的详尽器以及解除个详尽器的不同的参数,会推崇很大的各异。比如作家也见过有的详尽器会径直给无驱动信号赋值为0,这种真心真意的遮挡反而导致随机候问题很难查找。 4. 多重驱动 在top.v的第16行,把原先的adder_d2改成adder_d1,酿成一个典型的笔误。底本是要分辨给信号addr_d1和addr_d2赋值,一不小心变成了给信号adder_d1赋值两次。
关于上述情况,详尽器明确指出了有信号被multi-driven了,如下图。
关联词,它指出的对象却并不是addr_d2,而是我数据源din_tdata。这是因为,在详尽器看来,din_tdata[15:0]和din_tdata[31:16]都和洽到了addr_d2[15:0],其实就是din_tdata[15:0]与din_tdata[31:16]径直点对点短接了,是以它们自身就濒临多驱动问题,addr_d2此时仅仅一个“别号”费力。好比你外出健忘戴帽子,而详尽器告诉你:请正式凉风照旧讲和头皮。这种机器式的申诉格调,随机候确凿会带来一些小进犯,不外民俗了就好了。 5. 复位缺失 top.v第31行的always语句摄取了异步复位。复位信号rst与时钟clk一说念手脚语句触发要求,在语句里面先按判断rst是否为真来选拔实际复位操作。这是verilog典型的异步复位语句写法。这里,尝试把第36行注目掉,如下图。
详尽器会给出如下的告诫。
字面背后的兴味不错贯穿为:语句中存在复位语段,关联词并莫得对acc_tvalid信号作念复位操作,导致逻辑缺失,或者说详尽器分不清应该set如故reset,于是总结详尽适度会与仿真适度不符。 这类告诫不错匡助咱们找出因为忘了写复位而启动值不细想法寄存器,这往往是许多要紧bug的着手。若是存在某些寄存器的确不需要复位操作,则应当单独写一个惟有clk作念触发的always句段,就能幸免上述告诫。 那么,此时详尽适度有莫得生成欲望的逻辑呢? 怒放详尽输出的逻辑图(如下),不错看到acc_tvalid由一个莫得复位和置位的D触发器驱动,适合修改后的语句欢喜。关联词,咱们仍然应该设法幸免这类不太轨范的写法。尤其是关于外行,务必要了解谈话与确凿逻辑的映射关系,牢记verilog就那么几种常见的语句套路。新奇的写法,可能导致十足不能预期的详尽适度。
6. 位宽失配
修改adder模块的端口声明,如下图,把din1和din2的位宽从16bit分辨改为17和15。
如下图,详尽器会明确指出在top.v中完毕adder模块时际遇了端口宽度不匹配的问题。
需要指出的是,至少关于vivado + verilog,位宽失配告诫只对模块端口和洽有用。若是是两个位宽不同的信号赋值,详尽器将会径直作念高位截断或者高位补零,而不给任何告诫,除非截断操作触发了毋庸信号告诫。是以,不管是wire类型如故reg类型,赋值时的位宽对皆问题,十足需要编程者自行关怀。举例底下的语段,16bit的src被赋值给16bit的dst1和15bit的dst2,澄澈赋值给dst2时最高位会丢失,关联词此时详尽器不会给出告诫,这是verilog谈话自身的脾性,改不了。何况,因为dst1用到了src的通盘bit位,是以在详尽器看来src里也不存在毋庸的bit位,也不会触发毋庸信号告诫。最终适度就是,可能你就是笔误给dst2少写了1位,但这个失误要到后期调试时通过多样故障才被发现。这里并不是详尽器犯懒,而是verilog谈话自身就是这么接洽的,比拟之下VHDL就要严格的多,不同位宽信号彼此赋值不给告诫,而是径直报错。
7. 不应有的锁存器 把top.v中对adder_d1和adder_d2的径直赋值语句改为always句段,如下图:
上述修改将产生如下图的告诫信息:adder_d1和adder_d2变量引入了锁存器(latch)。
分析上述语句,不错看到din_tvalid的确极度于锁存使能信号,当它为1时din_tdata可穿透到adder_d1和adder_d2。若是怒放schematic不雅察详尽适度,会发现此处使用了一个名为LDCE的锁存器元件。 咱们知说念,FPGA公认的基础逻辑资源是查找表和D触发器,是否具备锁存器要看具体的FPGA型号和详尽器的算法,是以在HDL谈话中书写锁存器格调的语句并不是好成见,亦然这条告诫存在的意旨。 至此,咱们毛糙先容了在详尽阶段常见的一些告诫问题。天然,在后续的implementation操作中,还会有许多更难贯穿的指示和告诫出现,它们愈加地与具体器件的里面结构和元素关连。到了这些阶段,愈加需要去关怀XDC文献、关怀物理和时序拘谨,而不是HDL谈话自身。
审核剪辑:黄飞高合 自慰