还剩15页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
Verilog HDL语言基础学问先来看两个Verilog HDL程序例
6.1一个8位全加器的Veri logHDL源代码module adder8cout,sum,ina,inb,cin;output[7:0]sum;output cout;input[7:0]ina,inb;input cin;assign{cout,sum}=ina+inb+cin;〃全力口endmodule【例
6.2]一个8位计数器的Verilog HDL源代码module countersout,cout,data,load,cin,elk;output[7:0]out;output cout;input[7:0]data;input load,cin,elk;reg[7:0]out;always©posedge elkbeginifload out二data;elseout=out+cin;endassign cout=outcin;endmodule从上面的例子可以看出
①Verilog HDL程序是由模块构成的每个模块的内容都是嵌在module endmodule两个语句之间,每个模块实现特定的功能,模块是可以进行层次嵌套的
②每个模块首先要进行端口定义,并说明输入input和输出output,然后对模块的功能进行逻辑描述
③Verilog HDL程序的书写格式自由,一行可以写几个语句,一个语句也可以分多行写
④除了endmodule语句外,每个语句的最终必需有分号
⑤可以用/*……*/和〃……对Verilog HDL程序的任何部分作注释
6.
1.2Verilog HDL模块的结构:低优先级
6.4语句Verilog HDL支持很多语句,从而成为结构化和过程性的语言Verilog HDL的语句包括:赋值语句,条件语句,循环语句,结构说明语句和编译预处理语句等每一类又包括几种不同的语句,详细如表
6.3所示表
6.3Verilog HDL语句赋值语句连续赋值语句过程赋值语句if-elsc语句条件语句case语句forever语句repeat语句循环语句while语句for语句initial语句结构说明语句always语句function语句define语句编译预处理语句include语句timescale语句
6.
4.1赋值语句
1.连续赋值语句assignassign为连续赋值语句,它用来对wire型变量进行赋值格式assign变量=表达式;如:assign c=ab;在上面的赋值中,a和b信号的任何变更,都将随时反映到c上来,因此称为连续赋值方式
2.过程赋值语句过程赋值语句用于对寄存器类型reg的变量进行赋值过程赋值有以下两种方式1非堵塞non_blocking赋值方式赋值号为=,如b=a;非堵塞赋值在块结束时才完成赋值操作,即b的值并不是立即就变更的2堵塞blocking赋值方式赋值号为=,如b=a;堵塞赋值在该语句结束时就完成赋值操作,即b的值在该赋值语句结束后立即变更假如在一个块语句中,有多条堵塞赋值语句,则在前面的赋值语句没有完成之前,后面的语句就不能执行,就像被堵塞blocking一样,因此称为堵塞赋值方式3堵塞赋值方式和非堵塞赋值方式的区分堵塞赋值方式和非堵塞赋值方式的区分常给设计人员带来问题问题主要是对“always”模块内的reg型变量得赋值不易把握为区分堵塞赋值及非堵塞赋值的不同,可看下面两例【例
6.4】非堵塞赋值【例
6.5】堵塞赋值module nonblock c,b,a,elk;module block c,b,a,elk;output c,b;output c,b;input elk,a;input elk,a;reg c,b;reg c,b;always@posedge elkalways@posedge elkbeginbeginb=a;b=a;c=b;c二b;encl enclendmodule将上面两段代码用MAX+PLUSI【进行综合,并进行仿真,可看到二者的区分对于非堵塞赋值,c的值落后b的值一个时钟周期,这是因为该always”块每一个时钟周期执行一次,因此信号的值每一个时钟周期更新一次,c的值是上一时钟周期的b值对于堵塞赋值,c的值和b的值一样,这是因为b的值是立即更新的为避开对这两种赋值语句的应用错误,建议在初学时刻只是用一种,比如接受堵塞赋值“二”,因为它类似C语言的赋值方式为避开出错,在同一块内,不要将输出重新作为输入运用而为实现上述非堵塞赋值功能,可接受两个always”块来实现,代码如下module nonblockc,b,a,elk;output c,b;input elk,a;reg c,b;always@posedge elkbeginb=a;endalways@posedge elkbeginc二b;endendmodule
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语句多用于多条件译码电路,如描述译码器,数据选择相,状态机及微处理器的指令译码等
(1).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的处理,即假如比较的双方有一方的某些位的值是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语句块,因此这里只介绍for和while两种语句
1.for语句格式for(表达式1;表达式2;表达式3)语句;即for(循环变量初值;循环结束条件;循环变量增值)执行语句;
2.while语句格式while(循环执行条件表达式)语句;while语句执行时,首先推断循环执行表达式是否为真,若为真,执行循环体中语句,然后,再推断循环执行条件表达式是否为真,……,直至条件表达式不为真为止循环体中语句可以是单句,也可以是多句,多句时用“begin-end”括起来
6.
4.4结构说明语句Verilog HDL中的任何过程模块都从属于以下4种结构说明语句◊initial OalwaysOtask Ofunctioninital说明语句一般用于仿真中的初始化,仅执行一次;always块内的语句则是不断重复执行的;task和function语句可以在程序模块中的一处或多处调用由于MAX+PLUS软件不支持task,initial语句,因此这里只介绍always和function两种结构说明语句
1.always块语句always块语句模板如下always®(〈敏感信号表达式》)begin〃过程赋值//if语句//case语句//while,repeat,for循环//task,function调用end在一个模块module中,运用always语句的次数是不受限制的always块内的语句是不断重复执行的说明⑴敏感信号表达式敏感信号表达式又称事务表达式或敏感表,当该表达式的值变更时,就会执行一遍块内语句因此在敏感信号表达式中应列出影响块内取值的全部信号一般为全部输入信号若有两个或两个以上信号时,它们之间用〃r〃连接例如,下面用case语句描述的4选1数据选择器,只要输入信号inO,ini,in2,in3或选择信号sel[l:0]变更则输出变更,所以敏感信号表达式写为inO or ini or in2orin3or sei【例
6.6]用case语句描述的4选1数据选择器module mux4_l out,inO,ini,in2,in3,sei;output out;input inO,ini,in2,in3;input[1:0]sei;reg out;always@inO orini orin2orin3or seicasesei2bOO:out=inO;2bOl:out=inl;2biO:out=in2;2bl1:out=in3;default:out=2,bx;endcasecndmodulc⑵posedge及negedge关键字对于时序电路,事务是由时钟边沿触发的为表达边沿这个概念,VerilogHDL供应了posedgealways@posedge elk〃上升沿时刻计数和negedge两个关键字来描述比如在例
6.2的8位计数器中有块语句posedge elk表示时钟信号elk的上升沿,negedge elk表示时钟信号elk的下降沿
2.函数function函数的目的是返回一个用于表达式的值函数的定义格式为function〈返回值位宽或类型说明》函数名;端口声明;局部变量定义;其他语句;endfunction【例
6.7】函数举例function[7:0]gefun;input[7:0]x;reg[7:0]count;integer i;begincount=0;fori=0;i<=7;i=i+lifx[i]=lT bOcount=count+1;gefun=count;endendfunction上面的gcfun函数循环核对输人的每一位,计算出0的个数,并返回一个适当的值《返回值位宽或类型说明》是一个可选项,假如缺省,则返回值为一位关于寄存器类型的数据函数的定义中蕴含了一个及函数同名的,函数内部的寄存器在函数定义时,将函数返回值所运用的寄存器设为及函数同名的内部变量,因此函数名被赐予的值就是函数的返回值例如在上例中,gefun最终赐予的值即为函数的返回值函数的调用是通过将函数作为表达式中的操作数来实现的调用格式如下<函数名,<表达式》〈表达式〉;比如运用连续赋值语句调用函数gefun时,可以接受如下语句assign out=is_legal gefunin:1*bO;留意,在函数中不能包含有任何的时间限制语句,并且定义函数时至少要有一个输人参量
6.5语句的依次执行和并行执行用Verilog HDL模块来设计电路,首先应当清晰哪些操作是同时发生的,哪些是依次发生的在“always”模块内,逻辑是依据指定的依次执行的,〃always〃块内的语句称为依次语句因为这些语句完全依据书写的依次来执行〃always〃模块之间,是同时执行的,或者说是并行执行的两个或更多个〃always〃模块,“assign”语句,实例元件等都是同时执行的通过下面的例子,可以清晰地看到〃always〃模块内的语句是依次执行的,而always〃模块之间是并行执行的【例
6.8】依次执行模块1module serialq,a,elk【例
6.9】依次执行模块2output q,a;input elk;reg q,a;module seria2q,a,elkalways@posedge elk;begin output q,a;input elk;q=q;reg q,a;a=q;end always@posedge elk;beginendmodule endmodulae=q;q=q;end上面的两个例子,其区分只是在〃always〃模块内,把两个赋值语句的依次相互颠倒分别对上面的两个模块用MAX+PLUSTI软件进行模拟仿真,从得到的波形可以看到在模块1中q先取反,然后再取反给a,a和q的波形是相反的;在模块2中,q取反后赋值给q和a,a和q的波形是相同的假如将上述两句赋值语句分别放在两个〃always〃模块中,如下面例
6.8和例
6.9两个程序所示,经过仿真可以发觉:这两个〃always”模块放置的依次对结果并没有影响,因为这两个模块是并行执行的【例
6.10】并行模块11例
6.11】并行模块2modulepara1q,a,elk;moduleparal2q,a,elk;output q,a;outputq,a;Input elk;Input elk;reg q,a;reg q,a;always@posedge elkalways@posedge elkbeginbeginq=q;a=q;endendalways@posedge elkalways@posedge elkbeginbegina二q;q二q;endendendmodu1eendmodu1e例
6.10和例
6.11的仿真波形及例
6.9的仿真波形是完全相同的
6.6小结本章介绍Verilog HDL的语法结构,包括变量,语句,模块和不同抽象级别的电路的设计和描述须要留意的是,全部的VerilogHDL编译软件都只支恃该语言的某一个子集所以,在运用VerilogHDL进行编译时,必需弄清晰所用编译软件的功能,用编译软件支持的语句来描述所设计的系统七.参考资料《数字系统设计及Verilog HDL》电子工业出版社王金明等编著《CPLD逻辑电路设计及实习》捷太出版社萧如宜著VerilogHDL的基本设计单元是〃模块block”一个模块是由两部分组成的,一部分描述接口;另一部分描述逻辑功能,即定义输入是如何影响输出的下面举例说明,图
6.1示出了一个〃及-或-非〃门电路图
6.1〃及-或-非〃电路该电路表示的逻辑函数可以写为F=AB+CD用Verlog HDL语言对该电路进行描述如下【例
6.3】及-或-非门电路module AOIA,B,C,D,F;input A,//模块名为A0I端口列表A,B,C,D,F定B,C,D;//义模块的输入端口A,B,C,D定义模块的output F;//输出端口Fassign F=~AB ICD;//模块内的逻辑描述enclmodule从上面的例子可知,电路图符号的引脚也就是程序模块的端口,在程序模块内描述了电路图符号所实现的逻辑功能在上面的Verilog HDL设计中,模块中的第2,第3行说明接口的信号流向,第4行说明白模块的逻辑功能Verilog HDL结构完全嵌在module和endmodule声明语句之间,每个Verilog程序包括4个主要部分端口定义,I/O说明,信号类型声明和功能描述
1.模块的端口定义模块的端口声明白模块的输入和输出口其格式如下module模块名口1,口2,口3,04,;
2.模块内容模块内容包括I/O说明,信号类型声明和功能定义1I/O说明的格式如下输人口input端口名L端口名2,……端口名N;输出口output端口名L端口名2,……端口名N;I/O说明也可以写在端口声明语句里其格式如下module modulename input portl,inputport2,••,output portl,output port2,…;2信号类型声明它是说明逻辑描述中所用信号的数据类型及函数声明如reg[7:0]out;〃定义out的数据类型为reg寄存器型对于端口信号的缺省定义类型为wire连线型
6.
1.3逻辑功能定义模块中最重要的部分是逻辑功能定义有3种方法可在模块中描述逻辑
1.用assign语句如assign F=~AB|CD;这种方法的句法很简洁,只须写一个“assign,后面再加一个方程式即可“assign〃语句一般适合于对组合逻辑进行赋值,称为连续赋值方式
2.用元件例化instantiate如and myand3f,a,b,c;这个语句利用Verilog HDL供应的及门库,定义了一个三输入的及门接受实例元件的方法同在电路图输入方式下调入库元件一样,键入元件的名字和引脚的名字即可要求每个实例元件的名字必需是唯一的
3.用always块语句在【例
6.2】的计数器模块中always©posedge elk〃每当时钟上升沿到来时执行一遍块内语句beginifloadout=data;elseout=out+cin;endalways块可用于产生各种逻辑,常用于描述时序逻辑这个例子用always块生成了一个带有同步置数的计数器always块可用很多种描述手段来表达逻辑,如此例中就用了if-else语句来表达逻辑关系综上所述,可给出Verilog HDL模块的模板如下Verilog HDL模块的模板仅考虑用于逻辑综合的部分,不考虑用于逻辑模拟的部分module<顶层模块名>,〈输入输出端口列表》;output输出端口列表;〃输出端口声明input输入端口列表;〃输入端口声明/*定义数据,信号的类型,函数声明,用关键字wire,reg,funtion等定义*/〃运用assign语句定义逻辑功能wire结果信号名;assign〈结果信号名>=<表达式>;〃运用always块描述逻辑功能always@(〈敏感信号表达式))begin//过程赋值//if语句,//case语句//while,for,repeat循环语句//function调用end//模块元件例化<module_name模块名>,<instance_name例化元件名>,(<port_list端口列表》);//门元件例化gate_type_keyword<instance_name例化元件名>(<port_list>);endmodule
6.2数据类型及常量,变量Verilog HDL中共有19种数据类型数据类型是用来表示数字电路中的数据存储和传送单元的在此介绍4个最基本的数据类型integer型,parameter型,reg型和wire型Verilog HDL中也有常量和变量之分,他们分属以上这些类型常量在程序运行过程中,其值不能被变更的量称为常量
1.数字
(1)整数在Verilog HDL中,整数型常量(即整常数)有以下4种进制表示形式◊二进制整数(b或B);◊十进制整数(d或D);◊十六进制整数(h或H);◊八进制整数(或0)完整的数字表达式为〈位宽>Y进制X数字》,位宽为对应二迸制数的宽度,如8bl1000101〃位宽为8位的二进制数11000101;8hc5〃位宽为8位的十六进制数c5;十进制的数可以缺省位宽和进制说明,如197〃代表十进制数197⑵x和z值X表示不定值,Z表示高阻值每个字符代表的宽度取决于所用的进制,例如8bl001xxxx;等价于8h9x;8bl010zzzz;等价于8haz;当常量不说明位数时,默认值为32位此外,是高阻态的z的另一种表示符号
2.常量在Verilog HDL中,用parameter来定义常量,即用parameter来定义一个标记符,代表一个常量,称为符号常量其定义格式如下parameter参数名1=表达式,参数名2=表达式,参数名3=表达式;例如parameter sel=8,code=8,ha3;〃分别定义参数sei为常数8(十进制),参数code为常数a3(十六进制)
6.
2.2变量变量是在程序运行过程中其值可以变更的量变量分为两种一种为网络型(nets type),另一种为寄存器型(register type)o1nets型变量wirenets型变量指输出始终依据输入的变更而更新其值的变量,它一般指的是硬件电路中的各种物理连接Verilog HDL中供应了多种nets型变量,详细见表
6.1表
6.1常用的nets型变量及说明类型功能说明wire,tri连线类型(wire和tri功能完全相同)wor,trior具有线或特性的连线(两者功能一样)wand,triand具有线及特性的连线(两者功能一样)tri1,triO分别为上拉电阻和下拉电阻supplyl,supplyO分别为电源(逻辑1)和地(逻辑0)这里着重介绍wire型变量wire是一种常用的nets型变量,wire型数据常用来表示assign语句赋值的组合逻辑信号Verilog HDL模块中的输入/输出信号类型缺省时自动定义为wire型Wire型信号可以用作任何方程式的输入,也可以用作assign语句和实例元件的输出,其取值为0,1,x,Zowire型变量格式如下⑴.定义宽度为1位的变量例如wire a,b;〃定义了两个宽度为1位wire型变量a,bwire数据名L数据名2,……数据名n;
2.定义宽度位n位的向量vectors wire[n-l:0]数据名L数据名2,数据名n;或wire[n:l]数据名L数据名2,……数据名n;例如wire[7:0]databus;〃定义一个8位wire型向量或wire[8:1]databus;wire型向量可按以下方式运用wire[7:0]in,out;〃定义两个8位wire型向量in,outassign out=in;若只运用其中某几位,可干脆指明,留意宽度要一样如wire[7:0]out;wire[3:0]in;assign out[5:2]=in;//out向量的其次位到第5位及in向量相等
2.register型变量regregister型变量对应的是具有状态保持作用的电路元件,如触发器,寄存器等register型变量及nets变量的根本区分在于register须要被明确地赋值,并在被重新赋值前始终保持原值在设计中必需将寄存器型变量放在过程块语句如initial,always中,通过过程赋值语句赋值另外,在always过程块内被赋值的每一个信号都必需定义成寄存器型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若定义一个向量,则按以下格式reg[n-l:0]数据名1,数据名2,……数据名n;或reg[n:l]数据名居数据名2,……数据名n;它们定义了数据的宽度为n位如F面的语句定义了8位宽的数据例如reg[7:0]data;〃定义data为8位宽的reg型向最或reg[8:1]data;
3.数组若干个相同宽度的向量构成数组,reg型数组变量即为memory型变量,即可定义存储器型数据如reg[7:0]mymem[1023:0];上面的语句定义了一个1024个字节,每个字节宽度为8位的存储器通常,存储器接受如下方式定义parameter wordwidth=8,memsize=1024;reg[wordwidth-l:0]mymem[memsize-l:0];上面的语句定义了一个宽度为8位,1024个存储单元的存储器,该存储器的名字是mymem,若对该存储器中的某一单元赋值的话,接受如下方式mymem
[8]=l;//mymem存储器中的第8个单元赋值为1留意Verilog HDL中的变量名,参数名等标记符是对大小写字母敏感的
6.3运算符及表达式
6.
3.1运算符
1.算术运算符+加-减*乘/除%求模算术运算符都是双目运算符
2.逻辑运算符逻辑及II逻辑或!逻辑非
3.位运算符位运算是将两个操作数按对应位进行逻辑运算位运算符包括按位取反按位及I按位或小按位异或K,“c按位同或当两个不同长度的数据进行位运算时,会自动地将两个操作数按右端对齐,位数少的操作数会在高位用0补齐
4.关系运算符小于二小于或等于大于=大于或等于在进行关系运算时,假如声明的关系是假,则返问值是0;假如声明的关系是真,则返回值是1;假如某个操作数的值不定,则其结果是模糊的,返回值是不定值
5.等式运算符==等于!=不等于二二二全等!==不全等这4种运算符都是双目运算符,得到的结果是1位的逻辑值假如得到1,说明声明的关系为真;如得到0,说明声明的关系为假相等运算符
(二二)和全等运算符(二=二)的区分是参及比较的两个操作数必需逐位相等,其相等比较的结果才为1,假如某些位是不定态或高阻值,其相等比较得到的结果就会是不定值而全等比较(二==)是对这些不定态或高阻值的位也进行比较,两个操作数必需完全一样,其结果才为1否则结果是0如设寄存器变量a=5bll0x01,b=5Tlx01,则=b”得到的结果为不定值x,而a===b”得到的结果为
16.缩减运算符(单目运算)及及非〜I或“I或非异或…,一同或缩减运算符及位运算符的逻辑运算法则一样,但缩减运算是对单个操作数进行及,或,非递推运算的如reg[3:0]a;b=a;〃等效于b=((a
[0]a
[1])a
[2])a
[3];例若A=5bl1001,则A=0;〃只有A的各位都为1时,其及缩减运算的值才为1|A=1;〃只有A的各位都为0时,其或缩减运算的值才为
07.移位运算符»右移«左移移位运算符用法An或A n表示把操作数A右移或左移n位,并用0填补移出位
8.条件运算符三目运算符格式信号=条件表达式L表达式2;当条件成立时,信号取表达式1的值,反之取表达式2的值.
9.位拼接运算符{}〃将两个或多个信号的某些位拼接起来用法{信号1的某几位,信号2的某几位,……,信号n的某几位}例如,在进行加法运算时,可将输出及和拼接在一起运用output[3:0]sum;〃sum代表和output cout;〃cout为进位输出input[3:0]ina,inb;input cin;assign{cout,sum}=ina+inb+cin;〃进位及和拼接在一起位拼接可以嵌套运用,还可以用重复法来减化书写,如{3{a,b}等同于{{a,b},{a,b,{a,b}},也等同于{a,b,a,b,a,b}
6.
3.
2.运算符的优先级以上运算符的优先级如下优先级!,IWJ*,/,%+,-«,»,=,=W|W IWW,•,y,~I,〜III。