Verilog 编译指令

前言

  • ˋ 符号说明一个编译指令
  • 这些编译指令使仿真编译器进行一些特殊的操作
  • 编译指令从出现时开始有效,直到被覆盖或使其失效。因此编译指令是全局的
  • ˋresetall 复位所有的编译指令为缺省值,应该在其它编译指令之前使用
  • 尽管编译指令是 Verilog 语言的一部分,但其作用取决于编译器,因此不同的仿真器中其作用可能不同。

下列编译指l令是 Verilog IEEE 标准中的:

  • 库单元分界
    ˋcelldefine
    ˋendcelldefine
  • 定义文本宏和基于文本宏的转换
    ˋdefine
    ˋundef
    ˋifdef
    ˋelse
    ˋelsif
    ˋifndef
    ˋendif
  • 复合编译指令
    ˋdefault_nettype
    ˋinclude
    ˋunconnected_drive
    ˋnounconnected_drive
    ˋresetall
    ˋtimescale

一、ˋcelldefine 和 ˋendcelldefine

这两个指令用于将模块标记为库单元。
建立 Verilog 模型库,需要:

  • 每个元件(或单元)用一个 module 描述
  • 将相关的 module 放在同一个文件或同一个目录中(当把 module 放到同一个目录时,文件名应与 module 名相同。文件名的扩展名是可选的)

可以用两种抽象级描述库单元

  • 结构级
    – 用 Verilog 基本单元或 UDP
    – 用于描述组合逻辑或简单的时序逻辑
  • 行为级
    – 用过程块或赋值语句
    – 用于描述大的或复杂的元件,如 RAM 或 ROM

库单元的特点:

  • 每个库单元的描述在编译指令 ˋcelldefine 和 ˋendcelldefine 之间
  • 每个库单元的描述有两部分:
    – 功能描述
    – 时序描述
`celldefine
`timescale 1ns/100ps //在模块定义之前插入 `timescale 定义单元所使用的时间单位和精度
module full_adder (cout, sum, a_in, b_in, c_in);
input a_in, b_in, c_in;
output cout, sum;
// 功能描述
...
// 时序描述
...
endmodule
`endcelldefine

二、ˋdefine 和 ˋundef

编译指令 ˋdefine 提供了一种简单的文本替换的功能
ˋdefine <macro_name> <macro_text>
在编译时 <macro_text> 替换 <macro_name>。可提高描述的可读性。

`define not_delay #1 // 定义 not_delay
`define and_delay #2
`define or_delay #1
module MUX2_1 (out, a, b, sel);
output out;
input a, b, sel;
not `not_delay not1( sel_, sel); // 使用 not_delay
and `and_delay and1( a1, a, sel_);
and `and_delay and2( b1, b, sel);
or `or_delay or1( out, a1, b1);
endmodule

ˋdefine 相关要点:

  • ˋdefine 可以写在模块外和模块内,有效范围为定义之后到原文件结束。通常将其定义在 module 外, 作为程序的一部分,在此程序内都有效。
  • 在引用已定义的宏名时,必须在宏名的前面加上符号ˋ,表示该名字是一个经过宏定义的名字。
  • 宏定义是用宏名代替字符串,也就是做简单的置换,不做语法检查。只有在编译已经被宏展开后的源程序时才报错。
  • 宏定义不是 Verilog HDL 语句,不必在行末加分号,加分号则分号也被当成宏内容字符串进行替换。
  • 宏定义可以嵌套,定义一个新的宏定义时可以引用之前定义过的宏定义进行嵌套。
  • 宏名和宏内容必须在同一行进行声明,宏内容中如果有注释行,注释行不会被替换。
  • 所有编译器指令均被视为预定义的宏名称; 将编译器指令重新定义为宏名称是非法的。

解除定义的宏,使用 ˋundef <macro_name>
使用编译指令 ˋdefine,可以

  • 提高描述的可读性
  • 定义全局设计参数,如延时和矢量的位数。这些参数可以定义在同一位置。这样,当要修改设计配置时,只需要在一个地方修改。
  • 定义 Verilog 命令的简写形式
    ˋdefine vectors_ file “/usr1/chrisz/library/vectors”
    ˋdefine results_ file “/ usr1/chrisz/library/results”

可以将ˋdefine 放在一个文件中,与其它文件一起编译。

三、ˋifdef,ˋelse,ˋelsif,ˋifndef 和 ˋendif

这些属于条件编译指令。例如下面的例子中,如果定义了 A,则使用第一种参数说明;如果没有定义 A、定义了 B,则使用第二种参数说明;如果两个都没有定义,则使用第三种参数说明。

`ifdef A
    parameter DATA_DW = 8;
`elsif B
    parameter DATA_DW = 64;
`else
    parameter DATA_DW = 32;
`endif

ˋelsif,ˋelse 编译指令对于 ˋifdef 指令是可选的,即可以只有 ˋifdef 和 ˋendif 组成一次条件编译指令块。
当然,也可用 ˋifndef 来设置条件编译,表示如果没有相关的宏定义,则执行相关语句。
下面例子中,如果定义了 A,则使用第二种参数说明。如果没有定义 A,则使用第一种参数说明。

`ifndef A
    parameter DATA_DW = 32;  
`else
	parameter DATA_DW = 64;
`endif

四、ˋdefault_nettype

Verilog 主要有三类(class)数据类型:

  • net (线网):表示器件之间的物理连接
  • register (寄存器):表示抽象存储元件
  • parameters(参数):运行时的常数(run-time constants)

net 需要被持续的驱动,驱动它的可以是门和模块。
当 net 驱动器的值发生变化时, Verilog 自动的将新值传送到 net 上。在例子中,线网 out 由 or 门驱动。当 or 门的输入信号置位时将传输到线网 net 上。
在这里插入图片描述
有多种 net 类型用于设计(design-specific)建模和工艺(technology-specific)建模。
在这里插入图片描述

  • wire 类型是最常用的类型,只有连接功能。
  • wire 和 tri 类型有相同的功能。用户可根据需要将线网定义为 wire 或 tri 以提高可读性。例如,可以用 tri 类型表示一个 net 有多个驱动源。或者将一个 net 声明为 tri 以指示这个 net 可以是高阻态 Z(hign-impedance)。可推广至 wand 和 triand、wor 和 trior。
  • wand、wor 有线逻辑功能;与 wire 的区别见下表。
  • trireg 类型很像 wire 类型,但 trireg 类型在没有驱动时保持以前的值。这个值的强度随时间减弱。

net 类在发生逻辑冲突时的决断:
在这里插入图片描述
没有声明的 net 的缺省类型为 1 位(标量)wire 类型。但这个
缺省类型可由下面的编译指令改变:
ˋdefault_nettype
nettype 不能是 supply1 和 supply0。

五、ˋinclude

编译指令 ˋinclude 在当前内容中插入一个文件
格式:ˋinclude “<file_name>”
如:
ˋinclude “global.v”
ˋinclude “parts/count. v”
ˋinclude "…/…/library/mux. v”
可以是相对路径或绝对路径。

  • ˋinclude 可用于:
    – ˋinclude 保存在文件中的全局的或经常用到的一些定义,如文本宏。
    – 在模块内部 ˋinclude 一些任务(tasks),提高代码的可维护性。

在这里插入图片描述

六、ˋunconnected_drive 和 ˋnounconnected_drive

在模块实例化中,出现在这两个编译指令间的任何未连接的输入端口,为正偏电路状态或者为反偏电路状态。

`unconnected_drive pull1
...
// 在这两个程序指令间的所有未连接的输入端口为正偏电路状态(连接到高电平)
`nounconnected_drive

`unconnected_drive pull0
...
// 在这两个程序指令间的所有未连接的输入端口为反偏电路状态(连接到低电平)
`nounconnected_drive 

七、ˋresetall

该编译指令将所有的编译指令重新设置为缺省值。

  • ˋresetall 可以使得缺省连线类型为线网类型。
  • 当 ˋresetall 加到模块最后时,可以将当前的 ˋtimescale 取消防止进一步传递,只保证当前的 ˋtimescale 在局部有效,避免 ˋtimescale 的错误继承。
  • 当使用编译指令 ˋresetall 时,IEEE 规范没有说明如何处理文本宏。 Cadence Verilog 仿真器在遇到 ˋresetall 时,文本宏定义不变。要清除文本宏定义,使用 ˋundef <macro_name>。

八、ˋtimescale

ˋtimescale 说明时间单位及精度
格式:ˋtimescale <time_unit> / <time_precision>
如:
ˋtimescale 1ns / 100ps
time_unit:延时或时间的测量单位
time_precision:延时或时间的精度,延时值超出精度要先舍入后使用

  • ˋtimescale 必须在模块之前出现
  • time_precision 不能大于 time_unit
  • time_precision 和 time_unit 的表示方法:integer unit_string
    – integer:可以是 1, 10, 100
    – unit_string:可以是 s(second), ms(millisecond), us(microsecond),ns(nanosecond), ps(picosecond), fs(femtosecond)
    – 以上 integer 和 unit_string 可任意组合
  • precision 的时间单位应尽量与设计的实际精度相同。
    – precision 是仿真器的仿真时间步。
    – 若 time_unit 与 precision_unit 差别很大将严重影响仿真速度。
    – 如说明一个 ˋtimescale 1s / 1ps,则仿真器在 1 秒内要扫描其事件序列 1012 次;而 ˋtimescale 1s / 1ms 则只需扫描 103 次。
  • 如果没有 ˋtimescale 说明将使用缺省值,一般是 ns。
  • 在编译过程中,ˋtimescale 指令会影响后面所有模块中的时延值,直至遇到另一个 ˋtimescale 指令或 ˋresetall 指令。
    – 由于在 Verilog 中没有默认的 ˋtimescale,如果没有指定 ˋtimescale,Verilog 模块就有会继承前面编译模块的 ˋtimescale 参数。有可能导致设计出错。
    – 所有 ˋtimescale 中的最小值决定仿真时的最小时间单位。这是因为仿真器必须对整个设计进行精确仿真。
    在下面的例子中,仿真时间单位(STU)为 100fs。
`timescale 1ns / 10ps
module1 (...);
	not #1.23 (...) // 1.23ns or 12300 STUs
	...
endmodule
`timescale 100ns / 1ns
module2 (...);
	not #1.23 (...) // 123ns or 1230000 STUs
	...
endmodule
`timescale 1ps / 100fs
module3 (...);
	not #1.23 (....) // 1.23ps or 12 STUs (rounded off)
	...
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值