返回介绍

19.8 虚拟接口

发布于 2020-09-09 22:55:56 字数 4724 浏览 1008 评论 0 收藏 0

Virtual interfaces provide a mechanism for separating abstract models and test programs from the actual signals that make up the design. A virtual interface allows the same subprogram to operate on different portions of a design, and to dynamically control the set of signals associated with the subprogram. Instead of referring to the actual set of signals directly, users are able to manipulate a set of virtual signals. Changes to the underlying design do not require the code using virtual interfaces to be re-written. By abstracting the connectivity and functionality of a set of blocks, virtual interfaces promote code-reuse.

A virtual interface is a variable that represents an interface instance. The syntax to declare a virtual interface variable is given below.

virtual_interface_declaration ::=        // from Annex A.2.9
    virtual [interface] interface_identifier list_of_virtual_interface_decl;

list_of_virtual_interface_decl ::=       // from Annex A.2.3
    variable_identifier [= interface_instance_identifier
        {, variable_identifier [= interface_instance_identifier]}

data_declaration ::=                    // from Annex A.2.1.3
    ...
  | virtual_interface_declaration

data_type ::=                           // from Annex A.2.2.1
    ...
  | virtual [interface] interface_identifier

Syntax 19-3—virtual interface declaration syntax (excerpt from Annex A)

Virtual interface variables can be passed as arguments to tasks, functions, or methods. A single virtual interface variable can thus represent different interface instances at different times throughout the simulation. A virtual interface must be initialized before it can be used; it has the value null before it is initialized. Attempting to use an uninitialized virtual interface shall result in a fatal run-time error.

Only the following operations are directly allowed on virtual interface variables:

  • Assignment ( = ) to:
    • another virtual interface of the same type
    • an interface instance of the same type
    • the special constant null
  • Equality ( == ) and inequality ( != ) with:
    • another virtual interface of the same type
    • an interface instance of the same type
    • the special constant null
Virtual interfaces shall not be used as ports, interface items, or as members of unions.

Once a virtual interface has been initialized, all the components of the underlying interface instance are directly available to the virtual interface via the dot notation. These components can only be used in procedural statements; they cannot be used in continuous assignments or sensitivity lists. In order for a net to be driven via a virtual interface, the interface itself must provide a procedural means to do so. This can be accomplished either via a clocking block or by including a driver that is updated by a continuous assignment from a variable within the interface.

Virtual interfaces can be declared as class properties, which can be initialized procedurally or by an argument to new(). This allows the same virtual interface to be used in different classes. The following example shows how the same transactor class can be used to interact with various different devices.

interface SBus; // A Simple bus interface
    logic req, grant;
    logic [7:0] addr, data;
endinterface

class SBusTransctor; // SBus transactor class
    virtual SBus bus; // virtual interface of type Sbus

    function new( virtual SBus s );
        bus = s; // initialize the virtual interface
    endfunction

    task request(); // request the bus
        bus.req <= 1’b1;
    endtask

    task wait_for_bus(); // wait for the bus to be granted
        @(posedge bus.grant);
    endtask
endclass

module devA( Sbus s ) ... endmodule // devices that use SBus

module devB( Sbus s ) ... endmodule

module top;
    SBus s[1:4] (); // instantiate 4 interfaces
    devA a1( s[1] ); // instantiate 4 devices
    devB b1( s[2] );
    devA a2( s[3] );
    devB b2( s[4] );

    initial begin
        SbusTransactor t[1:4]; // create 4 bus-transactors and bind
        t[1] = new( s[1] );
        t[2] = new( s[2] );
        t[3] = new( s[3] );
        t[4] = new( s[4] );
        // test t[1:4]
    end
endmodule

In the preceding example, the transaction class SbusTransctor is a simple reusable component. It is written without any global or hierarchical references, and is unaware of the particular device with which it will interact. Nevertheless, the class can interact with any number of devices (4 in the example) that adhere to the interface’s protocol.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文