在用ModelSIM做post-synthesis仿真时遇到一个问题,一个计数器明明复位时给它赋值为20,可是仿真时却显示复位值为0,如图1,refresh_counter计数器。当时马上检查了一下代码,发现确实没什么问题,而且之前还做过RTL仿真,复位时正常的。于是马上想到是QUARTUS II综合的问题,第一反应就是寄存器被优化掉了。然后查看了QUARTUS II编译报告,在报告Analysis & Synthesis –> Optimization Results->Register Statistic->Register Removed During Synthesis部分,如图2,发现出现问题的寄存器refresh_counter并没有被移除。
图1 ModelSIM仿真结果
图2 QUARTUS II综合寄存器移除优化报告
那就奇怪了,为什么复位会是0呢,难道ModelSIM有问题?于是又换QUARTUS II自带的仿真软件来做时序仿真,发现结果也一样。
RTL仿真结果正常,post-synthesis仿真结果有差异。此时,我敢肯定就是编译器综合时出现了优化,使寄存器的输出看起来“不正常”。再次查看编译报告,发现优化结果关于寄存器的报告,有个Inverted Register Statistic,当时非常不以为然。在多次检查综合Settings并继续了几次全编译->仿真结果依旧后,我突然想到了这个Inverted Register。
如图3,我再次打开了编译报告Analysis & Synthesis –> Optimization Results->Register Statistic->Inverted Register Statistic部分,发现在综合过程中refresh_counter计数器的第4位和第2位都被反转了。我马上把复位的结果16’d0的第4位和第2位取反,经计算,刚好是16’d20(10100b = 20d),看来找到问题所在了。
图3 QUARTUS II综合寄存器反转优化报告
既然问题找到了,那为什么QUARTUS II综合时要这样做呢?带着疑问,我仔细的查看了QUARTUS II的综合设置Settings,发现没有一项是明确标明有“Inverted register”这一类字眼的。于是上GOOGLE搜索,在应该是QUARTUS II的帮助手册里看到了这一字眼。链接:http://quartushelp.altera.com/10.1/mergedProjects/eda/quartus2/eda_gid_qis_fv.htm。原文如下:
Register inversion
The Encounter Conformal software compares the behavior of each sequential node in the design. However, if an inversion is pushed through a register and implemented on the data input (NOT gate push-back), the value of the data input for the node is inverted, and the Encounter Conformal software may report an inverted equivalent signal. These registers are automatically added to the <design name>.ctc script file.
上面这段话什么意思呢,说实话我也不是很清楚,但我注意到了里面的“NOT gate push-back”(红色标注部分)。我记得QUARTUS II综合设置Settings里面是有关这么一项的。这项的QUARTUS II说明如下:
Allows the Compiler to push an inversion (that is, a NOT gate) back through a register and implement it on that register's data input if it is necessary to implement the design. If this option is turned on, a register may power up to an active-high state, so it may need to be explicitly cleared during initial operation of the device. This option is ignored if it is applied to anything other than an individual register or a design entity containing registers. If it is applied to an output pin that is directly fed by a register, it is automatically transferred to that register.
大概意思是,如果设计需要,综合器会在寄存器的输出后面加一个NOT门送回寄存器的数据输入端。如果这个选项开启,寄存器上电可能会处于一个active-high状态,因此可能需要我们在设备初始化操作时明确的清零。这个选项能应用于独立的寄存器或者包含寄存器的设计实体。如果该选项运用于一个输出引脚,而这个引脚是与一个寄存器的输出直接相连的,则该选项自动应用到这个寄存器上。
我试着去禁止该选项,然后重新编译仿真,发现结果依旧。注意到了编译警告中有句:Warning: NOT_GATE_PUSH_BACK-forbidden assignments are ignored,然后右键这警告,点help,QUARTUS II help里对此的说明是,尝试不要使用寄存器的preset端口。
到此,原因已经明白了。因为我对该寄存器使用异步复位,复位值不为0,QUARTUS II综合时会使用寄存器的preset端来使寄存器复位值为1。而在我所使用的器件Cyclone II EP2C8Q208中,里面支持的寄存器资源并没有preset端口,所以,综合器只能用NOT gate push-back的方式来实现复位值不为0。查看Technology Map Viewer关于refresh_counter,发现确实如此,如图4红色部分所示,这里给出refresh_counter[4]。所以,仿真并没有错,只是我们仿真时查看的信号节点错了,实际正确的输出应该是NOT门的输出。
图4 Technology Map Viewer
总结:好的设计要考虑目标器件的资源和资源类型,根据器件上的资源和资源类型来选择合适的代码描述方式。像我这次遇到的情况还算简单,这样写从综合结果来看对资源和性能影响可以忽略不计。如果要改,可以换成复位值是0,采用加1运算来实现计数要求,如果一个计数模块这样会冲突,可以考虑拆成两个模块来写。但是如果遇到比较复杂的情况,综合器会在没有现成资源的情况下添加较大的额外逻辑来实现设计,这样可能就会造成资源浪费和时序问题,为了避免这一情况,我们可能就要重新更改我们的设计代码。所以,我们多少要对目标器件的资源情况有个大概的了解,以便在设计时合理的选择合适的编码风格。
文章评论(0条评论)
登录后参与讨论