Verilog  8 种编译指令使用详解

目录
  • Verilog 编译指令
    • define, undef
    • `include
    • `timescale
    • `default_nettype
    • `resetall
    • celldefine, endcelldefine
    • unconnected_drive, nounconnected_drive

Verilog 编译指令

编译指令为 Verilog 代码的撰写、编译、调试等提供了极大的便利。

下面介绍下完整的 8 种编译指令,其中前 4 种使用频率较高。

define, undef

在编译阶段,`define 用于文本替换,类似于 C 语言中的 #define

一旦 `define 指令被编译,其在整个编译过程中都会有效。例如,在一个文件中定义:

`define    DATA_DW     32

则在另一个文件中也可以直接使用 DATA_DW。

`define    S     $stop;
//用`S来代替系统函数$stop; (包括分号)
`define    WORD_DEF   reg [31:0]
//可以用`WORD_DEF来声明32bit寄存器变量

`undef 用来取消之前的宏定义,例如:

`define    DATA_DW     32
……
reg  [DATA_DW-1:0]    data_in   ;
……
`undef DATA_DW
`ifdef, `ifndef, `elsif, `else, `endif

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

`ifdef       MCU51
    parameter DATA_DW = 8   ;
`elsif       WINDOW
    parameter DATA_DW = 64  ;
`else
    parameter DATA_DW = 32  ;
`endif

elsif, else 编译指令对于 ifdef 指令是可选的,即可以只有 ifdef 和 `endif 组成一次条件编译指令块。

当然,也可用 `ifndef 来设置条件编译,表示如果没有相关的宏定义,则执行相关语句。

下面例子中,如果定义了 WINDOW,则使用第二种参数说明。如果没有定义 WINDOW,则使用第一种参数说明。

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

`include

使用 `include 可以在编译时将一个 Verilog 文件内嵌到另一个 Verilog 文件中,作用类似于 C 语言中的 #include 结构。该指令通常用于将全局或公用的头文件包含在设计文件里。

文件路径既可以使用相对路径,也可以使用绝对路径。

`include         "../../param.v"
`include         "header.v"

`timescale

在 Verilog 模型中,时延有具体的单位时间表述,并用 `timescale 编译指令将时间单位与实际时间相关联。

该指令用于定义时延、仿真的单位和精度,格式为:

time_unit 表示时间单位,time_precision 表示时间精度,它们均是由数字以及单位 s(秒),ms(毫秒),us(微妙),ns(纳秒),ps(皮秒)和 fs(飞秒)组成。时间精度可以和时间单位一样,但是时间精度大小不能超过时间单位大小,例如下面例子中,输出端 Z 会延迟 5.21ns 输出 A&B 的结果。

`timescale 1ns/100ps    //时间单位为1ns,精度为100ps,合法
//`timescale 100ps/1ns  //不合法
module AndFunc(Z, A, B);
    output Z;
    input A, B ;
    assign #5.207 Z = A & B
endmodule

在编译过程中,timescale 指令会影响后面所有模块中的时延值,直至遇到另一个 timescale 指令或 `resetall 指令。

由于在 Verilog 中没有默认的 timescale,如果没有指定 timescale,Verilog 模块就有会继承前面编译模块的 `timescale 参数。有可能导致设计出错。

如果一个设计中的多个模块都带有 `timescale 时,模拟器总是定位在所有模块的最小时延精度上,并且所有时延都相应地换算为最小时延精度,时延单位并不受影响。例如:

`timescale 10ns/1ns
module test;
    reg        A, B ;
    wire       OUTZ ;

    initial begin
        A     = 1;
        B     = 0;
        # 1.28    B = 1;
        # 3.1     A = 0;
    end

    AndFunc        u_and(OUTZ, A, B) ;
endmodule

在模块 AndFunc 中,5.207 对应 5.21ns。

在模块 test 中,1.28 对应 13ns,3.1 对应 31ns。

但是,当仿真 test 时,由于 AndFunc 中的最小精度为 100ps,因此 test 中的时延精度将进行重新调整。13ns 将对应 130100ps,31ns 将对应 310100ps。仿真时,时延精度也会使用 100ps。仿真时间单位大小没有影响。

如果有并行子模块,子模块间的 `timescale 并不会相互影响。

例如在模块 test 中再例化一个子模块 OrFunc。仿真 test 时,OrFunc 中的 #5.207 延时依然对应 52ns。

//子模块:
`timescale 10ns/1ns      //时间单位为1ns,精度为100ps,合法
module OrFunc(Z, A, B);
    output Z;
    input A, B ;
    assign #5.207 Z = A | B
endmodule

//顶层模块:
`timescale 10ns/1ns
module test;
    reg        A, B ;
    wire       OUTZ ;
    wire       OUTX ;

    initial begin
        A     = 1;
        B     = 0;
        # 1.28    B = 1;
        # 3.1     A = 0;
    end

    AndFunc        u_and(OUTZ, A, B) ;
    OrFunc         u_and(OUTX, A, B) ;

endmodule

此例中,仿真 test 时,OrFunc 中的 #5.207 延时依然对应 52ns。

`timescale 的时间精度设置是会影响仿真时间的。时间精度越小,仿真时占用内存越多,实际使用的仿真时间就越长。所以如果没有必要,应尽量将时间精度设置的大一些。

`default_nettype

该指令用于为隐式的线网变量指定为线网类型,即将没有被声明的连线定义为线网类型。

该实例定义的缺省的线网为线与类型。因此,如果在此指令后面的任何模块中的连线没有说明,那么该线网被假定为线与类型。

该实例定义后,将不再自动产生 wire 型变量。

例如下面第一种写法编译时不会报 Error,第二种写法编译将不会通过。

//Z1 无定义就使用,系统默认Z1为wire型变量,有 Warning 无 Error
module test_and(
        input      A,
        input      B,
        output     Z);
    assign Z1 = A & B ;
endmodule
//Z1无定义就使用,由于编译指令的存在,系统会报Error,从而检查出书写错误
`default_nettype none
module test_and(
        input      A,
        input      B,
        output     Z);
    assign Z1 = A & B ;
endmodule

`resetall

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

`resetall 可以使得缺省连线类型为线网类型。

当 resetall 加到模块最后时,可以将当前的 timescale 取消防止进一步传递,只保证当前的 timescale 在局部有效,避免 timescale 的错误继承。

celldefine, endcelldefine

这两个程序指令用于将模块标记为单元模块,他们包含模块的定义。例如一些与、或、非门,一些 PLL 单元,PAD 模型,以及一些 Analog IP 等。

`celldefine
module (
    input      clk,
    input      rst,
    output     clk_pll,
    output     flag);
        ……
endmodule
`endcelldefine

unconnected_drive, nounconnected_drive

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

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

以上就是Verilog 8 种编译指令使用详解的详细内容,更多关于Verilog 编译指令的资料请关注我们其它相关文章!

(0)

相关推荐

  • Verilog关键词的多分支语句实例详解

    目录 关键词:case,选择器 case 语句 casex/casez 语句 关键词:case,选择器 case 语句是一种多路条件分支的形式,可以解决 if 语句中有多个条件选项时使用不方便的问题. case 语句 case 语句格式如下: case(case_expr) condition1 : true_statement1 ; condition2 : true_statement2 ; -- default : default_statement ; endcase case 语句执行

  • Verilog语言关键字模块例化实例讲解

    目录 关键字:例化,generate,全加器,层次访问 命名端口连接 顺序端口连接 端口连接规则 用 generate 进行模块例化 层次访问 关键字:例化,generate,全加器,层次访问 在一个模块中引用另一个模块,对其端口进行相关连接,叫做模块例化.模块例化建立了描述的层次.信号端口可以通过位置或名称关联,端口连接也必须遵循一些规则. 命名端口连接 这种方法将需要例化的模块端口与外部信号按照其名字进行连接,端口顺序随意,可以与引用 module 的声明端口顺序不一致,只要保证端口名字与外

  • Verilog语言的循环语句示例详解

    目录 关键词:while, for, repeat, forever while 循环 for 循环 repeat 循环 forever 循环 关键词:while, for, repeat, forever Verilog 循环语句有 4 种类型,分别是 while,for,repeat,和 forever 循环.循环语句只能在 always 或 initial 块中使用,但可以包含延迟表达式. while 循环 while 循环语法格式如下: while (condition) begin -

  • Verilog  8 种编译指令使用详解

    目录 Verilog 编译指令 define, undef `include `timescale `default_nettype `resetall celldefine, endcelldefine unconnected_drive, nounconnected_drive Verilog 编译指令 编译指令为 Verilog 代码的撰写.编译.调试等提供了极大的便利. 下面介绍下完整的 8 种编译指令,其中前 4 种使用频率较高. define, undef 在编译阶段,`define

  • Java JVM编译策略案例详解

    解释器 当虚拟机启动时,解释器可以首先发挥作用,而不必等待编译器全部编译完成再执行,这样可以省去许多不必要的编译时间.并且随着程序运行时间的推移,编译器逐渐发挥作用,根据热点探测功能,,将有价值的字节码编译为本地机器指令,以换取更高的程序执行效率. hotspot中内嵌有2个JIT编译器,分别为Client Compiler,Server Compiler,但大多数情况下我们称之为C1编译器和C2编译器. C1编译器 client compiler,又称C1编译器,较为轻量,只做少量性能开销比较

  • python os.system执行cmd指令代码详解

    1.执行cmd指令,在cmd输出的内容会直接在控制台输出,返回结果为0表示执行成功. 2.在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码. os.system()方法是简单粗暴的执行cmd指令,没有办法获取到cmd输出的内容. 实例 # coding:utf-8 import os os.system("ls") Python如何使用OS模块调用cmd 在os模块中提供了两种调用 cmd 的方法,os.popen() 和 os

  • Python线性表种的单链表详解

    目录 1. 线性表简介 2. 数组 3. 单向链表 设计链表的实现 链表与顺序表的对比 1. 线性表简介 线性表是一种线性结构,它是由零个或多个数据元素构成的有限序列.线性表的特征是在一个序列中,除了头尾元素,每个元素都有且只有一个直接前驱,有且只有一个直接后继,而序列头元素没有直接前驱,序列尾元素没有直接后继. 数据结构中常见的线性结构有数组.单链表.双链表.循环链表等.线性表中的元素为某种相同的抽象数据类型.可以是C语言的内置类型或结构体,也可以是C++自定义类型. 2. 数组 数组在实际的

  • 使用AngularJS编写多选按钮选中时触发指定方法的指令代码详解

    最近在做项目时,遇到了需要用到多选按钮选中触发事件的功能,因此我查找了一下AngularJS的提供的指令,但是没有发现相应的指令.而一个看起来很像的指令就是ng-checked,但是这个指令是用来代替标签里面checked属性的,所以也用不了.因此我就自己动手试着写一个这样的指令,相应的代码如下: <form name="test_form" ng-controller="TestCtrl"> <input type="checkbox&

  • Angularjs自定义指令Directive详解

    今天学习angularjs自定义指令Directive. Directive是一个非常棒的功能.可以实现我们自义的的功能方法. 下面的例子是演示用户在文本框输入的帐号是否为管理员的帐号"Admin". 在网页上放一个文本框和一个铵钮: <form id="form1" name="form1" ng-app="app" ng-controller="ctrl" novalidate> <i

  • Spark三种属性配置方式详解

    随着Spark项目的逐渐成熟, 越来越多的可配置参数被添加到Spark中来.在Spark中提供了三个地方用于配置: 1.Spark properties:这个可以控制应用程序的绝大部分属性.并且可以通过 SparkConf对象或者Java 系统属性进行设置: 2.环境变量(Environment variables):这个可以分别对每台机器进行相应的设置,比如IP.这个可以在每台机器的$SPARK_HOME/ conf/spark-env.sh脚本中进行设置: 3.日志:所有的日志相关的属性可以

  • Angular 中 select指令用法详解

    最近在angular中使用select指令时,出现了很多问题,搞得很郁闷.查看了很多资料后,发现select指令并不简单,决定总结一下. select用法: <select ng-model="" [name=""] [required=""] [ng-required=""] [ng-options=""]> </select> 属性说明: 发现并没有ng-change属性 ng-

  • MySQL两种临时表的用法详解

    外部临时表 通过CREATE TEMPORARY TABLE 创建的临时表,这种临时表称为外部临时表.这种临时表只对当前用户可见,当前会话结束的时候,该临时表会自动关闭.这种临时表的命名与非临时表可以同名(同名后非临时表将对当前会话不可见,直到临时表被删除). 内部临时表 内部临时表是一种特殊轻量级的临时表,用来进行性能优化.这种临时表会被MySQL自动创建并用来存储某些操作的中间结果.这些操作可能包括在优化阶段或者执行阶段.这种内部表对用户来说是不可见的,但是通过EXPLAIN或者SHOW S

随机推荐