tag 标签: hdl

相关帖子
相关博文
  • 热度 15
    2015-6-11 14:27
    1038 次阅读|
    0 个评论
      我常年担任多个有关FPGA学习研讨的QQ群管理员,长期以来很多新入群的菜鸟们总是在重复的问一些非常简单但是又让新手困惑不解的问题。作为管理员经常要给这些菜鸟们普及基础知识,但是非常不幸的是很多菜鸟怀着一种浮躁的心态来学习FPGA,总是急于求成。再加上国内大量有关FPGA的垃圾教材的误导,所以很多菜鸟始终无法入门。 为什么大量的人会觉得FPGA难学?本管理员决心来详细讲一下菜鸟觉得FPGA难学的几大原因。 1、不熟悉FPGA的内部结构,不了解可编程逻辑器件的基本原理。 FPGA为什么是可以编程的?恐怕很多菜鸟不知道,他们也不想知道。因为他们觉得这是无关紧要的。他们潜意识的认为可编程嘛,肯定就是像写软件一样啦。软件编程的思想根深蒂固,看到Verilog或者VHDL就像看到C语言或者其它软件编程语言一样。一条条的读,一条条的分析。如果这些菜鸟们始终拒绝去了解为什么FPGA是可以编程的,不去了解FPGA的内部结构,要想学会FPGA恐怕是天方夜谭。虽然现在EDA软件已经非常先进,像写软件那样照猫画虎也能综合出点东西,但也许只有天知道EDA软件最后综合出来的到底是什么。也许点个灯,跑个马还行。这样就是为什么很多菜鸟学了N久以后依然是一个菜鸟的原因。 那么FPGA为什么是可以“编程”的呢?首先来了解一下什么叫“程”。启示“程”只不过是一堆具有一定含义的01编码而已。编程,其实就是编写这些01编码。只不过我们现在有了很多开发工具,通常都不是直接编写这些01编码,而是以高级语言的形式来编写,最后由开发工具转换为这种01编码而已。对于软件编程而言,处理器会有一个专门的译码电路逐条把这些01编码翻译为各种控制信号,然后控制其内部的电路完成一个个的运算或者是其它操作。所以软件是一条一条的读,因为软件的操作是一步一步完成的。 而FPGA得可编程,本质也是依靠这些01编码实现其功能的改变,但不同的是FPGA之所以可以完成不同的功能,不是依靠像软件那样将01编码翻译出来再去控制一个运算电路,FPGA里面没有这些东西。FPGA内部主要三块:可编程的逻辑单元、可编程的连线和可编程的IO模块。可编程的逻辑单元是什么?其基本结构某种存储器(SRAM、FLASH等)制成的4输入或6输入1输出地“真值表”加上一个D触发器构成。任何一个4输入1输出组合逻辑电路,都有一张对应的“真值表”,同样的如果用这么一个存储器制成的4输入1输出地“真值表”,只需要修改其“真值表”内部值就可以等效出任意4输入1输出的组合逻辑。这些“真值表”内部值是什么?就是那些01编码而已。如果要实现时序逻辑电路怎么办?这不又D触发器嘛,任何的时序逻辑都可以转换为组合逻辑 D触发器来完成。但这毕竟只实现了4输入1输出的逻辑电路而已,通常逻辑电路的规模那是相当的大哦。那怎么办呢?这个时候就需要用到可编程连线了。在这些连线上有很多用存储器控制的链接点,通过改写对应存储器的值就可以确定哪些线是连上的而哪些线是断开的。就可以把很多可编程逻辑单元组合起来形成大型的逻辑电路。最后就是可编程的IO,这其实是FPGA作为芯片级使用必须要注意的。任何芯片都必然有输入引脚和输出引脚。有可编程的IO可以任意的定义某个非专用引脚(FPGA中有专门的非用户可使用的测试、下载用引脚)为输入还是输出,还可以对IO的电平标准进行设置。 总归一句话,FPGA之所以可编程是因为可以通过特殊的01代码制作成一张张“真值表”,并将这些“真值表”组合起来以实现大规模的逻辑功能。不了解FPGA内部结构,就不能明白最终代码如何变到FPGA里面去的。也就无法深入的了解如何能够充分运用FPGA。现在的FPGA,不单单是有前面讲的那三块,还有很多专用的硬件功能单元,如何利用好这些单元实现复杂的逻辑电路设计,是从菜鸟迈向高手的路上必须要克服的障碍。而这一切,还是必须先从了解FPGA内部逻辑及其工作原理做起。 2、错误理解HDL语言,怎么看都看不出硬件结构。 HDL语言的英语全称是:Hardware Description Language,注意这个单词Description,而不是Design。老外为什么要用Description这个词而不是Design呢?因为HDL确实不是用用来设计硬件的,而仅仅是用来描述硬件的。描述这个词精确地反映了HDL语言的本质,HDL语言不过是已知硬件电路的文本表现形式而已,只是将以后的电路用文本的形式描述出来而已。而在编写语言之前,硬件电路应该已经被设计出来了。语言只不过是将这种设计转化为文字表达形式而已。但是很多人就不理解了,既然硬件都已经被设计出来了,直接拿去制作部就完了,为什么还要转化为文字表达形式再通过EDA工具这些麻烦的流程呢?其实这就是很多菜鸟没有了解设计的抽象层次的问题,任何设计包括什么服装、机械、广告设计都有一个抽象层次的问题。就拿广告设计来说吧,最初的设计也许就是一个概念,设计出这个概念也是就是一个点子而已,离最终拍成广告还差得很远。 硬件设计也是有不同的抽象层次,没一个层次都需要设计。最高的抽象层次为算法级、然后依次是体系结构级、寄存器传输级、门级、物理版图级。使用HDL的好处在于我们已经设计好了一个寄存器传输级的电路,那么用HDL描述以后转化为文本的形式,剩下的向更低层次的转换就可以让EDA工具去做了,者就大大的降低了工作量。这就是可综合的概念,也就是说在对这一抽象层次上硬件单元进行描述可以被EDA工具理解并转化为底层的门级电路或其他结构的电路。在FPGA设计中,就是在将这以抽象层级的意见描述成HDL语言,就可以通过FPGA开发软件转化为问题1中所述的FPGA内部逻辑功能实现形式。HDL也可以描述更高的抽象层级如算法级或者是体系结构级,但目前受限于EDA软件的发展,EDA软件还无法理解这么高的抽象层次,所以HDL描述这样抽象层级是无法被转化为较低的抽象层级的,这也就是所谓的不可综合。 所以在阅读或编写HDL语言,尤其是可综合的HDL,不应该看到的是语言本身,而是要看到语言背后所对应的硬件电路结构。如果看到的HDL始终是一条条的代码,那么这种人永远摆脱不了菜鸟的宿命。假如哪一天看到的代码不再是一行行的代码而是一块一块的硬件模块,那么恭喜脱离了菜鸟的级别,进入不那么菜的鸟级别。 3、FPGA本身不算什么,一切皆在FPGA之外 这一点恐怕也是很多学FPGA的菜鸟最难理解的地方。FPGA是给谁用的?很多学校解释为给学微电子专业或者集成电路设计专业的学生用的,其实这不过是很多学校受资金限制,卖不起专业的集成电路设计工具而用FPGA工具替代而已。其实FPGA是给设计电子系统的工程师使用的。这些工程师通常是使用已有的芯片搭配在一起完成一个电子设备,如基站、机顶盒、视频监控设备等。当现有芯片无法满足系统的需求时,就需要用FPGA来快速的定义一个能用的芯片。前面说了,FPGA里面无法就是一些“真值表”、触发器、各种连线以及一些硬件资源,电子系统工程师使用FPGA进行设计时无非就是考虑如何将这些以后资源组合起来实现一定的逻辑功能而已,而不必像IC设计工程师那样一直要关注到最后芯片是不是能够被制造出来。本质上和利用现有芯片组合成不同的电子系统没有区别,只是需要关注更底层的资源而已。 要想把FPGA用起来还是简单的,因为无法就是那些资源,在理解了前面两点再搞个实验板,跑跑实验,做点简单的东西是可以的。而真正要把FPGA用好,那光懂点FPGA知识就远远不够了。因为最终要让FPGA里面的资源如何组合,实现何种功能才能满足系统的需要,那就需要懂得更多更广泛的知识。 目前FPGA的应用主要是三个方向:第一个方向,也是传统方向主要用于通信设备的高速接口电路设计,这一方向主要是用FPGA处理高速接口的协议,并完成高速的数据收发和交换。这类应用通常要求采用具备高速收发接口的FPGA,同时要求设计者懂得高速接口电路设计和高速数字电路板级设计,具备EMC/EMI设计知识,以及较好的模拟电路基础,需要解决在高速收发过程中产生的信号完整性问题。FPGA最初以及到目前最广的应用就是在通信领域,一方面通信领域需要高速的通信协议处理方式,另一方面通信协议随时在修改,非常不适合做成专门的芯片。因此能够灵活改变功能的FPGA就成为首选。到目前为止FPGA的一半以上的应用也是在通信行业。 第二个方向,可以称为数字信号处理方向或者数学计算方向,因为很大程度上这一方向已经大大超出了信号处理的范畴。例如早就在2006年就听说老美将FPGA用于金融数据分析,后来又见到有将FPGA用于医学数据分析的案例。在这一方向要求FPGA设计者有一定的数学功底,能够理解并改进较为复杂的数学算法,并利用FPGA内部的各种资源使之能够变为实际的运算电路。目前真正投入实用的还是在通信领域的无线信号处理、信道编解码以及图像信号处理等领域,其它领域的研究正在开展中,之所以没有大量实用的主要原因还是因为学金融的、学医学的不了解这玩意。不过最近发现欧美有很多电子工程、计算机类的博士转入到金融行业,开展金融信号处理,相信随着转入的人增加,FPGA在其它领域的数学计算功能会更好的发挥出来,而我也有意做一些这些方面的研究。不过国内学金融的、学医的恐怕连数学都很少用到,就不用说用FPGA来帮助他们完成数学运算了,这个问题只有再议了。 第三个方向就是所谓的SOPC方向,其实严格意义上来说这个已经在FPGA设计的范畴之内,只不过是利用FPGA这个平台搭建的一个嵌入式系统的底层硬件环境,然后设计者主要是在上面进行嵌入式软件开发而已。设计对于FPGA本身的设计时相当少的。但如果涉及到需要在FPGA做专门的算法加速,实际上需要用到第二个方向的知识,而如果需要设计专用的接口电路则需要用到第一个方向的知识。就目前SOPC方向发展其实远不如第一和第二个方向,其主要原因是因为SOPC以FPGA为主,或者是在FPGA内部的资源实现一个“软”的处理器,或者是在FPGA内部嵌入一个处理器核。但大多数的嵌入式设计却是以软件为核心,以现有的硬件发展情况来看,多数情况下的接口都已经标准化,并不需要那么大的FPGA逻辑资源去设计太过复杂的接口。而且就目前看来SOPC相关的开发工具还非常的不完善,以ARM为代表的各类嵌入式处理器开发工具却早已深入人心,大多数以ARM为核心的SOC芯片提供了大多数标准的接口,大量成系列的单片机/嵌入式处理器提供了相关行业所需要的硬件加速电路,需要专门定制硬件场合确实很少。通常是在一些特种行业才会在这方面有非常迫切的需求。即使目前Xilinx将ARM的硬核加入到FPGA里面,相信目前的情况不会有太大改观,不要忘了很多老掉牙的8位单片机还在嵌入式领域混呢,嵌入式主要不是靠硬件的差异而更多的是靠软件的差异来体现价值的。我曾经看好的是cypress的Psoc这一想法。和SOPC系列不同,Psoc的思想史载SOC芯片里面去嵌入那么一小块FPGA,那这样其实可以满足嵌入式的那些微小的硬件接口差异,比如某个运用需要4个USB,而通常的处理器不会提供那么多,就可以用这么一块FPGA来提供多的USB接口。而另一种运用需要6个UART,也可以用同样的方法完成。对于嵌入式设计公司来说他们只需要备货一种芯片,就可以满足这些设计中各种微小的差异变化。其主要的差异化仍然是通过软件来完成。但目前cypress过于封闭,如果其采用ARM作为处理器内核,借助其完整的工具链。同时开放IP合作,让大量的第三方为它提供IP设计,其实是很有希望的。但目前cypress的日子怕不太好过,Psoc的思想也不知道何时能够发光。 4、数字逻辑知识是根本。 无论是FPGA的哪个方向,都离不开数字逻辑知识的支撑。FPGA说白了是一种实现数字逻辑的方式而已。如果连最基本的数字逻辑的知识都有问题,学习FPGA的愿望只是空中楼阁而已。而这,恰恰是很多菜鸟最不愿意去面对的问题。数字逻辑是任何电子电气类专业的专业基础知识,也是必须要学好的一门课。很多人无非是学习了,考个试,完了。如果不能将数字逻辑知识烂熟于心,养成良好的设计习惯,学FPGA到最后仍然是雾里看花水中望月,始终是一场空的。 以上四条只是我目前总结菜鸟们在学习FPGA时所最容易跑偏的地方,FPGA的学习其实就像学习围棋一样,学会如何在棋盘上落子很容易,成为一位高手却是难上加难。要真成为李昌镐那样的神一般的选手,除了靠刻苦专研,恐怕还确实得要一点天赋。 做项目才是最快学习FPGA的方法,好好珍惜这次机会吧。 ——转载自互联网  
  • 热度 18
    2015-3-24 13:54
    1195 次阅读|
    0 个评论
       引言: 数字滤波器是语音与图像处理、模式识别、雷达信号处理、频谱分析等应用中的一种基本的处理部件,它能满足波器对幅度和相位特性的严格要求,避免模拟滤波器所无法克服的电压漂移、温度漂移和噪声等问题。有限冲激响应(FIR)滤波器能在设计任意幅频特性的同时保证严格的线性相位特性。   一、FIR数字滤波器   FIR滤波器用当前和过去输入样值的加权和来形成它的输出,如下所示的前馈差分方程所描述的。   FIR滤波器又称为移动均值滤波器,因为任何时间点的输出均依赖于包含有最新的M个输入样值的一个窗。由于它的响应只依赖于有限个输入,FIR滤波器对一个离散事件冲激有一个有限长非零响应,即一个M阶FIR滤波器对一个冲激的响应在M个时钟周期之后为零。   FIR滤波器可用图1所示的z域块图来描述。   其中每个标有z-1的方框都代表了有一个时钟周期延时的寄存器单元。这个图中标出了数据通道和必须由滤波器完成的操作。滤波器的每一级都保存了一个已延时的输入样值,各级的输入连接和输出连接被称为抽头,并且系数集合{hk}称为滤波器的抽头系数。一个M阶的滤波器有M+1个抽头。通过移位寄存器 用每个时钟边沿n(时间下标)处的数据流采样值乘以抽头,并且求和得到输出yFIR 。滤波器的加法和乘法必须足够快,在下一个时钟来到之前形成y 。并且在每一级中都必须测量它们的大小以适应他们数据通道的宽度。在要求精度的实际应用中,Lattice结构可以减少有限字长的影响,但增加了计算成本。一般的目标是尽可能快地滤波,以达到高采样率。通过组合逻辑的最长信号通路包括M级加法和一级乘法运算。FIR结构指定机器的每一个算术单元有限字长,并且管理运算过程中数据流。   二、FIR数字滤波器设计的实现   目前FIR滤波器的实现方法有三种:利用单片通用数字滤波器集成电路、DSP器件和可编程逻辑器件实现。单片通用数字滤波器使用方便,但由于字长和阶数的规格较少,不能完全满足实际需要。使用DSP器件实现虽然简单,但由于程序顺序执行,执行速度必然不快。FPGA/CPLD有着规整的内部逻辑阵列和丰富的连线资源,特别适合于数字信号处理任务,相对于串行运算为主导的通用DSP芯片来说,其并行性和可扩展性更好。但长期以来,FPGA/CPLD一直被用于系统逻辑或时序控制上,很少有信号处理方面的应用,其原因主要是因为在FPGA/CPLD中缺乏实现乘法运算的有效结构。   现在的FPGA产品已经能够完全胜任这种任务了。其中Altera公司的Stratix系列产品采用1.5V内核,0.13um全铜工艺制造,它除了具有以前Altera FPGA芯片的所有特性外,还有如下特点:芯片内有三种RAM块,即512bit容量的小RAM(M512)、4KB容量的标准RAM(M4K) 、512KB的大容量RAM(MegaRAM)。内嵌硬件乘法器和乘加结构的DSP块,适于实现高速信号处理;采用全新的布线结构,分为三种长度的行列布线,在保证延时可预测的同时增加布线的灵活性;增加片内终端匹配电阻,提高信号完整性,简化PCB布线;同时具有时钟管理和锁相环能力。   FIR滤波器的Verilog HDL设计实例   1、设计意图   本例主要是在Stratix器件内实现基本有限脉冲响应滤波器。   FIR的基本结构包括一系列的乘法和加法。FIR的运算可用式(1)的方程描述,现重写如下:   一个L=8的FIR设计如图2,利用了输入的8个样本。因此称之为8抽头滤波器。该结构是有一个移位寄存器,乘法器和加法器组成的,可实现L=8阶的FIR。其数据通道必须足够宽,以适应乘法器和加法器的输出。这些采样值被编码为有限字长的形式,然后通过M个寄存器并行移动。可见用一个MAC级连链就可以构成这种机器。每个寄存器提供一个单位样本内延迟。这些延迟输入与各自的系数相乘,然后叠加得到输出。图2所示为基于MAC的8阶FIR数字滤波器结构   在该设计中有八个抽头,各抽头有18位输入和滤波器系数。由于一个DSP块可以支持4个18位输入的分支,所以设计需要2个DSP块。输入数据串行加载到DSP块中,DSP内部的移入/移出寄存器链用于产生延迟。滤波器系数从TriMatrix™ 的ROM存储器中加载。   2、Verilog HDL代码编写风格   HDL代码编写应该具有很好的易读性和可重用性,而自顶向下的分割方法可以帮助我们达到最佳的结果。HDL代码在达到功能的情况下要尽可能的简洁,尽量避免使用带有特殊库单元的实例,因为这样会使得整个进程变得不可靠。   在本设计中,我们将设计划分成一个顶级文件和三个次级文件,并且调用了QuartusII中的MegaFunction功能辅助完成整个设计。   图3显示FIR滤波器的顶级方块图   表1:FIR滤波器的设计范例的端口列表       3、验证仿真   完全可综合设计的一个优点就是同样的HDL代码能够用于验证和综合。在使用HDL代码之前必须要验证设计的功能,最好且最简单的方法就是利用验证工具,其次是利用仿真工具作有目的的仿真。   QuartusII内部带有仿真器,只要通过建立正确的Vector Waveform File(向量波形文件)就可以开始仿真了。图4所示为QuartusII内部仿真器得到的8阶FIR的脉冲响应波形。   五、结论   利用Verilog HDL设计数字滤波 器的最大优点就是可使设计更加灵活。比较硬件电路图设计,Verilog HDL语言设计的参数可以很容易在Verilog程序中更改,通过综合工具的简化和综合即可以得到电路图,其效率要高出利用卡诺图进行人工设计许多。而且编译过程也非常简单高效。优秀编码风格能够在综合过程中节省芯片使用的单元,从而降低设计成本。   参考文献:    . 夏宇闻。VerilogHDL数字系统设计教程,北京航空航天大学出版社,北京. 2003.    . Altera Corporation. Introduction to QuartusII. 2003    . Michael D. Ciletti. Advanced Digital Design with Verilog HDL. Prentice Hall, NJ.2005.    .彭保等.基于VerilogHDL的FPGA设计. 微计算机信息, 2004年第20卷第10期
  • 热度 17
    2015-3-24 13:45
    1835 次阅读|
    0 个评论
      1 Testbench 的结构   1) 单 顶层 结构   一种结构是testbench 只有一个顶层,顶层再把所有的模块实例化进去。打个比方,类似树结构,只有一个模块有子节点而没有父节点,其它模块都有父节点。如下图结构所示:   测试模块是一些接口模型,接口模型还可能包含了一些激励在内。测试模块和DUV之间通过端口映射进行互连。   2) 多顶层结构   另外一种结构是多顶层结构,如下图所示:   在这种结构中,有一个顶层是作为测试向量模块,一个或多个顶层是一些公用子程序,这些子程序由于完成一些通用的功能被封装成任务、函数等被公用。   还有一个叫harness的顶层,该顶层由DUV和一些接口模型构成一个狭义上的测试平台,其它模块可以调用BFM里面的 task 或 event 等,向DUV施加激励。注意这些顶层之间是没有端口映射的,它们之间的互相调用和访问是通过层次路径名的方式来访问,上图的虚线表示层次路径名的访问。下面举例说明层次路径是如何访问的。   由于大部分人对C都有所认识,在这里作个比较,便于了解。 Verilog HDL 的顶层类似于C的结构体,而实例化的模块、任务、函数、变量等就是结构体里的成员,可以通过句点( . )隔开的方式访问结构体里面的每一个成员。如:顶层 harness 实例化进来的模块 BFM1 里面有一个任务SEND_DATA , 该任务可以产生激励输入到DUV,在 testcase 里调用该任务就可写为: initial begin   ……   harness . BFM1 . SEND_DATA ( …… ) ; end   多顶层结构的可扩展和重用性比单顶层结构强得多。层次路径的访问方式非常有用,在下一节会讲述更多的应用。   2 如何编写Testbench   1) 何时使用initial和always   initial和always 是2个基本的过程结构语句,在仿真的一开始即开始相互并行执行。通常被动的检测响应使用always语句,而主动的产生激励使用initial语句。   initial和always的区别是always 语句不断地重复执行,initial语句则只执行一次。但是,如果希望在initial里的多次运行一个语句块,怎么办?这时可以在initial里嵌入循环语句(while,repeat,for,forever 等),如: initial begin forever /* 无条件连续执行*/ begin   ……   end end   其它循环语句请参考一些教材,这里不作赘述。   另外,如果希望在仿真的某一时刻同时启动多个任务,可以使用fork....join语句。例如,在仿真开始的 100 ns 后,希望同时启动发送和接收任务,而不是发送完毕后再进行接收,如下所示: initial begin   #100 ;   fork /*并行执行 */ Send_task ; Receive_task ;   join End   2) 如何作多种工作模式的遍历测试   如果设计的工作模式很多,免不了做各种模式的遍历测试,而遍历测试是需要非常大的工作量的。我们经常遇到这样的情况:很多时候,各种模式之间仅仅是部分寄存器配置值的不同,而各模式间的测试都是雷同的。有什么方法可以减轻这种遍历测试的工作量?不妨试试for循环语句,采用循环变量来传递各种模式的配置值,会帮助减少很多测试代码,而且不会漏掉每一种模式. initial begin   for ( i = 0 ; i m ; i = i + 1 ) /*遍历模式1至模式m*/ for ( j = 0 ; j n ; j = j +1 ) /*遍历子模式1至子模式n */ begin   case ( j ) /* 设置每种模式所需的配置值 */   0 : 配置值 = a ;   1 : 配置值 = b ;   2 : 配置值 = c ;   ……   endcase /*共同的测试向量*/ end end    3) 如何加速问题定位过程   在这部分里,通过一些实际例子,介绍在出现问题时如何借助 testbench 加快问题的定位过程。   1、监测内存分配     内存分配和回收示意图   在这个例子里,假设总共有2K的内存块,希望在测试程序里监测内存分配和回收的块号是否正确,监测是否存在同一块号重复分配、重复回收的情况。设置一个 2K位的变量对内存的使用情况进行记录,每一位对应一个内存块,空闲的块号记为1,被占用的块号记为0。该变量的初始值为全1,当分配一 个块号出去时先判断该位是否为空闲,若是空闲则将该位设置为被占用,否则就为重复分配错误。相反,当回收一个块号时,先判断该位是否被占用,若是被占用则将该位设置为空闲,否则就为重复回收错误。程序如下: always @(posedge Clk or negedge Rst ) begin   if ( Rst == 1'b0 ) Mem_status = 2048 {1'b1} ;   else   begin if ( 层次路径 . rd ) /* 监测内存分配,block_rd 是分配的内存块号*/   if ( Mem_status == 1'b1 ) Mem_status = 1'b0 ;   else   begin $display ( "Error! 重复分配同一内存块! ") ; $stop ;   end if ( 层次路径 . wr ) /* 监测内存回收,block_wr 是回收的内存块号*/   if ( Mem_status == 1'b0 ) Mem_status = 1'b1 ;   else   begin   $display ( "Error! 重复回收同一内存块! ") ;   $stop ;   end end End   2、监测内部接口   如果你是位验证工程师,在做芯片级的仿真时,相信你会或曾遇到过这样的问题:在一个端口输入了激励数据,但另一端口却得不到正确的响应,而且这条路径涉及到很多模块和很多个不同设计者,为了定位问题,你可能很盲目地逐个找来设计人员,逐个模块地记录仿真波形,到解决问题时,可能几天已经过去了。   我们都知道,如果问题定位在越小的范围,就越便于解决问题。所以,我们可以把模块接口间交换的数据记录到文件里,当出现问题时,就可以查看各接口的记录数据,看问题到底出现在哪个区间,简单地查看记录文件后,你就明确该找那位designer来解决问题。   3、记录有用的DEBUG信息   记录有用的debug信息,输出到标准的I/O设备上(屏幕或文件),会给你的debug带来很大的便利,由上面的例子也可见一斑,在检测到有错误时也可使用$stop令仿真停下来。   值得注意的是,UNIX系统只有32个I/O,每个输出文件占用1个I/O设备号,其中第1个是屏幕显示,设备号是32'b1,其它I/O设备号由输出文件占用,一个信息可同时输出到屏幕和文件,如: initial begin   Ptr_log = $fopen ("log.txt ") ; /* 创建一个文件,获得文件指针 */   Ptr_log = Ptr_log | 32'b1 ; /* 指针同时指向 log.txt 文件和屏幕 */ end always @(……) begin   $fwrite ( Ptr_log, "useul message ",……) ; /*信息除了记录到文件同时,还显示到屏幕*/   …… end   虽然记录文件会给debug带来很多便利,但文件操作会降低仿真的速度,因此应当适可而止。   另外写文件通常有2种方式,不同的仿真工具有所差异。一种是每写一个字节打开关闭一次文件,如Verilog-XL。另一种是先把字符暂存到内存,等累积到一定数量(如8K字节)后再通过DMA方式把字符从内存写到文件,如Verilog-NC。因此,后一种方式就大大地降低了文件的操作次数,有利于提高仿真速度。    3 编写 Testbench 的一些高级技巧    Verilog HDL 提供很多方便和高效的建模语句,这在大多数参考书上都有介绍,在这节,只介绍一些参考教材很少介绍而较有用的建模语句。    1) force 和 release   望文生义,force即是可以对变量和信号强制性地赋予确定的值,而release就是解除force的作用,恢复为驱动源的值。例如: wire a ; assign a = 1'b0 ; initial begin   #10 ;   force a = 1'b1 ;   #10   release a ; end   在10 ns时,a 的值由0变为1,在20ns时,a 的值又恢复为0 。   force 和release并不常用,有时,可以利用它们和仿真工具做简单的交互操作。例如,Verilog-XL的图形界面可以方便的将一个信号或变量force 为0或1,在 Testbench 里,可以检测变量是否被force为固定的值,当被force为固定的值时就执行预定的操作,实现了简单交互操作。   2) 事件   事件有些类似于任务。首先需要定义一个事件,而事件可以作为敏感变量激活一个语句块的操作,事件可由“-”符号进行触发,如下例: event e1 ; /*定义一个事件*/ always @( e1 ) /*事件e1 作为敏感变量*/ begin   ..... end initial begin   — e1 ; /*创建事件e1来触发上面的always语句*/   ..... end   事件(event )与任务(task)的区别是:执行事件触发后可以立即继续往下执行语句,只起一个触发作用,至于被触发的事件何时执行完毕并不影响程序继续执行。而调用一个任务后,必须等待任务完成才能返回控制权。   3) 模块参数   当一个模块引用另外一个模块时,高层模块可以改变低层模块用parameter定义的参数值,改变低层模块的参数值可采用以下两种方式:   1)defparam 重定义参数   语法:defparam path_name = value ;   低层模块的参数可以通过层次路径名重新定义,如下例: module top ( .....) input....; output....; defparam U1 . Para1 = 10 ; /*修改实例 U1 模块中的para1 */ M1 U1 (..........); endmodule module M1(....); parameter para1 = 5 ; input...; output...; ...... endmodule   在上例中,模块M1参数 para1 的缺省值为5,而模块top实例了M1后将参数的值改为10。   2) 实例化时传递参数   在这种方法中,实例化时把参数传递进去,如下例所示: module top ( .....) input....; output....; M1 #( 10 ) U1 (..........); endmodule   在该例中,用#( 10 )修改了上例中的参数para1,当有多个参数时,用逗号隔开,如#( 10 , 5 ,   3 )传递了3个参数值。   模块参数的方法使得模块的重用性更强,当需要在同一个设计中多次实例化同样的模块,只是参数值不同时,就可以采用模块参数的方式,而不必只因为参数不同产生了多个文件。   4) 其他要注意的几个点   4) 注意@与wait的区别   @都是使用沿触发。   wait语句都是使用电平触发。   5) 注意$sreadmemb(h)与$readmemb(h)的区别   $sreadmemb(Memory, StartAddr, FinishAddr, String , ……) :读字符串到Memory。 $readmemb("File", Memory ]) :读取的第一个数字存储在地址 StartAddr,直到FinishAddr。   6) 常用系统任务 $time 返回64位整型时间 。 $stime 返回32位整型时间 。 $realtime 向调用它的模块返回实型模拟时间。
  • 热度 23
    2015-3-24 13:42
    1220 次阅读|
    0 个评论
      0引言   现场可编程门阵列(FPGA)是1985年由美国Xilinx公司首先推出的一种新型的PLD。 FPGA在结构上由逻辑功能模块排列成阵列,并由可编程的内部连线连接这些功能模块来实现一定的逻辑功能。FPGA的功能由逻辑结构的配置数据决定,这些配置数据存放在片外的EPROM或其他存储器上。由于FPGA规模大、集成度高、灵活性更强,实现的逻辑功能更广,因此已逐步成为复杂数字硬件电路设计的首选。   1 FPGA的基本结构   FPGA通常由可编程逻辑单元 CLB、可编程输入输出单元lOB及可编程连线资源组成。通常CLB包含组合逻辑部分和时序逻辑部分,组合逻辑一般又包括查询表(Look-up Table)和相关的多路选择器(Multiplexer)。而时序逻辑部分则包含触发器(DFF)和一些相关的多路选择器。lOB主要提供FPGA内部和外部的接口,连线资源则提供CLB与lOB之间以及各CLB之间的通讯功能。FPGA芯片的基本结构如图1所示,其中开关盒可对水平和竖直连线资源进行切换,连接盒可将CLB的输入输出连接到连线资源中。   2 Verilog HDL语言的特点与优化设计   Verilog HDL语言是硬件描述语言的一种。它能形式化地抽象表示电路的行为和结构,同时支持层次设计中逻辑和范围的描述。设计时可借用高级语言的精巧结构来简化电路行为的描述。此外,该语言还具有电路仿真与验证机制,可以保证设计的正确性,同时支持电路描述由高层到低层的综合转换,且硬件描述与实现工艺无关,便于文档管理,易于理解和设计重用。   由于Verilog HDL语言易于理解、设计灵活,因此,Verilog HDL语言已经成为目前FPGA编程最常用的工具之一。然而,正是其设计灵活的特点使工程师必须面对采用哪种编程风格才能使逻辑电路精确工作的问题。因为如果某些原因导致逻辑电路发生误动作,则有可能会造成系统无法正常工作。而电路设计中的"毛刺"问题则是电路设计中最常见的。下面,本文将对容易产生"毛刺"的电路进行分析,并给出对应的优化方法及仿真波形。   3出现"毛刺"的原因   当信号在FPGA器件内部通过连线和逻辑门时,一般都有一定的延时。延时的大小与连线的长短和门单元的数目有关,同时还受器件的制造工艺、工作电压、温度等条件的影响。此外,信号的高/低电平转换也需要一定的过渡时间。由于存在这些因素的影响,多路信号的电平值发生变化时,在信号变化的瞬间,组合逻辑的输出都有先后顺序,而并不是同时变化,这往往就会出现一些不正确的"毛刺"。   "毛刺"信号的电路有两种类型。第一种是输入信号经过FPGA内部布线以后产生不同延时的异步电路;第二种是由于在编程时内部信号变化落后。在多个信号关联时,第一个信号变化如果发生落后情况,后面的信号将产生不确定状况,从而出现"毛刺"。 "毛刺"的存在说明该电路存在不稳定状况,因此,这很可能导致整个系统的误动作。   4 "毛刺"信号的消除    4.1组合逻辑电路"毛刺"的同步消除   现以一个组合逻辑电路为例来介绍该方法。从图2所示的仿真波形可以看出,"in1、in2、in3、in4"四个输入信号经过布线延时以后,其高低电平变换不是同时发生的,这会导致输出信号"out"出现了毛刺。由于设计时无法保证所有连线的长度一致,所以,即使四个输入信号在输入端同时变化,经过 FPGA内部走线到达或门的时间也是不一样的,毛刺必然产生。一般情况下,即使输入信号同时变化,经过内部走线后的组合逻辑也将产生"毛刺"。这样,如果将它们的输出直接连接到时钟输入端、清零或置位端口,就可能会导致不可预料的结果。   针对这类"毛刺"电路,设计时可以通过"毛刺"信号对同步电路不敏感的特性,来在系统中加入同步时钟,这是因为同步电路信号的变化都发生在时钟沿的保持时间。因而可以在电路中加入同步时钟,使输出信号跟随时钟同步变化。图3所示是同步法去除"毛刺"的对应仿真波形。   4.2信号变化落后的"毛刺"消除   程序中的内部信号的判别赋值并不是立即发生变化,而是存在一个延迟。这也是最容易产生"毛刺"的一种情况。这样,在计数分频器程序设计中,可使用 counter%(delay-1)==0这个条件来约束分频的模数,由于条件判别的延时使分频输出产生"毛刺"的仿真波形如图4所示。     对于这种电路,设计时可以采用加触发器的方法来消除"毛刺",可以引入一个名为temp的触发器来有效除去这些"毛刺",其仿真波形如图5所示。具体的程序代码如下:   5结束语   "毛刺"信号是威胁逻辑电路稳定性的重大隐患,因此,发现"毛刺"和去除"毛刺"就成为FPGA开发人员必须要考虑的问题。本文总结了最为容易产生"毛刺"信号的两种典型电路,并且分别给出了有效的消除方法及仿真波形图。
  • 热度 17
    2015-3-24 13:35
    1158 次阅读|
    0 个评论
       0 引 言   数字电位器是利用微电子技术制成的集成电路,它是依靠电阻阵列和多路模拟开关的组合完成阻值的变化。它没有可动的滑臂,而通过按钮输入信号,或是通过数字输入信号改变数字电位器的阻值。数字电位器由于可调精度高,更稳定,定位更准确,操作更方便,数据可长期保存和随时刷新等优点,在某些场合具有模拟电位器不可比拟的优势。    1 ADN2850的基本结构和工作原理   ADN2850是ADI公司的双通道,1 024阶非易失性数字电位器。温度系数仅为35 ppm/℃。其功能模块图如图1所示。它的输出电阻W和B之间的阻值主要由中间寄存器RDAC中存储的值决定。RDAC的值可以由外部指令直接赋予或者从内部非易失性存储器E2MEM中载入。E2MEM中的值可以被修改或者被保护。当RDAC中的值被改变后,新的值也可以被存入E2MEM中。之后,新的值将在系统重新上电后自动加载到RDAC中。   ADN2850的指令系统包含16种模式,通过一个标准SPI串行接口传送24位命令字决定,高位在先。24位命令字的前4位是命令,接下来4位是地址,后面16位是数据。这些指令可以用于RDAC的值的写入,E2MEM值的改写与复原,电阻值的回读等。    2 SPI接口简介   SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用4根线,节约了芯片的管脚,同时为PCB的布局上节省空间。正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。   SPI的通信以主从方式工作,这种模式通常有1个主设备和1个或多个从设备,一般需要4根线,事实上3根也可以(单向传输时)。其也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCLK(时钟),CS(片选)。由SCLK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成1位数据传输,输入也使用同样原理。这样,在至少8次时钟信号的改变(上沿和下沿为1次),就可以完成8位数据的传输。ADN2850的SPI接口的4根引脚线分别是SDI,SDO,CLK,CS。   这里利用FPGA对SPI接口进行配置。为了方便对输入SPI的指令的随时改变,而不需要程序的重复写入,24位指令通过串口输入到FPGA。串口通信由微机上的串口调试助手协助进行。由于少了重新写入程序的时间,从而调试速度和效率明显增高。    3 串口简介   串口是计算机上一种通用的设备通信的协议,可以用于获取远程采集设备的数据。   串口按位(b)发送和接收字节。通信使用3根线完成:地线、发送、接收功能。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验位。波特率是衡量通信速度的参数,它表示每秒钟传送的bit的个数。数据位则是衡量通信中实际数据位的参数。停止位一般是为了平衡两个系统的时钟而在实际数据位结束后传送的。奇偶校验位是串口通信中检错的一种方式,没有校验位也可以。整个系统的连接框图如图2所示。    4 ADN2850的串口控制   用串口控制ADN2850的流程图如图3所示。一旦有指令从串口发送,就重新经FPGA后写入ADN2850。   Verilog HDL程序分为3个模块,分别为复位rstgen模块,串口接收datagen模块和SPI接口操作spi模块。24位指令由微机输入,经串口接收模块后输出1个24位数据和1个标志位,用于SPI接口模块把数据传入ADN2850中。   datagen模块关键程序如下所示(相关变量声明省略):   该程序已经通过前仿真,并在Altera公司的EP2C70 FPGA上通过了验证,达到了预期的效果。    5 结 语   通过串口的应用,ADN2850的控制过程变的很方便。而串口本身连线简单占用资源少,应用也比较广泛,所以数字电位器ADN2850的串口控制不失为一种可行的方法。
相关资源