一位同事所设计的状态机使用Synplify综合和XST(Xilinx ISE内嵌的综合工具)综合的结果不一致,对Synplify的综合结果以及布局布线后上板调试完全正确,而对XST的综合结果布局布线后上板调试发现了错误,因此认为XST的综合结果有误,并对为什么XST综合会出现错误结果产生疑问。

在帮助他解决这个疑问后,我发现其中涉及的许多问题很具代表性,希望通过对这个问题的分析能对设计工程师的实际工作有指导意义。
下面是这位同事设计的状态机源代码:
状态转移图
该同事设计的是一个数据通讯中同步接收装置的状态机:当“Reset_b”复位后,进入“DROP”状态;当接收指示信号“RXDV”有效后,从“IDLE”状态进入接收前缀信号状态“PREAMBLE”;当控制信号“RxDEQ5”有效后进入“SFD”状态接收一些指示关键字;当控制信号“RxDEQ”有效时,进入数据接收状态“DATA0”;接收完“DATA0”后接收“DATA1”,直到接收指示信号“RxDV”无效,返回到“IDLE”状态。其状态转移图如图1所示。
竞争冒险

粗略地读一下代码就发现一处问题,状态“DATA1”执行的代码有“竞争冒险”。该段为:
当前状态为DATA1,且“RxDV”为低电平的时候,NextState到底是什么?是IDLE还是DATA0?这是一处比较明显的竞争冒险,不同的综合器会综合出不同的逻辑结构,而且会出现毛刺。造成这个错误的原因是在使用if语句的时不慎重,这类问题是比较常见的问题。根据前面状态转移图描述的设计意图,修改为:
在消除竞争冒险后,再作综合后仿真,比较更改前后综合后仿真的结果。图2为该同事在更改“竞争冒险”前后,综合后仿真波形示意图。从综合后仿真波形可以看出,更改“竞争冒险”后XST的综合结果有了改进,但是仍然不符合设计要求。
锁存器的使用
为了验证综合后仿真结果,本人用相同的测试激励,在ModelSim中对修改了“竞争冒险”的代码进行功能仿真、XST综合后仿真、Synplify综合后仿真,综合时所用参数为默认参数。
从仿真波形可以看出,两种综合后仿真波形的最大差异在于“RxDEQ5”信号有效后状态转移的情况不同:Synplify的综合结果,在“RxDEQ5”信号有效期间锁存了状态“2”;而XST的综合结果,在“RxDEQ5”信号有效期间并未锁存状态“2”。这时再次分析代码,观察代码中大量使用的锁存器是否符合设计需求(当初认为是作者的设计意图)。原设计中在状态“IDLE”、“PREAMBLE”、“SFD”的转移条件中都使用了如下的命令格式:

if(某转移条件) NextState<=某状态;
这种描述方法常会被综合器综合成锁存器结构,而在设计准则中我们常说“同步时序设计最好不要使用锁存器”。在同步状态机设计中使用锁存器也会带来时序、稳定性等诸多方面的问题。而且在综合优化参数不一致的情况下,不同综合器对锁存器的综合结果有可能不一致。XST与Synplify是否因为该问题造成的综合结果不一致呢?带着这个问题,我们分析XST和Synplify的综合结果。
分析综合结果的方法多种多样,我们可以直接打开综合输出的网表文件,观察逻辑网表的连接。但是更为方便的分析方法是使用RTL视图(寄存器传输级)分析综合结果。
Synplify Pro的RTL View是对源代码编译结果应用B.E.S.T技术再现的寄存器传输级原理图。该图高度抽象为模块化结构,帮助用户理解源代码对应的具体电路结构,检验设计的正确性。Xilinx的FPGA/CPLD设计平台ISE也提供了功能相似的RTL视图工具,可以使用ECS(原理图编辑器)观察XST的综合结果。

图6是Synplify的RTL视图,观察到状态转移变量“NextState”被综合成了锁存器(锁存器)。
图7是XST的RTL视图,其中状态转移变量“NextState”条件判断部分被综合成了组合判断电路,而不是锁存器。
从XST和Synplify的状态转移图可以清晰的看到,两种综合工具在默认参数条件下对“IDLE”、“PREAMBLE”、“SFD”等状态的转移条件的综合结果不一致,故而导致了综合后仿真波形的不同。Synplify将这些状态转移条件综合为锁存器,而XST却综合为组合逻辑判断电路,未使用锁存器资源。

但是我们并不能因此说XST综合器的综合结果是错误的,该综合器不可靠。这里两种综合结果有差异的根本原因在于作者的代码风格不合理。作者在同步状态机描述中使用了大量不完整的条件判断语句,而XST在默认参数条件下尽量避免使用锁存器,而通过组合逻辑判断实现状态转移。当然我们也可以通过设置XST参数,使XST将上述代码描述也综合为锁存器。但是好的同步时序设计要尽量避免使用锁存器,这里使用锁存器好像电路功能正确了,但是有很多隐含的错误。请读者思考一下,进入“PREAMBLE”状态后,如果“RxDV”变低将会出现什么情况?同理,进入SFD状态后,条件不满足呢?这时发生的状态转移未必是作者的设计意图。总之,使用锁存器造成的后果是状态机不健壮!
解决方法
解决上面的问题很简单,只需根据设计意图将“IDLE”、“PREAMBLE”、“SFD”等状态的转移条件进行改写,将不完整的“if”条件语句改为“if...else”条件语句即可。如下所示:
List4
作者提供的源代码在经过修改“竞争冒险”和“锁存器”两类问题后,XST和Synplify的综合结果的仿真波形完全一致,都符合了设计意图。
本文小结

通过前面的分析,我们发现造成XST与Synplify的综合结果不一致的原因在于作者错误使用了锁存器结构。为了加强读者对“代码风格”、“综合后仿真”、RTL视图等概念的理解,在此引申谈一下上述问题。
1. 综合后仿真的概念与作用
综合后仿真的最主要作用在于验证综合器的综合结果是否与设计意图一致。仿真时,把综合生成的延时文件反标到综合仿真文件中去,可估计逻辑门延时带来的影响。该仿真只能估计门延时,而不能估计线延时,仿真结果与布线后的实际情况还有一定的差距,并不十分准确。有些设计工程师认为综合器是永远可靠的,综合出的电路应该与设计意图一致,综合后仿真与功能仿真结果一致。这种观点是错误的,只要当代码风格合理,不出现让综合器误解的描述时,综合结果才会和设计意图完全一致。在一般情况下建议不要省略此步骤。
2. 代码设计风格对设计的影响
在学习逻辑设计之初,老师总是强调代码风格的重要性。有些设计工程师认为现在综合器的优化功能越来越强,对大部分设计都可以优化。这种观点是不对的,综合器的优化结果主要是依靠设计工程师的代码风格。设计风格对综合结果的影响可以用一句话概括:“好的代码设计风格会使综合器事半功倍,达到最优的综合结果;不好的代码设计风格会使综合器南辕北辙,产生错误的综合结果。”本文的实例的所有问题都源于其代码风格不尽合理,而并不在于综合器。
3. 状态机设计方法。
状态机的设计方法很多,描述方法不一而同,目前如StateCAD等状态机辅助设计软件给用户提供了很多的帮助。这里需要强调的是在状态机的设计中使用条件判断语句一定要慎重,尽量使用“if...else”这种完整的判断结构。有时判断语句使用不合理,会造成综合器对设计的误解,不同的综合器的默认综合结果会因为是否使用了锁存器,是否使用了带有优先级的编译码器等结构而不同。

4. 一些有用的辅助分析工具。
FPGA/CPLD等可编程逻辑器件的长足发展在一定程度上就是因为其EDA辅助设计工具的智能化、易学易用、功能强大等优势。在本例分析综合结果的过程中,并未直接分析综合器的输出网表,而是使用了RTL视图进行分析,直观、快捷,提高了分析效率。
作者:王诚,钟信潮,吴蕾
中兴通讯公司
薛小刚
Email: wang.cheng@zte.com.cn |