首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【例说】Verilog HDL 编译器指令,你见过几个?

Verilog HDL 编译器指令

复杂一点的系统在进行设计或者验证时,都会用到一些编译器指令,那么什么是编译器指令?

Verilog HDL编译器指令由重音符(')开始。在Verilog 语言编译时,特定的编译器指令在整个编译过程中有效(编译过程可跨越多个文件),直到遇到其它的不同编译程序指令。不完整的标准编译器指令如下:

下面分解一下,每个指令单独说明一下:

’define和’undef

1.’define指令

’define指令用于文本替换,它很像C语言中#define指令。它生成一个文本宏。该指令既可以在模块内部定义,也可以在模块之外定义。一旦编译了’define指令,它在整个编译过程中都有效。

如果已经定义了一个文本宏,那么在它的宏名之前加上重音符号(’)就可以在源程序中'引用该文本宏。

在编译器编译时,将会自动用相应的文本块代替字符串'macro_name。将Verilog HDL中的所有编译指令都看作预定义的宏名,将一个编译指令重新定义为一个宏名是非法的。

一个文本宏定义可以带有一个参数。这样,就允许为每一个单独的应用定制文本宏。

文本宏定义的语法格式如下:

其中:(1)为文本的宏名字,其语法格式为

text_macro_identifier[]

text_macro_identifier为宏标识符,要求简单标识符。

为形参列表。一旦定义一个宏名,就可以在源程序的任何地方使用它,而没有范围限制。

(2)为宏文本,可以是与宏名同行的任意指定文本。

如果指定的文本超过一行,那么新的一行需要用反斜杠()作为起始。这样,反斜杠后面的文本也将作为宏文本的一部分,参与宏替换。反斜杠本身并不参与宏替换,编译时将忽略它。

如果宏文本包含了一个单行注释语句(以“//”开始的注释语句),则该语句不属于替换文本,编译时不参与替换。

宏文本可以空白。

[例] ’define指令Verilog HDL化述的例子1。

[例] ’define指令Verilog HDL非法描述的例子2

[例] 'define 指令 Verilog HDL 非法描述的例子 3。

将要扩展为

2.'undef指令

'undef指令用于取消前面定义的宏。如果先前并没有使用指令’define进行宏定义,那么使用’undef指令将会导致一个警告。

’undef指令的语法格式如下:

一个取消的宏没有值, 就如同没有被定义一样。

’celldefine和’endcelldefine

这两个指令用于将模块标记为单元模块,它们表示包含模块定义。某些PLI使用单元模块用于这些应用,如计算延迟。

该命令可以出现在源代码描述中的任何地方。但是,推荐将其放在模块定义的外部。

[例] ’celldefine指令Verilog HDL描述的例子。

’default_nettype

该指令用于为隐含网络指定网络类型,也就是为那些没有被说明的连线定义网络类型。它只可以出现在模块声明的外部,允许多个’default_netype指令。

如果没有出现’default_netype指令,或者如果指定了’resetall指令,则隐含的网络类型是wire。当default_netype设置为none时,需要明确地声明所有网络;如果没有明确地声明网络,则产生错误。

’default_netype指令格式为:

其中default_nettype_value的值可以是wire、tri、tri0、tri1、wand、triand、wor、trior、trireg、uwire和none。

'ifdef、 'else、 ’elsif、 ’endif 和’ifndef

'ifdef编译器命令

条件编译:

显而易见,即只有在条件满足的时候才对这部分代码进行编译,也就是对一部分内容指定了编译的条件:

当满足条件时对一组语句进行编译,

当条件不满足时则对另外一组语句进行编译。

用途:

1、选择一个模板的不同代表部分。

2、选择不同的时序或结构信息。

3、对不同的EDA工具,选择不同的激励。(如:Verilog代码中的一部分可能因编译环境不同而不同,为避免在不同环境需要替换不同版本的Verilog 设计,条件编译就是一个很好的解决方案)

用法

当宏名被定义过了,就编译程序段1;反之,当宏名未被定义过,就编译程序段2;

其中,else部分可以省略。即:当宏名被定义过了,就编译程序段1;反之,不编译程序段1;

[例] ’ifdef 指令 Verilog HDL 描述的例子。

‘ifndef编译器命令

额外的,还有‘ifndef语句,与’ifdef功能相反:

即当宏名没被定义过,就编译程序段1;反之,当宏名未被定义过了,就编译程序段2;

[例] ’ifndef 指令 Verilog HDL 描述的例子。

这里还有一个‘elsif指令,简单说明一下。

当遇到’ifndef时,测试’ifdef文本宏标识符,查看在Verilog HDL源文件描述中是否使用'define作为一个文本宏名字;如果’ifndef没有定义文本宏标识符,则对’ifndef所包含的行作为描述的一部分进行编译,如果还有’else或者’dsif编译器指令,则忽略这些编译器指令和相关的行组;如果定义’ifiidef文本宏标识符,则忽略’ifndef所包含的行;如果有’elsif编译器指令,测试'elsif文本宏标识符,查看在Verilog HDL源文件描述中,是否使用'define作为一个文本宏名字;如果’elsdef定义文本宏标识符,则对’elsdef所包含的行作为描述的一部分进行编译,如果还有’else或者’elsif编译器指令,则忽略这些编译器指令和相关的行组;如果没有定义第一个'elsif文本宏标识符,则忽略第一个’elsif所包含的行;如果有多个’elsif编译器命令,将按照它们在Verilog HDL源文件中的描述顺序和评估第一个’elsif编译器指令的方法,对这些指令进行评估;如果有一个’else编译器命令,则将’else所包含的行作为描述的一部分进行编译。

’include

在编译期间,’include编译器指令用于嵌入另一个文件的内容。既可以用相对路径名定义文件,也可以用全路径名定义文件。其语法格式为:

使用’inchide编译器指令的优势主要体现在以下几方面:

(1)提供了一个配置管理不可分割的一部分;

(2)改善了VerilogHDL源文件描述的组织结构;

(3)便于维护Verilog HDL源文件描述。

[例 ]’include指令Verilog HDL描述的例子。

'resetall

该编译器遇到’resetall指令时,会将所有的编译指令重新设置为默认值。推荐在源文件的开始放置’resetall.将'resetall命令放置在模块内或者UDP声明中是非法的。其语法格式为

’line

对于Verilog工具来说,跟踪Verilog HDL源文件的名字和文件的行的行号是非常重要的,这些信息可以用于调试错误消息或者源代码,Verilog PL1访问可以它。

然而,在很多情况下,Verilog源文件由其他工具进行了预处理。由于预处理工具可能在Verilog HDL源文件中添加了额外的行,或者将多个源代码行合并为一个行,或者并置多个源文件,等等,可能会丢失原始的源文件和行信息。

'line编译器命令可以用于指定的原始源代码的行号和文件名。如果其他过程修改了源文件,这允许定位原始的文件。当指定了新行的行号和文件名时,编译器就可以正确地定位原始的源文件位置。然而,这要求相应的工具不产生’line命令。

其语法格式为

其中,number是一个正整数,用于指定跟随文本行的新行行号,filename是一个字符串常数,将其看作文件的新名字,文件名可以是全路径名字或者相对路径名字;level为该参数的值,可以是0、1或者2:当为1的时候,输入一个include行后的下面一行是第一行;当为2的时候,退出一个inlcude行后的下面一行是第一行;当为0的时候,指示任何其他行。

[例] 'line 指令 Verilog HDL 描述的例子。

//该行是 orig.v 存在 include 文件后的第 3 行。

’timescale

在Verilog HDL模型中,所有的时延都用单位时间表述。可使用'timescale编译器指令将时间单位与实际时间相关联,该指令用于定义时延的单位和时延精度。

作用:

timescale  1ns/100ps那么时间单位就是1ns,精度就是100ps。

时间单位,表示了仿真时测量的单位,比如延时1,1ns;精度则表示仿真器只识别的范围,比如精度是100ps,那么如果你1.3ns,编译器是识别,但是如果写1.32,那么由于精度达不到那么细,所以0.02被四舍五入掉。

`timescale影响着全部模块,直到遇到另外的timescale。

’timescale编译器指令格式为:

其中,time_unit指定用于时间和延迟测量的单位,可选的值为1、10或100;time_precision用于仿真前,确定四舍五入延迟值。时间分辨率子,可选的单位为s \ms\us\ns\ps或fs。

[例] 'timescale 指令 Verilog HDL 描述的例子。

根据时间精度, 参数 d 的值从 1.55 四舍五入到 1.6。模块的时间单位是 10ns 精度是1 ns。因此, 参数 d 的延迟从 1.6 标定到 16。

’unconnected_drive和'nounconnected_drive

当一个模块所有未连接的端口出现在'unconnected_drive和’nounconnecteddrive指令之间时,将这些未连接的端口上拉或者下拉,而不是按通常的默认值处理。

指令’unconnected_drive使用pull1/pull0参数中的一个:当指定pull时,所有未连接的端口自动上拉;当指定pill0时,所有未连接的端口自动下拉。

建议成对使用’unconnected_drive和'nounconnected_drive指令,但不是强制要求。这些指令在模块外部成对指定。

'resetall指令包括'nounconnected_drive指令的效果。

[例]nounconnected_drive/ 'unconnected drive 指令 Verilog HDL 描述的例子。

'pragma

’pragma指令是一个结构化的说明,它用于改变对Verilog HDL源文件的理解。由这个指令所引入的说明称为编译指示。编译指示不同于Verilog HDL标准所指定的结果,它为指定实现的结果。其语法格式为

其中 ,pragma_name 为编译指示的名字, 可以是 $ 开头的系统标识符或者一般标识符; pragma_expression 为编译指示表达式。

注:reset和resetall编译指示将恢复默认值和pragma_keywords所影响的状态。

'begin_keywords和’end_keyword

'begin_keywords和'end_keyword指令用于指定在一个源代码块中,基于不同版本的IEEE_Stdl364标准,确定用于关键字的保留字。该对指令只指定那些作为保留关键字的标识符。只能在设计元素(模块、原语和配置)外指定该关键字,并且需要成对使用。其语法格式为:

其中,version_specifier为可选的参数,包括1364-1995、1364-2001、1364-2001-noconfig和1364-2005。

[例] ’begin_keywords 和 'end_keyword 指令 Verilog HDL 描述的例子。

(补充一)Verilog编译器指示语句

设计者在写设计代码时,有时可能针对仿真写一些语句,这些语句可能是不为DC所接受,也不希望DC接受;设计者如果不对这些语句进行特殊说明,DC读入设计代码时就会产生语法错误。另一种情况是,设计者在写设计代码,有些设计代码是为专有的对象写的(如公司内部),这些专有的设计代码可能不希望被综合。Synopsys提供了引导语句,设计者可以使用这些引导语句控制DC综合的对象

可以利用HDL描述中的一些特定的注释语句来控制综合工具的工作,从而弥补仿真环境和综合环境之间的差异,这些注释语句称为编译器指示语句。

translate_off/ translate_on

这组语句用来指示DC停止翻译 “//synopsys.。.translate_off”之后的Verilog描述,直至出现 “//synopsys translate_on”。当Verilog代码钟含有供仿真用的不可综合语句时,这项功能能使代码方便地在仿真工具与综合工具之间移植。

例1(translate_off/ translate_on指示语句的使用):

parallel_case/ full_case

DC可能使用带优先级的结构来综合Verilog的case语句,为避免这种情况,可以使用“//synopsys.。.parallel_case”指示DC将case语句综合为并行的多路选择器结构。

(parallel_case指示语句的使用):

另外,Verilog允许case语句不覆盖所有可能情况,当这样的代码由DC综合时将产生锁存器。为避免这种情况,可以使用“//synopsys full_case”指示DC所有可能已完全覆盖。

例2 (full_case指示语句的使用):

(补充二)Verilog PL1是什么?

上面有提到过PLI接口,这里简单介绍下,因为用的比较少,所以就一笔带过。

编程语言接口(Program Language Interface,PLI)提供了通过C语言函数对Verilog数据结构进行存储和读取操作的方法。

PLI接口主要提供以下三种功能。

(1)PLI接口允许用户编写自定义的系统任务和系统函数。用户写出相应的PLI程序并连接到仿真器后,就可以在自己写的VerilogHDL程序中使用这些系统任务和系统函数。一旦在仿真过程中调用这些任务或者函数,仿真器就会找到对应的用户所编写的PLI程序并执行,从而实现仿真器的定制。

(2)这个接口还允许用户在自己的PLI程序中与仿真器中例化的VerilogHDL硬件进行交互,如读一个线网络的值、向一排寄存器写值以及设置一个单元的延迟,等等。

对于PLI程序而言,仿真器中的Verilog实例完全透明,用户可以对这些硬件做任何操作(当然,不能修改硬件结构)。有了这个功能,用户就可以在自定义的任务/函数中对硬件执行某些用VerilogHDL语言难以完成的操作。

(3)某些特定的操作需要对仿真过程中一些信号的变化做出响应,虽然可以用always过程语句来监控少量信号的变化,但如果需要监测大量信号,这种机制并不现实。

PLI接口提供了一种函数回调机制解决这个问题。用户可以将某个线网络/寄存器等信号挂上一个PLI程序中的C函数。每当该信号变化时,调用这个C函数,从而很方便地监测信号。

除了上面所说的这些机制外,PLI还能让用户控制仿真的过程,例如暂停、退出以及向日志文件里写信息等,还可以获取仿真过程的数据,如当前仿真时间等。在实际的PLI程序中,同样不可缺少这些功能。

参考资料

1、http://www.elecfans.com/d/651393.html

2、EDA原理及Verilog实现

3、https://www.cnblogs.com/IClearner/p/7258983.html

NOW现在行动!

学习Xilinx FPGA最好的资料其实就是官方手册,下表总结了部分手册的主要介绍内容,关注我,持续更新中......

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20210930A02O0F00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券