2.19 编译指令
编译指令用来设置编译过程的一些属性、控制编译流程等,Verilog所有的编译指令均以沉音符号“`”(ASCII码0x60)开头。注意不要将沉音符号与撇点“'”混淆。编译指令均独占一行,并不以分号结尾,可带有注释。这里简单介绍几个常用的编译指令。
·`default_nettype,设定默认线网类型
·`define、`undef和`undefineall,宏定义。
·`include,包含文件。
·`ifdef、`ifndef、`elsif、`else和`endif,条件编译。
·`timescale,时间单位和精度设置。
·`resetall,重置所有编译指令。
`default_nettype用来设置默认的线网类型,形式为:
2.13节提到了模块端口的默认线网类型为wire,便可以使用这个编译指令来更改。Verilog有一个比较危险的特性是可以隐式定义线网,即编译器将把未定义过的标识符认定为默认类型的线网,因而任何地方一个笔误,都将形成一个默认类型的线网,这多半是不可预期的,所以建议初学者将线网类型的默认值设置为none:
这样便杜绝了编译器将笔误认定为新线网,当然也使得我们在简写模块的端口定义时,不能省略wire关键字。
`define、`undef和`undefineall用来定义宏和解除宏定义,宏可以在代码中使用或用于条件编译指令中,编译器直接将宏按定义时的文本展开。它们的使用形式如下:
其中`define还可以带有参数,宏内容中参数部分会以使用时的参数内容替代,`undefineall用于解除所有已定义的宏。例如:
注意其中MAX宏的内容大量使用了括号,这是为了防止处于复杂表达式中的宏展开时优先级错乱。
使用宏的格式是:`<宏名>。注意宏名前面带有沉音符。
`include用于包含文件,等同于直接将被包含的文件的全部内容替换在当前位置,当需要实例化位于其他文件中的模块、导入位于其他文件中的包时,往往需要使用该编译指令。一般形式为:
其中文件路径可以是绝对路径或相对路径。使用双引号时,相对路径以编译器当前工作目录(常常是文件所在目录)为起点;使用尖括号时,以编译器和规范设定的目录为起点。
大多数EDA工具,特别是带有图形界面的工具,都以工程的形式管理多个源文件,在同一个工程中的任何源文件中均可直接实例化定义在其他源文件中的模块,并不需要使用`include编译指令。
`ifdef、`ifndef、`elsif、`else和`endif为条件编译指令,常用形式为:
使用`ifdef时,如果宏名1被定义,则代码段1将被编译,否则如果宏名i被定义,代码段i将被编译;如果宏名1至宏名i均未定义,则代码段k将被编译。使用`ifndef时,如果宏名1未被定义,则代码段1将被编译,否则,如果宏名i被定义,代码段i将被编译;如果宏名1被定义而宏名i均未被定义,则代码段k将被编译。
`timescale用于设定时间单位和精度,在2.12.1节中介绍延迟时,所有的时间都带有单位,比如“ns”,而如果使用`timescale编译指令设定了单位和精度,则可省略单位。一般形式是:
其中m、u(μ)、n、p、f为国际单位制词头,“/”左侧为时间单位,右侧为时间精度,时间精度必须不大于时间单位。定义了时间单位和精度之后,所有不带单位的时间均会乘以时间单位,所有时间均会被四舍五入到时间精度。例如:
代码2-46 begin-end块中延迟的示例
第3章 ModelSim和仿真
本章介绍使用ModelSim软件进行仿真的方法,相当于ModelSim的简明入门教程。书中使用的ModelSim软件为ModelSim PE Student Edition 10.4a(以下简称ModelSim PESE或ModelSim),它为免费的学生版,支持Windows操作系统,虽有仿真效率和代码长度的限制,但应对学习过程中涉及的小规模设计绰绰有余。
读者可在Mentor公司官方网站中ModelSim PESE相关页面下载安装文件。安装过程比较简单,可参照页面上的介绍。安装完成需填写相关表格,并通过电子邮件获取学生版授权文件。
本章介绍的仿真都是2.2节中提及的功能验证,至于门级时序验证,则需要结合具体的FPGA及其开发工具。
3.1 仿真和测试的相关概念
第2章已经提到,任何数字系统不可能设计完成就能保证正确,一定是需要经过测试的,仿真技术使得数字系统不必真实地把电路或芯片做出来就能做测试,而是在代码设计完成后或综合完成后便