• 沒有找到結果。

Unified Hardware Design, Specification, and Verification Language

3. Design and verification building blocks

3.2 Design elements

A design element is a SystemVerilog module (see Clause 23), program (see Clause 24), interface (see Clause 25), checker (see Clause 17), package (see Clause 26), primitive (see Clause 28) or configuration (see Clause 33). These constructs are introduced by the keywords module, program, interface, checker, package, primitive, and config, respectively.

Design elements are the primary building blocks used to model and build up a design and verification environment. These building blocks are the containers for the declarations and procedural code that are discussed in subsequent clauses of this document.

This clause describes the purpose of these building blocks. Full details on the syntax and semantics of these blocks are defined in later clauses of this standard.

3.3 Modules

The basic building block in SystemVerilog is the module, enclosed between the keywords module and endmodule. Modules are primarily used to represent design blocks, but can also serve as containers for verification code and interconnections between verification blocks and design blocks. Some of the constructs that modules can contain include the following:

— Ports, with port declarations

— Data declarations, such as nets, variables, structures, and unions

— Constant declarations

— User-defined type definitions

— Class definitions

— Imports of declarations from packages

— Subroutine definitions

— Instantiations of other modules, programs, interfaces, checkers, and primitives

— Instantiations of class objects

— Continuous assignments

VERIFICATION LANGUAGE

— Procedural blocks

— Generate blocks

— Specify blocks

Each of the constructs in the preceding list is discussed in detail in subsequent clauses of this standard.

NOTE—The preceding list is not all inclusive. Modules can contain additional constructs, which are also discussed in subsequent clauses of this standard.

Following is a simple example of a module that represents a 2-to-1 multiplexer:

module mux2to1 (input wire a, b, sel, // combined port and type declaration output logic y);

always_comb begin // procedural block if (sel) y = a; // procedural statement else y = b;

end

endmodule: mux2to1

Modules are presented in more detail in Clause 23. See also 3.11 on creating design hierarchy with modules.

3.4 Programs

The program building block is enclosed between the keywords program...endprogram. This construct is provided for modeling the testbench environment. The module construct works well for the description of hardware. However, for the testbench, the emphasis is not on the hardware-level details such as wires, structural hierarchy, and interconnects, but in modeling the complete environment in which a design is verified.

The program block serves the following three basic purposes:

— It provides an entry point to the execution of testbenches.

— It creates a scope that encapsulates program-wide data, tasks, and functions.

— It provides a syntactic context that specifies scheduling in the Reactive region.

The program construct serves as a clear separator between design and testbench, and, more importantly, it specifies specialized simulation execution semantics. Together with clocking blocks (see Clause 14), the program construct provides for race-free interaction between the design and the testbench and enables cycle-and transaction-level abstractions.

A program block can contain data declarations, class definitions, subroutine definitions, object instances, and one or more initial or final procedures. It cannot contain always procedures, primitive instances, module instances, interface instances, or other program instances.

The abstraction and modeling constructs of SystemVerilog simplify the creation and maintenance of testbenches. The ability to instantiate and individually connect each program instance enables their use as generalized models.

A sample program declaration is as follows:

program test (input clk, input [16:1] addr, inout [7:0] data);

initial begin ...

endprogram

The program construct is discussed more fully in Clause 24.

3.5 Interfaces

The interface construct, enclosed between the keywords interface...endinterface, encapsulates the communication between design blocks, and between design and verification blocks, allowing a smooth migration from abstract system-level design through successive refinement down to lower level register-transfer and structural views of the design. By encapsulating the communication between blocks, the interface construct also facilitates design reuse.

At its lowest level, an interface is a named bundle of nets or variables. The interface is instantiated in a design and can be connected to interface ports of other instantiated modules, interfaces and programs. An interface can be accessed through a port as a single item, and the component nets or variables referenced where needed. A significant proportion of a design often consists of port lists and port connection lists, which are just repetitions of names. The ability to replace a group of names by a single name can significantly reduce the size of a description and improve its maintainability.

Additional power of the interface comes from its ability to encapsulate functionality as well as connectivity, making an interface, at its highest level, more like a class template. An interface can have parameters, constants, variables, functions, and tasks. The types of elements in an interface can be declared, or the types can be passed in as parameters. The member variables and functions are referenced relative to the instance name of the interface as instance members. Thus, modules that are connected via an interface can simply call the subroutine members of that interface to drive the communication. With the functionality thus encapsulated in the interface and isolated from the module, the abstraction level and/or granularity of the communication protocol can be easily changed by replacing the interface with a different interface containing the same members, but implemented at a different level of abstraction. The modules connected via the interface do not need to change at all.

To provide direction information for module ports and to control the use of subroutines within particular modules, the modport construct is provided. As the name indicates, the directions are those seen from the module.

In addition to subroutine methods, an interface can also contain processes (i.e., initial or always procedures) and continuous assignments, which are useful for system-level modeling and testbench applications. This allows the interface to include, for example, its own protocol checker, which automatically verifies that all modules connected via the interface conform to the specified protocol. Other applications, such as functional coverage recording and reporting, protocol checking, and assertions can also be built into the interface.

A simple example of an interface definition and usage is as follows:

interface simple_bus(input logic clk); // Define the interface logic req, gnt;

logic [7:0] addr, data;

logic [1:0] mode;

logic start, rdy;

endinterface: simple_bus

module memMod(simple_bus a); // simple_bus interface port logic avail;

// When memMod is instantiated in module top, a.req is the req // signal in the sb_intf instance of the 'simple_bus' interface always @(posedge clk) a.gnt <= a.req & avail;

endmodule

VERIFICATION LANGUAGE

module cpuMod(simple_bus b); // simple_bus interface port ...

endmodule module top;

logic clk = 0;

simple_bus sb_intf(.clk(clk)); // Instantiate the interface memMod mem(.a(sb_intf)); // Connect interface to module instance cpuMod cpu(.b(sb_intf)); // Connect interface to module instance endmodule

See Clause 25 for a full description of interfaces.

3.6 Checkers

The checker construct, enclosed by the keywords checker...endchecker, represents a verification block encapsulating assertions along with the modeling code. The intended use of checkers is to serve as verification library units or as building blocks for creating abstract auxiliary models used in formal verification. The checker construct is discussed in detail in Clause 17.

3.7 Primitives

The primitive building block is used to represent low-level logic gates and switches. SystemVerilog includes a number of built-in primitive types. Designers can supplement the built-in primitives with user-defined primitives (UDPs). A UDP is enclosed between the keywords primitive...endprimitive. The built-in and UDP constructs allow modeling timing-accurate digital circuits, commonly referred to as gate-level models. Gate-level modeling is discussed more fully in Clause 28 through Clause 31.

3.8 Subroutines

Subroutines provide a mechanism to encapsulate executable code that can be invoked from one or more places. There are two forms of subroutines, tasks (13.3) and functions (13.4).

A task is called as a statement. A task can have any number of input, output, inout, and ref arguments, but does not return a value. Tasks can block simulation time during execution. That is, the task exit can occur at a later simulation time than when the task was called.

A function can return a value or can be defined as a void function, which does not return a value. A nonvoid function call is used as an operand within an expression. A void function is called as a statement. A function can have input, output, inout, and ref arguments. Functions must execute without blocking simulation time, but can fork off processes that do block time.

3.9 Packages

Modules, interfaces, programs, and checkers provide a local name space for declarations. Identifiers declared within a module, interface, program, or checker are local to that scope, and do not affect or conflict with declarations in other building blocks.

Packages provide a declaration space, which can be shared by other building blocks. Package declarations can be imported into other building blocks, including other packages.

A package is defined between the keywords package...endpackage. For example:

package ComplexPkg;

typedef struct { shortreal i, r;

} Complex;

function Complex add(Complex a, b);

add.r = a.r + b.r;

add.i = a.i + b.i;

endfunction

function Complex mul(Complex a, b);

mul.r = (a.r * b.r) - (a.i * b.i);

mul.i = (a.r * b.i) + (a.i * b.r);

endfunction

endpackage : ComplexPkg

The full syntax and semantics of packages are described in Clause 26.

3.10 Configurations

SystemVerilog provides the ability to specify design configurations, which specify the binding information of module instances to specific SystemVerilog source code. Configurations utilize libraries. A library is a collection of modules, interfaces, programs, checkers, primitives, packages, and other configurations.

Separate library map files specify the source code location for the cells contained within the libraries. The names of the library map files are typically specified as invocation options to simulators or other software tools reading in SystemVerilog source code.

See Clause 33 for details of configurations.