您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 质量控制/管理 > System-Verilog笔记总结
Systemverilog数据类型l合并数组和非合并数组1)合并数组:存储方式是连续的,中间没有闲置空间。例如,32bit的寄存器,可以看成是4个8bit的数据,或者也可以看成是1个32bit的数据。表示方法:数组大小和位,必须在变量名前指定,数组大小必须是【msb:lsb】Bit[3:0][7:0]bytes;2)二维数组和合并数组识别:合并数组:bit[3:0][7:0]arrys;大小在变量名前面放得,且降序二维数组:intarrays[0:7][0:3];大小在变量名后面放得,可降序可升序位宽在变量名前面,用于识别合并和非合并数组,位宽在后面,用于识别数组中元素个数。3)非合并数组一般仿真器存放数组元素时使用32bit的字边界,byte、shortint、int都放在一个字中。非合并数组:字的地位存放变量,高位不用。表示方法:Bit[7:0]bytes;4)合并数组和非合并数组的选择(1)当需要以字节或字为单位对存储单元操作。(2)当需要等待数组中变化的,则必须使用合并数组。例如测试平台需要通过存储器数据的变化来唤醒,需要用到@,@只能用于标量或者合并数组。Bit[3:0][7:0]barray[3];表示合并数组,合并数组中有3个元素,每个元素时8bit,4个元素可以组成合并数组可以使用barry[0]作敏感信号。l动态数组随机事物不确定大小。使用方法:数组在开始是空的,同时使用new[]来分配空间,在new[n]指定元素的个数。Intdyn[];Dyn=new[5];//分配5个元素空间Dyn.delete();//释放空间l队列在队列中增加或删除元素比较方便。l关联数组当你需要建立一个超大容量的数组。关联数组,存放稀疏矩阵中的值。表示方法:采用在方括号中放置数据类型的形式声明:Bit[63:0]assoc[bit[63:0]];l常量:1)Verilog推荐使用文本宏。好处:全局作用范围,且可以用于位段或类型定义缺点:当需要局部常量时,可能引起冲突。2)Parameter作用范围仅限于单个module3)Systemverilog:参数可以在多个模块里共同使用,可以用typedef代替单调乏味的宏。过程语句l可以在for循环中定义变量,作用范围仅在循环内部for(inti=0;i10;i++)array[i]=i;l任务、函数及void函数1)区别:Verilog中task和function最重要的区别是:task可以消耗时间而函数不能。函数中不能使用#100的延时或@的阻塞语句,也不能调用任务;Systemverilog中函数可以调用任务,但只能在forkjoinnone生成的线程中。2)使用:如果有一个不消耗时间的systemverilog任务,应该把它定义成void函数;这样它可以被任何函数或任务调用。从最大灵活性角度考虑,所有用于调用的子程序都应该被定义成函数而非任务,以便被任何其它任务或函数调用。(因为定义成任务,函数调用任务很有限制)l类静态变量作用:1)类的静态变量,可以被这个类的对象实例所共享。当你想使用全局变量的时候,应该先想到创建一个类的静态变量静态变量在声明的时候初始化。2)类的每一个实例都需要从同一个对象获取信息。l静态方法作用:当静态变量很多的时候,操作它们的代码是一个很大的程序,可以用在类中创建一个静态方法读写静态变量,但是静态方法不能读写非静态变量。lref高级的参数类型Ref参数传递为引用而不是复制。Ref比input、output、inout更好用。Functionvoidprint_checksum(constrefbit[31:0]a[]);1)也可以不用ref进行数组参数传递,这时数组会被复制到堆栈区,代价很高。2)用带ref进行数组参数传递,仅仅是引用,不需要复制;向子程序传递数组时,应尽量使用ref以获得最佳性能,如果不希望子程序改变数组的值,可以使用constref。3)Ref参数,用ref传递变量;可以在任务里修改变量而且,修改结果对调用它的函数可见,相对于指针的功能。lReturn语句增加了return语句。Task任务由于发现了错误而需要提前返回,如果不这样,那么任务中剩下的语句就必须被放到一个else条件语句中。体会下Taskload_array(intlen.Refintarray[]);If(len0)begin$display(“Badlen”);Returun;//任务中其它代码…endtaskl局部数据存储automatic作用Verilog中由于任务中局部变量会使静态存储区,当在多个地方调用同一个任务时,不同线程之间会窜用这些局部变量。Systemverilog中,module和program块中,缺省使用静态存储;如果想使用自动存储,需加入automatic关键词。测试平台lInterface背景:一个信号可能连接几个设计层次,如果增加一个信号,必须在多个文件中定义和连接。接口可以解决这些问题。好处:如果希望在接口中增加一个信号,不需要改变其他模块,如TOP模块。使用方法:(1)接口中去掉信号的方向类型;(2)DUT和测试平台中,信号列表中采用接口名,例化一个名字注意:因为去掉了方向类型,接口中不需要考虑方向信号,简单的接口,可以看做是一组双向信号的集合。这些信号使用logic类型[d1]。双向信号为何可以使用logic呢?这里的双向,只是概念上的双向,不想verilog中databus多驱动的双向。双向信号如何做接口?(1)仲裁器的简单接口Interfacearb_if(inputbitclk);Logic[1:0]grant,request;Logicrst;EndinterfaceDUT使用接口:Modulearb(arb_ifarbif);…Always@(posedgearbif.clkornegedgearbif.rst)…endmodule(2)DUT不采用接口,测试平台中使用接口(推荐)DUT中源代码不需要修改,只需要再top中,将接口连接到端口上。Moduletop;Bitclk;Always#2clk=~clk;Arb_ifarbif(clk);Arb_portal(.grant(arbif.grant),.request(arbif.grant),.rst(arbif.rst),.clk(arbif.clk));Testt1(arbif);EndmodulelModport背景:端口的连接方式包含了方向信息,编译器依次来检查连续错误;接口使用无信号的连接方式。Modport将接口中信号分组并指定方向。例子:l在总线设计中使用modport并非接口中每个信号都必须连接。Data总线接口中就解决不了,个人觉得?因为data是一个双驱动l时钟块作用:一旦定义了时钟块,测试平台就可以采用@arbif.cb等待时钟,而不需要描述确切的时钟信号和边沿,即使改变了时钟块中的时钟或边沿,也不需要修改测试代码应用:将测试平台中的信号,都放在clocking中,并指定方向(以测试平台为参考的方向)。并且在modprottest(clockingcb,最完整的接口:Interfacearb_if(inputbitclk);Logic[1:0]grant,request;Logicrst;Clockingcb@(posedgeclk);Outputrequest;Inputgrant;EndclockingModporttest(clockingcb,Outputrst);Modportdut(inputclk,request,rst,Outputgrant);endinterface变化:将request和grant移动到时钟块中去了,test中没有使用了。l接口中的双向信号Interfacemaster_if(inputbitclk);//在类中为了,不使用有符号数,常用bit[]定义变量Wire[7:0]data;Clockingcb@(posedgeclk);Inoutdata;EndclockingModportTEST(clockingcb);endinterfaceprogramtest(master_ifmif);initialbeginmif.cb.data=‘z;@mif.cb;$display(mif.cb.data);//总线中读数据@mif.cb;Mif.cb.data=8’h5a;//驱动总线@mif.cb;Mif.cb.data=‘z;//释放总线注:(1)interface列表中clk采用的是inputbitclk;为什么要用bit?(2)时钟块clockingcb中,一般将testbench中需要的信号,方向指定在这里;而在modprot指定test信号方向的时候,采用clockingcb。(3)interface中信号,不一定都用logic,也可采用wire(双驱动);systemverilog中如果采用C代码的风格(参数列表中方向和类型写一起),必须采用logic类型(4)现在的风格,DUT没才用clockingcb,测试平台和DUT的时钟如何统一?l激励时序DUT和测试平台之间时序必须密切配合。l测试平台和设计间的竞争状态好的风格:使用非阻塞赋值可以减少竞争。systemverilog验证中initial中都采用=赋值,而等待延迟采用@arbif.cb等待一个周期来实现。而verilog中采用的风格时,initial中采用=阻塞赋值,沿时可以采用#2,等实现。因此时钟发生器,只能放在module中,而不能放在program中lProgram中不能使用always块测试平台可以使用initial但不能使用always,使用always模块不能正常工作。原因:测试平台的执行过程是进过初始化、驱动和响应等步骤后结束仿真。如果确实需要一个always块,可以使用initialforever来完成。比如:在产生时钟时。类l类中static变量背景:如果一个变量需要被其他对象所共享,如果没有OPP,就需要创建全局变量,这样会污染全局名字空间,导致你想定义局部变量,但变量对每个人都是可见的。1)作用:类中static变量,将被这个类的所有实例(对象)所共享,使用范围仅限于这个类。例:classtransaction;Staticintcount=0;Intid;EndclassTrasactiontr1,tr2;Id不是静态变量,所以每个trasaction对象都有自己的id;count是静态变量,所有对象只有一个count变量。如何用?当你打算创建一个全局变量的时候,首先考虑创建一个类的静态变量。2)static变量的引用句柄或类名加::4)static变量的初始化static变量通常在声明时初始化。不能在构造函数中初始化,因为每一个新的对象都会调用构造函数。l静态句柄:背景:当类的每一个对象,都需要从同一个对象(另一个类)中获取信息的时候。如果定义成非静态句柄,则每个对象都会有一份copy,造成内存浪费。l静态方法背景:当使用更多静态变量的时候,操作他们的代码会很长。作用:可以在类中创建一个静态方法用于读写静态变量。注:systemverilog不允许,静态方法读写非静态变量。l类之外的方法背景:解决类太长的问题。类最好控制在一页内,如果方法很都很长。lThis背景:如果在类很深的底层作用域,却想引用类一级的对象。在构造函数中最常见。作用:this指向类一级变量l如何做类,类做多大?上限:类不能太大当类中存在多处相同的代码,你需要将这段代码做成当前类的一个成员函数或父类的成员函数。下限:类不能太小类太小,增加了层次。方法:如果一个小类只被例化了一次,可以将它合并到父类中去。l动态对象概念区分:方法中修改对象和修改句柄修改对象——将对象的变量重新赋值。修改句柄——在任务中new()对象。1)当你将对象传递给方法背景:句柄,new()后变成对象,在将其作为参数传递给方法。实质和作用:传递的是句
本文标题:System-Verilog笔记总结
链接地址:https://www.777doc.com/doc-5582675 .html