数字电子技术基础PPT第9章VerilogHDL语言.ppt

上传人:小飞机 文档编号:5984728 上传时间:2023-09-11 格式:PPT 页数:54 大小:358KB
返回 下载 相关 举报
数字电子技术基础PPT第9章VerilogHDL语言.ppt_第1页
第1页 / 共54页
数字电子技术基础PPT第9章VerilogHDL语言.ppt_第2页
第2页 / 共54页
数字电子技术基础PPT第9章VerilogHDL语言.ppt_第3页
第3页 / 共54页
数字电子技术基础PPT第9章VerilogHDL语言.ppt_第4页
第4页 / 共54页
数字电子技术基础PPT第9章VerilogHDL语言.ppt_第5页
第5页 / 共54页
点击查看更多>>
资源描述

《数字电子技术基础PPT第9章VerilogHDL语言.ppt》由会员分享,可在线阅读,更多相关《数字电子技术基础PPT第9章VerilogHDL语言.ppt(54页珍藏版)》请在三一办公上搜索。

1、第9章 Verilog HDL语言 Verilog HDL是使用广泛的硬件描述语言,该语言的特点是语言能力强,代码简单,有大量支持仿真的语句与可综合语句。本章介绍该语言中的可综合语句描述数字电路与系统,重点介绍该语言的基本语法、组合电路与时序电路的描述与实际描述举例。,9.1 Verilog HDL语言基础Verilog HDL语言以模块(module)的形式来描述数字电路,模块接口部分用来描述与其他模块之间的连接,一般一个文件就是一个模块。模块的定义从关键词module开始,到关键词endmodule结束,每条Verilog HDL语句以分号“;”作为结束(块语句、endmodule等少数语

2、句除外)。注释语句单行以“/”开头,多行以“/*”开始、以“*/”结束。该语言很多规定与C语言相似。,【例9-1】Verilog HDL描述与非门。module NAND(in1,in2,out);/以module开头,随后是模块名和括号内的端口名列表,最后以分/号结束 input in1,in2;/定义端口类型,只有输入(input)、输出(output)和双向(inout)三种 output out;/凡是在端口列表的端口,都必须经过定义/wire in1,in2,out;/由于in1、in2和out是1位宽连线类型,所以可以采用默认定义,此/语句可省略 assign out=(in1/连

3、续赋值语句assign描述组合电路/在Verilog中,还有initial叙述、always叙述、模块调用、门调用等endmodule/关键字endmodule用于结束行,注意其后没有分号,9.1.1 Verilog HDL中的基本约定1可用在描述语句中的逻辑状态0表示逻辑0、逻辑非、低电平、假;1表示逻辑1、逻辑真、高电平、真。x或X表示不确定的逻辑状态;z或Z表示高阻态。2整数及其表示整数可以按照简单十进制数格式或基数格式书写。(1)简单十进制数格式简单十进制数的整数表示与普通十进制数表示相同,例如,35、-46。(2)基数格式表示格式:+/-其中:+/-是符号位;位宽就是数的等效二进制数

4、的位数(bit),位宽用十进制数表示;二进制的基数符号位b或B;八进制的基数符号是o或O;十进制的基数符号是d或D,可默认不写基数符号;十六进制的基数符号是h或H。一些规定:数值中,左边是数值最高位(MSB),右边是最低有效位(LSB);在二进制中,x、z只代表相应位的逻辑状态,x表示不定,z表示高阻;当位宽默认时,位宽为32位。例如:3b000是位宽为3的二进制数;res=8b11111110是8位二进制数;9o671是位宽为9的八进制数;8h3f是位宽为8的十六进制数。,3标志符取名标志符取名的规定:标志符必须是字母或下画线开头,长度小于1024;后续部分可以是字母、数字或下画线;Veri

5、log HDL中的标志符区分大小写。例如,_bus,topp,BUS。4系统命令以$开头的标志符代表Verilog HDL中的命令(系统任务与系统函数),普通的标志符不能以$开头。5保留字Verilog HDL语言内部已经使用的保留字,在Verilog HDL语言编辑器中,保留字以醒目的颜色表示。,9.1.2 数据类型 Verilog HDL中的4种最基本数据类型是:整型(integer)、参数(parameter)型、寄存器(reg)类型和连线(wire)类型。,1连线类型常用的连线类型关键字为wire。连线类型的逻辑状态为0、1、x(任意)、z(高阻),连线类型主要用在模块的结构描述中,对

6、应硬件的物理信号连线,当用数字表示其逻辑值时,不存在符号位。在用连线类型的信号时,必须用连线类型定义语句对信号进行类型说明,当说明被省略时,表示位宽为1bit的wire型连线信号。wire是基本的、不附带其他功能的连线,也是最常用的连线类型。对于input,output和inout端口,若未指明数据类型,默认为连线类型。连线类型定义格式:矢量范围,连线名;矢量范围以MSB:LSB格式描述。例如:wire 0:31 w1,w2;/w1和w2是32位连线类型,高位MSB为bit0wir5e 7:0 tmp;/tmp为8位连线,高位MSB为bit7,低位LSB是位0,2寄存器类型常用的寄存器类型的关

7、键字为reg。寄存器类型的信号,必须通过过程赋值语句进行赋值,只能出现在always后面的过程语句中。寄存器变量的定义格式:矢量范围,寄存器名;矢量范围以MSB:LSB格式描述。例如:reg a;/a为寄存器类型reg 3:0 v;/v为4位寄存器类型reg 7:0 m,n;/m和n为8位寄存器类型在Verilog HDL中,线宽为一位的连线和只有一位的寄存器变量称为标量;线宽大于一位的连线和位宽大于一位的寄存器变量为矢量。按位或部分位赋值的矢量称为标量类矢量,相当于多个一位标量的集合,标量类矢量进行类型说明时,需要关键字scalared(可以默认)。例如,reg scalared 7:0 r

8、eg_a;/reg_a被定义成标量类矢量该说明可以默认关键字scalared,因此可以写成:reg 7:0 reg_a;,3端口信号与内部信号 信号可以分为端口信号和内部信号。出现在端口列表中的信号是端口信号,其他的信号为内部信号。对于端口信号,输入端口只能是连线类型。输出端口可以是连线(wire)类型,也可以是寄存器(register)类型。若输出端口在过程块中赋值则为register类型;若在过程块外赋值,则为wire类型。内部信号类型与输出端口相同,可以是连线(wire)类型或寄存器(register)类型。若在过程块(always叙述)中赋值,则为register类型;若在过程块外赋值

9、,则为wire类型。端口类型只有输入(input)、输出(output)和双向(inout)三种,凡是在端口列表中的端口,都必须定义端口类型。例如,“output6:0ag;”定义端口ag为输出端口,“input3:0hex;”定义端口hex为输入端口。,4其他定义语句(1)参数定义语句 参数定义语句经常用于对时延、线宽、寄存器位数等物理量的定义,其方法是用一个文字参数来代替一个数字量,从而增加描述语句的可修改性。参数定义的格式:parameter 其中参数定义部分给出具体的各个参数与数字之间的关系,各个关系之间用逗号隔开。例如:module module_name();parameter m

10、sb=7,lsb=0;/定义参数regmsb:lsb reg_a;/使用参数.endmodule,9.1.3 运算符1算术运算符算术运算符包括加法、减法与乘法,例如a+b,a-b,a*b。有些综合工具不支持乘法。2位运算符按位运算的运算符是位运算符,原来的操作数有几位,结果就有几位。若两个操作数位数不同,则短的操作数左端会自动补0处理。位运算符为:按位取反、按位与&、按位或|、按位异或、按位同或或。例如,a=b0110,b=b0100 则a|b=0110,a&b=0100。3缩位(归约)运算符缩位运算符是单目运算符,也是按位进行逻辑运算,但结果是一位逻辑值。例如,对a3,a2,a1,a0进行缩

11、位运算时,先对a3和a2进行缩位运算符指定的运算,产生一位结果,再将这个结果与a1进行缩位运算,然后再将产生的结果与a0缩位运算,产生最后的结果。缩位运算符包括:与缩位&、或缩位|、异或缩位,以及与、或、异或缩位运算符和非操作运算符组成的复合运算符&、|、。例如,a=b0110,b=b0100 则|b=1,&b=0,|a=0。,4逻辑运算符逻辑运算符包括:逻辑与&、逻辑或|、逻辑非运算符!。逻辑与和逻辑或为双目运算符,逻辑非为单目运算符。如果操作数是一位的,则1代表真值,0代表逻辑假。如果操作数是多位的,则将操作数看做整体。如果操作数中每一位都是0,则具有逻辑0值。若其中有一位为1,就把这个操

12、作数看做逻辑1值。因此可以把逻辑运算符看做是字逻辑运算符。5关系运算符关系运算符包含:小于、小于等于=。关系运算符都是双目运算符,用于比较两个操作数的大小,比较结果是1位逻辑值,值1代表关系成立,值0代表比较关系不成立。6相等与全等运算符相等与全等运算符包括:相等=、不等!=、全等=、不全等!=。这四个运算符都是双目运算符,结果是一位的逻辑值。7逻辑移位运算符逻辑移位运算符包括:逻辑左移。若设a是操作对象,n是移位位数,则an表示将a左移n位。进行移位操作时,用0填补移出的空位。,8连接运算符该运算符可以将两组信号用大括号括起来,拼接成一个新的信号。例如,a,b,c,b101,若a、b、c都是

13、一位信号,则该连接运算的结果是6位宽信号。对于一些重复信号,连接运算符有简化表示方法na,这里n是重复数。例如:4w表示w,w,w,w。,【例9-3】使用Verilog HDL连接运算符描述全加器。module addr(sum,co,ci,ina,inb);output 3:0 sum;/4位宽的和 input 3:0 ina,inb;/4位宽的加数与被加数 output co;/1位宽的进位输出 input ci;/1位宽的进位输入 assign co,sum=ina+inb+ci;/连接运算Endmodule/*将co和sum拼接成一个新信号为co,sum3,sum2,sum1,sum0

14、*/,9条件运算符条件运算符是三目运算符,它的格式是条件表达式?条件为真时的表达式:条件为假时的表达式例如,assign tri_bus=(drv_enable)?data:16bz;【例9-4】Verilog HDL描述三态门。module likebufif(in,en,out);input in;input en;output out;assign out=(en=1)?in:bz;/如果en=1,则输出out=in,否则输出out=zendmodule,9.2 Verilog HDL语言中的描述1Verilog HDL数据流描述Verilog HDL语言的数据流描述可以很好地描述组合电

15、路。(1)连续赋值语句连续赋值语句将值赋给连线信号,格式为:assign=例如:wire3:0 z,pre,clr;assign z=pre/a等于b时,equal输出为1;a不等于b时,equal输出为0endmodule,2Verilog HDL行为描述(1)过程块 Verilog HDL对模块的行为描述以过程块为基本单位,一个模块的行为描述由一个或多个并行运行的过程块组成。过程块格式如下:过程语句(事件控制敏感表)块语句开始标志符:块名 块内局部变量说明;一条或多条过程赋值或其他程序语句;块语句结束标志符 过程语句就是指关键字always开始的语句,事件控制敏感表中的信号用于激活过程语句

16、的执行;块语句标志符为begin-end,块名和块内局部变量说明均为可选项。(2)过程语句always 如图9-1所示,always从时刻0开始执行,并循环重复执行后面的块语句。always语句常带有触发(激活或敏感)条件,只有当触发条件满足时,块中的语句才真正开始执行,若触发条件默认,则触发条件始终成立。一个模块的行为描述中可以有多个always语句,这些语句之间相互独立,并行运行。,3块语句(1)串行块串行块的标志符是begin-end,位于串行块中的语句按串行方式顺序执行。综合工具支持串行块描述。(2)串行块的行为描述可以形象地理解为硬件电路中,数据在时钟与控制信号的作用下,沿数据通道的

17、各级寄存器之间的传送过程。例如,begin reg_a=reg_b;reg_c=reg_a;end4过程赋值语句Verilog HDL对模块的行为描述由一个或多个并行运行的过程块构成,而位于过程块中赋值语句称为过程赋值语句。在过程赋值语句中表达式左边的信号必须是寄存器类型(如reg类型);在过程赋值语句等式右边可以是任何有效的表达式,数据类型也没有限制。如果一个信号没有声明则默认为wire类型,使用过程赋值语句给wire赋值会产生错误。过程赋值的基本格式是:=例如:如果sum定义为寄存器信号,而carry为连线信号,则在always过程块中有:sum=a b cin;/正确carry=a/错误

18、,(1)事件控制事件控制以“”开头,后面紧跟的是事件敏感表a)(信号名)。其中信号名通常是一位标量,也可以是多位矢量,数据类型没有限制,其含义是只有检测到信号名所确定的信号发生变化时,后面的赋值语句才能执行。例如,(clock)reg_a=reg_b;/当时钟信号clock发生变化的时候,执行reg_a=reg_bb)(posedge 信号名)。与前一情况相比,只关心信号上升沿(posedge)跳变的情况。例如,(posedge clock)reg_a=reg_b;/当时钟上升沿到来的时候,执行reg_a=reg_bc)(negedge 信号名)。只关心信号下降沿(negedge)跳变的情况。

19、例如,(negedge clock)reg_a=reg_b;/当时钟下降沿到来的时候,执行reg_a=reg_b,d)(敏感事件1 or 敏感事件2 or 敏感事件3)。在这个表达式中,敏感事件可以是上面、三类事件控制中的任一种,只要所列举的任意一种情况发生,都将激活事件控制,各个敏感事件之间是“或”的关系。例如,(posedge reset or negedge clear)reg_out=0;always语句的敏感信号表中,注意敏感信号的动作类型应该一致,例如:always(posedge clk or negedge rst_n)/正确,都是边沿动作。负沿可以代替低电平,/正沿可以代替高

20、电平,这里rst_n为低电平有效always(state or go or ws)/正确,都是电平动作always(posedge clk or go or ws)/不正确,有边沿和电平两类,动作类型不一致,(2)阻塞型过程赋值与非阻塞型过程赋值等号赋值符“=”,在Verilog HDL中称为阻塞(blocking)型过程赋值符,该赋值符的特点是它在串行块的执行过程中,前一条语句没有完成赋值过程之前,后面的语句不能执行,阻塞的意义就是前一条语句阻塞了后面语句的执行。非阻塞(non_blocking)赋值符“=”可以改变阻塞的情况,在串行块中,非阻塞赋值符是并行执行的。例如:阻塞赋值:a=1;b

21、=a;c=b;结果是a、b、c都等于1,相当于图9-2所示的组合逻辑电路。非阻塞赋值:a=1;b=a;c=b;则a等于1,b是a的老值,c是b的老值,相当于图9-3所示的寄存器电路。,图9-2 阻塞型赋值示意图 图9-3 非阻塞型示意图,【例9-6】如果实现图9-4所示的逻辑图,必须在过程块中使用阻塞型赋值语句,程序如下:module blocking(a,b,c,x,y);/a、b和c是输入,x、y是输出input a,b,c;output x,y;reg x,y;always(a or b or c)begin x=a endendmodule,【例9-7】对于图9-5所示的电路,必须在过

22、程块中使用非阻塞型赋值语句,程序如下:module demo1(reg_a,reg_b,d,clock);/该例相当于两个寄存器串联input d,clock;output reg_a,reg_b;reg reg_a,reg_b;always(posedge clock)/时钟上升沿动作 begin reg_a=d;/reg_a的输入为d reg_b=reg_a;/reg_b的输出为reg_a的老值 endendmodule,(3)连续赋值语句与过程赋值语句的区别Verilog HDL语言中的过程赋值语句与连续赋值语句之间的区别如下。赋值对象不同:连续赋值语句用于连线类型信号,过程赋值语句用于

23、寄存器类型信号。赋值语句的实现过程不同:连线信号一旦被连续赋值语句赋值后,赋值语句右端表达式中的信号有任何变化,都将反映到左端的连线变量中;过程赋值语句只有在执行时才有效。语句的位置不同:连续赋值语句不能出现在过程块中;而过程赋值语句只能出现在过程块中。语句结构不同:连续赋值语句以assign开头;而过程赋值不需要先导字。,9.3 Verilog HDL语言中的分支语句1if-else语句(1)if(条件表达式)块语句当条件表达式成立时,执行后面的块语句,否则不执行。(2)if(条件表达式)块语句1else 块语句2当条件表达式成立时,执行块语句1,否则执行块语句2。(3)if(条件表达式)块

24、语句1else if(条件表达式)块语句2else if(条件表达式)块语句nelse(条件表达式)块语句n+1if-else 语句可以嵌套使用,使用方法同C语言,注意else与最近的if搭配。,2case语句语句格式:case(敏感表达式)值1:块语句1 值2:块语句2 值n:块语句n default:块语句n+1Endcaseif语句、case语句必须在always块中使用,assign语句不能在always块中使用。if语句中,关系表达式之间应该用逻辑运算符(&、|、!)连接。注意不要用赋值语句代替关系运算符。,9.4 Verilog HDL语言中的结构描述1结构描述方法Verilog

25、HDL 结构描述只是将逻辑图方式的连接关系转换成文字表达,若是已经有了模块的逻辑图,则可以按照如下步骤将逻辑图转换成Verilog HDL模块。给逻辑电路图中的每个输入/输出端口命名端口名。给逻辑电路图中的内部连线命名连线信号名。给每个逻辑单元命名调用名。命名模块名。书写模块名和输入/输出端口,进行端口的类型说明。依据逻辑电路图,描述信号之间的连接关系。,2模块调用模块调用是Verilog HDL结构描述的基本构成方式,一个模块可以调用其他模块,则被调用的模块是底层模块,而调用底层模块的模块是顶层模块。模块调用分为两类:一类是调用基本门,另一类是调用用户自己写的模块。模块调用的格式:模块名 调

26、用名(端口名列表)调用时注意端口名列表中端口名的排列顺序、输入/输出类型,它们都必须与被调用模块定义的顺序保持一致。(1)位置对应调用法将被调用模块定义时的端口名,对应地用与之相连的信号名代替。(2)端口名对应调用法调用格式:定义时的端口名(调用时与之相连的信号名)。,9.5 Verilog HDL语言描述组合逻辑电路组合逻辑电路是输出仅与当前输入信号有关的电路,描述组合电路可用always块或连续赋值assign语句。1always块实现组合电路在使用always块实现组合电路时,需要将所有影响always块内赋值的信号都列入always 的敏感信号表中,同时注意在always块内部赋值一定

27、要使用声明过的reg型信号。在敏感信号表中不能有描述时钟边沿的posedge和negedge关键字。,【例9-8】Verilog HDL描述8线-3线编码器例1。module encoder1(none_on,out2,out1,out0,h,g,f,e,d,c,b,a);input h,g,f,e,d,c,b,a;/编码器输入信号,可以是按钮信号,高电平有效output out2,out1,out0;/编码器输出信号output none_on;/有编码输出信号reg 3:0 out;assign none_on,out2,out1,out0=out;/连接运算always(a or b o

28、r c or d or e or f or g or h)/always过程块,敏感信号中没有边沿描述关键字 begin if(h)outvec=4b0111;/使用如果语句,如果h为1,则输出out等于4b0111 else if(g)out=4b0110;else if(f)out=4b0101;else if(e)out=4b0100;else if(d)out=4b0011;else if(c)out=4b0010;else if(b)out=4b0001;else if(a)out=4b0000;else out=4b1000;endendmodule,2连续赋值语句实现组合电路使用

29、连续赋值语句assign需要注意:连续赋值的信号型式一定是连线wire型。使用assign关键字,格式是assign 被赋值的连线变量=表达式;只要等式右侧的值发生改变时,就会重新对左侧被赋值变量进行赋值。所有输出(output)和输入(input)端口都默认为连线类型,不需要特别的连线类型声明。,【例9-9】Verilog HDL描述8线-3线编码器例2。module encoder(none_on,out2,out1,out0,h,g,f,e,d,c,b,a);input h,g,f,e,d,c,b,a;output none_on,out2,out1,out0;wire 3:0 out;

30、/定义out为内部连线信号 assign out=h?4b0111:g?4b0110:f?4b0101:e?4b0100:d?4b0011:c?4b0010:b?4b0001:a?4b0000:4b1000;/条件操作符 assign none_on=out3;/正在编码信号,用于编码器级联 assign out2=out2;assign out1=out1;assign out0=out0;endmodule,9.6 Verilog HDL语言描述时序电路时序逻辑是具有状态记忆的电路,其输出不仅依赖于当前的输入,而且依赖于以前的状态。可以使用always块和连续赋值assign语句实现时序电

31、路。1使用always块实现触发器只要在always块敏感信号表中定义有效的时钟沿,然后使用非阻塞过程赋值语句对信号赋值,就可以实现触发器或寄存器了。需要注意的是在always块中的过程赋值语句只能对reg型的信号进行赋值。【例9-10】Verilog HDL描述D触发器。module dff(q,a,b,clk);/q是输出,a、b是输入,clk是时钟信号 output q;input a,b,clk;reg q;always(posedge clk)/时钟clk的上升沿是敏感信号 begin q=a|b;/D触发器的驱动方程是a|b,这里使用非阻塞型赋值语句 endendmodule,2使

32、用连续赋值语句实现电平敏感的触发器在Verilog HDL中实现电平敏感的触发器最好使用连续赋值语句assign。【例9-11】Verilog HDL连续赋值语句描述电平敏感的同步触发器。module latch(q,a,b,clk);/q是输出,a、b是输入,clk是时钟信号 output q;input a,b,clk;assign q=clk?(a|b):q;/连续赋值语句endmodule,3使用always块实现电平敏感的触发器always块同样能实现电平敏感的触发器。【例9-12】Verilog HDL中的always块实现电平敏感的触发器。module lat2(q,a,b,cl

33、k);/q是输出,a、b是输入,clk是时钟信号output q;input a,b,clk;reg q;always(clk or a or b)begin if(clk)q=a|b;endendmodule,4置位与清零异步置位与清零的触发器中,置位与清零信号的作用与时钟信号无关;同步置位与清零的触发器中,置位与清零信号的作用一定等到时钟的有效边沿出现时起作用。(1)异步置位与清零异步置位(set)与清零(reset)的触发器描述,always块中的敏感信号应该为:always(时钟边沿关键字 时钟信号 or 时钟边沿关键字 置位信号 or 时钟边沿关键字 复位信号)其中对于高电平有效的置

34、位和清零信号,使用的时钟边沿关键字是posedge;而对于低电平有效的置位和清零信号,应该使用的时钟边沿关键字是negedge。对于高电平置位和清零的D触发器,一般有如下格式:always(posedge clk or posedge set or posedge reset)/上升沿时钟,高电平置位与复位begin if(reset)begin/*置位输出为0*/end else if(set)begin/*置位输出为1*/end else begin/*时钟边沿执行的逻辑*/endend,(2)同步置位与清零对于同步置位与清零的触发器,其置位和清零信号是在时钟信号的有效沿发挥作用的,描述这

35、些触发器的always块的敏感信号只有时钟,但是在块内总是首先检查置位和清零信号。对于高电平置位清零的同步触发器,有如下格式:always(posedge clk)/敏感信号表中只有时钟沿begin if(reset)begin/*触发器清零*/end else if(set)begin/*触发器置位*/end else begin/*时钟逻辑*/endend,9.7 Verilog HDL语言描述状态机Verilog HDL中常用always块和case语句描述状态机。状态机描述一般可分为次态逻辑、输出逻辑和状态寄存器三部分。1状态机描述 Verilog中需要定义寄存器变量,并进行状态编码。

36、定义寄存器变量分现态与次态,例如:reg 1:0 state,next_state;/定义位宽为2的寄存器信号state和next_state使用参数语句定义状态编码,例如:parameter s0=2b00,s1=2b01,s2=2b10,s3=2b11;/只能用1个参数语句定义状态编码 使用always语句描述状态寄存器的状态转换,例如:always(posedge clk)/描述状态寄存器的always块,在时钟的上升沿begin state=next_state;end/实现从现态到次态的状态转换 使用always语句、case语句描述次态逻辑。使用always语句或是连续赋值语句as

37、sign描述输出。或者使用always语句、case语句描述输出与次态逻辑,先描述输出,再描述次态逻辑。,2Verilog HDL描述状态机时应该注意的约定 每一个模块只描述一个状态机。在组合always块的顶部(case语句前)可给出次态的初始值,还可给输出赋初值。一旦在case语句前给输出赋初值,则在各状态下,可只对不同于初值的输出赋值。若是输出未赋过初值,则应该在各状态对所有输出信号赋值。若只对部分输出信号赋值,则在仿真时,有些状态下输出信号为任意值。状态转移描述,要把向其他状态转移的条件与保持在自己状态的条件同时写清楚。一般情况下,还应该给状态机设置一个异步或是同步复位引脚,以便在任何

38、情况下可以把状态机复位到初始状态。在复位或是在某些条件下,所有状态都向初始状态转移的情况,可以在状态寄存always块中处理。例如,按钮key在低电平时,从所有状态返回状态s0,则可以写成如下:always(posedge clk or negedge key)begin if(!key)state=s0;/描述key=0时,返回初始状态s0的语句 else state=next_state;/否则,从现态转到次态end,3状态机描述例题下面举例说明如何描述状态机的这三个部分。【例9-13】试用Verilog HDL描述图9-6所示的4状态摩尔状态机,该状态机有一个输入信号x和一个输出信号z。

39、,第1种描述:次态逻辑、输出逻辑使用一个always块描述,状态寄存器单独使用一个always描述的例子。Verilog HDL描述如下:module fsm1(clk,x,z);input x,clk;output z;reg z;reg 1:0 state,next_state;/定义寄存器类型的状态变量 parameter s0=2b00,s1=2b01,s2=2b10,s3=2b11;/用参数语句描述状态编码 always(posedge clk)/描述状态寄存器的always块 begin state=next_state;end/实现状态转换 always(state or x)/

40、次态逻辑和输出逻辑always块 begin case(state)s0:begin z=1;/状态s0,先描述输出z=1 if(!x)begin next_state=s1;end/再描述次态逻辑 else begin next_state=s0;end end,s1:begin z=0;/状态s1 if(x)begin next_state=s2;end else begin next_state=s1;end end s2:begin z=0;/状态s2 if(!x)begin next_state=s3;end else begin next_state=s2;end end s3:b

41、egin z=1;/状态s3 if(x)begin next_state=s0;end else begin next_state=s3;end end endcaseendEndmodule该例使用了两个always块,将次态逻辑、输出逻辑与状态寄存器分开描述,采用Max+Plus II软件,可以得到该例的仿真结果如图9-7所示,可以看出输出的变化与状态变化同时发生。,第2种描述:分别使用三个always块描述次态逻辑、输出逻辑和状态寄存器的例子。该描述的Verilog HDL源程序如下。module fsm2(clk,x,z);/clk是时钟。x是输入,z是输出input x,clk;ou

42、tput z;reg z;reg 1:0 state,next_state;/定义寄存器类型的状态变量parameter s0=2b00,s1=2b01,s2=2b10,s3=2b11;/用参数语句描述状态编码 always(posedge clk)/描述状态寄存器always块 begin state=next_state;end/实现状态转移 always(state or x)/描述次态逻辑的always块 begin case(state)s0:begin/状态s0 if(!x)begin next_state=s1;end else begin next_state=s0;end e

43、nd s1:begin/状态s1 if(x)begin next_state=s2;end else begin next_state=s1;end end,s2:begin/状态s2 if(!x)begin next_state=s3;end else begin next_state=s2;end end s3:begin/状态s3 if(x)begin next_state=s0;end else begin next_state=s3;end end endcaseendalways(state)/描述输出逻辑的always块 begin if(state=s0)|(state=s3)

44、z=1;else z=0;endEndmodule该例的仿真结果也如图9-7所示。,第3种描述:该例采用状态为独一编码的次态逻辑、状态寄存器和输出逻辑,分三个always块描述。module fsm3(clk,x,z);input x,clk;output z;reg z;reg 2:0 state,next_state;/初始状态的编码应该与复位、上电后的触发器状态一致parameter s0=4b000,s1=4b001,s2=4b010,s3=4b100;/参数语句描述独一编码 always(posedge clk)/状态寄存器的always块描述 begin state=next_st

45、ate;end always(state or x)/次态逻辑的always块 begin case(state)s0:begin/S0状态 if(!x)begin next_state=s1;end else begin next_state=s0;end end s1:begin/S1状态 if(x)begin next_state=s2;end else begin next_state=s1;end end,s2:begin/S2状态 if(!x)begin next_state=s3;end else begin next_state=s2;end end s3:begin/S3状态

46、 if(x)begin next_state=s0;end else begin next_state=s3;end end default:next_state=s0;endcaseend always(state)/描述输出逻辑的always块 begin if(state=s0)|(state=s3)z=1;else z=0;endEndmodule该例的仿真结果如图9-8所示。从仿真结果可知除了状态编码发生了变化,输出z的波形与前例的一样。,【例9-14】Verilog HDL描述图9-9(a)所示的状态机。该状态机的框图如图9-9(b)所示。该状态机的信号如下:低电平有效异步复位信号

47、rst_n,时钟信号clk。两个输入信号:运行信号go和等待信号ws。两个输出信号:读信号rd、选通信号ds。当复位信号为0,进入IDLE状态;若go信号为1,则进入读状态READ,这时读信号rd=1,选通信号ds=0;随后进入延时状态DLY,若是等待信号ws=1,则在READ状态与DLY状态之间交换,若是ws=0,则进入状态DONE,使ds=1后返回IDLE状态。该状态机用于控制CPU读存储器的过程,在go=1时,输出rd=1,进入读存储器状态,但是由于存储器速度慢,需要等待若干个CPU周期,当等待周期数未到ws=1,则等待;当等待周期数到后ws=0,使读选通信号ds=1后结束读操作。,如下

48、采用两个always块描述该状态机,其中一个always块采用非阻塞赋值,另一个always块采用阻塞赋值。module first(rd,ds,go,ws,clk,rst_n);output rd,ds;input go,ws,clk,rst_n;reg rd,ds;parameter IDLE=2b00,READ=2b01,DLY=2b11,DONE=2b10;/状态编码reg 1:0 state,next;always(posedge clk or negedge rst_n)/状态寄存器always块,该块采用非阻塞赋值 if(!rst_n)state=IDLE;else state=

49、next;always(state or go or ws)/次态逻辑与输出always块,该块采用阻塞赋值 begin next=bx;/设置初始次态为任意 rd=1b0;/设置输出rd初始状态 ds=1b0;/设置输出ds初始状态 case(state)IDLE:if(go)next=READ;/空闲状态 else next=IDLE;,READ:begin/读状态 rd=1b1;/由于在case语句前已经有了输出赋值,则这里只对变化/的输出赋值 next=DLY;endDLY:begin/延时状态 rd=1b1;if(!ws)next=DONE;else next=READ;end DO

50、NE:begin/完成状态 ds=1b1;next=IDLE;/返回空闲状态 end endcase endEndmodule该状态机的仿真结果如图9-10所示。,【例9-15】某控制器在按钮a按下后,控制信号y1输出高电平21s,然后输出低电平5s,再输出高电平25s。任何时候当按钮b为低电平时,将返回初始状态。该题的控制器框图如图9-11所示。状态图如图9-12所示。,该例题的状态机Verilog HDL描述如下,状态机的仿真如图9-13所示。module state(a,b,t,db1,db2,clk,td,state_out,y1);/state_out输出状态编码output t,d

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号