2020年1月10日1数据类型用来表示数字电路硬件中的数据存储和传送的元素。VerilogHDL共有19种数据类型,分2大类数据:线网类型表示器件之间的物理连接。其数值由驱动元件决定,如果没有驱动元件连接到线网上,则其默认值为高阻Z。寄存器类型表示数据的储存单元。其默认值为不定X。两者最大的区别:寄存器类型保持最后一次的赋值,而线网类型则需要持续的驱动。数据类型2020年1月10日2wire(网络连线):由模块或门驱动的连线。驱动端信号的改变会立刻传递到输出的连线上。例如:右图上,selb的改变,会自动地立刻影响或门的输出。netsabslselbselanslout线网类型2020年1月10日3线网类型线网型数据常用来表示以assign关键字指定的组合逻辑信号。Verilog程序模块中输入输出信号类型缺省时自动定义为wire型。wire型信号可以用作任何方程式的输入,也可以用作“assign”语句或实例元件的输出。定义格式:wire[位宽]数据名1,数据名2,…数据名n;wirea;//定义了一个一位的wire型数据wire[7:0]b;//定义了一个八位的wire型数据wire[4:1]c,d;//定义了二个四位的wire型数据2020年1月10日4线网类型变量的种类:类型功能wire,tri对应于标准的互连线(缺省)supply1,supply2对应于电源线或接地线wor,trior对应于有多个驱动源的线或逻辑连接wand,triand对应于有多个驱动源的线与逻辑连接trireg对应于有电容存在能暂时存储电平连接tri1,tri0对应于需要上拉或下拉的连接如果不明确地说明连接是何种类型,默认为wire类型。其中只有wire,tri,supply1,supply2是可综合的,其余只能用于仿真语句2020年1月10日5线网类型Verilog语法规定可以对wire型变量有多个驱动,但只有用于仿真,在实际电路中,对任何信号有多个驱动源都会产生不确定的后果,因此综合是过不去的wirea,b,c;assignc=a;assignc=b;在Verilog定义中,wire、tri功能是完全一致的,提供这两种不同名称的目的是为了与模型中所使用的变量实际情况相一致。2020年1月10日6wireab;ababcNAND2wirea,b,c;assignc=a&b;线网类型2020年1月10日7寄存器类型寄存器型变量具有存储性,即在接受下一个赋值前,将保持原值,默认的初始状态为“X”。寄存器数据类型包含下列5类数据类型:reg:最常用的,用于行为描述中对寄存器类的说明integer:32位带符号整形变量time:64位无符号时间变量real:64位浮点、双精度、带符号实形变量realtime:其特征与real型变量一致2020年1月10日8寄存器类型(reg)定义寄存器数据类型的关键字是reg,可以通过赋值语句改变寄存器存储的值。reg类型数据的缺省初始值为不定值x,这在电路仿真时需要十分注意,建议仿真前都要明确给每一个寄存器确定初始值。在“always或initial”块内被赋值每一个信号都必须定义成reg类型。定义方式:reg[位宽]数据名1,数据名2,…数据名i;regrega;//定义了一个1位reg型数据reg[3:0]regb;//定义一个4位的reg型数据reg[4:0]regc,regd;//定义两个5位的reg型数据2020年1月10日9reg型变量能保持其值,直到它被赋于新值。reg型变量常用于行为建模,产生测试的激励信号。常用行为语句结构来给reg类型的变量赋值。abslselbselansloutreg_areg_selreg_b寄存器(register)类型变量2020年1月10日10wireclk,d;regq;always@(posedgeclk)q=d;•reg型数据常用来表示“always”模块内的指定信号,代表触发器。寄存器类型(reg)2020年1月10日11dout2AND2i1clkout1DQDFFmodulerw2(clk,d,out1,out2);inputclk,d;outputout1,out2;regout1;wireout2;assignout2=d&(~out1);always@(posedgeclk)beginout1=d;endendmodule用寄存器(reg)类型变量生成触发器例子2020年1月10日12寄存器类型(reg)注意:reg型只表示被定义的信号将用在“always或initial”块内,理解这一点很重要。虽然reg型信号常常是寄存器或触发器的输出,但并不是说reg型信号一定是寄存器或触发器的输出。aout2BUFFbINVout1modulerw1(a,b,out1,out2);inputa,b;outputout1,out2;regout1;wireout2;assignout2=a;always@(b)out1=~b;endmodule2020年1月10日13reg和wire类型变量的区别reg类型的变量可以被直接赋予数值,向外输出信号而wire类型的变量值是由驱动它的电路决定的2020年1月10日14位选择和部分选择位选择从向量中抽取特定的位。形式如下:wire或者reg向量名[bit_select_expr]reg[5:0]State;wire[3:0]Prt;State[1]&&State[4]//寄存器位选择。Prt[0]|Bbq//线网位选择。2020年1月10日15位选择和部分选择在部分选择中,向量的连续序列被选择。形式如下:wire或者reg向量名[常数表达式1:常数表达式2]reg[5:0]State;wire[3:0]Prt;State[4:1]//寄存器部分选择。Prt[3:2]//线网部分选择。2020年1月10日16存储器通过对reg型变量建立数组来对存储器进行建模。reg[n-1:0]存储器名[m-1:0];reg[n-1:0]定义了存储器中每一个存储单元的大小,即该存储单元是一个n位的寄存器。存储器名后的[m-1:0]则定义了该存储器中有多少个这样的寄存器(即地址),最后用分号结束定义语句。reg[7:0]mema[255:0];//256x8位的存储器。2020年1月10日17存储器一个由n个1位寄存器构成的存储器组不同于一个n位的寄存器。reg[n-1:0]rega;//一个n位的寄存器regmema[n-1:0];//一个由n个1位寄存器构成存储器组一个n位的寄存器可以在一条赋值语句里进行赋值,而一个完整的存储器则不行。rega=0;//合法赋值语句mema=0;//非法赋值语句mema[3]=0;//正确.给memory中的第3个存储单元赋值0.2020年1月10日18输入口(input)可以由寄存器或网络连接驱动,(即外部连接它可以是reg或wire型),但它本身只能是wire型。输出口(output)可以是wire或reg型,但它本身只能驱动线网型,即外部连接它只能是wire型。输入/输出口(inout)只能定义为wire型,并且与它连接也只能是wire型。如果信号变量是在过程块(initial块或always块)中被赋值的,必须把它声明为寄存器类型变量如何选择数据类型2020年1月10日19如何选择数据类型举例说明例化时数据类型的选择moduletop;wirey;rega,b;DUTu1(y,a,b);initialbegina=0;b=0;#10a=1;….endendmodule模块DUT的边界输入口输出口输出/入口netnetnet/registernetnet/registernetinoutmoduleDUT(Y,A,B);outputY;inputA,B:wireY,A,B;and(Y,A,B);endmodule2020年1月10日20选择数据类型时常犯的错误把模块的输入信号定义为寄存器类型了。把例化后的输出连接出去时,把它定义为寄存器类型了。在过程块中对变量赋值时,忘了把它定义为寄存器类型(reg)或已把它定义为连接类型了(wire)。这是经常犯的三个错误!!!如何选择数据类型2020年1月10日21参数(parameters)在Verilog中用parameter定义一个代表常量的标识符,称为符号常量,采用标识符代表一个常量可提高程序的可读性和可维护性,且在有限状态机中经常使用符号常量。参数型常数也经常用于定义延迟时间和变量宽度。parameter参数名1=表达式1,…,参数名n=表达式n;parameterwordsize=16,memsize=256;//定义二个参数;reg[wordsize-1:0]mem[memsize-1:0];//存储器声明参数是本地的,其定义只在本模块内有效2020年1月10日22参数值的改写:•在模块或实例引用时可通过参数传递来改变被引用模块或实例中已定义的参数。参数(parameters)moduleadder(a,b,sum);parameterwid=8;Input[wid-1:0]a,b;output[wid:0]sum;……endmodulemoduleTOP(ina,inb,out);input[8:0]ina,inb;output[9:0]out;…..adderu1(ina,inb,out,);defparamu1.wid=9;……endmodule参数值的改写:方法一2020年1月10日23参数(parameters)moduleadder(a,b,sum);parameterwid=8;Input[wid-1:0]a,b;output[wid:0]sum;……endmodulemoduleTOP(ina,inb,out);input[8:0]ina,inb;output[9:0]out;…..adder#(9)u1(ina,inb,out,);……endmodule参数值的改写:方法二2020年1月10日24赋值运算符分连续赋值和过程赋值两种过程赋值主要用于两种结构模块(initial和always),分为阻塞和非阻塞赋值。连续赋值语句只能对线网型变量进行赋值,而不能对寄存器变量进行赋值连续赋值语句的语法为:assign#延时量线网型变量名=赋值表达式只要右端表达式中任一个操作数值发生变化,就会立即触发对被赋值变量的更新操作2020年1月10日25连续赋值语句应用对标量线网赋值wirea,b;assigna=b;对矢量线网赋值wire[7:0]a,b;assigna=b;对矢量线网某几位赋值wire[7:0]a,b;assigna[3:0]=b[4:1];对任意拼接线网赋值wirea,b;wire[1:0]c,d;assignc={a,b};assign{a,b}=d;2020年1月10日26Verilog中的大小(size)与符号Verilog会根据表达式中变量长度对表达式值自动地进行调整。Verilog自动截断或扩展赋值语句中右边的值以适应左边变量的长度。modulesign_size;reg[3:0]a,b;reg[15:0]c;initialbegina=-1;//a是无符号数,因此其值为1111b=8;c=8;//b=c=1000#10b=b+a;//结果10111截断,b=0111#10c=c+a;//c=10111endendmodule当一个负数赋值给无符号变量如reg时,Verilog自动完成二进制补码计算2020年1月10日27逻辑反与位反的对比modulenegation();reg[3:0]rega,regb;reg[3:0]bit;reglog;initialbeginrega=4'b1011;regb=4'b0000;endinitialfork#10bit=~rega;//num=01