VerilogHDL的基本语法.docx

上传人:b****1 文档编号:3512366 上传时间:2023-05-06 格式:DOCX 页数:100 大小:237.63KB
下载 相关 举报
VerilogHDL的基本语法.docx_第1页
第1页 / 共100页
VerilogHDL的基本语法.docx_第2页
第2页 / 共100页
VerilogHDL的基本语法.docx_第3页
第3页 / 共100页
VerilogHDL的基本语法.docx_第4页
第4页 / 共100页
VerilogHDL的基本语法.docx_第5页
第5页 / 共100页
VerilogHDL的基本语法.docx_第6页
第6页 / 共100页
VerilogHDL的基本语法.docx_第7页
第7页 / 共100页
VerilogHDL的基本语法.docx_第8页
第8页 / 共100页
VerilogHDL的基本语法.docx_第9页
第9页 / 共100页
VerilogHDL的基本语法.docx_第10页
第10页 / 共100页
VerilogHDL的基本语法.docx_第11页
第11页 / 共100页
VerilogHDL的基本语法.docx_第12页
第12页 / 共100页
VerilogHDL的基本语法.docx_第13页
第13页 / 共100页
VerilogHDL的基本语法.docx_第14页
第14页 / 共100页
VerilogHDL的基本语法.docx_第15页
第15页 / 共100页
VerilogHDL的基本语法.docx_第16页
第16页 / 共100页
VerilogHDL的基本语法.docx_第17页
第17页 / 共100页
VerilogHDL的基本语法.docx_第18页
第18页 / 共100页
VerilogHDL的基本语法.docx_第19页
第19页 / 共100页
VerilogHDL的基本语法.docx_第20页
第20页 / 共100页
亲,该文档总共100页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

VerilogHDL的基本语法.docx

《VerilogHDL的基本语法.docx》由会员分享,可在线阅读,更多相关《VerilogHDL的基本语法.docx(100页珍藏版)》请在冰点文库上搜索。

VerilogHDL的基本语法.docx

VerilogHDL的基本语法

第三章VerilogHDL的基本语法

 

前言

VerilogHDL是一种用于数字逻辑电路设计的语言。

用VerilogHDL描述的电路设计就是该电路的VerilogHDL模型。

VerilogHDL既是一种行为描述的语言也是一种结构描述的语言。

这也就是说,既可以用电路的功能描述也可以用元器件和它们之间的连接来建立所设计电路的VerilogHDL模型。

Verilog模型可以是实际电路的不同级别的抽象。

这些抽象的级别和它们对应的模型类型共有以下五种:

∙系统级(system):

用高级语言结构实现设计模块的外部性能的模型。

∙算法级(algorithm):

用高级语言结构实现设计算法的模型。

∙RTL级(RegisterTransferLevel):

描述数据在寄存器之间流动和如何处理这些数据的模型。

∙门级(gate-level):

描述逻辑门以及逻辑门之间的连接的模型。

∙开关级(switch-level):

描述器件中三极管和储存节点以及它们之间连接的模型。

一个复杂电路系统的完整VerilogHDL模型是由若干个VerilogHDL模块构成的,每一个模块又可以由若干个子模块构成。

其中有些模块需要综合成具体电路,而有些模块只是与用户所设计的模块交互的现存电路或激励信号源。

利用VerilogHDL语言结构所提供的这种功能就可以构造一个模块间的清晰层次结构来描述极其复杂的大型设计,并对所作设计的逻辑电路进行严格的验证。

VerilogHDL行为描述语言作为一种结构化和过程性的语言,其语法结构非常适合于算法级和RTL级的模型设计。

这种行为描述语言具有以下功能:

∙可描述顺序执行或并行执行的程序结构。

∙用延迟表达式或事件表达式来明确地控制过程的启动时间。

∙通过命名的事件来触发其它过程里的激活行为或停止行为。

∙提供了条件、if-else、case、循环程序结构。

∙提供了可带参数且非零延续时间的任务(task)程序结构。

∙提供了可定义新的操作符的函数结构(function)。

∙提供了用于建立表达式的算术运算符、逻辑运算符、位运算符。

∙VerilogHDL语言作为一种结构化的语言也非常适合于门级和开关级的模型设计。

因其结构化的特点又使它具有以下功能:

-提供了完整的一套组合型原语(primitive);

-提供了双向通路和电阻器件的原语;

-可建立MOS器件的电荷分享和电荷衰减动态模型。

VerilogHDL的构造性语句可以精确地建立信号的模型。

这是因为在VerilogHDL中,提供了延迟和输出强度的原语来建立精确程度很高的信号模型。

信号值可以有不同的的强度,可以通过设定宽范围的模糊值来降低不确定条件的影响。

VerilogHDL作为一种高级的硬件描述编程语言,有着类似C语言的风格。

其中有许多语句如:

if语句、case语句等和C语言中的对应语句十分相似。

如果读者已经掌握C语言编程的基础,那么学习VerilogHDL并不困难,我们只要对VerilogHDL某些语句的特殊方面着重理解,并加强上机练习就能很好地掌握它,利用它的强大功能来设计复杂的数字逻辑电路。

下面我们将对VerilogHDL中的基本语法逐一加以介绍。

 

3.1.简单的VerilogHDL模块

3.1.1.简单的VerilogHDL程序介绍

下面先介绍几个简单的VerilogHDL程序,然后从中分析VerilogHDL程序的特性。

例[3.1.1]:

moduleadder(count,sum,a,b,cin);

input[2:

0]a,b;

inputcin;

outputcount;

output[2:

0]sum;

assign{count,sum}=a+b+cin;

endmodule

这个例子通过连续赋值语句描述了一个名为adder的三位加法器可以根据两个三比特数a、b和进位(cin)计算出和(sum)和进位(count)。

从例子中可以看出整个VerilogHDL程序是嵌套在module和endmodule声明语句里的。

例[3.1.2]:

modulecompare(equal,a,b);

outputequal;//声明输出信号equal

input[1:

0]a,b;//声明输入信号a,b

assignequal=(a==b)?

1:

0;

/*如果a、b两个输入信号相等,输出为1。

否则为0*/

endmodule

这个程序通过连续赋值语句描述了一个名为compare的比较器。

对两比特数a、b进行比较,如a与b相等,则输出equal为高电平,否则为低电平。

在这个程序中,/*........*/和//.........表示注释部分,注释只是为了方便程序员理解程序,对编译是不起作用的。

例[3.1.3]:

moduletrist2(out,in,enable);

outputout;

inputin,enable;

bufif1mybuf(out,in,enable);

endmodule

这个程序描述了一个名为trist2的三态驱动器。

程序通过调用一个在Verilog语言库中现存的三态驱动器实例元件bufif1来实现其功能。

例[3.1.4]:

moduletrist1(out,in,enable);

outputout;

inputin,enable;

mytritri_inst(out,in,enable);

//调用由mytri模块定义的实例元件tri_inst

endmodule

modulemytri(out,in,enable);

outputout;

inputin,enable;

assignout=enable?

in:

'bz;

endmodule

这个程序例子通过另一种方法描述了一个三态门。

在这个例子中存在着两个模块。

模块trist1调用由模块mytri定义的实例元件tri_inst。

模块trist1是顶层模块。

模块mytri则被称为子模块。

通过上面的例子可以看到:

∙VerilogHDL程序是由模块构成的。

每个模块的内容都是嵌在module和endmodule两个语句之间。

每个模块实现特定的功能。

模块是可以进行层次嵌套的。

正因为如此,才可以将大型的数字电路设计分割成不同的小模块来实现特定的功能,最后通过顶层模块调用子模块来实现整体功能。

∙每个模块要进行端口定义,并说明输入输出口,然后对模块的功能进行行为逻辑描述。

∙VerilogHDL程序的书写格式自由,一行可以写几个语句,一个语句也可以分写多行。

∙除了endmodule语句外,每个语句和数据定义的最后必须有分号。

∙可以用/*.....*/和//.......对VerilogHDL程序的任何部分作注释。

一个好的,有使用价值的源程序都应当加上必要的注释,以增强程序的可读性和可维护性。

 

3.1.2.模块的结构

Verilog的基本设计单元是“模块”(block)。

一个模块是由两部分组成的,一部分描述接口,另一部分描述逻辑功能,即定义输入是如何影响输出的。

下面举例说明:

请看上面的例子,程序模块旁边有一个电路图的符号。

在许多方面,程序模块和电路图符号是一致的,这是因为电路图符号的引脚也就是程序模块的接口。

而程序模块描述了电路图符号所实现的逻辑功能。

上面的Verilog设计中,模块中的第二、第三行说明接口的信号流向,第四、第五行说明了模块的逻辑功能。

以上就是设计一个简单的Verilog程序模块所需的全部内容。

从上面的例子可以看出,Verilog结构完全嵌在module和endmodule声明语句之间,每个Verilog程序包括四个主要部分:

端口定义、I/O说明、内部信号声明、功能定义。

3.1.3.模块的端口定义

模块的端口声明了模块的输入输出口。

其格式如下:

module模块名(口1,口2,口3,口4,………);

3.1.4.模块内容

模块的内容包括I/O说明、内部信号声明、功能定义。

•I/O说明的格式如下:

输入口:

input端口名1,端口名2,………,端口名i;//(共有i个输入口)

输出口:

output端口名1,端口名2,………,端口名j;//(共有j个输出口)

I/O说明也可以写在端口声明语句里。

其格式如下:

modulemodule_name(inputport1,inputport2,…

outputport1,outputport2…);

•内部信号说明:

在模块内用到的和与端口有关的wire和reg变量的声明。

如:

reg[width-1:

0]R变量1,R变量2。

wire[width-1:

0]W变量1,W变量2。

………..

•功能定义:

模块中最重要的部分是逻辑功能定义部分。

有三种方法可在模块中产生逻辑。

1).用“assign”声明语句

如:

assigna=b&c;

这种方法的句法很简单,只需写一个“assign”,后面再加一个方程式即可。

例子中的方程式描述了一个有两个输入的与门。

2).用实例元件

如:

andand_inst(q,a,b);

采用实例元件的方法象在电路图输入方式下,调入库元件一样。

键入元件的名字和相连的引脚即可,表示在设计中用到一个跟与门(and)一样的名为and_inst的与门,其输入端为a,b,输出为q。

要求每个实例元件的名字必须是唯一的,以避免与其他调用与门(and)的实例混淆。

3).用“always”块

如:

always@(posedgeclkorposedgeclr)

begin

if(clr)q<=0;

elseif(en)q<=d;

end

采用“assign”语句是描述组合逻辑最常用的方法之一。

而“always”块既可用于描述组合逻辑也可描述时序逻辑。

上面的例子用“always”块生成了一个带有异步清除端的D触发器。

“always”块可用很多种描述手段来表达逻辑,例如上例中就用了if...else语句来表达逻辑关系。

如按一定的风格来编写“always”块,可以通过综合工具把源代码自动综合成用门级结构表示的组合或时序逻辑电路。

注意:

如果用Verilog模块实现一定的功能,首先应该清楚哪些是同时发生的,哪些是顺序发生的。

上面三个例子分别采用了“assign”语句、实例元件和“always”块。

这三个例子描述的逻辑功能是同时执行的。

也就是说,如果把这三项写到一个VeriIog模块文件中去,它们的次序不会影响逻辑实现的功能。

这三项是同时执行的,也就是并发的。

然而,在“always”模块内,逻辑是按照指定的顺序执行的。

“always”块中的语句称为“顺序语句”,因为它们是顺序执行的。

请注意,两个或更多的“always”模块也是同时执行的,但是模块内部的语句是顺序执行的。

看一下“always”内的语句,你就会明白它是如何实现功能的。

if..else…if必须顺序执行,否则其功能就没有任何意义。

如果else语句在if语句之前执行,功能就会不符合要求!

为了能实现上述描述的功能,“always”模块内部的语句将按照书写的顺序执行。

 

3.2.数据类型及其常量、变量

VerilogHDL中总共有十九种数据类型,数据类型是用来表示数字电路硬件中的数据储存和传送元素的。

在本教材中我们先只介绍四个最基本的数据类型,它们是:

reg型、wire型、integer型、parameter型

其它数据类型在后面的章节里逐步介绍,同学们也可以查阅附录中VerilogHDL语法参考书的有关章节逐步掌握。

其它的类型如下:

large型、medium型、scalared型、time型、small型、tri型、trio型、tri1型、triand型、trior型、trireg型、vectored型、wand型、wor型。

这些数据类型除time型外都与基本逻辑单元建库有关,与系统设计没有很大的关系。

在一般电路设计自动化的环境下,仿真用的基本部件库是由半导体厂家和EDA工具厂家共同提供的。

系统设计工程师不必过多地关心门级和开关级的VerilogHDL语法现象。

VerilogHDL语言中也有常量和变量之分。

它们分别属于以上这些类型。

下面就最常用的几种进行介绍。

 

3.2.1.常量

在程序运行过程中,其值不能被改变的量称为常量。

下面首先对在VerilogHDL语言中使用的数字及其表示方式进行介绍。

一.数字

•整数:

在VerilogHDL中,整型常量即整常数有以下四种进制表示形式:

1)二进制整数(b或B)

2)十进制整数(d或D)

3)十六进制整数(h或H)

4)八进制整数(o或O)

数字表达方式有以下三种:

1)<位宽><进制><数字>这是一种全面的描述方式。

2)<进制><数字>在这种描述方式中,数字的位宽采用缺省位宽(这由具体的机器系统决定,但至少32位)。

3)<数字>在这种描述方式中,采用缺省进制十进制。

在表达式中,位宽指明了数字的精确位数。

例如:

一个4位二进制数的数字的位宽为4,一个4位十六进制数的数字的位宽为16(因为每单个十六进制数就要用4位二进制数来表示)。

见下例:

8'b10101100//位宽为8的数的二进制表示,'b表示二进制

8'ha2//位宽为8的数的十六进制,'h表示十六进制。

•x和z值:

在数字电路中,x代表不定值,z代表高阻值。

一个x可以用来定义十六进制数的四位二进制数的状态,八进制数的三位,二进制数的一位。

z的表示方式同x类似。

z还有一种表达方式是可以写作?

在使用case表达式时建议使用这种写法,以提高程序的可读性。

见下例:

4'b10x0//位宽为4的二进制数从低位数起第二位为不定值

4'b101z//位宽为4的二进制数从低位数起第一位为高阻值

12'dz//位宽为12的十进制数其值为高阻值(第一种表达方式)

12'd?

//位宽为12的十进制数其值为高阻值(第二种表达方式)

8'h4x//位宽为8的十六进制数其低四位值为不定值

•负数:

一个数字可以被定义为负数,只需在位宽表达式前加一个减号,减号必须写在数字定义表达式的最前面。

注意减号不可以放在位宽和进制之间也不可以放在进制和具体的数之间。

见下例:

-8'd5//这个表达式代表5的补数(用八位二进制数表示)

8'd-5//非法格式

•下划线(underscore_):

下划线可以用来分隔开数的表达以提高程序可读性。

但不可以用在位宽和进制处,只能用在具体的数字之间。

见下例:

16'b1010_1011_1111_1010//合法格式

8'b_0011_1010//非法格式

当常量不说明位数时,默认值是32位,每个字母用8位的ASCII值表示。

例:

10=32’d10=32’b1010

1=32’d1=32’b1

-1=-32’d1=32’hFFFFFFFF

‘BX=32’BX=32’BXXXXXXX…X

“AB”=16’B01000001_01000010

二.参数(Parameter)型

在VerilogHDL中用parameter来定义常量,即用parameter来定义一个标识符代表一个常量,称为符号常量,即标识符形式的常量,采用标识符代表一个常量可提高程序的可读性和可维护性。

parameter型数据是一种常数型的数据,其说明格式如下:

parameter参数名1=表达式,参数名2=表达式,…,参数名n=表达式;

parameter是参数型数据的确认符,确认符后跟着一个用逗号分隔开的赋值语句表。

在每一个赋值语句的右边必须是一个常数表达式。

也就是说,该表达式只能包含数字或先前已定义过的参数。

见下列:

parametermsb=7;//定义参数msb为常量7

parametere=25,f=29;//定义二个常数参数

parameterr=5.7;//声明r为一个实型参数

parameterbyte_size=8,byte_msb=byte_size-1;//用常数表达式赋值

parameteraverage_delay=(r+f)/2;//用常数表达式赋值

参数型常数经常用于定义延迟时间和变量宽度。

在模块或实例引用时可通过参数传递改变在被引用模块或实例中已定义的参数。

下面将通过两个例子进一步说明在层次调用的电路中改变参数常用的一些用法。

[例1]:

在引用Decode实例时,D1,D2的Width将采用不同的值4和5,且D1的Polarity将为0。

可用例子中所用的方法来改变参数,即用#(4,0)向D1中传递Width=4,Polarity=0;用#(5)向D2中传递Width=5,Polarity仍为1。

moduleDecode(A,F);

parameterWidth=1,Polarity=1;

……………

endmodule

moduleTop;

wire[3:

0]A4;

wire[4:

0]A5;

wire[15:

0]F16;

wire[31:

0]F32;

Decode#(4,0)D1(A4,F16);

Decode#(5)D2(A5,F32);

Endmodule

[例2]:

下面是一个多层次模块构成的电路,在一个模块中改变另一个模块的参数时,需要使用defparam命令

 

3.2.2变量

变量即在程序运行过程中其值可以改变的量,在VerilogHDL中变量的数据类型有很多种,这里只对常用的几种进行介绍。

网络数据类型表示结构实体(例如门)之间的物理连接。

网络类型的变量不能储存值,而且它必需受到驱动器(例如门或连续赋值语句,assign)的驱动。

如果没有驱动器连接到网络类型的变量上,则该变量就是高阻的,即其值为z。

常用的网络数据类型包括wire型和tri型。

这两种变量都是用于连接器件单元,它们具有相同的语法格式和功能。

之所以提供这两种名字来表达相同的概念是为了与模型中所使用的变量的实际情况相一致。

wire型变量通常是用来表示单个门驱动或连续赋值语句驱动的网络型数据,tri型变量则用来表示多驱动器驱动的网络型数据。

如果wire型或tri型变量没有定义逻辑强度(logicstrength),在多驱动源的情况下,逻辑值会发生冲突从而产生不确定值。

下表为wire型和tri型变量的真值表(注意:

这里假设两个驱动源的强度是一致的,关于逻辑强度建模请参阅附录:

Verilog语言参考书)。

wire/tri

0

1

x

z

0

0

x

x

0

1

x

1

x

1

x

x

x

x

x

z

0

1

x

z

一.wire型

wire型数据常用来表示用于以assign关键字指定的组合逻辑信号。

Verilog程序模块中输入输出信号类型缺省时自动定义为wire型。

wire型信号可以用作任何方程式的输入,也可以用作“assign”语句或实例元件的输出。

wire型信号的格式同reg型信号的很类似。

其格式如下:

wire[n-1:

0]数据名1,数据名2,…数据名i;//共有i条总线,每条总线内有n条线路

wire[n:

1]数据名1,数据名2,…数据名i;

wire是wire型数据的确认符,[n-1:

0]和[n:

1]代表该数据的位宽,即该数据有几位。

最后跟着的是数据的名字。

如果一次定义多个数据,数据名之间用逗号隔开。

声明语句的最后要用分号表示语句结束。

看下面的几个例子。

wirea;//定义了一个一位的wire型数据

wire[7:

0]b;//定义了一个八位的wire型数据

wire[4:

1]c,d;//定义了二个四位的wire型数据

二.reg型

寄存器是数据储存单元的抽象。

寄存器数据类型的关键字是reg.通过赋值语句可以改变寄存器储存的值,其作用与改变触发器储存的值相当。

VerilogHDL语言提供了功能强大的结构语句使设计者能有效地控制是否执行这些赋值语句。

这些控制结构用来描述硬件触发条件,例如时钟的上升沿和多路器的选通信号。

在行为模块介绍这一节中我们还要详细地介绍这些控制结构。

reg类型数据的缺省初始值为不定值,x。

reg型数据常用来表示用于“always”模块内的指定信号,常代表触发器。

通常,在设计中要由“always”块通过使用行为描述语句来表达逻辑关系。

在“always”块内被赋值的每一个信号都必须定义成reg型。

reg型数据的格式如下:

reg[n-1:

0]数据名1,数据名2,…数据名i;

reg[n:

1]数据名1,数据名2,…数据名i;

reg是reg型数据的确认标识符,[n-1:

0]和[n:

1]代表该数据的位宽,即该数据有几位(bit)。

最后跟着的是数据的名字。

如果一次定义多个数据,数据名之间用逗号隔开。

声明语句的最后要用分号表示语句结束。

看下面的几个例子:

regrega;//定义了一个一位的名为rega的reg型数据

reg[3:

0]regb;//定义了一个四位的名为regb的reg型数据

reg[4:

1]regc,regd;//定义了两个四位的名为regc和regd的reg型数据

对于reg型数据,其赋值语句的作用就象改变一组触发器的存储单元的值。

在Verilog中有许多构造(construct)用来控制何时或是否执行这些赋值语句。

这些控制构造可用来描述硬件触发器的各种具体情况,如触发条件用时钟的上升沿等,或用来描述具体判断逻辑的细节,如各种多路选择器。

reg型数据的缺省初始值是不定值。

reg型数据可以赋正值,也可以赋负值。

但当一个reg型数据是一个表达式中的操作数时,它的值被当作是无符号值,即正值。

例如:

当一个四位的寄存器用作表达式中的操作数时,如果开始寄存器被赋以值-1,则在表达式中进行运算时,其值被认为是+15。

注意:

reg型只表示被定义的信号将用在“always”块内,理解这一点很重要。

并不是说reg型信号一定是寄存器或触发器的输出。

虽然reg型信号常常是寄存器或触发器的输出,但并不一定总是这样。

在本书中我们还会对这一点作更详细的解释。

三.memory型

VerilogHDL通过对reg型变量建立数组来对存储器建模,可以描述RAM型存储器,ROM存储器和reg文件。

数组中的每一个单元通过一个数组索引进行寻址。

在Verilog语言中没有多维数组存在。

memory型数据是通过扩展reg型数据的地址范围来生成的。

其格式如下:

reg[n-1:

0]存储器名[m-1:

0];

或reg[n-1:

0]存储器名[m:

1];

在这里,reg[n-1:

0]定义了存储器中每一个存储单元的大小,即该存储单元是一个n位的寄存器。

存储器名后的[m-1:

0]或[m:

1]则定义了该存储器中有多少个这样的寄存器。

最后用分号结束定义语句。

下面举例说明:

reg[7:

0]mema[255:

0];

这个例子定义了一个名为mema的存储器,该存储器有256个8位的存储器。

该存储器的地址范围是0到255。

注意:

对存储器进行地址索引的表达式必须是常数表达式。

另外,在同一个数据类型声明语句里,可以同时定义存储器型数据和reg型数据。

见下例:

pa

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2