当前位置:文档之家› Verilog语法入门,初学者必看

Verilog语法入门,初学者必看

Verilog的词法约定1Verilog是大小写相关的,其中的关键字全部为小写。

2空白符由空格、制表符、和换行符组成。

3单行注释以“//”开始,verilog将忽略此处到行尾的内容。

多行注释以“/*”开始,以“*/”结束。

多行注释不允许嵌套4操作符有三种:单目操作符、双目操作符和三目操作符。

5数字声明Verilog中有两种数字生命:指明位数的数字和不指明位数的数字指明位数的数字表示形式:<size>’<base format><number>Size用来指明数字位宽度,只能用十进制整数表示Base format包括十进制(’d或’D),二进制(’b或’B),八进制(‘o或’O),十六进制(‘h或’H)例如4’b1111 //4位2进制数12’h3ac //12位16进制数不指明位数的数字:如果数字说明中没有指定基数,那么默认表示为十进制数。

如果没有指定位宽,则默认的位宽度与仿真器和使用的计算机有关(最小为32位)。

‘o21 //32位八进制数X值和Z值:不确定值用X表示,高阻用Z值表示。

在八进制数中代表3位,十六进制中代表4位。

12’h12X //这是一个12位16进制数,其中低四位不确定负数:在表示位宽的数字前面增加一个减号来表示它是一个负数。

-6’d3 //一个6位的用二进制补码形式存储的十进制数3,表示负数-6’sd3 //一个6位的带符号算数运算的负数下划线符号和问号:除了第一个字符,下划线“_”可以出现在数字中的任何位置,它的作用只是提高可读性,在编译阶段会被忽略掉问号“?”是z的另一种表示,使用问号的目的在于增强casex和casez语句的可读性。

在这两条语句中,“?”表示不必关心的情况。

12’B1111_0011_1110 // 增强可读性4’b10?? //相当于4’b10zz6字符串是双引号括起来的一个字符队列。

对于字符串的限制是,它必须在一行中书写完,不可书写在多行中,也不能包含回车符。

Verilog将字符串当作一个单字节的ASCII字符队列。

“Hello Verilog world” //是一个字符串7标识符和关键字关键字是语言中预留的用于定义语言结构的特殊标识符。

Verilog中关键字全部小写。

标识符是程序代码中对象的名字,程序员使用标识符来访问对象。

Verilog中标识符由字母数字字符、下划线和美元符号组成,区分大小写。

其第一个字符必须是数字字符或下划线。

reg value; //reg是关键字;value是标识符8转义标识符转义标识符以“\”开始,以空白符结束。

Verilog将反斜线和空白符之间的字符逐个进行处理。

所有的可打印字符均可包含在转义字符中,而反斜线和表示结束的空白符不作为标识符的一部分。

系统任务Verilog为某些常用操作提供了标准的系统任务(也叫系统函数)这些操作包括屏幕显示、线网值动态监视、暂停和结束仿真等。

所有的系统任务都具有$<keyword>的形式。

显示信息$display(p1,p2,p3,…,pn);$display会自动在字符串的结尾处插入一个换行符,因此如果参数列表为空,则display的效果是现实光标移动到下一行监视信息$monitor(p1,p2,p3,…,pm);系统函数$monitor对其参数列表中的变量值或者信号值进行不间断的监视,当其中任何一个发生变化的时候,显示所有参数的数值。

$monitor 只需调用一次即可在整个仿真过程中生效。

编译指令Verilog提供了一些编译指令供用户使用,其使用方式为’<keyword>‘define用于定义verilog中的文本宏。

类似于c中的#define.‘define WORD_SIZE32‘i nclude 在编译期间将一个verilog源文件包含在另一个verilog文件中,类似于c中的#i nclude结构。

‘include header.vVerilog的数据类型11值的种类四值电平逻辑如果两个具有不同强度的信号驱动同一个线网,则竞争结果值为高强度信号的值。

如果两个强度相同的信号之间发生竞争,则结果为不确定值。

2线网线网(net)表示硬件单元之间的连接。

线网一般使用关键字wire进行声明。

如果没有显式的说明为向量,则默认线网的位宽为1。

线网的默认值为Z,(trireg类型线网例外,其默认值为X)。

其值由驱动源确定,如果没有驱动源则线网的值为ZNet并不是一个关键字,它代表了一组数据类型,包括wire,wand,wor,tri,triand,trior以及trireg等。

3寄存器寄存器用来表示存储元件,它保持原有的数值,直到被改写。

注意:不要将这里的寄存器和实际电路中由边沿触发器构成的硬件寄存器混淆。

在Verilog中,术语register仅意味着一个保持数值的变量。

与线网不同,寄存器不需要驱动源,而且也不像硬件寄存器那样需要时钟信号。

在仿真过程中的任意时刻,寄存器的值都可以通过赋值来改变。

寄存器的数据类型通过关键字reg来声明,默认值为X。

4向量线网和寄存器类型的数据均可声明为向量(位宽大于1)。

如果在声明中没有指定位宽,则默认为标量(1位)wire a; //标量线网变量,默认wire [7:0] bus; //8位的总线reg clock ; //标量寄存器,默认reg [0:40] virtual_addr; //向量寄存器,41位宽的虚拟地址向量通过[high#:low#]进行说明,方括号中左边的数总是代表向量的最高有效位。

向量域选择对于上面例子中声明的向量,我们可以指定它的某一位或者若干个相邻位。

Verilog的数据类型21整数、实数和时间寄存器类型整数是一种通用的寄存器数据类型,用于对数量进行操作,使用integer进行声明。

integer counter; //一般用途的变量用作计数器initialcounter = -1; //把-1存储到寄存器中实数:实常量和实数寄存器数据类型使用关键字real来声明,可以用十进制或科学计数法来表示。

实数声明不能带有范围,其默认值为0.如果将一个实数赋予一个整数,那么实数将会被取为最接近的整数。

real delta; //定义一个名为delta的实型变量时间寄存器:仿真是按照仿真时间进行的,verilog使用一个特殊的时间寄存器数据类型来保存仿真时间。

时间变量通过使用关键字time来声明,其宽度与具体实现无关,最小为64位。

通过调用系统函数$time可以取得当前的仿真时间。

2数组Verilog中允许声明reg、integer、time、real、realtime及其向量类型的数组,对数组的维数没有限制,即可声明任意维数的数组。

线网数组也可用于连接实例的端口,数组中的每个元素都可以作为一个标量或者向量,以同样的方式来使用,形如<数组名>[<下标>]。

Integer count[0:7]; //由八位计数变量组成的数组reg bool [31:0]; //由32个1位的布尔寄存器变量组成的数组wire [7:0] w_array2 [5:0]; //声明8位向量的数组注意:不要把数组和线网或寄存器向量混淆起来。

向量是一个单独的元件,它的位宽是n,数组由多个元件组成,其中每个元件的位宽为n或1.3存储器Verilog中使用寄存器一维数组来表示存储器。

数字的每个元素成为一个元素或一个字(word),由一个数组索引来指定。

每个字的位宽为1位或者多位。

注意n个1位寄存器和一个n位寄存器是不同的。

如果需要访问存储器中的一个特定的字,则可通过子的地址作为数组的下标来完成。

reg mem1bit[0:1023]; //1k的1位存储器reg [7:0] membyte [0:1023]; //1k的字节(8位)存储器membytemembyet[511] //取出membyte中地址511所处的字节4参数Verilog使用关键字parameter在模块内定义常数。

参数代表常数,不能像变量那样赋值,但是每个模块实例的参数值可以在编译阶段被重载。

通过参数重载使得用户可以对模块实例进行定制。

除此之外还可以对参数的类型和范围进行定义。

parameter port_id = 5; //定义常数port_id 为55字符串字符串保存在reg类型的变量中,每个字符占用8位(一个字节),因此寄存器变量的宽度应足够大,以保证容纳全部字符。

如果寄存器变量的宽度大于字符串的大小,则verilog用0来填充左边的空余位。

如果寄存器变来那个的宽度小于字符串的大小,则verilog截去字符串最左边的位。

模块模块的定义以关键字module开始,模块名、端口列表、端口声明和可选的参数声明必须出现在其他部分的前面,endmodule语句必须为模块的最后一条语句。

端口是模块与外部环境交互的通道,只有在模块有端口的情况下才需要有端口列表和端口声明。

模块内部的5个组成部分是:变量声明、数据流语句、低层模块实例、行为语句块以及任务和函数。

端口端口是模块与外界环境交互的接口。

对外部环境来讲,模块内部是不可见的,对模块的调用只能通过其端口进行。

这种特点为设计者提供了很大的灵活性:只要接口保持不变,模块内部的修改并不会影响到外部环境。

常将端口成为终端。

(terminal)端口列表:在模块的定义中包括一个可选的端口列表。

如果模块和外部环境没有交换任何信号,则可以没有端口列表。

端口声明端口列表中的所有端口必须在模块中进行声明,verilog中的端口具有以下三种了类型:input、output、和inout。

在verilog中,所有的端口隐含地声明为wire类型,因此如果希望端口具有wire数据类型,将其声明为三种类型之一即可:如果输出类型的端口需要保存数值,则必须将其显式的声明为reg数据类型。

不能将input和inout类型的端口声明为reg数据类型,这是因为reg类型的变量是用于保存数值的,而输入端口只反映与其相连的外部信号的变化,并不能保存这些信号的值。

注意,在verilog中,也可以使用ANSI C风格进行端口声明。

这种风格的声明的优点是避免了端口名在端口列表和端口声明语句中的重复。

如果声明中未指明端口的数据类型,那么默认端口具有wire数据类型。

如:module fulladd4(output reg [3:0] sum,output reg c_out,input [3:0] a,b,input c_in);…………endmodule端口连接规则将一个端口看成由相互链接的两个部分组成,一部分位于模块内部,另一部分位于模块外部。

当在一个模块中调用(实例引用)另一个模块时,端口之间的连接必须遵守一些规则。

相关主题