概述
SystemVerilog Interface是modport的一种,但比简单的输入、输出或输入输出端口的功能更多。在其最简单的形式中,Interface端口将相关的信号捆绑在一起作为一个单一的复合端口。例如,构成AMBA AXI总线的所有单个信号都可以被归纳为一个Interface端口。一个Interface可以做的不仅仅是封装总线信号。SystemVerilog Interface为设计者提供了一种集中总线功能的方法,而不是将功能分散在设计中的几个模块中。这就模拟了设计工程师在RTL层面的工作,并让综合工作在整个设计中适当地分配门级总线硬件。
当遵循特定的建模准则和限制时,Interface是可以综合的。Interface也可以用在不可综合级别的建模,并作为验证测试平台的一部分。先进的验证方法,如UVM 、OVM和VMM,都使用Interface。
Interface方法(任务和函数)
SystemVerilog Interface的作用不仅仅是将相关的信号组合在一起。Interface还可以封装模块间的通信功能。通过将通信功能添加到Interface中,每个使用该Interface的模块可以简单地引用该功能,而不必在每个模块中重复该功能。Interface中的封装功能也可以独立于使用该Interface的模块进行验证。
Interface中封装的功能可以通过使用任务和函数来定义。Interface中的任务和函数被称为Interface方法(interface methods)。Interface方法(任务和函数)可以通过在模块的modport定义中使用导入语句被导入到需要它们的模块中。在modport中导入函数类似于从包中导入函数。
下面的例子给简单的AHB Interface增加了两个函数--一个是生成奇偶校验位值(使用奇数校验),另一个函数是检查数据是否与计算出的奇偶校验相符。hwdata和hrdata向量被声明为比以前的例子宽1位,额外的位被用作奇偶校验位。
例10-6:带有奇偶性逻辑Interface方法(函数)的Interface
/////////////////////////////////////////////////////////// //SimpleAHBInterfacewithparitymethods /////////////////////////////////////////////////////////// //`begin_keywords"1800-2012" interfacesimple_ahb( inputlogichclk,//bustransferclk inputlogichresetN//busreset,activelow ); logic[31:0]haddr;//transferstartaddress logic[32:0]hwdata;//datatoslave,withparitybit logic[32:0]hrdata;//datafromslave,withparitybit logic[2:0]hsize;//transfersize logichwrite;//1forwrite,0forread logichready;//1fortransferfinished functionautomaticlogicparity_gen(logic[31:0]data); return(^data);//calculateparityofdata(oddparity) endfunction functionautomaticlogicparity_chk(logic[31:0]data, logicparity); return(parity===^data);//1=OK,0=parityerror endfunction //mastermoduleportdirections modportmaster_ports( outputhaddr,hwdata,hsize,hwrite,//toAHBslave inputhrdata,hready,//fromAHBslave inputhclk,hresetN,//fromchiplevel importparity_gen,parity_check//functionimport ); //slavemoduleportdirections modportslave_ports( outputhrdata,hready,//toAHBmaster inputhaddr,hwdata,hsize,hwrite,//fromAHBmaster inputhclk,hresetN,//fromchiplevel importparity_check//functionimport ); //slavemoduleportdirections modportslave_ports_alt( outputhrdata,hready,//toAHBmaster inputhaddr,hwdata,hsize,hwrite,//fromAHBmaster inputhclk,hresetN,//fromchiplevel importfunctionlogicparity_chk(logic[31:0]data, logicparity) ); endinterface:simple_ahb //`end_keywords
在这个例子中,master_ports 的modport定义同时导入了parity_gen 和 parity_chk。modport从主模块的角度定义了端口方向和导入。因此,一个使用master_portsmodport的模块正在导入这些函数,类似于一个模块从包中导入函数的方式。
slave_portsmodport只导入parity_chk。一个使用slave_ports modport的模块不能访问parity_gen。因为这个方法没有被包含在modport 的导入中,所以从 slave_ports 提供的Interface来看,这个方法就好像不存在一样。
使用方法原型导入方法。作为选择,modport导入声明可以指定任务或函数参数的完整原型。而不是仅仅导入方法名,导入关键字后面是实际方法定义的声明行。这种风格的导入声明的基本语法是:
modport(import task( ))。 modport(importfunction ( ))。
比如说。
函数原型不包括automatic关键字,即使实际的函数被声明为automatic(这是综合所需要的)。
使用完整的原型来导入一个方法并没有什么好处。一些工程师认为,完整的原型可以直接记录任务或函数的参数,作为模口声明的一部分。当实际的任务或函数被定义在一个包中,并被导入到Interface中时,这种额外的代码记录会很方便。原型使方法类型和参数在Interface定义中可见,这样工程师就不需要到包含包的文件中去看方法类型和参数。
调用Interface中定义的方法
导入的方法是Interface的一部分,通过使用Interface端口名称来调用,与引用Interface中的信号的方式相同。语法是
. 。
前面展示的主模块有一个名为ahb 的 Interface端口 。因此,主模块可以通过引用ahb.parity_gen来调用Interface parity_gen方法。例如:
always_ff@(posedgeahb.hclk) ahb.hwdata[32]<= ahb.parity_gen(ahb.hwdata[31:0])。
综合Interface方法
从概念上讲,综合编译器通过在模块中创建该方法的本地副本来替换导入的方法,然后对该本地副本进行综合。综合后的模块版本将包含导入方法的逻辑,而不再从Interface中获取该功能。
最佳实践指南10-4 |
---|
对于可综合的RTL Interface,只在Interface中使用函数和无效函数。不要使用任务或always程序。 |
综合编译器对放置在模块中的Interface内容施加了同样的RTL编码限制。这些限制之一是,任务必须在零时间内执行。使用void函数而不是任务来执行这个综合限制。
注意事项 |
---|
导入的函数或任务必须被声明为automatic,并且不能包含静态声明,以便被综合。这与模块从包中导入函数或任务时的同义词规则相同。 |
一个automatic函数或任务在每次被调用时都会分配新的存储空间。当一个模块调用一个导入的方法时,所有内部存储的新副本被分配。这允许综合处理该方法,就好像它是模块内的一个本地副本。
抽象的、不可综合的Interface
SystemVerilog Interface能够以比RTL综合编译器所支持的更高的抽象水平来表示总线协议。例如,一个Interface任务,可能需要多个时钟周期来执行,可以代表一个完整的主从握手协议。该协议可以从主机发出传输请求开始,仲裁哪个从机收到请求,等待从机的反馈,传输数据,并收到数据被接收的确认信息。
这些Interface功能对抽象的事务级建模很有用,但目前的RTL综合编译器不支持。目前的SystemVerilog综合工具要求将Interface中编码的功能限制为零延迟和零时钟周期模型。这些综合限制可以通过将Interface中定义的功能代码限制为函数来满足。SystemVerilog的语法规则要求函数必须在零模拟时间内执行,这就要求综合器对零延迟Interface功能的要求。
一个Interface也可以包含验证程序和断言。这些验证代码可以通过将其包含在pragma中而隐藏起来。
//synthesistranslateoffand//synthesistranslateon.
Interface程序代码
除了任务和函数方法,Interface还可以包含初始和always程序块和assign。程序代码可以用来在一个Interface内建立功能模型,这些功能会影响到在Interface所代表的总线上交流的信息。
例10-7为简单AHB总线增加了一个时钟发生器hclk,为总线增加了一个复位同步器hresetN。在这个Interface的前几个例子中,这些信号是在Interface的外部产生的,并作为简单AHB Interface的输入端口传入。这个例子用芯片(或系统)级的时钟和复位取代了这些输入,并使用这些芯片级的信号来产生本地总线时钟和总线复位。这个本地功能然后成为主模块和从模块之间封装的总线通信的一部分。
例10-7:与内部程序代码的Interface,生成总线功能
/////////////////////////////////////////////////////////// //SimpleAHBInterfacewithclockgeneratorandreset //synchronizerproceduralcode /////////////////////////////////////////////////////////// //`begin_keywords"1800-2012" interfacesimple_ahb( inputlogicchip_clk,//externalclockfromthechip inputlogicchip_rstN//busreset,activelow ); logichclk;//localbustransferclk logichresetN;//localbusreset,activelow logic[31:0]haddr;//transferstartaddress logic[31:0]hwdata;//datasenttoslave logic[31:0]hrdata;//returndatafromslave logic[2:0]hsize;//transfersize logichwrite;//1forwrite,0forread logichready;//1fortransferfinished //generateAHBclock(divide-by-twoofchip_clk) always_ff@(posedgechip_clkornegedgechip_rstN) if(!chip_rstN)hclk<= '0; else hclk <= ~hclk; // sync trailing edge of hresetN to hclk logic rstN_tmp; // temp variable used inside the interface always_ff @(posedge hclk or negedge chip_rstN) if (!chip_rstN) begin // asynchronous active-low reset rstN_tmp <= '0; hresetN <= '0; end else begin rstN_tmp <= '1; // begin end of reset hresetN <= rstN_tmp; // stabilize reset end // master module port directions modport master_ports ( output haddr, hwdata, hsize, hwrite, // to AHB slave input hrdata, hready, // from AHB slave input hclk, hresetN // from chip level ); // slave module port directions modport slave_ports ( output hrdata, hready, // to AHB master input haddr, hwdata, hsize, hwrite, // from AHB master input hclk, hresetN // from chip level ); endinterface: simple_ahb //`end_keywords
综合Interface程序。综合编译器如何处理Interface中的程序代码并没有很好的定义,这与Interface方法(任务和函数)的情况不同。方法的综合是通过在概念上将方法代码复制到具有Interface端口的模块中,并对本地副本进行综合。这可以做到,因为方法是从模块内调用的,执行起来就像方法是该模块的一部分。然而,程序代码是从Interface内执行的,并影响到所有使用该Interface的模块。Interface中的程序代码类似于全局功能,综合编译器并不支持这种功能,如果有的话。
最佳实践指南10-5 |
---|
使用函数来模拟Interface内的功能。不要在可综合的RTL Interface中使用初始程序、always程序或assign赋值。 |
综合编译器对Interface内的程序代码的支持并不充分。如果支持的话,不同的综合编译器对程序性代码的处理方式也可能大相径庭。
参数化的Interface
Interface可以用与模块相同的方式使用参数重定义。这使得Interface模型可以被配置,因此Interface的每个实例可以有不同的配置。通过使用SystemVerilog的参数重定义结构,参数可以在Interface中使用,使向量大小和Interface中的其他声明可以重新配置。当Interface被实例化时,Interface的参数值可以被重新细化,这与模块重新定义的方式相同。
下面是简单AHB例子的变化,增加了参数,使数据矢量宽度在Interface实例化时可以配置。任何与Interface实例相连的模块间面端口将使用该Interface实例的向量大小。
例10-8:具有可配置总线数据字大小的参数化Interface
/////////////////////////////////////////////////////////// //SimpleAHBInterfacewithpareterizedbuswidths /////////////////////////////////////////////////////////// //`begin_keywords"1800-2012" interfacesimple_ahb #(parameterDWIDTH=32)//Databuswidth ( inputlogichclk,//bustransferclk inputlogichresetN//busreset,activelow ); logic[31:0]haddr;//transferstartaddress logic[DWIDTH-1:0]hwdata;//datasenttoslave logic[DWIDTH-1:0]hrdata;//returndatafromslave logic[2:0]hsize;//transfersize logichwrite;//1forwrite,0forread logichready;//1fortransferfinished //mastermoduleportdirections modportmaster_ports( outputhaddr,hwdata,hsize,hwrite,//toAHBslave inputhrdata,hready,//fromAHBslave inputhclk,hresetN//fromchiplevel ); //slavemoduleportdirections modportslave_ports( outputhrdata,hready,//toAHBmaster inputhaddr,hwdata,hsize,hwrite,//fromAHBmaster inputhclk,hresetN//fromchiplevel ); endinterface:simple_ahb //`end_keywords
下面的代码片断将例10-8中Interface的数据字大小重新定义为64位字大小。
simple_ahb#(.DWIDTH(64)) ahbl(.hclk, .hresetN );
综合Interface
Interface是SystemVerilog在原有的Verilog HDL中加入的一个强大的建模结构。Interface端口是从传统的Verilog模型中抽象出来的,在传统的Verilog模型中,一组相关的信号必须每次都要声明一个信号。这些单独的声明必须在每个使用相关信号的模块以及连接模块的块级中重复进行。
在其最基本的形式中,SystemVerilog Interface将相关信号封装在一起,作为一个可重复使用的建模组件。然后,该Interface可以作为模块上的一个端口,取代一组相关信号的多个单独端口。Interface所提供的建模抽象可以成为RTL设计工程师的强大工具。设计师可以一次性定义一组相关的信号,作为一个Interface,然后可以多次使用这些信号,而不必重复定义。
综合编译器能很好地处理使用Interface来封装相关信号的问题。设计工程师可以在更高的抽象水平上工作--具有抽象的所有优点--综合编译器将信号的抽象封装转化为各个模块的端口,工程师不需要为各个端口的声明而烦恼,并确保多个模块中冗余的声明完全匹配。
综合编译器支持两种方式,即在端口声明中指定与模块一起使用的modport,或者在模块例化时指定modport。然而,如果一个模块是独立于其他模块综合的,则必须在端口声明中指定modport。
当一个模块独立于其他模块进行综合时,或者在综合编译器配置为保留RTL模块层次的情况下综合多个模块时,综合编译器将把一个模块的Interface端口扩展为modport定义中代表的各个端口。大多数综合编译器将使用Verilog-1995的端口声明风格,其中端口列表包含端口名称和顺序,而端口大小和数据类型在模块内部声明,而不是在端口列表中。一个模块可以有任意数量的Interface端口,Interface端口可以与其他端口以任意顺序指定。本文中的例子将Interface端口列在前面,只是为了强调Interface端口的作用。
下面的代码片断显示了一个主模块可能的综合前和综合后的模块定义,该模块使用简单ahb Interface。
预综合modport列表,有一个Interface端口。
综合后模型,使用Verilog-1995编码风格。下面的综合后例子说明了一个Interface端口如何综合的典型结果。
如果指定了一个modport的定义,综合将使用modport中指定的方向。如果在模型综合时没有指定modport,那么在综合的模块中,Interface内的所有信号都会成为双向的inout端口。
可配置的Interface与可配置的模块一样,都是可综合的。Interface可以使用参数来配置总线宽度和数据类型。Interface也可以用同样的方式进行配置。
Interface也可以通过使用方法(任务和函数)和程序代码来封装与这些信号有关的功能。Interface中的函数是可以综合的。这可能很有用,RTL设计工程师应该利用这种综合能力。将函数与它们所操作的信号封装在一起,是编写稳健、可重复使用的代码的最佳实践编码方式。
最佳实践指南10-6 |
---|
将Interface的功能限制在可以用函数建模的范围内。 |
在编写本文时,现有的RTL综合编译器在支持使用Interface来封装使用任务和程序代码的功能方面有些局限。
例如,有可能在一个Interface内封装FIFO的全部功能,这将允许使用封装信号的模块在不同的时钟速度下运行而不损失任何数据。完整的纠错功能以及与一组信号相关的其他复杂操作也可以与这些信号捆绑在一起。这种更高级的封装水平不被大多数综合编译器所支持,或只有有限的支持。这些限制限制了程序性代码在Interface中的实用性。
Interface也可以捆绑验证代码,例如为封装的信号和功能提供断言和自我检查程序。Interface中的验证相关代码可以被综合编译器使用综合translate_off和trans1ate_on pragmas或'if def条件编译忽略。
审核编辑:刘清
-
时钟发生器
+关注
关注
1文章
198浏览量
67222 -
RTL
+关注
关注
1文章
385浏览量
59692 -
UVM
+关注
关注
0文章
181浏览量
19132 -
Verilog语言
+关注
关注
0文章
113浏览量
8211
原文标题:数字硬件建模SystemVerilog-通信总线建模 --Interface方法
文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论