Verilog语言介绍_第1页
Verilog语言介绍_第2页
Verilog语言介绍_第3页
Verilog语言介绍_第4页
Verilog语言介绍_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、六Verilog HDL语言介绍 6.1 Verilog HDL基本结构 6.1.1 简单的Verilog HDL 例子首先来看两个简单的Verilog HDL程序。【例6.1】 一个8位全加器的 Verilog HDL源代码module adder8(cout,sum,ina,inb,cin);output7:0 sum;output cout;input7:0 ina,inb;input cin;assign cout,sum=ina+inb+cin;/全加endmodule【例6.2】一个8位计数器的Verilog HDL源代码module counter8(out,cout,data,

2、load,cin,clk);output7:0 out;output cout;input7:0 data;input load,cin,clk;reg7:0 out;always (posedge clk)beginif(load) out=data;else out=out+cin;endassign cout=&out&cin;endmodule 从上面的例子可以看出: Verilog HDL程序是由模块构成的。每个模块的内容都是嵌在module 和endmodule 两个语句之间,每个模块实现特定的功能,模块是可以进行层次嵌套的。 每个模块首先要进行端口定义,并说明输入

3、(input)和输出(output),然后对模块的功能进行逻辑描述。 Verilog HDL程序的书写格式自由,一行可以写几个语句,一个语句也可以分多行写。 除了endmodule语句外,每个语句的最后必须有分号。 可以用/*/和/ 对Verilog HDL程序的任何部分作注释。 6.1.2 Verilog HDL模块的结构 Verilog HDL的基本设计单元是"模块(block)"。一个模块是由两部分组成的,一部分描述接口;另一部分描述逻辑功能,即定义输入是如何影响输出的。下面举例说明,图6.1示出了一个"与-或-非"门电路。 图6.1"与

4、-或-非"电路该电路表示的逻辑函数可以写为: F = AB + CD 用Verlog HDL语言对该电路进行描述如下:【例6.3】与-或-非门电路module AOI(A,B,C,D,F); / 模块名为AOI(端口列表A,B,C,D,F)input A,B,C,D; / 定义模块的输入端口A,B,C,Doutput F; / 定义模块的输出端口Fassign F= (A&B)(C&D); / 模块内的逻辑描述endmodule 从上面的例子可知,电路图符号的引脚也就是程序模块的端口,在程序模块内描述了电路图符号所实现的逻辑功能。在上面的Verilog HDL设计中,

5、模块中的第2、第3行说明接口的信号流向,第4行说明了模块的逻辑功能。 Verilog HDL结构完全嵌在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说明也可以写在端口声明语句里。其格式如下: m

6、odule module_name(input portl,input port2,output portl,output port2,);(2)信号类型声明:它是说明逻辑描述中所用信号的数据类型及函数声明。如reg7:0 out; /定义out的数据类型为reg(寄存器)型对于端口信号的缺省定义类型为wire(连线)型。6.1.3 逻辑功能定义模块中最重要的部分是逻辑功能定义。有3种方法可在模块中描述逻辑。1 用assign语句如:assign F = (A&B)|(C&D);这种方法的句法很简单,只须写一个“assign”,后面再加一个方程式即可。"assign&

7、quot;语句一般适合于对组合逻辑进行赋值,称为连续赋值方式。2 用元件例化(instantiate)如: and myand3(f, a,b,c);这个语句利用Verilog HDL提供的与门库,定义了一个三输人的与门。采用实例元件的方法同在电路图输入方式下调入库元件一样,键入元件的名字和引脚的名字即可。要求每个实例元件的名字必须是唯一的。3 用always块语句在【例6.2】的计数器模块中always (posedge clk)/每当时钟上升沿到来时执行一遍块内语句begin if(load) out=data;else out=out+cin;endalways块可用于产生各种逻辑,常用

8、于描述时序逻辑。这个例子用always块生成了一个带有同步置数的计数器。always块可用很多种描述手段来表达逻辑,如此例中就用了if-else语句来表达逻辑关系。综上所述,可给出Verilog HDL模块的模板如下:Verilog HDL模块的模板(仅考虑用于逻辑综合的部分,不考虑用于逻辑模拟的部分)。module <顶层模块名>,(<输入输出端口列表>);output输出端口列表;/输出端口声明input输入端口列表; /输入端口声明/* 定义数据,信号的类型,函数声明,用关键字wire,reg,funtion等定义 */使用assign语句定义逻辑功能wire 结

9、果信号名;assign <结果信号名> = <表达式>/使用 always块描述逻辑功能always (<敏感信号表达式>) begin/ 过程赋值 / if语句,/ case语句 / while,for,repeat循环语句 / function调用end/ 模块元件例化< module_name模块名>,<instance_name例化元件名>,(<port_list端口列表>);/ 门元件例化gate_type_keyword <instance_name例化元件名> (<port_list>

10、);endmodule6.2 数据类型及常量、变量 Verilog HDL中共有19种数据类型。数据类型是用来表示数字电路中的数据存储和传送单元的。在此介绍4个最基本的数据类型: integer型、parameter型、reg型和wire型。Verilog HDL中也有常量和变量之分,他们分属以上这些类型。6.2.1 常量 在程序运行过程中,其值不能被改变的量称为常量。1. 数字 (1)整数 在Verilog HDL中,整数型常量(即整常数)有以下4种进制表示形式: 二进制整数(b或B); 十进制整数(d或D); 十六进制整数(h或H); 八进制整数(o或O)。 完整的数字表达式为: <

11、位宽>'<进制> <数字>, 位宽为对应二迸制数的宽度,如:8'b11000101 /位宽为8位的二进制数11000101; 8'hc5 /位宽为8位的十六进制数c5; 十进制的数可以缺省位宽和进制说明,如: 197 /代表十进制数197 (2)x和z值 x表示不定值,z表示高阻值。每个字符代表的宽度取决于所用的进制,例如: 8'b1001xxxx; 等价于8'h9x; 8'b1010zzzz; 等价于8'haz;当常量不说明位数时,默认值为32位。此外,“?”是高阻态的z的另一种表示符号。2常量 在Veri

12、log HDL中,用parameter来定义常量,即用parameter来定义一个标志符,代表一个常量,称为符号常量。其定义格式如下:parameter 参数名1=表达式,参数名2=表达式,参数名3=表达式;例如:parameter sel=8,code=8'ha3;/分别定义参数sel为常数8(十进制),参数code为常数a3(十六进制)6.2.2 变量 变量是在程序运行过程中其值可以改变的量。变量分为两种:一种为网络型(nets type),另一种为寄存器型(register type)。1. nets型变量 wirenets型变量指输出始终根据输入的变化而更新其值的变量,它一般指

13、的是硬件电路中的各种物理连接。Verilog HDL中提供了多种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语句赋值的组合逻辑信号。Verilog HDL模块中的输入/输出信号类型缺省时自动定义

14、为wire型。Wire型信号可以用作任何方程式的输入,也可以用作assign语句和实例元件的输出,其取值为0,1,x,z。wire型变量格式如下 :定义宽度为1位的变量:wire 数据名1,数据名2,数据名n;例如:wire a,b;/定义了两个宽度为1位wire型变量a,b定义宽度位n位的向量(vectors):wiren-1:0 数据名1,数据名2,数据名n;或 wiren:1 数据名1,数据名2,数据名n;例如:wire7:0 databus;/定义一个8位wire型向量或wire8:1 databus;wire型向量可按以下方式使用:wire7:0 in,out;/定义两个8位wire

15、型向量in,outassign out=in;若只使用其中某几位,可直接指明,注意宽度要一致。如:wire7:0 out;wire3:0 in;assign out5:2=in;/out向量的第二位到第5位与in向量相等2. register型变量 regregister型变量对应的是具有状态保持作用的电路元件,如触发器、寄存器等。register型变量与nets变量的根本区别在于:register需要被明确地赋值,并在被重新赋值前一直保持原值。在设计中必须将寄存器型变量放在过程块语句(如initial,always)中,通过过程赋值语句赋值。另外,在always过程块内被赋值的每一个信号都必

16、须定义成寄存器型。Verilog HDL中,有4种寄存器型变量,见表6.2表6.2常用的register型变量及说明类型功能说明reg常用的寄存器型变量integer32位带符号整数型变量real64位带符号整数型变量time无符号时间变量Integer、real、time等3种寄存器型变量都是纯数学的抽象描述,不对应任何具体的硬件电路。reg型变量是最常用的一种寄存器型变量,下面介绍reg型变量。 reg型变量格式如下: reg 数据名1,数据名2,数据名n;例如: reg a,b; /定义了两个宽度为1位的reg型变量a,b若定义一个向量,则按以下格式:regn-l:0数据名1,数据名2,

17、数据名n;或regn:l数据名1,数据名2,数据名n;它们定义了数据的宽度为n位。如下面的语句定义了8位宽的数据例如:reg7:0 data; /定义data为8位宽的reg型向量或:reg8:1 data;3. 数组 若干个相同宽度的向量构成数组,reg型数组变量即为memory型变量,即可定义存储器型数据。如: reg7:0 mymeml023:0;上面的语句定义了一个1024个字节、每个字节宽度为8位的存储器。通常,存储器采用如下方式定义:parameter wordwidth=8,memsize = l024;regwordwidth-l:0 mymemmemsize-l:0;上面的语

18、句定义了一个宽度为8位、1024个存储单元的存储器,该存储器的名字是mymem,若对该存储器中的某一单元赋值的话,采用如下方式:mymem8=1; /mymem存储器中的第8个单元赋值为1注意: Verilog HDL中的变量名、参数名等标记符是对大小写字母敏感的。6.3 运算符及表达式6.3.1 运算符1. 算术运算符+加-减*乘/除%求模算术运算符都是双目运算符。2. 逻辑运算符&& 逻辑与| 逻辑或! 逻辑非3. 位运算符位运算是将两个操作数按对应位进行逻辑运算。位运算符包括- 按位取反& 按位与| 按位或 按位异或, 按位同或当两个不同长度的数据进行位运算时,会

19、自动地将两个操作数按右端对齐,位数少的操作数会在高位用0补齐。4. 关系运算符<小于< =小于或等于>大于> =大于或等于在进行关系运算时,如果声明的关系是假,则返问值是0;如果声明的关系是真,则返回值是1;如果某个操作数的值不定,则其结果是模糊的,返回值是不定值。5. 等式运算符= = 等于!= 不等于= = = 全等!= = 不全等这4种运算符都是双目运算符,得到的结果是1位的逻辑值。如果得到1,说明声明的关系为真;如得到0,说明声明的关系为假。相等运算符(= =)和全等运算符(= = =)的区别是参与比较的两个操作数必须逐位相等,其相等比较的结果才为l,如果某些位

20、是不定态或高阻值,其相等比较得到的结果就会是不定值。而全等比较(= = =)是对这些不定态或高阻值的位也进行比较,两个操作数必须完全一致,其结果才为1。否则结果是0。如:设寄存器变量a=5'b110x01,b=5'11x01,则“a= = b”得到的结果为不定值x,而“a= = =b”得到的结果为l。6. 缩减运算符(单目运算)&与 &与非|或 |或非异或 , 同或缩减运算符与位运算符的逻辑运算法则一样,但缩减运算是对单个操作数进行与、或、非递推运算的。如:reg3:0 a;b=&a;/等效于b=(a0&a1)&a2)&a3; 例

21、:若A=5'b11001,则:&A=0;/只有A的各位都为1时,其与缩减运算的值才为l。|A=l;/只有A的各位都为0时,其或缩减运算的值才为0。7. 移位运算符>>右移<< 左移移位运算符用法:A >> n或 A<< n 表示把操作数A右移或左移n位,并用0填补移出位。8. 条件运算符(三目运算符)?:格式:信号 = 条件 ? 表达式1:表达式2; 当条件成立时,信号取表达式1的值,反之取表达式2的值. 9.位拼接运算符 /将两个或多个信号的某些位拼接起来。用法:信号1的某几位,信号2的某几位,,信号n的某几位例如,在进行加法运

22、算时,可将输出与和拼接在一起使用。output3:0 sum; /sum代表和output cout; /cout为进位输出input3:0 ina,inb;input cin;assign cout,sum=ina+inb+cin; /进位与和拼接在一起位拼接可以嵌套使用,还可以用重复法来减化书写,如:3a,b等同于a,b,a,b,a,b,也等同于a,b,a,b,a,b。6.3.2. 运算符的优先级以上运算符的优先级如下:!,高优先级*,/,%+,-<< , >>< , < = , > , > = = , != , = = = , != =&a

23、mp; , & , | , | &&|? : 低优先级6.4 语句Verilog HDL支持许多语句,从而成为结构化和过程性的语言。Verilog HDL的语句包括:赋值语句、条件语句、循环语句、结构说明语句和编译预处理语句等。每一类又包括几种不同的语句,具体如表6.3所示。表6.3 Verilog HDL语句赋值语句连续赋值语句过程赋值语句条件语句if-else语句case语句 循环语句forever语句repeat语句while语句for语句结构说明语句initial语句always语句function语句编译预处理语句'define语句'inclu

24、de 语句'timescale语句6.4.1 赋 值 语 句1. 连续赋值语句 assignassign为连续赋值语句,它用来对wire型变量进行赋值。格式:assign 变量 = 表达式;如: assign c = a & b;在上面的赋值中,a和b信号的任何变化,都将随时反映到c上来,因此称为连续赋值方式。2. 过程赋值语句过程赋值语句用于对寄存器类型(reg)的变量进行赋值。过程赋值有以下两种方式。(1)非阻塞(non_blocking)赋值方式赋值号为 <= ,如 b<=a; 非阻塞赋值在块结束时才完成赋值操作,即b的值并不是立刻就改变的。(2)阻塞(blo

25、cking)赋值方式赋值号为 = ,如 b=a;阻塞赋值在该语句结束时就完成赋值操作,即b的值在该赋值语句结束后立刻改变。如果在一个块语句中,有多条阻塞赋值语句,那么在前面的赋值语句没有完成之前,后面的语句就不能执行,就像被阻塞(blocking)一样,因此称为阻塞赋值方式(3)阻塞赋值方式和非阻塞赋值方式的区别阻塞赋值方式和非阻塞赋值方式的区别常给设计人员带来问题。问题主要是对“always”模块内的reg型变量得赋值不易把握。为区分阻塞赋值与非阻塞赋值的不同,可看下面两例。【例6.4】非阻塞赋值 【例6.5】阻塞赋值module non_block(c,b,a,clk); module b

26、lock(c,b,a,clk);output c,b; output c,b;input clk,a; input clk,a;reg c,b; reg c,b;always (posedge clk) always (posedge clk) begin begin b<=a; b=a; c<=b; c=b; end endendmodule endmodule将上面两段代码用MAX+PLUS进行综合,并进行仿真,可看到二者的区别:对于非阻塞赋值,c的值落后b的值一个时钟周期,这是因为该“always”块每一个时钟周期执行一次,因此信号的值每一个时钟周期更新一次,c的值是上一时钟

27、周期的b值。对于阻塞赋值,c的值和b的值一样,这是因为b的值是立即更新的。为避免对这两种赋值语句的应用错误,建议在初学时刻只是用一种,比如采用阻塞赋值“=”,因为它类似C语言的赋值方式。为避免出错,在同一块内,不要将输出重新作为输入使用。而为实现上述非阻塞赋值功能,可采用两个“always”块来实现,代码如下:module non_block(c,b,a,clk); output c,b;input clk,a; reg c,b; always (posedge clk) begin b=a; end always (posedge clk) begin c=b; end endmodule

28、6.4.2 条件语句条件语句是顺序语句,应放在“always”块内。1. if-else语句使用方法有以下3种 if(表达式) 语句; if(表达式1) 语句1;else 语句2; if(表达式1) 语句1;else if(表达式2) 语句2;else if(表达式3) 语句3;else if(表达式n) 语句n;else 语句n+1;这三种方式中,“表达式”一般为逻辑表达式或关系表达式,也可能是一位变量。若表达式的值为0,x,z,视为“假”;若为1,视为“真”。语句可以是单句,也可以是多句,多句时用“begin-end”括起来。2. case语句多用于多条件译码电路,如描述译码器、数据选择器

29、、状态机及微处理器的指令译码等。. case语句格式:case (敏感表达式)值1:语句1;值2:语句2;值n:语句n;default: 语句n+1;endcase. casez和casex语句case 语句中,敏感表达式与值1值n之间的比较是一种全等比较,必须保证两者的对应位全等。 casez与 casex语 句是case语句的两种变体,三者的表示形式中唯一的区别是3个关键词case,casez,casex的不同。在casez语句中,如果分支表达式某些位的值为高阻z,那么对这些位的比较就不予考虑,因此,只需关注其他位的比较结果。而在casex语句中,则把这种处理方式进一步扩展到对x的处理,即

30、如果比较的双方有一方的某些位的值是x或z,那么这些位的比较就不予考虑。此外,还有另外一种标识x或z的方式,即用表示无关值的“?”来表示。6.4.3 循环语句Verilog HDL中存在4种类型的循环语句,用来控制语句的执行次数。这4种语句分别为: foreve 连续地执行语句,多用在"initial"块中,以生成周期性输入波形。 repeat 连续执行一条语句n次。 while 执行一条语句,直到循环条件不满足。 for 语句由于MAX+PLUS 软件不支持repeat语句。forever语句一般用在initial语句块中,而MAX+PLUS 软件不支持initial语句块

31、,因此这里只介绍for和while两种语句。1for语句格式:for(表达式1;表达式2;表达式3)语句;即:for (循环变量初值;循环结束条件;循环变量增值) 执行语句; 2while语句格式:while(循环执行条件表达式) 语句;while语句执行时,首先判断循环执行表达式是否为真,若为真,执行循环体中语句,然后,再判断循环执行条件表达式是否为真,直至条件表达式不为真为止。循环体中语句可以是单句,也可以是多句,多句时用“begin-end”括起来。6.4.4 结构说明语句Verilog HDL中的任何过程模块都从属于以下4种结构说明语句:initialalwaystaskfunctio

32、ninital说明语句一般用于仿真中的初始化,仅执行一次;always块内的语句则是不断重复执行的;task和function语句可以在程序模块中的一处或多处调用。由于MAX+PLUS 软件不支持task,initial语句, 因此这里只介绍always和function两种结构说明语句1always块语句always块语句模板如下:always(<敏感信号表达式>)begin/过程赋值/if语句/case语句/while,repeat,for循环/task,function调用end在一个模块(module)中,使用always语句的次数是不受限制的。always块内的语句是不断

33、重复执行的。说明:敏感信号表达式敏感信号表达式又称事件表达式或敏感表,当该表达式的值改变时,就会执行一遍块内语句。因此在敏感信号表达式中应列出影响块内取值的所有信号(一般为所有输入信号)。若有两个或两个以上信号时,它们之间用"or"连接。 例如,下面用case语句描述的4选1数据选择器,只要输入信号in0,inl,in2,in3或选择信号sel1:0改变则输出改变,所以敏感信号表达式写为:in0 or in1 or in2 or in3 or sel 【例6.6】用case语句描述的4选1数据选择器module mux4_1(out,in0,in1,in2,in3,sel)

34、;output out;input in0,in1,in2,in3;input1:0 sel;reg out;always (in0 or in1 or in2 or in3 or sel)case(sel)2b00: out=in0;2b01: out=in1;2b10: out=in2;2b11: out=in3;default: out=2bx;endcaseendmodule posedge与 negedge关键字对于时序电路,事件是由时钟边沿触发的。为表达边沿这个概念,Verilog HDL提供了posedge和negedge两个关键字来描述。比如在例6.2的8位计数器中有块语句:a

35、lways (posedge clk) /上升沿时刻计数posedge clk表示时钟信号clk的上升沿,negedge clk表示时钟信号clk的下降沿。2. 函数 function 函数的目的是返回一个用于表达式的值。函数的定义格式为:function <返回值位宽或类型说明> 函数名;端口声明;局部变量定义;其他语句;endfunction【例6.7】函数举例function7:0 gefun;input7:0 x;reg7:0 count;integer i;begincount=0;for(i=0;i<=7;i=i+1)if(xi=1b0) count=count+

36、1;gefun=count;endendfunction 上面的gefun函数循环核对输人的每一位,计算出0的个数,并返回一个适当的值。<返回值位宽或类型说明>是一个可选项,如果缺省,则返回值为一位关于寄存器类型的数据。函数的定义中蕴含了一个与函数同名的、函数内部的寄存器。在函数定义时,将函数返回值所使用的寄存器设为与函数同名的内部变量,因此函数名被赋予的值就是函数的返回值。例如在上例中,gefun最终赋予的值即为函数的返回值。函数的调用是通过将函数作为表达式中的操作数来实现的。调用格式如下:<函数名>,(<表达式> <表达式>);比如使用连续赋值语句调用函数gefun时,可以采用如下语句:assign out=is_legal ? gefun(in) : 1'b0;注意,在函数中不能包含有任何的时间控制语句,并且定义函数时至少要有一个输人参量。6.5 语句的顺序执行和并行执行 用Verilog HDL模块来设计电路,首先应该清楚哪些操作是同时发生的,哪些是顺序发生的。在“always”模块内,逻辑是按照指定的顺序执行的,"always"块内的语句

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论