
Verilog-AMS HDL supports a hierarchical hardware description by allowing modules to be embedded within other modules. Higher-level modules create instances of lower-level modules and communicate with them through input, output, and bidirectional ports.
Verilog-AMS HDL provides a mechanism to customize the behavior of embedded modules using parameters. The embedded module parameter default value can be modified through a higher-level module's parameter override or a hierarchy independent defparam statement.
To describe a hierarchy of modules, the user provides textual definitions of various modules. Each module definition stands alone; the definitions are not nested. Statements within the module definitions create instances of other modules, thus describing the hierarchy.
7.1 Modules
A module definition is enclosed between the keywords module and endmodule, as shown in Syntax 71. The identifier following the keyword module is the name of the module being defined. The optional list of ports specify an ordered list of the module's ports. The order used can be significant when instantiating the module (see 7.1.2). The identifiers in this list shall be declared in input, output, or inout declaration statements within the module definition. The module items define what constitutes a module and include many different types of declarations and definitions. A module definition can have at most one analog block.
The keyword macromodule can be used interchangeably with the keyword module to define a module. An implementation can choose to treat module definitions beginning with the macromodule keyword differently.
![]()
The definitions for module_item_declaration and parameter_override are shown in Syntax 72.
The definition of module_instantiation is shown in Syntax 73.
7.1.1 Toplevel modules
Top-level modules are modules which are included in the source text but are not instantiated, as described in 7.1.2.
7.1.2 Module instantiation
Instantiation allows one module to incorporate a copy of another module into itself. Module definitions do not nest. That is, one module definition does not contain the text of another module definition within its module-endmodule keyword pair. A module definition nests another module by instantiating it.
Syntax 73 shows the syntax for specifying instantiations of modules.
![]()
The following concepts apply:
· The instantiations of modules can contain a range specification. This allows an array of instances to be created.
· One or more module instances (identical copies of a module definition) can be specified in a single module instantiation statement.
· The list of module connections can be provided only for modules defined with ports. The parentheses, however, are always required. When a list of module connections is given, the first element in the list connects to the first port, the second element to the second port, and so on. See 7.3 for a more detailed discussion of ports and port connection rules.
· A connection can be a simple reference to a net identifier or a sub-range of a vector net.
Examples:
The example below illustrates a comparator and an integrator (lower-level modules) which are instantiated in sigma-delta A/D converter module (the higher-level module).
module comparator(cout, inp, inm);
output cout;
input inp, inm;
ground gnd;
electrical cout, inp, inm;
parameter real td = 1n, tr = 1n, tf = 1n;
real vcout;
analog begin
@(cross(V(inp) - V(inm), 0))
vcout = ((V(inp) > V(inm)) ? 1 : 0);
V(vcout) <+ transition(vcout, td, tr, tf);
end
endmodule
module integrator(out, in);
output out;
input in;
electrical in, out;
parameter real gain = 1.0;
parameter real ic = 0.0;
analog begin
V(out) <+ gain*idt(V(in), ic);
end
endmodule
module sigmadelta(out, ref, in);
output out;
input ref, in;
comparator C1(.cout(aa0), .inp(in), .inm(aa2));
integrator #(1.0) I1(.out(aa1), .in(aa0));
comparator C2(out, aa1, gnd);
d2a #(.width(1)) D1(aa2, ref, out); // A D/A converter
endmodule
The comparator instance C1 and the integrator instance I1 in Figure 71 use named port connections, whereas the comparator instance C2 and the d2a (not described here) instance D1 use ordered port connections. Note the integrator instance I1 overrides gain parameter positionally, whereas the d2a instance D1 overrides width parameter by named association.
![]()
7.2 Overriding module parameter values
When one module instantiates another module, it can alter the values of any parameters declared within the instantiated module. There are two ways to alter parameter values: the defparam statement, which allows assignment to parameters using their hierarchical names, and the module instance parameter value assignment, which allows values to be assigned inline during module instantiation. If a defparam assignment conflicts with a module instance parameter, the parameter in the module shall take the value specified by the defparam.
The module instance parameter value assignment comes in two forms, by ordered list or by name. The first form is module instance parameter value assignment by order, which allows values to be assigned in-line during module instantiation in the order of their declaration. The second form is module instance parameter value assignment by name, which allows values to be assigned in-line during module instantiation by explicitly associating parameter names with the overriding values.
7.2.1 Defparam statement
Using the defparam statement, parameter values can be changed in any module instance throughout the design using the hierarchical name of the parameter. See 7.4 for details about hierarchical names.
The expression on the right-hand side of a defparam assignments shall be a constant expression involving only constant numbers and references to parameters. The referenced parameters (on the right-hand side of a defparam) shall be declared in the same module as the defparam statement.
The defparam statement is particularly useful for grouping all of the parameter value override assignments together in one module. Its syntax is shown in Syntax 74.
![]()
Examples:
module tgate;
electrical io1,io2,control,control_bar;
mosn m1 (io1, io2, control);
mosp m2 (io1, io2, control_bar);
endmodule
module mosp (source,drain,gate);
inout source, drain, gate;
electrical source, drain, gate;
parameter gate_length = 0.3e-6,
gate_width = 4.0e-6;
spice_pmos #(.l(gate_length),.w(gate_width)) p(gate,source,drain);
endmodule
module mosn (source,drain,gate);
inout source, drain, gate;
electrical source, drain, gate;
parameter gate_length = 0.3e-6,
gate_width = 4.0e-6;
spice_nmos #(.l(gate_length),.w(gate_width)) n(gate,source,drain);
endmodule
module annotate;
defparam
tgate.m1.gate_width = 5e-6,
tgate.m2.gate_width = 10e-6;
endmodule
7.2.2 Module instance parameter value assignment by order
The order of the assignments in module instance parameter value assignment shall follow the order of declaration of the parameters within the module. It is not necessary to assign values to all of the parameters within a module when using this method. However, the left-most parameter assignment(s) can not be skipped. Therefore, to assign values to a subset of the parameters declared within a module, the declarations of the parameters which make up this subset shall precede the declarations of the remaining (optional) parameters. An alternative is to assign values to all of the parameters, but use the default value (the same value assigned in the declaration of the parameter within the module definition) for those parameters which do not need new values.
Examples:
Consider the following example, where the parameters within module instance weakp are changed during instantiation.
module m;
electrical clk;
electrical out_a, in_a;
electrical out_b, in_b;
// create an instance and set parameters
mosp #(2e-6,1e-6) weakp(out_a, in_a, clk);
// create an instance leaving default values
mosp plainp(out_b, in_b, clk);
endmodule
7.2.3 Module instance parameter value assignment by name
Parameter assignment by name consists of explicitly linking the parameter name and it's value. The name of the parameter shall be the name specified in the instantiated module. It is not necessary to assign values to all the parameters within a module when using this method. Only those parameters which are assigned new values need to be specified.
The parameter expression is optional so the instantiating module can document the existance of a parameter without assigning anything to it. The parentheses are required and in this case the parameter retains its default value. Once a parameter is assigned a value, there shall not be another assignment to this parameter name.
Example:
In the following example of instantiating a voltage-controlled oscillator, the parameters are specified on a named-association basis much as they are for ports.
module n(lo_out, rf_in):
electrical lo_out, rf_in;
//create an instance and set parameters
vco #(.centerFreq(5000), .convGain(1000)) vco1(lo_out, rf_in);
endmodule
Here, the name of the instantiated vco module is vco1. The centerFreq parameter is passed a value of 5000 and the convGain parameter is passed a value of 1000. The positional assignment mechanism for ports assigns lo_out as the first port and rf_in as the second port of vco1.
7.2.4 Parameter dependence
A parameter (for example, gate_cap) can be defined with an expression containing another parameter (for example, gate_width or gate_length). Since gate_cap depends on the value of gate_width and gate_length, a modification of gate_width or gate_length changes the value of gate_cap.
Examples:
In the following parameter declaration, an update of gate_width, whether by a defparam statement or in an instantiation statement for the module which defined these parameters, automatically updates gate_cap.
parameter
gate_width = 0.3e-6,
gate_length = 4.0e-6,
gate_cap = gate_length * gate_width * `COX;
7.3 Ports
Ports provide a means of interconnecting instances of modules. For example, if a module A instantiates module B, the ports of module B are associated with either the ports or the internal nets of module A.
7.3.1 Port association
The syntax for a port association is shown in Syntax 75.
![]()
The port expression in the port definition can be one of the following:
· a simple net identifier
· a scalar member of a vector net or port declared within the module
· a sub-range of a vector net or port declared within the module
The two types of module port definitions cannot be mixed; the ports of a particular module definition shall all be defined by order or by name. The port expression is optional because ports can be defined which do not connect to anything internal to the module.
7.3.2 Port declarations
The type and direction of each port listed in the module definition's list of ports are declared in the body of the module.
7.3.2.1 Port type
The type of a port is declared by giving its discipline, as shown in Syntax 76. If the type of a port is not declared, the port can only be used in a structural description. (It can be passed to instances of modules, but cannot be accessed in a behavioral description.)
![]()
7.3.2.2 Port direction
Each port listed in the list of ports for the module definition shall be declared in the body of the module as an input, output,or inout (bidirectional). This is in addition to any other declaration for a particular port - for example, a net_discipline, reg, or wire. The syntax for port declarations is shown in Syntax 77.
![]()
A port can be declared in both a port type declaration and a port direction declaration. If a port is declared as a vector, the range specification between the two declarations of a port shall be identical.
Note: Implementations can limit the maximum number of ports in a module definition, but this shall be a minimum of 256 ports per implementation.
7.3.3 Real valued ports
Verilog-AMS HDL supports ports which are declared to be real-valued and have a discrete-time discipline. This is done using the net type wreal (defined in 3.5). There can be a maximum of one driver of a real-valued net.
Examples:
module testbench(out, clk);
output out;
input clk;
real out;
wire clk;
always @(posedge clk) begin
out = out + $abstime;
end
endmodule
module a2d(dout, in, clk);
output [1:8] dout;
input in, clk;
wreal in;
wire clk;
reg [1:8] dout;
real residue;
integer i;
always @(negedge clk) begin
residue = in;
for (i = 8; i >= 1; i = i - 1) begin
if (residue > 0.5) begin
dout[i] = 1'b1;
residue = residue - 0.5;
end else begin
dout[i] = 1'b0;
end
residue = residue*2;
end
end
endmodule
Real-valued port connections of busses and arrays are not supported.
7.3.4 Connecting module ports by ordered list
One way to connect the ports listed in a module instantiation with the ports defined by the instantiated module is via an ordered list-that is, the ports listed for the module instance shall be in the same order as the ports listed in the module definition.
Examples:
module adc4 (out, rem, in);
output [3:0] out ; output rem;
input in;
electrical [3:0] out;
electrical in, rem, rem_chain;
adc2 hi2 (out[3:2], rem_chain, in) ;
adc2 lo2 (out[1:0], rem, rem_chain) ;
endmodule
module adc2 (out, remainder, in);
output [1:0] out ; output remainder;
input in;
electrical [1:0] out ;
electrical in, remainder, r;
adc hi1 (out[1], r, in) ;
adc lo1 (out[0], remainder, r) ;
endmodule
module adc (out, remainder, in);
output out, remainder;
input in;
electrical out, in, remainder;
integer d;
analog begin
d = (V(in) > 0.5) ;
V(out) <+ transition(d) ;
V(remainder) <+ 2.0 * V(in) ;
if (d)
V(remainder) <+ -1.0 ;
end
endmodule
7.3.5 Connecting module ports by name
The second way to connect module ports consists of explicitly linking the two names for each side of the connection - specify the name used in the module definition, followed by the name used in the instantiating module. This compound name is then placed in the list of module connections.
The following rules apply:
· The name of port shall be the name specified in the module definition.
· The name of port cannot be a bit select or a part select.
· The port expression shall be the name used by the instantiating module and can be one of the following:
- a simple net identifier
- a scalar member of a vector net or port declared within the module
- a sub-range of a vector net or port declared within the module
- a vector net formed as a result of the concatenation operator
· The port expression is optional so the instantiating module can document the existence of the port without connecting it to anything. The parentheses are required.
· The two types of module port connections can not be mixed; connections to the ports of a particular module instance shall be all by order or all by name.
Examples:
module adc4 (out, rem, in);
input in;
output [3:0] out; output rem;
electrical [3:0] out;
electrical in, rem, rem_chain;
adc2 hi (.in(in), .out(out[3:2]), .remainder(rem_chain)) ;
adc2 lo (.in(rem_chain), .out(out[1:0]), .remainder(rem)) ;
endmodule
module adc2 (out, in, remainder);
output [1:0] out; output remainder;
input in;
electrical [1:0] out;
electrical in, remainder, r;
adc hi1 (out[1], r, in) ; // adc is same as defined in 7.3.4
adc lo1 (out[0], remainder, r) ;
endmodule
Since these connections were made by port name, the order in which the connections appear is irrelevant.
7.3.6 Port connection rules
All digital ports connected to a net shall be of compatible disciplines, as shall all analog ports connected to a net. Ports of both analog and digital discipline may be connected to a net provided the appropriate connect statements exist (see 8.7).
7.3.6.1 Matching size rule
A scalar port can be connected to a scalar net and a vector port can be connected to a vector net or concatenated net expression of the matching width. In other words, the sizes of the ports and net need to match.
7.3.6.2 Resolving discipline of undeclared interconnect signal
Verilog-AMS HDL supports undeclared interconnects between module instances when describing hierarchical structures. That is, a signal appearing in the connection list of a module instantiation need not appear in any port declaration or discipline declaration (see 8.4).
7.3.7 Inheriting port natures
A net of continuous discipline shall have a potential nature and may have a flow nature. Because of hierarchical connections, an analog node may be associated with a number of analog nets, and thus, a number of continuous disciplines. The node shall be treated as having a potential abstol with a value equal to the smallest abstol of all the potential natures of all the disciplines with which it is associated. The node shall be treated as having a flow abstol with a value equal to the smallest abstol of all the flow natures, if any, of all the disciplines with which it is associated.
7.4 Hierarchical names
Every identifier in Verilog-AMS HDL has a unique hierarchical path name. The hierarchy of modules and the definition of items such as named blocks within the modules define these names. The hierarchy of names can be viewed as a tree structure, where each module instance or a named begin-end block defines a new hierarchical level, or as a scope (of a particular branch of the tree).
At the top of the name hierarchy are the names of modules where no instances have been created. This is the root of the hierarchy. Inside any module, each module instance and named begin-end block define a new branch of the hierarchy. Named blocks within named blocks also create new branches.
Each net in the hierarchical name tree is treated as a separate scope with respect to identifiers. A particular identifier can be declared only once in any scope.
Any named object can be referenced uniquely in its full form by concatenating the names of the module instance or named blocks that contain it. The period character (.) is used to separate names in the hierarchy. The complete path name to any object starts at a top-level module. This path name can be used from any level in the description. The first name in a path name can also be the top of a hierarchy which starts at the level where the path is being used.
Examples:
module samplehold (in, cntrl, out );
input in, cntrl ;
output out ;
electrical in, cntrl, out ;
electrical store, sample ;
parameter real vthresh = 0.0 ;
parameter real cap = 10e-9 ;
amp op1 (in, sample, sample);
amp op2 (store, out, out) ;
analog begin
I(store) <+ cap * ddt(V(store)) ;
if (V(cntrl) > vthresh)
V(store, sample) <+ 0 ;
else
I(store, sample) <+ 0 ;
end
endmodule
module amp(inp, inm, out) ;
input inp, inm ;
output out ;
electrical inp, inm, out ;
parameter real gain=1e5;
analog begin
V(out) <+ gain*V(inp,inm) ;
end
endmodule
Figure 72 illustrates the hierarchy implicit in the example code.
![]()
Figure 73 is a list of the hierarchical forms of the names of all the object defined in the example code.
![]()
From within an analog block, it is possible to use hierarchical name referencing to access signals on an external branch, but not external analog variables or parameters. When accessing external branches, a branch signal (its potential or flow) can be monitored (probed); for source branches, contributions can be made to the output signal.
7.5 Scope rules
The following elements define a new scope in Verilog-AMS HDL:
· modules
· tasks
· named blocks
· functions
· analog functions
An identifier can be used to declare only one item within a scope. This means it is illegal to declare two or more variables which have the same name or to give an instance the same name as the name of the net connected to its output.
If an identifier is referenced directly (without a hierarchical path) within a named block, it shall be declared either locally within the named block, within a module, or within a named block which is higher in the same branch of the name tree containing the named block. If it is declared locally, the local item shall be used; if not, the search shall continue upward until an item by that name is found or until a module boundary is encountered. The search can cross named block boundaries, but not module boundaries.
Note: Because of the upward searching process, path names which are not strictly on a downward path can be used.
|
Quadralay Corporation http://www.webworks.com Voice: (512) 719-3399 Fax: (512) 719-3606 sales@webworks.com |