verilog部分语法

来源:互联网 发布:算法注册机apk 编辑:程序博客网 时间:2024/05/07 15:05

 

二. reg型


always块内被赋值的每一个信号都必须定义成reg型。


reg型数据的缺省初始值是不定值


reg型只表示被定义的信号将用在always块内,理解这一点很重要。并不是说reg型信号一定是寄存器或触发器的输出。虽然reg型信号常常是寄存器或触发器的输出,但并不一定总是这样。



三. memory型


memory型数据是通过扩展reg型数据的地址范围来生成的。其格式如下:



reg [n-1:0] 存储器名[m-1:0];


或  reg [n-1:0] 存储器名[m:1];



在这里,reg[n-1:0]定义了存储器中每一个存储单元的大小,即该存储单元是一个n位的寄存器。存储器名后的[m-1:0]或[m:1]则定义了该存储器中有多少个这样的寄存器


reg [7:0]  mema[255:0];



这个例子定义了一个名为mema的存储器,该存储器有256个8位的存储器。该存储器的地址范围是0到255。注意:对存储器进行地址索引的表达式必须是常数表达式。


尽管memory型数据和reg型数据的定义格式很相似,但要注意其不同之处。如一个由n个1位寄存器构成的存储器组是不同于一个n位的寄存器的。见下例:



reg [n-1:0] rega;     //一个n位的寄存器


reg mema [n-1:0];     //一个由n个1位寄存器构成的存储器组



一个n位的寄存器可以在一条赋值语句里进行赋值,而一个完整的存储器则不行。见下例:



rega =0;    //合法赋值语句


mema =0;    //非法赋值语句



如果想对memory中的存储单元进行读写操作,必须指定该单元在存储器中的地址。下面的写法是正确的。


mema[3]=0;  //给memory中的第3个存储单元赋值为0。


3.3.1.基本的算术运算符



在Verilog HDL语言中,算术运算符又称为二进制运算符,共有下面几种:


1)       + (加法运算符,或正值运算符,如 rega+regb,+3)


2)       - (减法运算符,或负值运算符,如 rega-3,-3)


3)       × (乘法运算符,如rega*3)


4)       / (除法运算符,如5/3)


5)       % (模运算符,或称为求余运算符,要求%两侧均为整型数据。如7%3的值为1)



注意: 在进行算术运算操作时,如果某一个操作数有不确定的值x,则整个结果也为不定值x。


1)       ~           //取反


2)       &           //按位与


3)       |           //按位或


4)       ^           //按位异或


5)       ^~          //按位同或(异或非)


在Verilog HDL语言中存在三种逻辑运算符:


1)       && 逻辑与


2)       || 逻辑或


3)       !  逻辑非



关系运算符共有以下四种:



a < b        a小于b


a > b        a大于b


a <= b       a小于或等于b


a >= b       a大于或等于b



3.3.5.等式运算符


3.3.6.移位运算符


3.3.7.位拼接运算符(Concatation)


3.3.10.关键词


在Verilog HDL中,所有的关键词是事先定义好的确认符,用来组织语言结构。关键词是用小写字母定义的,因此在编写原程序时要注意关键词的书写,以避免出错。下面是Verilog HDL中使用的关键词(请参阅附录:Verilog语言参考手册):



always, and, assign,begin,buf,bufif0,bufif1,case,casex,casez,cmos,deassign,default,defparam,disable,edge,else,end,endcase,endmodule,endfunction,endprimitive, endspecify, endtable, endtask, event, for, force, forever, fork, function,highz0, highz1, if,initial, inout, input,integer,join,large,macromodule,medium,module,nand,negedge,nmos,nor,not,notif0,notifl, or, output, parameter, pmos, posedge, primitive, pull0, pull1, pullup, pulldown, rcmos, reg, releses, repeat, mmos, rpmos, rtran, rtranif0,rtranif1,scalared,small,specify,specparam,strength,strong0, strong1, supply0, supply1, table, task, time, tran, tranif0, tranif1, tri, tri0, tri1, triand, trior, trireg,vectored,wait,wand,weak0,weak1,while, wire,wor, xnor, xor





(1).非阻塞(Non_Blocking)赋值方式( 如 b <= a; )


1)       块结束后才完成赋值操作。


2)       b的值并不是立刻就改变的。


3)       这是一种比较常用的赋值方法。(特别在编写可综合模块时)



(2).阻塞(Blocking)赋值方式( 如 b = a; )


1)       赋值语句执行完后,块才结束。


2)       b的值在赋值语句执行完后立刻就改变的。


3)       可能会产生意想不到的结果。



一.顺序块


顺序块有以下特点:


1)       块内的语句是按顺序执行的,即只有上面一条语句执行完后下面的语句才能执行。


2)       每条语句的延迟时间是相对于前一条语句的仿真时间而言的。


3)       直到最后一条语句执行完,程序流程控制才跳出该语句块。


顺序块的格式如下:


begin


语句1;


语句2;


......


语句n;


end


其中:


Ÿ         块名即该块的名字,一个标识名。其作用后面再详细介绍。


Ÿ         块内声明语句可以是参数声明语句、reg型变量声明语句、integer型变量声明语句、real型变量声明语句。



二. 并行块


并行块有以下四个特点:


1)       块内语句是同时执行的,即程序流程控制一进入到该并行块,块内语句则开始同时并行地执行。


2)       块内每条语句的延迟时间是相对于程序流程控制进入到块内时的仿真时间的。


3)       延迟时间是用来给赋值语句提供执行时序的。


4)       当按时间时序排序在最后的语句执行完后或一个disable语句执行时,程序流程控制跳出该程序块。



并行块的格式如下:


fork


语句1;


语句2;


.......


语句n;


join


其中:


·         块名即标识该块的一个名字,相当于一个标识符。


·         块内说明语句可以是参数说明语句、reg型变量声明语句、integer型变量声明语句、real型变量声明语句、time型变量声明语句、事件(event)说明语句。



在fork_join块内,各条语句不必按顺序给出,因此在并行块里,各条语句在前还是在后是无关紧要的。见下例:



三. 块名


在VerilgHDL语言中,可以给每个块取一个名字,只需将名字加在关键词begin或fork后面即可。这样做的原因有以下几点


1)       这样可以在块内定义局部变量,即只在块内使用的变量。


2)       这样可以允许块被其它语句调用,如被disable语句。


3)       在Verilog语言里,所有的变量都是静态的,即所有的变量都只有一个唯一的存储地址,因此进入或跳出块并不影响存储在变量内的值。


基于以上原因,块名就提供了一个在任何仿真时刻确认变量值的方法。





   
       
           
           


           


           
       
   





casez语句用来处理不考虑高阻值z的比较过程,casex语句则将高阻值z和不定值都视为不必关心的情况。



如果用到if语句,最好写上else项。如果用case语句,最好写上default项。遵循上面两条原则,就可以避免发生这种错误,使设计者更加明确设计目标,同时也增强了Verilog程序的可读性。


3.6.循环语句



在Verilog HDL中存在着四种类型的循环语句,用来控制执行语句的执行次数。



1)     forever    连续的执行语句。


2)     repeat 连续执行一条语句 n 次