原创 维护遗留代码(2)——从搭建仿真环境入手

2009-12-28 16:59 3337 6 8 分类: FPGA/CPLD
        代码移交完成后,为了尽快掌握第三方开发的FPGA代码,我面临的首要任务是搭建一个完备的仿真环境。 riple

        原工程在Quartus II下采用波形文件搭建了仿真环境。用过Quartus II集成仿真工具的朋友应该了解,与Modelsim相比这个仿真工具存在以下几点不足:
        1. 仿真的对象是综合后的网表,而不是HDL语言。如果把仿真对象看作是一个“黑盒子”,网表级仿真和语言级仿真是等价的;但是我面临的问题是尽快学习和掌握FPGA代码,而且后续的工作涉及到调试和维护,我需要的是对代码内部每一个网线型和寄存器型对象的观察和控制能力。这一点,只有支持语言级仿真的工具才能提供。(原有的仿真环境是通过把内部节点引出到顶层输出引脚来增强观察能力的。) riple
        2. 测试向量的输入只能是波形,而不是HDL语言。在测试向量很简单的情况下,手工输入波形比编写和调试行为级的HDL语言代码要快捷。但是在测试向量变得复杂后,手工输入和维护波形文件是繁琐易错的,而且波形文件很难进行版本差异比较,失去了版本控制工具提供的便利。进一步说,基于波形输入的仿真工具只能由设计者目视检查仿真结果的对错,不能实现仿真结果的自动化检查,也就不能支持基于仿真的回归测试。 riple
        基于上述原因,在对原有的仿真环境进行了初步的学习后,我转向了在Modelsim下搭建仿真环境。 riple

        在Modelsim下搭建仿真环境时遇到了下面几个问题,相应的解决方案也一起列出:
        1. 原有的设计顶层采用了图形文件输入,Modelsim不能直接支持,需要在Quartus II下手工把图形设计文件转化为HDL文件。 riple
        为了保证每次修改图形文件后在仿真中能够不遗漏相应的更新,需要自动保持图形文件和HDL文件的一致性。我编写了一个Tcl脚本bdf2vlog.tclzip来完成这个任务,这个脚本可以包含在Modelsim的仿真脚本中,每次运行Modelsim编译前自动执行。 riple
        2. 原有的设计没有全局复位信号,仿真初始时刻所有的信号都是未知态。缺少初始复位的设计在Modelsim下进行HDL语言级别的仿真是不能运行的,但是在Quartus II和Modelsim下进行综合后网表级别的仿真是可以运行的,而且这样的设计在硬件中是可以正确运行的。在Quartus II手册中明确指出,FPGA器件中所有寄存器在配置完成后是确定处于逻辑“0”状态的(代码中明确指定复位后需要初始化为逻辑“1”的寄存器可以通过NOT Gate Push-back功能初始化为逻辑“1”状态)。这样看来,由于缺少复位设计而导致的HDL语言级别仿真失败,并不是因为原设计本身存在问题(尽管这样的风格并不好),而是因为我们在惯用的HDL语言中对时序逻辑的描述没能包含真实器件的初始值。综合后网表中对D触发器的描述包含了这一正确的初始值,所以能够在Quartus II和Modelsim下正常仿真。 riple
        这一问题,是不可能通过修改HDL设计输入文件来解决的——无论是手工添加复位信号,还是修改对时序逻辑的初始化描述,涉及的工作量都太大了。好在Modelsim提供了一条控制仿真模型内部信号状态的命令:force。force命令的选项很多,可以支持多种用法,比如快速创建某种临时或永久的仿真模型内部状态或输入状态。在这里,我采用了“-cancel 0”选项来实现对被测对象内部时序逻辑的初始化,再配合上find signals /*这一通配查找命令,就可以快速全面地完成对时序逻辑的初始赋值操作,把未知态消灭在了仿真的初始0时刻。通过在各个模块加载完毕之后仿真运行之前执行脚本reg_init.tclzip,这一问题得到了解决。 riple
        3.随后这个问题与上述问题类似,都是初始化问题——存储器初始化问题。这一问题同样只出现在HDL语言级别的仿真下,在网表级的仿真下和真实器件中都是不出现的。正常情况下,通过MegaWizard Plug-in Manager生成的存储器例化语句中,对存储器在仿真中的初始值是有设置的:POWER_UP_UNINITIALIZED = "FALSE"。有了这一参数,在仿真中,存储器取值可以自动初始化为逻辑“0”;对于Cyclone III器件,即使没有指定,这一参数的缺省值也是“FALSE”,从而保证了仿真和真实器件行为的一致性。原设计在输入文件中直接用HDL语言例化了存储器模块,但是由于该设计历经了多个FPGA器件系列,出于兼容性考虑,所有的存储器模块在例化时都没有指定器件系列(INTENDED_DEVICE_FAMILY)。由于没有指定器件系列,POWER_UP_UNINITIALIZED参数的指定值和缺省值都是无效的,这就导致了在HDL语言级别的仿真中,所有存储器的初始值为“X”,一些由存储器输出直接驱动的逻辑就不能正确运行了。 riple
        这一问题,是可以通过修改HDL文件来解决的——存储器的例化数量并不多,位置也好找。我采用了跟第二个问题同样的解决方法:通过Modelsim提供的命令从被测对象外部来给存储器赋值。这里我采用mem list查找所有的存储器,采用mem load加载特定的存储器。加载存储器内容为“0”的命令不能在仿真0时刻立即运行,因为在仿真开始运行后存储器的仿真模型会把初始值设置为“X”。只有在存储器仿真模型正常初始化完成后,比如仿真运行1ns后,才能执行脚本mem_init.tclzip riple

        用一个周末的时间解决了上述几个“非正常”问题后,搭建仿真环境的工作就剩下编写外部接口模型了。在接下来的几天内,我又编写了RGMII和MDIO接口的行为模型,最后完成了CPU接口的BFM行为模型。其中,CPU接口的行为模型采用了Modelsim控制台交互式激励输入方式,但是这个我自创的方法还不成熟,只有在配备了双核处理器的PC机上才能顺畅运行。等到这一方法成熟后,我会在博客上介绍这一技术。 riple


June 26 2009 - June 30 2009

文章评论2条评论)

登录后参与讨论

用户1073592 2009-11-26 16:51

学习了

用户1546547 2009-11-25 20:17

看样子这是一个比较盘大的工程了,如果有一个完整的任务书或是需求说明干脆重新设计好了
相关推荐阅读
ash_riple_768180695 2015-12-18 11:06
学习示例程序:FPGA快速系统原型设计--敏捷实践
        学习与开发板配套的示例程序,是敏捷实践的起点。示例程序是厂商针对开发板上提供的硬件资源和接口量身定做的工程,可以展示其FPGA芯片的功能和性能特点。从示例程序入手最大的好处就是:示...
ash_riple_768180695 2015-11-03 16:46
开发板选取:FPGA快速系统原型设计--敏捷实践
    既然是“实践”,就不能只谈编码和仿真,必须要上板运行、调试。这个虚拟项目的目标是实现一块兼容Intel82574L以太网控制器的千兆网卡,需要运行在一块具备PCIe接口和10/100/10...
ash_riple_768180695 2015-10-22 12:41
开篇:FPGA快速系统原型设计--敏捷实践
    虽然借用了 “系统原型开发”的标题,本系列文章将围绕FPGA IP级别的开发这个主题展开,如果可能的话,将扩展至FPGA System级别的开发。     先上一篇PPT:RSPwFP...
ash_riple_768180695 2013-08-26 10:21
学习SystemVerilog(二)——学习它的理由
    学习SystemVerilog的理由也很多,我在阅读SystemVerilog for Design 和 SystemVerilog for Verification两本书前言的过程中,总...
ash_riple_768180695 2013-08-26 10:19
学习SystemVerilog(一)——不学习它的理由
    想要学习SystemVerilog已经很久了。曾经尝试通过Accellera网站上给出的LRM学习,怎奈内容众多,找不出入手点和重点,只能望而却步。虽然手头有三本SystemVerilog...
ash_riple_768180695 2011-06-26 23:20
Hardware-Assisted IEEE1588 Implementation Analysis
06/18/11 11:00:05 PM         最近一段时间在研究IEEE1588-2008精确时间同步协议(PTP)。该协议可以在软件中实现,如果需要提高时间同步...
我要评论
2
6
关闭 站长推荐上一条 /2 下一条