• 沒有找到結果。

Unified Hardware Design, Specification, and Verification Language

6. Data types

6.6 Net types

6.6.7 User-defined nettypes

A user-defined nettype allows users to describe more general abstract values for a wire, including its resolution function. This nettype is similar to a typedef in some ways, but shall only be used in declaring a net. It provides a name for a particular data type and optionally an associated resolution function.

The syntax for net type declarations is given in Syntax 6-1.

net_type_declaration ::= // from A.2.1.3

nettype data_type net_type_identifier

[ with [ package_scope | class_scope ] tf_identifier ] ;

| nettype [ package_scope | class_scope ] net_type_identifier net_type_identifier ; Syntax 6-1—Syntax for net type declarations (excerpt from Annex A)

A net declared with a nettype therefore uses that data type and, if specified, the associated resolution function. An explicit data type is required for a user-defined nettype.

Table 6-5—Truth table for tri0 net

tri0 0 1 x z

0 0 x x 0

1 x 1 x 1

x x x x x

z 0 1 x 0

Table 6-6—Truth table for tri1 net

tri1 0 1 x z

0 0 x x 0

1 x 1 x 1

x x x x x

z 0 1 x 1

Certain restrictions apply to the data type of a net with a user-defined nettype. A valid data type shall be one of the following:

a) A 4-state integral type, including a packed array, packed structure or union.

b) A 2-state integral type, including a packed array, packed structure or union with 2-state data type members.

c) A real or shortreal type.

d) A fixed-size unpacked array, unpacked structure or union, where each element has a valid data type for a net of a user-defined nettype.

A second form of a nettype declaration is to create another name for an existing nettype.

An atomic net is a net whose value is updated and resolved as a whole. A net declared with a user-defined nettype is an atomic net. Similarly, a logic net is an atomic net, but a logic vector net is not an atomic net as each logic element is resolved and updated independently. While an atomic net may have a singular or aggregate value, each atomic net is intended to describe a single connection point in the design.

The resolution for a user-defined nettype is specified using a SystemVerilog function declaration. If a resolution function is specified, then when a driver of the net changes value, an update event is scheduled on the net in the Active (or Reactive) region. When the update event matures, the simulator calls the resolution function to compute the value of the net from the values of the drivers. The return type of the function shall match the data type of the nettype. The function shall accept an arbitrary number of drivers, since different instances of the net could be connected to different numbers of drivers. Any change in the value of one or more of the drivers shall trigger the evaluation of the resolution function associated with that nettype. A user-defined resolution function for a net of a user-defined nettype with a data type T shall be a function with a return type of T and a single input argument whose type is a dynamic array of elements of type T. A resolution function shall be automatic (or preserve no state information) and have no side effects. A resolution function shall not resize the dynamic array input argument nor shall it write to any part of the dynamic array input argument. While a class function method may be used for a resolution function, such functions shall be class static methods as the method call occurs in a context where no class object is involved in the call. Parameterized variants of such methods can be created through the use of parameterized class methods as described in 13.8.

Two different nettypes can use the same data type, but have different resolution functions A nettype may be declared without a resolution function, in which case it shall be an error for a net of that nettype to have multiple drivers.

Due to nondeterminism within scheduling regions, if there are multiple driver updates within a scheduling region, there may be multiple evaluations of the resolution function.

A force statement can override the value of a net of a user-defined nettype. When released, the net returns to the resolved value.

// user-defined data type T typedef struct {

real field1;

bit field2;

} T;

// user-defined resolution function Tsum function automatic T Tsum (input T driver[]);

Tsum.field1 = 0.0;

foreach (driver[i])

Tsum.field1 += driver[i].field1;

VERIFICATION LANGUAGE

endfunction

nettype T wT; // an unresolved nettype wT whose data type is T // a nettype wTsum whose data type is T and

// resolution function is Tsum nettype T wTsum with Tsum;

// user-defined data type TR typedef real TR[5];

// an unresolved nettype wTR whose data type // is an array of real

nettype TR wTR;

// declare another name nettypeid2 for nettype wTsum nettype wTsum nettypeid2;

The following example shows how to use a combination of a parameterized class definition with class static methods to parameterize the data type of a user-defined nettype.

class Base #(parameter p = 1);

typedef struct { real r;

bit[p-1:0] data;

} T;

static function T Tsum (input T driver[]);

Tsum.r = 0.0;

nettype MyBaseT::T narrowTsum with MyBaseT::Tsum;

typedef Base#(64) MyBaseType;

nettype MyBaseType::T wideTsum with MyBaseType::Tsum;

narrowTsum net1; // data is 32 bits wide wideTsum net2; // data is 64 bits wide 6.6.8 Generic interconnect

In SystemVerilog it is possible to use net types and configurations to create design models with varying levels of abstraction. In order to support netlist designs, which primarily specify design element instances and the net connections between the design elements, SystemVerilog defines a generic form of nets. Such generic nets allow the separation of the specification of the net connections from the types of the connections.

A net or port declared as interconnect (an interconnect net or port) indicates a typeless or generic net.

Such nets or ports are only able to express net port and terminal connections and shall not be used in any procedural context nor in any continuous or procedural continuous assignments. An interconnect net or port shall not be used in any expression other than a net_lvalue expression in which all nets or ports in the expression are also interconnect nets. An interconnect array shall be considered valid even if different bits in the array are resolved to different net types as demonstrated in the following example. It

shall be legal to specify a net_alias statement with an interconnect net_lvalue. See 23.3.3.7.1 and 23.3.3.7.2 for port and terminal connection rules for interconnect nets.

package NetsPkg;

module lDriver(output wire logic out);

endmodule : lDriver module rDriver

import NetsPkg::*;

(output realNet out);

endmodule : rDriver

module rlMod(input interconnect [0:1] iBus);

lMod l1(iBus[0]);

rMod r1(iBus[1]);

endmodule : rlMod

The following simple example serves to illustrate the usefulness of an interconnect net. The example contains a top level module (top) that instantiates a stimulus module (driver) and a comparator module (cmp). This configuration is intended to compare two elements and determine if they are equal. There are two different versions of the configuration, as described by the two different config blocks: one that works on real values and one that works on logic values. By using the typeless interconnect net, we can use the same testbench with both configurations, without having to change anything in the testbench itself. The interconnect net aBus takes its data type from the type of its connections.

<file lib.map>

VERIFICATION LANGUAGE

#(parameter int delay = 30, int iterations = 256)

module driver #(parameter int delay = 30, int iterations = 256) (output wire logic [0:1] out);

timeunit 1ns / 1ps;

#(parameter real hyst = 0.65) (input realNet [0:1] inA,

else if (inA[0] > inA[1]) out <= 1’b1;

else if (inA[0] < inA[1] - hyst) out <= 1’b0;

end

endmodule : cmp

<file cmp.sv>

module cmp #(parameter real hyst = 0.65)

(input wire logic [0:1] inA, input logic rst,

output logic out);

initial out = 1’b0;

always @(inA, rst) begin if (rst) out <= 1'b0;

else if (inA[0] & ~inA[1]) out <= 1'b1;

else out <= 1'b0;

end

endmodule : cmp