verilog学习--1、语言要素
先看一个例子
/*This is first Verilog progaram*/
·timescale 1ns/1ns
module HalfAdder(A,B,Sum,Carry);input A,B;output Sum, Carry;
/**/assign #2 Sum=A^B;assign #5 Carry=A&B;
endmodule;
Verilog以module为单位编写,每个文件一个module,文件名与module名相同
- 第1行为注释;
- 第2行为编译指令;
- 第3行为模块声明开始,模块的名称为halfAdder,模块有4个端口;
- 第4、5行对端口的类型进行了声明;
- 第6、7、8对模块的行为进行了描述(或定义或设计);
- 第9行声明模块结束
一个模块的基本语法如下:
module module_name (port_list);Declarations:reg, wire, parameter,input, output, inout,function, task, . . .Statements:Initial statementAlways statementModule instantiationGate instantiationUDP instantiationContinuous assignment
endmodule
这些语句在模块中出现的顺序无关紧要,这些语句是并发的。
1.注释:
有两种形式---与C语言相同
/*第一种形式:可以扩展至多行 */
//第二种形式:在本行结束。
2.编译指令
以`(反引号)开始的某些标识符是编译器指令。在 Verilog 语言编译时,特定的编译器指令在整个编译过程中有效(编译过程可跨越多个文件),直到遇到其它的不同编译程序指令。
完整的标准编译器指令如下 :
• `define, `undef
• `ifdef, `else, `endif
• `default_nettype
• `include
• `resetall
• `timescale
• `unconnected_drive, `nounconnected_drive
• `celldefine, `endcelldefine
2.1`define 和`undef
`define指令用于文本替换,它很像 C语言中的#define 指令
2.2 `ifdef, `else, `endif
这些编译指令用于条件编译
2.3`default_nettype
该指令用于为隐式线网指定线网类型。也就是将那些没有被说明的连线定义线网类型。
`default_nettype wand
该实例定义的缺省的线网为线与类型。因此,如果在此指令后面的任何模块中没有说明的连线,那么该线网被假定为线与类型。
2.4`include
`include 编译器指令用于嵌入内嵌文件的内容。
2.5 `resetall
该编译器指令将所有的编译指令重新设置为缺省值。
2.6 `timescale
在Verilog HDL 模型中,所有时延都用单位时间表述。
2.7 `unconnected_drive和`nounconnected_drive
在模块实例化中,出现在这两个编译器指令间的任何未连接的输入端口或者为正偏电路状态或者为反偏电路状态。
`unconnected_drive pull1
. . .
/*在这两个程序指令间的所有未连接的输入端口为正偏电路状态(连接到高电平) */
`nounconnected_drive
`unconnected_drive pull0
. . .
/*在这两个程序指令间的所有未连接的输入端口为反偏电路状态(连接到低电平) */
`nounconnected_drive
2.8 `celldefine 和 `endcelldefine
这两个程序指令用于将模块标记为单元模块。它们表示包含模块定义,如下例所示。
`celldefine
module FD1S3AX (D, CK, Z) ;
. . .
endmodule
`endcelldefine
某些PLI例程使用单元模块。
3.常量
3.1基本型:4种
0、1、x、z
3.2数值型:整型和实型
3.2.1 整型
两种表示方法:
1.简单的十进制格式
2.基数格式
这种形式的整数格式为:
[size ] 'base value
s i z e 定义以位计的常量的位长; b a s e为o或O(表示八进制),b或B(表示二进制),d或D(表示十进制),h或H(表示十六进制)之一; v a l u e是基于 b a s e的值的数字序列。值 x和z以及十六进制中的 a到f不区分大小写。
- 基数格式计数形式的数通常为无符号数。
- 如果没有定义一个整数型的长度,数的长度为相应值中定义的位数。
- 如果定义的长度比为常量指定的长度长,通常在左边填 0补位。但是如果数最左边一位为x或z,就相应地用x或z在左边补位。
- 如果长度定义得更小,那么最左边的位相应地被截断。
- ?字符在数中可以代替值z在值z被解释为不分大小写的情况下提高可读性
3.2.2 实型
两种表示方法:
1.简单的十进制格式
2.科学计数法
Ve r i l o g语言定义了实数如何隐式地转换为整数。实数通过四舍五入被转换为最相近的整
数。
3.3字符串型
字符串是双引号内的字符序列。字符串不能分成多行书写。
5.变量
5.1.标识符
Verilog HDL中的标识符(identifier)可以是任意一组字母、数字、 $符号和_(下划线)符号的
组合,但标识符的第一个字符必须是字母或者下划线。另外,标识符是区分大小写的。
*转义标识符:
转义标识符以 \(反斜线 )符号开头,以空白结尾(空白可以是一个空格、一个制表字符或换行符)。
*关键字:
Verilog HDL 定义的一系列保留字,注意只有小写的关键字才是保留字。
5.2变量的类型
2类:net 和 register
5.2.1 线网类型net type
具体又分为6大类11种
net type 表示Verilog结构化元件间的物理连线。它的值由驱动元件的值决定,例如连续赋值或门的输出。如果没有驱动元件连接到线网,线网的缺省值为 z。
简单的线网类型说明语法为:
net_kind [msb:lsb] net1, net2, . . . , netN;
n e t _ k i n d 是上述线网类型的一种。 m s b和l s b 是用于定义线网范围的常量表达式;范围定义是可选的;如果没有定义范围,缺省的线网类型为 1位。
- 1.wire和tri
- 2.wand和triand
- 3.wor和trior
- 4.trireg
- 5.tri0和tri1
- 6.supply0和supply1
supply0用于对“地”建模,即低电平 0;s u p p l y 1网用于对电源建模,即高电平 1;例如:
supply0 Gnd, ClkGnd;
supply1 [2:0] Vcc;
5.2.2 寄存器类型 register type
具体有5种:reg、integer、time、real、realtime
- 1.reg寄存器类
register type表示一个抽象的数据存储单元,它只能在 always语句和initial语句中被赋值,并且它的值从一个赋值到另一个赋值被保存下来。寄存器类型的变量具有 x的缺省值。
寄存器数据类型 reg是最常见的数据类型。 reg类型使用保留字 reg加以说明,形式如下:
reg [ msb: lsb] reg1, reg2, . . . regN;
- 2存储器类型:
存储器是一个寄存器数组。存储器使用如下方式说明:
reg [ msb: lsb] memory1[ upper1: lower1], memory2[ upper2: lower2], . . . ;
- 3.integer整数寄存器类
- 4.time类
- 5.real和realtime类
6.参数
参数是一个常量。参数经常用于定义时延和变量的宽度。使用参数说明的参数只被赋值一次。参数说明形式如下:
parameter param1 = const_expr1, param2 = const_expr2, ...,paramN = const_exprN;
7.行为描述方式
7.1数据流描述
用数据流描述方式对一个设计建模的最基本的机制就是使用连续赋值语句。在连续赋值语句中,某个值被指派给线网变量。 连续赋值语句的语法为 :
assign [delay] LHS_net = RHS_ expression;
7.2行为描述方式
设计的行为功能使用下述过程语句结构描述:
1) initial语句:此语句只执行一次。
2) always语句:此语句总是循环执行 , 或者说此语句重复执行
只有寄存器类型数据能够在这两种语句中被赋值。寄存器类型数据在被赋新值前保持原
有值不变。所有的初始化语句和 always语句在0时刻并发执行。
7.3结构化模式方式
在Verilog HDL中可使用如下方式描述结构 :
1) 内置门原语 (在门级);
2) 开关级原语 (在晶体管级 );
3) 用户定义的原语 (在门级);
4) 模块实例 (创建层次结构)。
通过使用线网来相互连接。
7.4混合描述方式
在模块中,结构的和行为的结构可以自由混合。也就是说,模块描述中可以包含实例化的门、模块实例化语句、连续赋值语句以及 a l w a y s语句和 i n i t i a l语句的混合。它们之间可以相互包含。来自 a l w a y s语句和 i n i t i a l语句(切记只有寄存器类型数据可以在这两种语句中赋值)的值能够驱动门或开关,而来自于门或连续赋值语句(只能驱动线网)的值能够反过来用于触发always语句和initial语句。