1、第7章 Verilog HDL语言简介 7.1 Verilog HDL语言总体结构7.2 端口声明与数据类型声明7.3 数值的表示7.4 连续赋值7.5 模块实例化7.6 验证设计7.7 运算符(operator)7.8 Verilog HDL行为级建模 7.9 任务和函数介绍7.10 综合设计:交通信号灯控制器7.11 Verilog HDL语言的仿真工具习题 第7章 Verilog HDL语言简介 第7章 Verilog HDL语言简介 Verilog HDL语言是一种硬件描述语言,在20世纪80年代由Gateway DesignAutomation公司开发,用于电路的模拟。1995年,V
2、erilog HDL成为IEEE(Instituteof Electrical and Electronics Engineers,电子电气工程师协会)标准,即IEEE1364标准(Verilog-1995),2001年对该标准进行了修改(Verilog-2001)。Verilog-2001在Verilog-95上增加了一些新的特性,使Verilog HDL的表述更简洁。目前大部分EDA工具都支持两个标准。本书按Verilog-95标准对Verilog HDL进行简要的介绍。第7章 Verilog HDL语言简介 Verilog HDL语言可以在系统级、算法级、寄存器传输级RTL(Regist
3、eredTransferLevel)、门级和开关级(晶体管级)等多个抽象设计层次对数字电路或者系统进行建模。Verilog HDL本质是一种复杂的描述数字系统的语言,句法上与语言相似,延用了C语言的多种操作符和结构,但是其语义上是基于并发硬件操作,完全不同于顺序执行的C语言。Verilog HDL是一种仿真能力非常强大的语言,语言中包含了一部分可以用EDA工具进行逻辑综合的子集。所谓的逻辑综合就是指利用电子设计自动化EDA(Electronic Design Automation)工具将Verilog HDL代码转换成电路。第7章 Verilog HDL语言简介 Verilog HDL可以用于
4、描述系统中的一个元件,也可以用于描述一个完整的系统。7.1 Verilog HDL语言总体结构语言总体结构第7章 Verilog HDL语言简介 Verilog HDL语言描述主要由三个部分构成:端口声明(Port Declaration)、信号数据类型声明(Data Type Declaration)、电路模块功能描述(Circuit Functionality),图7-1给出了一个基本Verilog HDL程序的组成结构。Verilog HDL程序以关键词module开始,以关键字endmodule结束。module后面是一个模块名标识符,它唯一地标识一个模块,模块名后括号中的port_l
5、ist是模块的输入和输出列表。当portlist是空的时候,该模块是一个仿真中模块。第7章 Verilog HDL语言简介 图7-1 Verilog HDL的模块组成结构第7章 Verilog HDL语言简介 端口声明(Port Declarations):声明一个端口的性质,如输入(Input)、输出(Output)还是双向口(inout)以及端口的宽度(PORT_WIDTH 1:0)。信号数据类型声明(Data Type Declarations):声明module中用到的数据类型,如regport1,wire port2。电路模块功能描述(Circuit functionality):描
6、述电路功能。与C语言一样,在Verilog HDL语言中,除了关键字endmodule行外,每行以“;”号结束。Verilog HDL是大小写敏感语言,语言中所有的关键字都是小写,其注释方式有两种:一是单行注释,注释内容在“/”之后,直至本行末;二是多行注释,注释内容自“/*”开始,至“*/”结束。第7章 Verilog HDL语言简介【例【例7-1】用Verilog语言描述两输入的异或门。图7-2(a)给出了一个异或门的Verilog描述,图(b)给出了图(a)的综合结果。图7-3是Verilog HDL语言的基本元素组成图,本章将按图7-3对Verilog HDL语言的各个部分作简单的介绍
7、。第7章 Verilog HDL语言简介 图7-2 异或门的Verilog HDL 描述第7章 Verilog HDL语言简介 图7-3 Verilog HDL语言的基本组成第7章 Verilog HDL语言简介 一个电路由多个不同的部件(模块)构成,这些部件之间并行地工作。一个部件可以是一个门,也可以是一个完成某些特殊功能的电路,如译码器、多路选择器和计数器等,还可以是完成复杂任务的子系统,如嵌入式微处理器等。Verilog语言中可以用三种方式来描述系统各个部件的功能:连续赋值(Continuous Assignment)、过程模块(Procedural Block)和模块实例化(Modul
8、eInstantiation)。此外,Verilog还可以用各种子程序如任务(task)、函数(function)或者系统任务(system task)来描述电路的行为或者仿真的行为。第7章 Verilog HDL语言简介 1.I/O端口声明端口声明I/O端口是一个模块和其周围环境进行通信的信号接口,模块内部的信号对于环境而言是不可见的。例如,图7-4是一个两输入异或门的I/O端口。Verilog HDL语言在模块内必须对输入、输出列表中的每个信号进行声明,同时对输入和输出信号的数据类型进行声明。7.2 端口声明与数据类型声明端口声明与数据类型声明 第7章 Verilog HDL语言简介 图7
9、-4 两输入XOR门的I/O端口第7章 Verilog HDL语言简介 基本语法是:module identifier(port_name1,port_name2,port_nameN);mode port_name1;/声明端口类型 modeport_nameN;data_type port_name1;/声明端口数据类型 data_type port_nameN;endmodule mode类型有三种:input(输入端口)、output(输出端口)和inout(双向端口)。第7章 Verilog HDL语言简介 这些都是关键字,不能用于信号名。(port_name1,port_nameN
10、)是一个模块的输入和输出端口名称列表,这些名称之间用“,”进行分离,输入、输出列表的最后一项没有“,”。JP2data_type port_name1,data_type port_nameN是对端口的数据类型进行声明。第7章 Verilog HDL语言简介【例【例7-2】两输入异或门的I/O端口声明。module xor_2(in1,in2,out);input in1,in2;/声明输入信号 output out;/声明输出信号 wire in1,in2;/声明输入端口的数据类型 wire out;/声明输出端口的数据类型 endmodule 第7章 Verilog HDL语言简介 要特别
11、注意的是:在模块中不能再次定义模块,即模块不能嵌套。例如,下面的写法是错误的。module and_2(in1,in2,ou1);module dff(clk,rst,din,dout);/错误定义!endmodule endmodule 第7章 Verilog HDL语言简介 2.信号的数据类型声明信号的数据类型声明在Verilog HDL中使用四值逻辑,它们分别是:(1)“0”:表示逻辑0或者判定条件假。(2)“1”:表示逻辑或者判定条件为真。(3)“z”:高阻状态。(4)“x”:未知状态。“z”表示高阻态,通常用于描述一个三态门;而“x”则是用于仿真或者建模,表示当前值不确定,当输入没有
12、初始化或者输出有冲突的时候,会出现“x”状态。信号的取值是这四种逻辑值中的任意一种。第7章 Verilog HDL语言简介 信号数据类型的声明说明在本模块中使用的信号和参数的数据类型。简单的语法是:data_type range signal_name;/声明一个信号变量或者 data_type range signal_name1,signal_name2,signal_nameN;/同时声明N个类型、范围相同的信号变量 Verilog HDL 有两大类数据类型:线网类型组及寄存器类型组。第7章 Verilog HDL语言简介(1)线网类型组线网类型组(net group)。在Verilog
13、 HDL语言中,线网类型组用于描述硬件元件间的物理连线。线网类型的变量是连续赋值的输出,也是不同部件之间的连接信号,它的值由驱动元件的值决定,如图7-5所示。如果没有驱动元件连接到线网,线网的缺省值为“z”。在net类型中最常用的类型是wire类型。正如其名字所表示,它表示一个连接线。第7章 Verilog HDL语言简介 图7-5 线网类型组第7章 Verilog HDL语言简介 wire数据类型表示比特信号。例如:wire p1,p2;/声明两个1比特的信号线网类型组(net group)中的其它数据类型包括:wand(线与)、supply0(电路地连接)、supply1(电源连接)等等,
14、表示某类逻辑操作和功能,本书不涉及这些类型,有兴趣的读者可以参看本书后面列出的参考文献。第7章 Verilog HDL语言简介(2)寄存器类型组寄存器类型组(register group)。寄存器组中的数据类型在行为模型中表示抽象存储,是过程赋值的输出。这个组中包括四种类型:reg、integer、real和time。大多数变量用reg类型,reg类型是可以综合的。注意:综合出来的电路既可以包含也可以不包含存储元件。后三种数据类型只是用于建模和仿真。第7章 Verilog HDL语言简介 例如:reg d_flip;/声明一个reg类型的信号变量 在Verilog HDL中可用rang表示一组
15、信号。wire和reg类型的变量可以声明成多位宽度的向量(vectors)。如果变量的宽度是一位,该变量即是标量(scalar)。我们可以用一维向量表示一组信号(总线)。第7章 Verilog HDL语言简介 例如:wire sel;/标量信号wire 7:0 data1,data2;/8比特数据wire 31:0 addr;/32比特地址reg 7:0 out;/8比特reg变量信号的索引范围可以是升序low#:high#,也可以是降序high#:low#,但是信号数据最左边的那位就是二进制数的最高位。第7章 Verilog HDL语言简介 可以用一个二维向量表示一个存储器,例如一个32*4
16、的存储器(表示一个存储器有32个字,每个字有4位),用Verilog HDL可以表示成 reg 3:0 data_mem 31:0;在Verilog HDL语言中允许使用一个向量中的一位或者多位,如:Data11;/向量data1的第2位;Data23:2;/向量data2中的第4比特和第3比特;第7章 Verilog HDL语言简介 在Verilog语言中,整数常量可以表示成各种各样的形式,一般的格式是:size base value 其中,base说明数字的基数,当一个数用十进制表示,可省略该项。该项有4种形式:b or B:二进制;o or O:八进制;h or H:十六进制;d or
17、D:十进制。7.3 数数 值值 的的 表表 示示第7章 Verilog HDL语言简介 value:说明在对应的基数表示方式下对应的数。为了方便阅读,一个数可以用“_”分割表示。如8b 1000_0011。size:说明一个数值用几位表示,这项是可选的。如果在一个数的表示中存在该项,那么这个数被认为是有位数表示的,否则是无位数表示的数。size项显式地表示了一个数值所用的位数。如果一个数所用位数小于 size所规定的位数,需要对该数扩展到size规定的位数。如果一个数值的最高位是x或z,那么在该数前用x或者z填充,扩展到规定的位数;如果一个数有符号位,那么用符号位填充,扩展到规定的位数;其它情
18、况下,在该数前用0填充,扩展至规定的位数。第7章 Verilog HDL语言简介 如果一个数前省略了size项,那么它实际的表示依赖于计算机的结构,但是至少扩展到32位。例如,表7-1所示为有位数表示的常数,表7-2所示为无位数表示的常数。第7章 Verilog HDL语言简介 表表7-1 有位数表示的常数示例有位数表示的常数示例 第7章 Verilog HDL语言简介 表表7-2 无位数表示的常数示例无位数表示的常数示例 第7章 Verilog HDL语言简介 可以通过连续赋值描述组合电路的功能,基本语法是:assign signalname=expression;assign是Verilo
19、g HDL语言的关键词;signalname的数据类型必须是wire类型;expression的数据类型没有限制,它是由操作数和操作符变量构成的表达式或者是函数。操作数类型可以是前面定义的任意数据类型。操作数可以是常数、整数、实数,线网、寄存器、向量或者向量的一位或者多位。7.4 连连 续续 赋赋 值值 第7章 Verilog HDL语言简介 在连续赋值语句中,等式右边表达式中的任何一个信号变量发生变化,表达式都要计算,例如:wire 9:0 addr;wire 31:0 bus;wire out;wire 7:0 result;assign addr=10b 0000_0010_11;/表达
20、式是常数 第7章 Verilog HDL语言简介 assign data=bus 32h 0000_ffff;/变量、常数和运算符构成的表达式 assign out=in1|in2;/变量、操作符和变量构成的表达式 assign result=mult(a,b);/表达式是函数值 第7章 Verilog HDL语言简介 模块实例化是创建模块的另外一个应用实例。通过模块的实例化可以构建更复杂的设计模块或者系统。实例化的一般语法形式:module_nameinstance_name(.port_name1(signal_name1),.port_name2(signal_name2),.port_
21、nameN(signal_nameN);7.5 模模 块块 实实 例例 化化 第7章 Verilog HDL语言简介【例【例7-3】一个两位的比较器可以通过两个一位比较器按照图7-6所示的连接方式实现。一位/两位的比较器verilog的描述方式有如下两种。第1种:module eq_1bit(i0,i1,eq);input i0,i1;output eq;wire p0,p1,eq;assign p0=i0&i1;assign p1=i0&i1;assign eq=p0|p1;endmodule 第7章 Verilog HDL语言简介 图7-6 一个两位比较器第7章 Verilog HDL语言
22、简介 第2种:module eq_2bit(a,b,a_eq_b);input 1:0 a,b;output a_eq_b;wire e0,e1,a_eq_b;eq_1bit eq_bit0_unit(.i0(a0),.i1(b0),.eq(e0);/实例化模块eq_1biteq_1bit eq_bit1_unit(.i0(a1),.i1(b1),.eq(e1);/实例化模块eq_1bit 第7章 Verilog HDL语言简介 assign a_eq_b=e0&e1;endmodule在第2种描述方式中,句子eq_1bit eq_bit0_unit(.i0(a0),.i1(b0),.eq(e
23、0)表示实例化eq_1bit模块,eq_bit0_unit是eq_1bit模块的一个实例,(.i0(a0),.i1(b0),.eq(e0)表示实例eq_bit0_unit的输入/输出信号在本模块中和其它模块之间的信号连接关系。在本例中,实例eq_bit0_unit是一个一位比较器,其输入端i0、i1在本模块中连接到信号a0和b0,其输出端连接到e0上。注意“.”不可缺少。第7章 Verilog HDL语言简介 一个设计完成后,必须要确认设计是否满足设计者所要求的功能。一种方法就是利用EDA软件,在计算机上通过仿真确认所完成电路是否正确,我们称之为电路验证。为了验证一个电路是否正确,需要对所设计
24、的电路提供输入激励,然后通过软件观察输出是否正确。因此,除了设计模块之外,还需要编写激励模块,我们把这种模块称为testbench模块。下面介绍如何编写一个设计的testbench模块。7.6 验验 证证 设设 计计 第7章 Verilog HDL语言简介 在testbench模块中,实例化设计模块,按照模块的功能编写模块的输入激励,检查和显示输出信息。以两输入的比较器为例,图7-7给出了testbench模块tb_eq_2bit和被仿真模块eq_2bit之间的关系。从图中可以看出,仿真模块tb_eq_2bit本身没有输入和输出,包含了模块eq_2bit(设计模块)的一个实例eq_2bit_i
25、nst。tb_eq_2bit内产生eq_2bit_inst实例所需要的输入激励a、b,检查和显示其输出信号a_eq_b。第7章 Verilog HDL语言简介 图7-7 测试模块和设计模块之间的关系第7章 Verilog HDL语言简介【例【例7-4】编写eq_2bit的测试模块。module tb_eq_2bit;/两位比较器电路的testbench模块名 reg1:0 a,b;/比较器输入信号 wire a_eq_b;/比较器输出信号 initial begin /给出所有可能的输入值 a=2b00;b=2b00;/初始时刻,给a,b赋值第7章 Verilog HDL语言简介#10 a=2
26、b00;b=2b01;/10个时间单位后,给a,b赋不同的值#10 a=2b00;b=2b10;/20个时间单位后,给a,b赋不同的值#10 a=2b00;b=2b11;/30个时间单位后,给a,b赋不同的值#10 a=2b01;b=2b00;/40个时间单位后,给a,b赋不同的值#10 a=2b01;b=2b01;/50个时间单位后,给a,b赋不同的值#10 a=2b01;b=2b10;/60个时间单位后,给a,b赋不同的值#10 a=2b01;b=2b11;/70个时间单位后,给a,b赋不同的值第7章 Verilog HDL语言简介#10 a=2b10;b=2b00;/80个时间单位后,给
27、a,b赋不同的值#10 a=2b10;b=2b01;/90个时间单位后,给a,b赋不同的值#10 a=2b10;b=2b10;/100个时间单位后,给a,b赋不同的值#10 a=2b10;b=2b11;/110个时间单位后,给a,b赋不同的值#10 a=2b11;b=2b00;/120个时间单位后,给a,b赋不同的值#10 a=2b11;b=2b01;/130个时间单位后,给a,b赋不同的值#10 a=2b11;b=2b10;/140个时间单位后,给a,b赋不同的值#10 a=2b11;b=2b11;/150个时间单元后,给a,b赋不同的值 end eq_2bit eq_2bit_inst(.
28、a(a),.b(b),.a_eq_b(a_eq_b);/两位比较器实例化 endmodule第7章 Verilog HDL语言简介 在上面的例子中,initial begin.end是一个过程块,下节将详细介绍。#10表示10个时间单位的延时。该过程块给出了随时间变化的输入值,完整的仿真eq_2bit设计需要输入a、b的全部组合,一共是16种,结果如图7-8所示。第7章 Verilog HDL语言简介 图7-8 两位比较器完整测试波形图第7章 Verilog HDL语言简介 上面的例子介绍了如何建立一个验证程序。验证程序也是一个module,但是它没有任何的输入和输出。在验证程序中,需要实例化
29、被验证的设计;定义设计所需要的输入和输出;为输入加载输入激励。第7章 Verilog HDL语言简介 在Verilog语言中包含了10类操作符、24种运算符。这些运算符对应着简单的器件,比如加法器和比较器。表7-3说明了Verilog HDL中的运算符,表7-4给出了运算符的优先级。7.7 运算符运算符(operator)第7章 Verilog HDL语言简介 表表7-3 Verilog HDL中的运算符中的运算符 第7章 Verilog HDL语言简介 表表7-4 运算符优先级运算符优先级 第7章 Verilog HDL语言简介 1.算术运算符算术运算符在Verilog中,算术运算符共有六个
30、:“+”、“-”、“*”、“/”、“%”和“*”,分别代表加、减、乘、除、取模和指数运算。“+”和“-”也可以作为一元运算符,例如:-a。在算术运算操作中,“+”和“-”运算符可以用EDA工具直接综合成加法器和减法器。乘法是一个复杂的操作,对于乘法运算符“*”的综合取决于综合软件以及目标器件的工艺。除法运算符“/”、求模运算符“%”和指数运算符“*”在通常情况下是不可综合的。第7章 Verilog HDL语言简介 2.移位运算符移位运算符移位运算符有四个:“”、“”,分别表示逻辑左移、逻辑右移、算术左移、算术右移。这组运算符是将一个向量向左或者向右移动给定的位数,如果是逻辑移位,则用0填充在向
31、量的高位(左移)或者低位(右移)。算术左移高位用低位填充,最低位用0来填充,符号位移出后,则丢弃,这样,算术左移和逻辑左移的运算结果一样。而算术右移低位用高位填充,把数的最高位看成符号位,用符号位填充高位,最低位移出后丢弃。第7章 Verilog HDL语言简介 例如:a=8b0100_1111,b=8b1100_1111,c=8b10100011,有 x=a2;/x=0001_0011 y=b2;/y=1111_0011 z=c3;/z=1111_0100 算术右移将b的最高位看成符号位,用符号位填充;z=a2;/z=0011_1100;w=b”、“=”、“10)【例【例7-6】表7-11给
32、出了逻辑运算和位运算的一些例子。由于Verilog HDL中用0和1来代表假和真,所以位运算和逻辑运算在某些条件下可以交换使用。第7章 Verilog HDL语言简介 表表7-11 逻辑运算例子逻辑运算例子 第7章 Verilog HDL语言简介 5.拼接运算符和复制运算符拼接运算符和复制运算符1)拼接运算符拼接运算符用表示拼接运算,使用这个运算符可以把两个或多个信号的某些位拼接形成一个向量,进行运算操作,多个信号变量用“,”隔开。wire a1;wire 3:0 a4;wire 7:0 b8,c8,d8;assign b8=a4,a4;assign c8=a1,a1,a4,2b00;assi
33、gn d8=b83:0,c83:0;第7章 Verilog HDL语言简介 拼接运算的一个应用是进行信号变量移位或循环操作,举例如下:wire 7:0 a;wire 7:0 rot,shl,sha;assign rot=a2:0,a7:3;/a向右循环3位assign shl=3b000,a8:3;/a逻辑右移3位assign sha=a8,a8,a8,a8:3;/a算术右移3位 第7章 Verilog HDL语言简介 2)复制运算符复制运算符 用N 表示对内的数复制N次,形成新的向量。该操作可以用于化简拼接的写法。例如,42b01等价于 8b01010101又如,assign sha=3a8
34、,a8:3;/a算术右移3位等价于:assign sha=a8,a8,a8,a8:3;/a算术右移3位 第7章 Verilog HDL语言简介 6.条件运算符条件运算符条件运算符“?:”是三目运算符,其基本格式如下:signal_name=boolean_exp?true_exp:false_exp;其中,boolean_exp是指布尔表达式,返回值是真(1b1)或假(1b0)。如果boolean_exp为真,则signal为true_exp的值,否则为false_exp的值。例如,wire 2:0 max;assign max=(a b)?a:b;第7章 Verilog HDL语言简介 该运
35、算用if-else语句表示如下:if boolean_exp signal=true_exp;else signal=false_exp;条件运算符还可以嵌套,例如:assign max =(a b)?(a c)?a:c):(b c)?b:c);在综合时,条件运算符会被综合成二选一选择器。第7章 Verilog HDL语言简介 7 表达式的位宽表达式的位宽Verilog HDL程序中的信号,连线和变量通常都具有不同的位宽,在存储中,选择的位数与位宽一致。例如,wire 7:0 a,b;assign a=8b00000000;assign b=0;第7章 Verilog HDL语言简介 上述代码
36、中,第一条assign语句是将8位的二进制数“00000000”赋给a,而第二条assign 语句是指将整数0赋给b。在Verilog中整数是32位,即“0000_0000_0000_0000_0000_0000_0000_0000”。由于b事先声明为8位,故正确地从32位中截取8位的“00000000”。尽管这两条assign语句的结果都是8位的“00000000”,但是我们必须清楚a和b分别是怎样获得的值。第7章 Verilog HDL语言简介 例如,wire 7:0 a,b;wire 7:0 sum8;wire 8:0 sum9;assign sum8=a+b;assign sum9=a
37、+b;上述代码中,第一条assign语句中所有的操作数都是8位,等号左边的sum8也是8位的,而附加的进位位被丢弃了。在第二条assign语句中,由于sum9是9位的,所有“a”和“b”也被扩展成9位,而sum99就是进位位的值。我们同样可以利用拼接运算符来完成上述运算:assign c_out,sum8=a+b;第7章 Verilog HDL语言简介 1 过程块结构过程块结构在Verilog HDL语言中有两种结构化过程语句always和initial,它们是行为建模中最基本的两个语句,所有其它的行为语句可以出现在这两个结构化过程中。always和initial语句不能嵌套。7.8 Veri
38、log HDL行为级建模行为级建模第7章 Verilog HDL语言简介 1)initial 语句语句initial语句只用于建立行为仿真,不能综合。所有出现在initial中的语句构成一个initial 块(initial block),一个initial块从时间0开始执行,在仿真过程中每个语句只执行一次。如果一个仿真程序中出现了多个initial块,这些块都是在0时刻开始执行的,每个initial 块的执行是相互独立的。第7章 Verilog HDL语言简介 基本的语法是:initial begin statements_sequence;end【例【例7-7】initial 模块示例。m
39、odule stimulus;/验证模块 reg x,y,a,b,m;initialm=1b0;/只有一个语句,可以省略begin/end第7章 Verilog HDL语言简介 initial begin#5 a=1b1;/多条语句,需要用begin/end#25 b=1b0;end initial begin#10 x=1b0;#25 y=1b1;end initial#50$finish;endmodule第7章 Verilog HDL语言简介 在上面的例子中有一个延时#delay,表示等待delay个时间单位。其执行的结果如下:time statement executed 0 m=1b
40、0;5 a=1b1;10 x=1b0;30 b=1b0;35 y=1b1;50$finish;第7章 Verilog HDL语言简介 2)always块块always块是Verilog语言中另外一种描述电路行为的语句,它是可综合语句。所有出现在always中的语句构成一个always块。always块使用行为语句描述电路的功能。always的一般形式为 always(event_list)begin statements_sequence end第7章 Verilog HDL语言简介 执行always块的条件是事件列表(event_list)中任何信号发生变化,即只要事件列表中的任何事件发生变
41、化,就重复执行语句序列。如果always块的语句只有一条,可以省略begin/end。statement_sequence是指过程赋值语句序列。过程赋值语句和(event_list)将在后续小节详细介绍。例如,reg out1;always(in1 or in2)/in1 或者in2发生变化,执行out1=in1|in2语句 out1=in1|in2;第7章 Verilog HDL语言简介 2 过程赋值语句过程赋值语句过程赋值语句的基本语法:lhs =rhs;lhs =rhs;上面两个语句都是过程赋值语句,前者我们称为阻塞赋值(=),而后者称为非阻塞赋值。过程赋值语句的作用是用等式右边的表达式
42、(rhs)更新等式左边的变量值(lhs)。第7章 Verilog HDL语言简介 等式左边的变量值的类型有reg、integer、real和time。过程赋值与连续赋值的不同之处是:在连续赋值语句中,等式右边表达式的值连续不断地赋给等式的左边,而在过程赋值语句中,一个变量存储的值保持不变,直到过程赋值语句用不同的值更新该变量。等式右边的表达式可以是下面的几种形式:(1)reg、integer、real和time型变量,如a,b,c;(2)变量的比特选择,如addr0;(3)变量的部分选择,如addr31:16;(4)上述类型的连接形式,如4h0,addr15:0,a。第7章 Verilog H
43、DL语言简介 1)阻塞赋值语句阻塞赋值语句用“=”进行赋值的语句是阻塞赋值语句。阻塞赋值可以按照它们在过程块中的次序顺序执行,在它执行结束之前,将阻止后续语句的执行【例【例7-8】下面的表达式形式都是合法的:reg a,b,c;reg 15:0 data;integer counter;initial begina=1b0;b=1b1;c=1b1;/在0时刻,将3b011分别赋给a,b,c;第7章 Verilog HDL语言简介 counter=0;/在0时刻,counter赋初值0;#10 data1=a;/在第10个时间单位,将a赋给data1;data7:2=6b00_1011;/将二进
44、制数001011赋给data7:2;#20 counter=counter+1;/在第30个时间单位,将counter加1 a,b,c=counter2:0;/在第30个时间单位,将counter的低三位分别赋给a,b,cend 第7章 Verilog HDL语言简介 注意注意:如果等式右边的数据宽度大于等式左边变量的宽度,那么抛弃高位,而保留低位。如果等式右边的数据宽度小于等式左边变量的宽度,则高位用0填充。2)非阻塞赋值语句非阻塞赋值语句一条非阻塞赋值语句不阻止后续语句的执行。【例【例7-9】阻塞与非阻塞赋值语句的执行情况。如下两段代码分别为阻塞和非阻塞赋值语句。第7章 Verilog H
45、DL语言简介 阻塞赋值:reg A,B;initial begin A=#10 1b1;B=#5 1b0;A=#20 1b0;B=#15 1b1;end 第7章 Verilog HDL语言简介 非阻塞赋值:reg A,Binitial begin A=#10 1b1;B=#5 1b0;A=#20 1b0;B=#15 1b1;end 第7章 Verilog HDL语言简介 我们来考察阻塞语句与非阻塞语句的执行情况,在本例中的时间单位是ns,如图7-9 所示,图(a)是阻塞赋值结果,图(b)是非阻塞赋值结果。初始,A、B值均为高阻态。对于非阻塞语句描述,10 ns执行语句A=1b1;在该句执行结束
46、后的5 s,即第15 ns执行B=1b0;而此后的20 ns,即到35 ns前,A一直为1;35 ns时执行语句A=1b1;在50 ns的时候执行B=1b1。可以看出阻塞语句一定是本句执行结束后,才允许运行其它语句的执行。在一个过程块中,它们是顺序执行的。第7章 Verilog HDL语言简介 图7-9 阻塞赋值和非阻塞赋值的输出波形第7章 Verilog HDL语言简介 而对于非阻塞语句,它的执行并不阻塞后续语句的执行。因此,调度器在5 ns时候执行B=0;在10 ns的时候执行A=1;在15 ns的时候执行B=1,而在20 ns的时候执行A=0,如图7-9(b)所示。为了进一步看清楚阻塞语
47、句与非阻塞语句的区别,我们再举一个例子。第7章 Verilog HDL语言简介【例【例7-10】阻塞语句与非阻塞语句的综合。阻塞赋值:module dff(clk,din,dout);input din,clk;output dout;reg a,dout;always(posedge clk)begin a =din;dout=a;endendmodule 第7章 Verilog HDL语言简介 非阻塞赋值:module dff(clk,din,dout);input din,clk;output dout;reg a,dout;always(posedge clk)begin a=din;
48、dout=a;endendmodule 第7章 Verilog HDL语言简介 在阻塞赋值代码中,由于a=din在瞬间完成后,执行dout=a,然后在时钟的上升沿到达的时候,更新等式左边的值。因此,从仿真结果看,a和dout的值相同,其综合的结果就是一个D触发器。而非阻塞赋值代码的综合结果是一个两位的移位寄存器,两个等式右边的表达式按照当前期的值计算出结果,然后保存在临时变量中,在时钟上升沿到达时,同时更新表达式的左边。这样,寄存器dout的结果是上一周期a的结果,而a则是上一个周期din的结果。图7-10给出了阻塞赋值与非阻塞赋值的综合结果。第7章 Verilog HDL语言简介 图7-10
49、 阻塞赋值和非阻塞赋值综合结果第7章 Verilog HDL语言简介 3.时序控制时序控制时序控制用于说明过程语句执行的仿真时间。有三种基本的时间控制语句:基于延时控制的时序控制、基于事件的时序控制和电平敏感的时序控制。1)基于延时的时序控制基于延时的时序控制表达式中基于延时的时序控制说明了仿真器遇到语句和执行语句之间的间隔。在Verilog 语言中用“#delay”说明延时。在过程赋值语句中,主要的两类延时控制是:(1)正则延时(regular delay):在过程表达式的左边说明非零延时。第7章 Verilog HDL语言简介 如#delay lhs=rhs;等待delay时间后将rhs的
50、值赋给lhs。(2)内定延时(intradelay):在赋值语句的右边说明延时。#delay1 lhs=#delay2 rhs;仿真器执行的过程如下:等待delay1;计算等式的右边rhs;等待delay2后,将rhs的值赋给lhs。第7章 Verilog HDL语言简介【例【例7-11】时间赋值语句举例,其延时时序图如图7-11所示。module test parameter latency=10,delta=2;reg 10:0 a,b;reg w1,w2;integer i1,i2,delay3;initial begin w1=1b0;w2=1b1;delay3=10;第7章 Veri