1VerilogHDL语言基础知识先来看两个VerilogHDL程序。例6.1一个8位全加器的VerilogHDL源代码moduleadder8(cout,sum,ina,inb,cin);output[7:0]sum;outputcout;input[7:0]ina,inb;inputcin;assign{cout,sum}=ina+inb+cin;//全加endmodule【例6.2】一个8位计数器的VerilogHDL源代码modulecounter8(out,cout,data,load,cin,clk);output[7:0]out;outputcout;input[7:0]data;inputload,cin,clk;reg[7:0]out;always@(posedgeclk)beginif(load)out=data;elseout=out+cin;endassigncout=&out&cin;endmodule从上面的例子可以看出:①VerilogHDL程序是由模块构成的。每个模块的内容都是嵌在module和endmodule两个语句之间,每个模块实现特定的功能,模块是可以进行层次嵌套的。②每个模块首先要进行端口定义,并说明输入(input)和输出(output),然后对模块的功能进行逻辑描述。③VerilogHDL程序的书写格式自由,一行可以写几个语句,一个语句也可以分多行写。④除了endmodule语句外,每个语句的最后必须有分号。⑤可以用/*……*/和//……对VerilogHDL程序的任何部分作注释。26.1.2VerilogHDL模块的结构VerilogHDL的基本设计单元是模块(block)。一个模块是由两部分组成的,一部分描述接口;另一部分描述逻辑功能,即定义输入是如何影响输出的。下面举例说明,图6.1示出了一个与-或-非门电路。123123ABCDF图6.1与-或-非电路该电路表示的逻辑函数可以写为:F=AB+CD用VerlogHDL语言对该电路进行描述如下:【例6.3】与-或-非门电路moduleAOI(A,B,C,D,F);//模块名为AOI(端口列表A,B,C,D,F)inputA,B,C,D;//定义模块的输入端口A,B,C,DoutputF;//定义模块的输出端口FassignF=~((A&B)︱(C&D));//模块内的逻辑描述endmodule从上面的例子可知,电路图符号的引脚也就是程序模块的端口,在程序模块内描述了电路图符号所实现的逻辑功能。在上面的VerilogHDL设计中,模块中的第2、第3行说明接口的信号流向,第4行说明了模块的逻辑功能。VerilogHDL结构完全嵌在module和endmodule声明语句之间,每个Verilog程序包括4个主要部分:端口定义,I/0说明,信号类型声明和功能描述。1.模块的端口定义模块的端口声明了模块的输人和输出口。其格式如下:module模块名(口1,口2,口3,口4,……);2.模块内容模块内容包括I/O说明,信号类型声明和功能定义。(1)I/O说明的格式如下:输人口:input端口名1,端口名2,……端口名N;输出口:output端口名l,端口名2,……端口名N;I/O说明也可以写在端口声明语句里。其格式如下:modulemodule_name(inputportl,inputport2,…outputportl,outputport2,…);3(2)信号类型声明:它是说明逻辑描述中所用信号的数据类型及函数声明。如reg[7:0]out;//定义out的数据类型为reg(寄存器)型对于端口信号的缺省定义类型为wire(连线)型。6.1.3逻辑功能定义模块中最重要的部分是逻辑功能定义。有3种方法可在模块中描述逻辑。1.用assign语句如:assignF=~((A&B)|(C&D));这种方法的句法很简单,只须写一个“assign”,后面再加一个方程式即可。assign语句一般适合于对组合逻辑进行赋值,称为连续赋值方式。2.用元件例化(instantiate)如:andmyand3(f,a,b,c);这个语句利用VerilogHDL提供的与门库,定义了一个三输人的与门。采用实例元件的方法同在电路图输入方式下调入库元件一样,键入元件的名字和引脚的名字即可。要求每个实例元件的名字必须是唯一的。3.用always块语句在【例6.2】的计数器模块中always@(posedgeclk)//每当时钟上升沿到来时执行一遍块内语句beginif(load)out=data;elseout=out+cin;endalways块可用于产生各种逻辑,常用于描述时序逻辑。这个例子用always块生成了一个带有同步置数的计数器。always块可用很多种描述手段来表达逻辑,如此例中就用了if-else语句来表达逻辑关系。综上所述,可给出VerilogHDL模块的模板如下:VerilogHDL模块的模板(仅考虑用于逻辑综合的部分,不考虑用于逻辑模拟的部分)。module顶层模块名,(输入输出端口列表);output输出端口列表;//输出端口声明input输入端口列表;//输入端口声明/*定义数据,信号的类型,函数声明,用关键字wire,reg,funtion等定义*///使用assign语句定义逻辑功能wire结果信号名;4assign结果信号名=表达式;//使用always块描述逻辑功能always@(敏感信号表达式)begin//过程赋值//if语句,//case语句//while,for,repeat循环语句//function调用end//模块元件例化module_name模块名,instance_name例化元件名,(port_list端口列表);//门元件例化gate_type_keywordinstance_name例化元件名(port_list);endmodule6.2数据类型及常量、变量VerilogHDL中共有19种数据类型。数据类型是用来表示数字电路中的数据存储和传送单元的。在此介绍4个最基本的数据类型:integer型、parameter型、reg型和wire型。VerilogHDL中也有常量和变量之分,他们分属以上这些类型。6.2.1常量在程序运行过程中,其值不能被改变的量称为常量。1.数字(1)整数在VerilogHDL中,整数型常量(即整常数)有以下4种进制表示形式:◇二进制整数(b或B);◇十进制整数(d或D);◇十六进制整数(h或H);◇八进制整数(o或O)。完整的数字表达式为:位宽'进制数字,位宽为对应二迸制数的宽度,如:8'b11000101//位宽为8位的二进制数11000101;8'hc5//位宽为8位的十六进制数c5;十进制的数可以缺省位宽和进制说明,如:197//代表十进制数1975(2)x和z值x表示不定值,z表示高阻值。每个字符代表的宽度取决于所用的进制,例如:8'b1001xxxx;等价于8'h9x;8'b1010zzzz;等价于8'haz;当常量不说明位数时,默认值为32位。此外,“?”是高阻态的z的另一种表示符号。2.常量在VerilogHDL中,用parameter来定义常量,即用parameter来定义一个标志符,代表一个常量,称为符号常量。其定义格式如下:parameter参数名1=表达式,参数名2=表达式,参数名3=表达式……;例如:parametersel=8,code=8'ha3;//分别定义参数sel为常数8(十进制),参数code为常数a3(十六进制)6.2.2变量变量是在程序运行过程中其值可以改变的量。变量分为两种:一种为网络型(netstype),另一种为寄存器型(registertype)。1.nets型变量wirenets型变量指输出始终根据输入的变化而更新其值的变量,它一般指的是硬件电路中的各种物理连接。VerilogHDL中提供了多种nets型变量,具体见表6.1。表6.1常用的nets型变量及说明类型功能说明wire,tri连线类型(wire和tri功能完全相同)wor,trior具有线或特性的连线(两者功能一致)wand,triand具有线与特性的连线(两者功能一致)tri1,tri0分别为上拉电阻和下拉电阻supply1,supply0分别为电源(逻辑1)和地(逻辑0)这里着重介绍wire型变量。wire是一种常用的nets型变量,wire型数据常用来表示assign语句赋值的组合逻辑信号。VerilogHDL模块中的输入/输出信号类型缺省时自动定义为wire型。Wire型信号可以用作任何方程式的输入,也可以用作assign语句和实例元件的输出,其取值为0,1,x,z。wire型变量格式如下:⑴.定义宽度为1位的变量:wire数据名1,数据名2,……数据名n;6例如:wirea,b;//定义了两个宽度为1位wire型变量a,b⑵.定义宽度位n位的向量(vectors):wire[n-1:0]数据名1,数据名2,……数据名n;或wire[n:1]数据名1,数据名2,……数据名n;例如:wire[7:0]databus;//定义一个8位wire型向量或wire[8:1]databus;wire型向量可按以下方式使用:wire[7:0]in,out;//定义两个8位wire型向量in,outassignout=in;若只使用其中某几位,可直接指明,注意宽度要一致。如:wire[7:0]out;wire[3:0]in;assignout[5:2]=in;//out向量的第二位到第5位与in向量相等2.register型变量regregister型变量对应的是具有状态保持作用的电路元件,如触发器、寄存器等。register型变量与nets变量的根本区别在于:register需要被明确地赋值,并在被重新赋值前一直保持原值。在设计中必须将寄存器型变量放在过程块语句(如initial,always)中,通过过程赋值语句赋值。另外,在always过程块内被赋值的每一个信号都必须定义成寄存器型。VerilogHDL中,有4种寄存器型变量,见表6.2表6.2常用的register型变量及说明类型功能说明reg常用的寄存器型变量integer32位带符号整数型变量real64位带符号整数型变量time无符号时间变量Integer、real、time等3种寄存器型变量都是纯数学的抽象描述,不对应任何具体的硬件电路。reg型变量是最常用的一种寄存器型变量,下面介绍reg型变量。reg型变量格式如下:reg数据名1,数据名2,……数据名n;例如:rega,b;//定义了两个宽度为1位的reg型变量a,b若定义一个向量,则按以下格式:7reg[n-l:0]数据名1,数据名2,……数据名n;或reg[n:l]数据名1,数据名2,……数据名n;它们定义了数据的宽度为n位。如下面的语句定义了8位宽的数据例如:reg[7:0]data;//定义data为8位宽的reg型向量或:reg[8:1]data;3.数组若干个相同宽度的向量构成数组,reg型数组变量即为memory型变量,即可定义存储器型数据。如:reg[7:0]mymem[l023:0];上面的语句定义了一个1024个字节、每个字节宽度为8位的存储器。通常,存储器采用如下方式定义:parameterwordwidth=8,memsize=l024;reg[wordwidth-l:0]mymem[memsize-l:0];上面的语句定义了一个宽度为8位、1024个存储单元的存储器,该存储器的名字是mymem,若对该存储器中的某一单元赋值的话,采用如下方式:mymem[8]=1;//mymem存储器中的第8个单元赋值为1注意:VerilogHDL中的变量名、参数名等标记符是对大小写字母敏感的。6.3运算符及表达式6.3.1运算符1.算术运算符+加-减*乘/除%求模算术运算符都是双目运算