《第4章VerilogHDL基本语法.ppt》由会员分享,可在线阅读,更多相关《第4章VerilogHDL基本语法.ppt(152页珍藏版)》请在三一办公上搜索。
1、第4章 Verilog HDL 基本语法,4.1 Verilog 简介硬件描述语言(Hardware Description Language,HDL)是电子系统硬件(1)行为描述、(2)结构描述、(3)数据流描述的一种语言。,数字电路系统的设计者通过这种语言a可以从上层到下层,从抽象到具体,逐层次地描述自己的设计思想,b用一系列分层次的模块来表示极其复杂的数字系统,C然后利用模块组合经由自动综合工具转换到门级电路网表,d再用自动布局布线工具把网表转换为具体电路进行布局布线后,e下载到专用集成电路(ASIC)或现场可编程逻辑器件。,4.1.1 Verilog HDL发展过程Verilog HD
2、L语言最初是于1983年由Gateway Design Automation公司为其模拟器产品开发的硬件建模语言。Verilog 语言于1995年成为IEEE标准,称为IEEE Std 13641995;2001年又发布了Verilog HDL1363-2001标准;随即在2005年又发布了System Verilog 1800-2005标准,这一系列标准的制定使得Verilog语言在综合、仿真、验证及IP重用等方面有很大幅度的提高。Verilog HDL 是System Verilog语言的基础。SystemVerilog结合了来自 Verilog、VHDL、C+的概念,它将硬件描述语言(H
3、DL)与现代的高层级验证语言结合了起来。System Verilog加入了一些C+的元素。近些年在国内Verilog的应用率显著增加,国内绝大多数IC设计公司都采用Verilog HDL。学习Verilog不仅可以对数字电路技术有更进一步的了解,而且可为以后学习高级的行为综合、物理综合、IP设计和复杂系统设计打下坚实的基础。,4.1.2 Verilog HDL 与C语言比较,C语言与Verilog HDL运算符基本相同。而C语言是一种在硬件上运行的语言,而Verilog是描述硬件的语言,要受到具体硬件电路的限制,它们的区别如下:在Verilog HDL中不能使用C语言中很多抽象的表示方法,如迭
4、代表示法、指针(C语言最具特点的语法)、不确定的循环及动态声明等等。C语言是一行一行地执行,按顺序执行;而Verilog HDL描述的是硬件,可以在同一时间内有很多硬件电路一起并行执行,两者之间有区别。C语言的输入/输出函数丰富,而Verilog HDL 能用的输入/输出函数很少。C语言无时间延迟的指定,而Verilog HDL可以指定时间延迟。C语言中函数的调用是唯一的,每一个都是相同的,可以无限制调用。而Verilog HDL对模块的每一次调用都必须赋予一个不同的别名,虽然调用的是同一模块实例,但不同的别名代表不同的模块,即生成了新的硬件电路模块。与C语言相比,Verilog HDL描述语
5、法较死,限制较多,能用的判断叙述有限。Verilog HDL中的延时语句只能用于仿真,不能被综合工具所综合。,4.2 Verilog HDL设计举例1、1位比较器的三种不同风格Verilog HDL程序设计【例4.2.1】1位比较器的Verilog HDL程序。通过对输入信号A,B的比较,把比较的结果反映到m,L,e端口。,2、测试模块例子Verilog HDL可以用来描述变化的测试信号,它给出模块的输入信号,通过观测被测试模块是否符合要求,可以调试和验证逻辑系统设计和结构的正确性,并能发现问题及时修改。,每一项工程是由大量功能各异的模块组合而成的。模块是由两部分组成的:(1)一部分是接口描述
6、(该模块与其他外部模块进行通信的端口),(2)另一部分是逻辑功能描述(描述某个设计的功能或者结构),即定义输入是如何影响输出的。模块可以进行层次嵌套,将大型的数字电路设计分割成不同的小模块来实现特定的功能,最后通过顶层模块调用子模块来实现整体功能。,4.3 Verilog 模块的结构,一个模块,由module1.模块名(module_name)2端口列表(port_list)3端口声明(input、output、inout)4变量声明(reg、wire、parameter)5行为描述语言(initial、always)6连续赋值语句(continuous assignment)7模块调用语句(
7、module instantiation)8任务及函数(task、function)endmodule在模块的所有组成部分中,只有module、模块名和endmodule必须出现,其它部分都是可选的,模块:verilog模块的部件,作用:端口是模块与外界交互的接口;于外部环境(使用者/连接者)来讲,模块内部 不可见,对模块的调用只能通过其端口进行。,举例:module sr_latch(q,qbar,sbar,rbar);说明:被处理信号(数据)从sbar,rbar进入模块,处理结果从q,qbar端口送出,这样它可被外界调用;,(2)实例引用,4.2 I/O说明常见I/O口类型有1.输入口(i
8、nput)2.输出口(output)3.双向口(inout),分别表示数据流的方向是输入,输出或双向的。,常用到的是assign语句和always块语句。1.assign语句-数据流描述风格的主要建模语句,通常用来描述组合逻辑。assign声明语句很简单,只需要写一个“assign”(赋值),后面再加一个方程式即可。例如:assign sa 该语句描述了一个三输入的与门,这是一个组合逻辑。注意:s的数据类型只能是wire类型。,4.4、功能描述,2.always块-行为级建模的主要语句 既可以用来描述组合逻辑,也可以用来描述时序逻辑。从字面上理解,always的意思是“总是,永远”。在Veri
9、log HDL中,只要指定的事件发生,由always指定的内容将不断地重复运行,不论该事件已经发生了多少次。这恰恰反映了实际电路的特征,即在通电的情况下电路将不断运行。最常用的两种事件是电平触发和边沿触发。电平触发是指当某个信号的电平发生变化时,执行always指定的内容;边沿触发是指当某个信号的上升沿或下降沿到来时,执行always指定的内容。电平触发的写法是在“”后面直接写触发信号的名称;边沿触发的写法是在“”后面写“posedge 信号名”或者“negedge 信号名”,posedge代表信号的上升沿,negedge则代表信号的下降沿。,4.5 模块调用-结构级建模的主要语句,4.4 V
10、erilog HDL语言要素与表达式介绍Verilog语法中的注释、常量、变量、操作符、字符串、关键字和标识符等基本语法要素。4.4.1 注释在代码中插入注释可以有效地增加程序的可读性,也便于文档管理。Verilog HDL允许单行注释和多行注释。单行注释以“/”开始,直到行末结束;多行注释以“/*”开始,以“*/”结束。这两种注释的方法和C+的注释方式相同。,4.4.2 常量1、数字(1)整数 有以下4种进制表示形式:二进制整数(b或B)、十进制整数(d或D)、十六进制整数(h或H)、八进制整数(o或O)。数字表达方式主要有三个部分:位宽、进制和数字。位宽指数字常量的二进制宽度,进制表示数字
11、的类型。,数字表达方式一共有三种:位宽 进制 数字,这种方式描述数字最为完整;进制 数字,这种描述方式省略了位宽,在这种情况下,数字的位宽采用系统默认位宽(由系统决定,至少是32位)数字,这种描述方式省略了位宽和进制信息,采用默认的位宽和进制(十进制)。例如:8b00101000/位宽为8的二进制表示,b表示二进制,(2)负数 数字同样也可以定义为负数,只需要在位宽表达式前面加一个减号。(3)x和z值 Verilog语法中,有x和z两种特殊值。在数字电路中,x代表不定值,z代表高阻值。在不同进制中,x和z表示的不定值或高阻值的位数不同。例如:4bx1x0/位宽为4的二进制数从低位数起的第二位和
12、第四位为不定值,(4)下画线 为了提高程序的可读性,尤其在使用二进制表示较长的数字常量的时候,我们可以使用下划线将数字分隔开来。例如:16 b0010_0100_1101_0001/合法格式,2、参数声明用parameter来定义常量,称为符号常量,即标识符形式常量,采用标识符代表一个常量可以提高程序的可读性和可维护性。参数的声明格式:parameter 参数名1=常数表达式1,参数名2=常数表达式2,;例如:parameter ALL_X=16bx;/定义参数ALL_X为常数16bxparameter state0=2b00,/定义参数state0为常数2b00,4.4.3 变量变量是在程序
13、运行过程中其值可以改变的量。1、线网类型线网类型可以理解为实际电路中的导线,通常用于表示结构实体之间的物理连接。,2、寄存器变量类型寄存器变量类型主要有以下6种:reg,integer,time,real,realtime,memory型。(1)寄存器是数据储存单元的抽象,寄存器数据类型的关键字是reg。,reg型变量定义格式如下:reg signed 最高位:最低位 寄存器名1,寄存器名2,寄存器名N;其中,signed表示数值为有符号数(以二进制补码形式保存),默认情况下为无符号数。例如:reg 3:0 bus;/定义了一个4位的名为bus 的reg型变量,总之,1.wire表示直通,即只
14、要输入有变化,输出马上无条件地变化;reg 一定要有触发,输出才会反映输入。2.wire只能被assign连续赋值,reg只能在initial和always中赋值。3.wire使用在连续赋值语句中,而reg使用在过程赋值语句中。,(2)使用integer、real、time关键字定义寄存器变量和使用reg进行定义并没有本质上的区别,仅仅是为了使程序的表述更加清晰明了。integer、real、time型变量的位宽是固定的,integer型变量的位宽为32,real型变量的位宽为64,time real型变量的位宽为64,它们已经是矢量,因此在定义变量时不可以加入位宽。如integera1,b1
15、;/定义a1、b1为32位整型变量,(3)memory型数据 可以通过reg型变量建立数组来对存储器建模,可以描述RAM型存储器、ROM存储器和reg文件。数组中的每一个单元通过一个数组索引进行寻址。memory型变量定义格式如下:reg 最高位:最低位 存储器名 最高位:最低位;下面举例说明:reg 7:0 mema 0:255;,4.4.4 操作符,1、算术运算符,算术运算符有+(加法符号,正值符号)、(减法符号,负值符号)、*(乘);/(除)、%(取模)、*(指数幂)6种。例如:reg1reg2/“”为加法符号-num/“-”为负值符号9/4/9除以4结果为2-/-5模以2结果为-1,取
16、第一个操作数的符号值2*4/2的4次方算术运算中任意一个操作符中含有一位或多位不确定值x或z,则整个运算结果为x。例如:4b10 x04b0001 结果为4bxxxx;,2、位运算符Verilog 作为一种硬件描述语言,是针对硬件电路而言的。硬件电路中信号有1,0,x,z。在硬件电路中信号进行与、或、非时,反映在Verilog中则是相应的操作数的位运算。Verilog 位运算符有(取反)、&(按位与)、|(按位或)、(按位异或)、,(按位同或)5种。,(3)逻辑运算符Verilog中逻辑运算符有&(逻辑与)、|(逻辑或)、!(逻辑非)三种。逻辑运算符只对逻辑0(定义为假)、1(定义为真)或者x
17、(逻辑关系不明确,未知)进行操作,操作产生的结果通常也只为0或1。,4、关系运算符关系运算符共有(大于)、(小于)、(大于等于)、(小于等于)4种。关系操作符的结果如果为真(ture),则返回值为1;结果如果为假(false),则返回值为0;如果操作数中有一个或多个含有不定值x和z,则逻辑为模糊,返回值为x。,5、等式运算符等式运算符有(等于)、!(不等于)、(全等于)、!(不全等于)4种。在全等比较(“”,“!”)中,不考虑实际物理意义,把 1,0,x,z均当做数值来进行比较,若全等结果为1,否则结果为0,它们常用于case表达式的判别,所以又称为“case等式运算符”;而在逻辑比较(“”,
18、“!”)中,若操作数中出现x或z,则结果很可能是不确定值x。,6、移位运算符 移位操作符有(逻辑左移运算符)、(逻辑右移运算符)、(算术左移运算符)、(算术右移运算符)4种。,7、位拼接运算符位拼接运算符可以把两个或多个信号的某些位拼接起来,其使用方法如下:expr1,expr2,expr3,exprN拼接运算符是把位于大括号“”中的两个或两个以上用逗号“,”分隔的小表达式按位连接在一起,形成一个大的表达式。,8、缩减运算符缩减运算符的操作数只有一个,并且只产生1位数据结果。缩减运算符运算有&(缩减与)、|(缩减或)、&(缩减与非)、|(缩减或非)、(缩减异或)、(缩减同或)六种。缩减运算符是
19、对单个操作数进行与、或、非递推运算,最后的运算结果是1位二进制数。缩减运算的具体运算过程是:第一步先将操作数的第1位与第2位进行与、或、非运算;第二步将运算结果与第3位进行与、或、非运算,依次类推,直到最后1位。,9、条件运算符条件运算符是一个三目运算符,其格式如下:条件表达式?表达式1:表达式2条件运算符根据条件表达式的值从两个表达式中选择一个表达式,若条件表达式为1,则执行表达式1;若条件表达式为0,则执行表达式2。,4.4.5 字符串、关键字、标识符1、字符串字符串是用双引号括起来的字符序列。2、关键字关键字是Verilog HDL预留的定义语言结构的特殊标识,全部由小写字母定义。3、标
20、识符标识符是模块、变量、端口、实例、块结构、函数等对象的名称,程序通过标识符访问相应的对象。,4.5 赋值语句Verilog HDL有两种为变量赋值的方法,一种叫做连续赋值(Continuous Assignment),另一种叫做过程赋值(Procedural Assignment)。过程赋值又分为阻塞赋值(Blocking Assignment)和非阻塞赋值(Nonblocking Assignment)。,4.5.1 连续赋值assign语句-是verilog数据流建模的基本语句,2.最基本的格式:assign#延时量 线网型变量名 赋值表达式3.赋值表达式可以是 a.标量 b.向量线网
21、c.向量寄存器 d.函数调用;被赋值的目标变量可以是a.线网变量 b.多个线网的拼接4.执行过程:连续赋值语句总是处于激活状态,只要右侧表达式中的任意一个操作数发生变化,表达式就会被立即重新计算,并且将结果赋值给对象。5.例如:/线网声明wire flag_tag;reg7:0 Data_byte;/连续赋值语句assign flag_tag&Data_byte,描述组合电路的主要手段,1.连续赋值是为线网型的变量提供驱动的一种方法,它只能为线网型变量赋值,并且线网型变量也必须用连续赋值的方法赋值。,普通赋值延迟,在连续赋值语句中说明延迟值,延迟值位于关键字assign的后面。assign#1
22、0 out=in1,6.2延迟,1.普通赋值延迟(惯性延迟)assign#10 out=in1,而有一些连续赋值语句有时延:assign#5 A_rst=gate_a 图4.5.1举例说明了时延的概念,A_rst是右端表达式的传输前的计算值。,4.5.2 过程赋值过程赋值提供了为寄存器型变量赋值的方法,出现的位置是在各种块结构中,例如always块、initial块等。过程赋值又分为阻塞赋值和非阻塞赋值两种。1、阻塞赋值阻塞赋值使用“=”为变量赋值,如a=b;在赋值结束以前不可以进行其它操作,在赋值结束后才继续后面的操作。这个过程好像阻断了程序的运行,因而被称为阻塞赋值。,阻塞赋值语句,阻塞赋
23、值方式(使用“=”为变量赋值,如a=b,在每个右端表达式计算完后立即赋给左端变量,也就是在该语句结束时就完成了赋值操作):赋值按顺序执行,只有上一条语句执行完成(赋值结束),才会执行(赋值)下一条语句;在赋值结束以前不可以进行其它操作,在赋值结束后才继续后面的操作。这个过程好像阻断了程序的运行,因而被称为阻塞赋值。显然,连续的阻塞赋值操作是顺序完成的。,阻塞过程性赋值所综合出来的电路为并接方式。,【例4.5.1】阻塞赋值举例。always(posedge clk)beginb=a;c=b;end,4位阻塞赋值程序reg_bpa.vmodule reg4_bpa(qout,clk,reset,d
24、in);output 3:0 qout;input clk,reset;input din;reg 3:0 qout;always(posedge clk or posedge reset)/上升沿clk异步复位reset if(reset)qout=4b0000;else begin qout0=din;qout1=qout0;qout2=qout1;qout3=qout2;endendmodule,2、非阻塞赋值非阻塞赋值使用“=”为变量赋值,在执行到连续的非赋值语句时,仅仅对“=”右端表达式进行评估,但并不立即赋值给左端,然后继续执行后面的操作,当块结构结束后所有的非阻塞赋值同时进行赋值
25、。这个过程好像没有阻断程序的运行,因而被称为非阻塞赋值。,非阻塞赋值语句,非阻塞赋值方式(“=”,在块结束时才完成赋值操作):所有语句的赋值都发生在当前仿真的最后一个时间步,赋值是并行执行的。执行步骤:(1)读取操作数,计算右侧表达式的值并保存在临时变量中;(2)对左侧的赋值由仿真器调度到相应的仿真时刻;(3)每个赋值操作在被调度的仿真时刻完成。典型应用:流水线建模 互斥数据传输问题:仿真速度下降 内存使用量增加,非阻塞过程性赋值所综合出来的电路为串接方式。,4位非阻塞赋值程序reg_nbp.vmodule reg4_nbp(qout,clk,reset,din);output 3:0 qou
26、t;input clk,reset;input din;reg 3:0 qout;always(posedge clk or posedge reset)/上升沿clk或异步复位reset if(reset)qout=4b0000;else begin qout0=din;qout1=qout0;qout2=qout1;qout3=qout2;endendmodule,3、使用阻塞赋值与非阻塞赋值语句的注意事项阻塞赋值语句的操作符为“=”,非阻塞赋值语句的操作符为“=”多条阻塞赋值语句是顺序执行的,而多条非阻塞赋值语句是并行执行的;在使用always块描述组合逻辑时,采用阻塞赋值;在使用alw
27、ays块描述时序逻辑时使用非阻塞赋值。在赋值时不要使用0延迟。不要在同一个always块中同时使用非阻塞赋值和阻塞赋值;无论是使用阻塞赋值和非阻塞赋值,不要在多个always块中为同一个变量赋值;,4.5.3 连续赋值和过程赋值的不同,4.6 块语句4.6.1 顺序语句块(begin-end)顺序语句块的语法如下:begin:标识符语句1;语句2:end,4.6.2 并行语句块(forkjoin)forkjoin之间也可以添加多条语句,这些语句的关系是并行的,是同时执行的,即程序流程控制一进入到该并行块,块内的语句则同时并行地执行。,并行语句块语法如下:fork:标识符语句1;语句2:join
28、,【例4.6.3】利用并行语句块(forkjoin)生成波形。fork#1 waves=1;#4 waves=0;#9 waves=1;#11 waves=0;#15 waves=1;#18 waves=0;join,4.6.3 起始时间和结束时间顺序块和并行块中都有一个起始时间和结束时间的概念。对于顺序块,起始时间就是第一条语句开始被执行的时间,结束时间就是最后一条语句执行完的时间。而对于并行块来说,起始时间对于块内所有的语句是相同的,即程序流程控制进入该块的时间,其结束时间是执行时间最长语句的执行结束的时间。,4.7 条件语句Verilog HDL 有2种实现条件结构的方法,一种是ifel
29、se语句,另一种是case语句。这和C语言非常类似,但这仅仅是表面现象。设计人员在用Verilog HDL进行编程时,应该时时刻刻牢记自己设计的是电路,而不是软件,只有这样才能掌握这门硬件描述语言。,4.7.1 if-else语句Verilog HDL的if-else语句常用的使用方式有三种:(1)if(条件表达式)操作1;else 操作2;这是最基本的形式,由一个if分支和一个else分支组成。系统将对条件表达式的值进行判断,若为1,按真处理,则执行操作1;若为0,x,z,按假处理,则执行操作2。,(2)if(条件表达式)操作;这种形式是第一种的简化形式。(3)if(条件表达式1)操作1;e
30、lse if(条件表达式2)操作2;else 操作N;,【例4.7.1】如果ab成立,out=1;否则out=0。if(ab)out=1;else out=0;,4.7.2 case 语句当分支有很多时,选用Verilog中的case语句,定义如下:case(控制表达式)分支表达式1:操作1;分支表达式2:操作2;分支表达式n:操作n;default:操作n+1;endcase,【例4.7.3】case 语句举例1。case(in)1b 0:out=a;1b 1:out=b default:out=1bz;/这里给一个默认值endcase,【例4.7.4】case 语句举例2。always(p
31、osedge clk)begin out=out;case(sel)/synopsys full-case 2b00:out=a;2b10:out=b;2b01:out=c;endcase end,和case语句功能相似的还有casex和casez语句。这两条语句用于处理在条件表达式和分支项的比较过程中存在x或者z的情况,casez语句将忽略比较过程中的值为z的位,而casex语句将忽略比较过程中的值为x或z的位。表4.7.1、表4.7.2、表4.7.3 所示是case、casez和casex语句的真值表。,4.7.3 比较if else嵌套与 case 语句,4.8 循环语句 Verilog
32、 HDL中有for循环语句、forever循环语句、repeat 循环语句、while 循环语句4类循环语句,用来控制执行语句的执行次数。,4.8.1 for循环语句Verilog HDL中for循环语句跟C语言中for循环语句的语法几乎一样,容易被学习过C语言的设计人员所接受。其格式如下:(1)for(循环变量赋初值;循环终止条件;更新循环变量)循环执行语句;(2)for(循环变量赋初值;循环终止条件;更新循环变量)begin 语句;end,在使用for循环时,需要先定义一个用于控制循环次数的变量。for语句执行过程是:(1)先求解循环变量的初值。(2)再求解循环终止条件,若其值为真(非0)
33、,则执行for语句中循环执行语句,然后执行下面的第3步;若其值为假(0),转到第5步。(3)执行更新循环变量。(4)转回第(2)步继续执行。(5)执行for语句下面的语句。,【例4.8.1】用for语句,对变量a进行加4操作。for(i=0;i4;i=i+1)begin a=a+1;end,4.8.2 forever循环语句 forever是永远执行的语句,也就是代表无穷的循环下去,不需要声明任何变量。如果想要退出循环,必须采用强制退出循环的方法。语法形式如下:(1)forever 语句;(2)forever begin 语句;end,4.8.3 repeat循环语句repeat带有一个控制循
34、环次数的常量或者变量,是最简单的循环语句,用于已知循环次数的情况。语法形式如下:repeat(循环次数)语句;repeat(循环次数)begin 语句;end,【例4.8.3】利用repeat语句实现连续4次加1操作。repeat(4)begin a=a+1;end,4.8.4 while循环语句repeat语句只能用于固定循环次数的情况,而while语句则灵活得多,它可以通过控制某个变量的取值来控制循环次数。while循环语句的语法格式如下:while(条件表达式)语句;while(条件表达式)begin 多条语句;end,4.9 过程语句在这里我们介绍两种过程性语句 always语句和in
35、itial语句。一个程序模块可以有多个initial和 always过程块。每个initial和always语句在仿真的一开始就同时立即开始执行。initial语句只执行一次,而always语句则是不断地重复被运行着,直到仿真过程结束。但always语句后跟着的过程块是否运行,则要看它的触发条件是否满足,如满足则运行过程块一次,再次满足则再运行一次,直至仿真过程结束。,4.9.1 initial 语句initial过程块由initial语句和语句块组成,一条initial语句只执行一次,initial语句在仿真开始时开始执行,其语法格式如下:initial 语句块语句块的格式:begin 行为
36、语句1;行为语句n;end,4.9.2 always 语句always语句在仿真过程中是不断重复执行的,但always 语句后跟着的过程块是否执行,则要看它的触发条件是否满足,如满足则运行过程块一次;如不满足,则不执行语句块。其语法格式如下:always(敏感时间列表)begin 行为语句1;行为语句n;end,针对上述格式做以下说明:(1)过程语句关键词always标明该过程块是一个always过程块;(2)(敏感时间列表)是一个可选项,带有敏感时间列表的语句块的执行要受到敏感时间的控制。敏感时间列表是由一个或者多个时间表达式组成的,当存在多个时间表达式的时候用or将他们组合起来。例如:al
37、ways(negative clk or positive rst)敏感时间是clk信号的下降沿或rst信号的上升沿,此时才执行下面的语句块;(3)为可选项,用来指定延时时间。,4.10 任务与函数,4.10.1 任务Verilog HDL中的任务与高级语言的过程类似,它不带返回值,可以直接调用。尽管任务不带有返回值,但任务的参数可以定义为输出端口或者双向端口,因此实际上任务可以返回多个值。定义一个任务使用关键字task endtask。,2、调用变量的传递任务调用语句给出传入任务的参数值和接收结果的变量值。任务调用语句是过程语句,可以在always语句或initial语句中使用。形式如下:任
38、务名(端口1,端口2,端口3,端口N);,4.10.2 函数函数类似于C语言中的函数。调用函数的目的是返回一个表达式的值。因此,函数至少需要一个输入参数,且参数必须都为输入端口,不可以包含输出或者双向端口。函数有一个返回值,返回值被赋给和函数名同名的变量,这也决定了函数只能存在一个返回值。定义函数使用functionendfunction 关键字。,4.11 预编译指令同C语言一样,Verilog HDL也可以对程序进行预编译处理。预编译处理的含义就是在程序被编译之前,将需要做处理的地方按照要求进行处理,然后再进行编译。在Verilog HDL中,预编译指令都有一个明显的标志,就是以符号“”开
39、头(注意在键盘上“”通常位于数字1的左边),总的来说,预编译指令不是Verilog HDL语句,结尾不用加分号。,4.11.1 宏定义语句(define、undef)宏定义语句define指令用于文本替换,很像C语言中的#define 指令,它用一个指定的标识符来代替一个字符串。在编译之前,编译器先将程序中出现的标识符全部替换为它所表示的字符串,然后再进行编译。宏定义主要可以起到两个作用:一是用一个有意义的标识符取代程序中反复出现的含义不明显的字符型;二是用一个较短的标识符替代反复出现的较长的字符串。宏定义的一般形式为difine 标识符(宏名)字符串(宏内容),例如:define BUS_S
40、IZE 32/宏名为BUS_SIZE,宏内容为32.reg BUS_SIZE-1:0 AddReg;/BUS_SIZE在编译前被替代为32,4.11.2 文件包含语句(include)Verilgo HDL中的文件包含指令include与语言中的预编译指令#include类似,在编译时,将其他文件中的源程序完整地插入当前的文件中。这样做的结果也就相当于将其他文件中的源程序内容复制到当前文件中出现指令include的地方。include编译指令可以将一些全局通用的定义或任务包含进文件中,而不用为每个文件编写一段重复的代码。文件包含语句include的一般形式如下:include“文件名”,4.1
41、1.3 时间尺度(timescale)时间尺度指令用来定义模块的仿真时间单位和时间精度,其使用格式如下:timescale 仿真时间单位时间精度,4.11.4 条件编译指令(ifdef、else、endif)一般情况下,Verilog HDL源程序中所有的语句都将参加编译。但是有时希望对其中的一部分内容只有在满足条件时才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。,条件编译命令格式:ifdef 宏名 程序段1else 程序段2endif,【例4.10.4】条件编译指令举例。ifdef WINDOWS parameter WORD_SIZE=16else parameter
42、WORD_SIZE=32endif,4.12 本章小结本章首先介绍了Verilog HDL语言,并通过1位比较器实例展示了Verilog模块的结构和特征。其次,介绍了Verilog HDL语言的模块的结构,包括模块的端口定义、I/O说明、内部信号声明和功能定义。最后,介绍了Verilog HDL语言的基本要素,包括常量、数据类型、运算符、过程语句、块语句、赋值语句、条件语句、循环语句、任务与函数等内容。,注意:这些语句虽然在形式上和C语言很类似,语法等各方面比较容易理解,但要注意的是它们表示的不是一个直接的计算结果,而是逻辑电路硬件的行为,语句间细微的差别可能导致其对应的硬件有很大的变化。希望
43、认真理解这些语句的本质,才能设计出符合要求的逻辑。,4.13 习题模块由几部分组成,如何描述模块的端口?为什么端口要说明信号的位宽?最基本的Verilog变量有几种类型?比较reg型和wire型变量的区别?逻辑运算符与按位逻辑运算符有什么不同,它们各在什么场合使用?拼接符的作用是什么?拼接符表示的操作其物理意义是什么?阻塞和非阻塞赋值有什么不同?举例说明它们的不同点?在并行块中,如果有一条语句是无限循环,它下面的语句如何执行?使用条件语句设计一个四选一多路选择器。,10、使用while循环设计一个时钟信号发生器。其时钟信号的初值为0,周期为10个时间单位。11、怎样理解initial语句只执行一次的概念?12、怎样理解由always语句引导的过程块是不断活动的?13、简单叙述任务与函数的相同点和不同点?14、设计一个2位十进制循环计数器,从00计数到99,然后再回到00。输入信号为clk和reset(低电平复位),输出为out1和out0,位宽均为4,分别表示十进制数的高位和低位。,