Friday, April 27, 2012

The IEEE Verilog 1364-2001 Standard What's New, and Why You Need It

http://www.sutherland-hdl.com/papers/2000-HDLCon-paper_Verilog-2000.pdf


3.2 Scalable models—Verilog generate


Verilog-2001 adds  generate loops, which permit generating multiple instances of modules and primitives, as well as generating multiple occurrences of variables, nets, tasks, functions, continuous assignments, initial procedures, and always procedures. Generated declarations and instantiations can be conditionally created, using if–else decisions and case statements.

3.4 Indexed vector part selects

The Verilog-2001 standard adds a new syntax, called indexed part selects. With an indexed part select, a base expression, a width expression, and an offset direction are provided, in the form of:
[base_expr +: width_expr] //positive offset
[base_expr -: width_expr] //negative offset




3.5 Multidimensional arrays
The Verilog-1995 standard allows one-dimensional arrays of variables. Verilog-2001 extends this by permitting:
• Multi-dimensional arrays
• Arrays of both variable and net data types




Friday, April 13, 2012

Verilog-Mode Emacs

http://www.veripool.org/papers/verilog-mode_veritedium_snug.pdf


Reduce spins on fixing lint or compiler warnings
ƒ Reduce sensitivity problems
- If you forget (or don’t have) a linter, these are horrible to debug!
ƒ Make it easier to name signals consistently
through the hierarchy
- Reduce cut & paste errors on multiple instantiations.
- Make it more obvious what a signal does.
ƒ Reducing the number of lines is goodness alone.
- Less code to "look" at.
- Less time typing.


This expansion is best if in the editor
• You can “see” the expansion and edit as needed
ƒ There is a Verilog package for Emacs
• Written by Michael McNamara <mac@versity.com>
• Auto highlighting of keywords
• Standardized indentation
ƒ Expanded it to read & expand /*AUTOs*/
• Magic key sequence for expand/deexpand

C-c C-a  and C-c C-d

With this key sequence,
Verilog-Mode parses the verilog code, and
expands the text after any /*AUTO*/ comments.




verilog and systemverilog real port

Subject: Literal number gotchas

There are several gotchas associated with defining literal integer numbers
in Verilog and System Verilog. There are actually two different sets of
rules involving literal integers: one that defines the generation of an
integer number, and another for assigning the number.

Many engineers have only a vague understanding of these two sets of rules,
and often confuse them with each other. Here we'll discuss gotchas on the
generation a literal integer. Sec 4.4 discusses the issues regarding the
assignment of integers.

Review of literal integer syntax. Literal integers can be specified as a
simple decimal integer (e.g. 5) or as a based integer (e.g.'h5). A based
literal integer is specified using the following syntax:

's

Where:

- is optional. If given, it specifies the total number of bits
represented by the literal value. If not given, the default size is
32 bits (the Verilog standard says "at least" 32 bits, but all
implementations the authors are aware of use exactly 32 bits).
- s is optional. If given, it specifies that the literal integer should
be treated as a 2's complemented signed value. If not given, the
default is unsigned.
- is required, and specifies whether the value is in binary,
octal, decimal, or hex.
- is required, and specifies the literal integer value.


4.1 Signed versus unsigned literal integers

Gotcha: Some literal integers default to signed; other literal
integers default to unsigned.

A simple literal integer (e.g. 5) defaults to a signed value, and cannot be
specified as unsigned. A based literal integer (e.g. 'h5) defaults to an
unsigned value, unless explicitly specified as signed (e.g. 'sh5). The s
specifier was added as part of the Verilog-2001 standard to allow the
specification of sized, signed literal values.

The difference in the default signed-ness of a value can catch engineers by
surprise. Signed-ness of a value affects several types of operations.
Unexpected operation results will occur if an engineer forgets -- or is not
aware of -- the different default signed-ness of a simple literal integer
versus a based literal integer number.

Are the following two signed counter statements the same? (Of course
not, or we wouldn't have included this example in this paper!)

byte in; // signed 8-bit variables
int out1, out2; // signed 32-bit variables

initial begin
in = -5;
out1 = in + 1; // OK: -5 + 1 = -4 (literal 1 is signed)
out2 = in + 1'b1; // GOTCHA: -5 + 1'b1 = 252 (1'b1 is unsigned)
end

How to avoid this gotcha: The difference between adding 1 and 1'b1 is that
the literal integer 1 is a signed value, whereas the literal integer 1'b1
is an unsigned value. This difference affects how the ADD operation is
performed. Signed arithmetic is discussed in more detail in Sec 5.3.


4.2 Default base of literal integers

Gotcha: Literal integers have a default base that might not be
what is intended.

A simple literal integer (e.g. 5) defaults to a decimal base. To use a
binary, octal or hex value, a based-literal number must be specified
(e.g. 'h5). The base options are represented using b, o, d, or h for
binary, octal, decimal and hex, respectively. The base specifier can be
either lower case or upper case (i.e. 'h5 and 'H5 are the same).

The following example of a 4-to-1 MUX illustrates a common gotcha when an
engineer forgets -- or is not aware -- that a simple integer number is a
decimal value:

logic [1:0] select; // 2-bit vector

always_comb begin
case (select) // intent is for a 4-to-1 MUX behavior
00: y = a;
01: y = b;
10: y = c; // GOTCHA! This branch is never selected
11: y = d; // GOTCHA! This branch is never selected
endcase
end

This gotcha fits nicely with the well known joke that only engineers laugh
at: "There are 10 types of people in the world, those that know binary, and
those that don't". The example above may look reasonable, and it is
syntactically correct. But, since the default base of a simple integer is
decimal, the values "10" and "11" are ten and eleven, respectively. The
size of the values is not specified, and so defaults to 32-bits wide. The
2-bit select signal will be zero-extended to 32-bits wide, and then compared
to zero, one, ten and eleven. The only values of select that will ever
match are a and b, which extend to 32-bit 00...00 and 00...01, respectively.
The extended value of select will never match the decimal "10" and "11".
Therefore, the c and d inputs of the multiplexer will never be selected.
Since this is not a syntax error, the problem shows up in simulation as a
functional failure which can be difficult to detect and debug. GOTCHA.

How to avoid this gotcha: to detect this use the System Verilog unique
modifier to the case statement, as in:

unique case (select) // intent is for a 4-to-1 MUX behavior

The unique modifier reports an error if two or more case select items are
true at the same time, or if no case select items are true. The example
above becomes a simulation error, rather than a functional bug in the code.

Code coverage utilities and/or System Verilog functional coverage can also
be used to detect that some branches of the case statement are not being
executed. Also, some EDA tools, such as LEDA and DC, will warn about a
mismatch in the size of select and the literal integer values to which
it is compared.


4.3 Size mismatch in literal integers

Gotcha: Too small a size truncates most-significant bits; too large
a size left-extends with...something.

Size smaller than value gotcha. Verilog rules state that if your bit size
specified is fewer bits than the value, then, no matter what, the left-most
bits of the value are truncated. This can be a gotcha when the value is
signed, because the sign bit will be truncated as well.

This can significantly affect the result of signed operations! In the
following example, a negative 15 (8-bit F1 hex) is truncated to 2-bits
wide, becoming a positive 1.

-2'sd15; // 11110001 is truncated to 01

How to avoid this gotcha: Be sure that the bit size specified is at least as
wide as the size of the value, especially when using signed values. Some
tools, such as rule checking programs like LEDA, will detect a size versus
value mismatch. Unfortunately, these tools will also report size mismatches
when using unsigned values, where a mismatch may not be a problem, and may
even be useful.

Size greater than value gotcha. Verilog rules state that when your bit size
specified is more bits than the value, then the value will be expanded to
the size by left-extending the value. The fill value used to left extend is
based on the most significant specified bit of the value, as follows:

- If the most significant bit of the value is a 0 or a 1, then the value
is left-extended zeros.
- If the most significant bit is an X, then the value is left-extended Xs.
- If the most significant bit is a Z, then the value is left-extended Zs.

This left extension can be very useful. For example, it is not necessary to
specify the value of each and every bit of a vector to reset the vector to
zero or to set the vector to high impedance.

64'h0; // fills all 64 bits with 0
64'bZ; // fills all 64 bits with Z

A surprising gotcha can occur when the bit-size is larger than the value,
and the value is signed. The expansion rules above do not sign-extend a
signed value. Even if the number is specified to be signed, and the most
significant bit is a 1, the value will still be extended by 0's. Example:

logic [11:0] a, b, c;

initial begin
a = 12'h3c; // unsigned value 00111100 expands to 000000111100
b = 12'sh3c; // signed value 00111100 expands to 000000111100
c = 12'so74; // signed value 111100 expands to 000000111100
if (a == b) ...; // evaluates as true
if (a == c) ...; // evaluates as true
end

In this example, a hex 3c is an 8-bit value, which does not set its most-
significant bit. When the value is expanded to the 12-bit size, the
expansion zero-extends, regardless of whether the value is signed or
unsigned. This is as expected.

The octal value 73 is the same bit pattern as a hex 3c, but is a 6-bit
value with its most-significant bit set. But, the expansion to the 12 bit
size still zero-extends, rather than sign-extends. If sign extension was
expected, then GOTCHA!.

How to avoid this gotcha: The subtlety in the preceding example is that the
sign bit is not the most-significant bit of the value. It is the most-
significant bit of the specified size. Thus, to specify a negative value
in the examples above, the value must explicitly set bit 12 of the literal
integer.

12'h805 // expands to 100000000101, which is 2053 decimal
12'sh805 // expands to 100000000101, which is -2043 decimal
12'shFFB // expands to 111111111011, which is -5 decimal
-12'sh5 // expands to 111111111011, which is -5 decimal

Unspecified size. If the size of a literal integer is not specified, then
the bit size of the literal number defaults to 32 bits. This default size
can be a gotcha when the is not 32 bits, as discussed earlier.


4.4 Literal number size mismatch in assignments

Gotcha: A size mismatch in literal numbers follows different rules
than a size mismatch in assignment statements.

Once a literal integer has been created and expanded via the rules in
Sec 4.3, the operator rules are then applied.

Note: This is a discussion on assignment of literal value (e.g. a = 5;)
gotchas. Sec 5 discusses assignment rules and gotchas when there are
operators on the right-hand side of the assignment.

The assignment operation rules for assigning literal values are:

- When the left-hand side expression of an assignment statement is
fewer bits than the right-hand side literal value, then the most
significant bits of the right-hand side value are truncated.
- When the left-hand side expression of an assignment statement is
more bits than the right-hand side literal value, ...
- If the right-hand side literal value is unsigned, it will be
left-extended with zeros.
- If the right-hand side literal value is signed, it will be
left-extended using sign extension.
- Exceptions: If the right-hand side is an unsized high-impedance
literal value (e.g.: 'bz) or unsized unknown (e.g.: 'bx), the value
will left-extend with Z or X, respectively, regardless of whether
signed or unsigned.

These rules might seem, at first glance, to be the same rules discussed in
Sec 4.3, when a literal integer size does not match the literal integer
value. But there is a subtle, and important difference in the rules. The
difference is that literal value expansion does not sign-extend, but an
assignment statement does sign-extend.

And now the gotcha. Sign extension of the right-hand side only occurs if
the expression on the right-hand side is signed. The signed-ness of the
left-hand side expression does not affect whether or not sign extension
will occur. Consider:

logic [3:0] a; // unsigned 4-bit variables
logic signed [3:0] b; // signed 4-bit variables
logic [7:0] u; // unsigned 8-bit variables
logic signed [7:0] s; // signed 8-bit variables

u = 4'hC; // 1100 (right-hand side) is zero-extended to 00001100
s = 4'hC; // 1100 (right-hand side) is zero-extended to 00001100
// even though s is a signed variable; GOTCHA

u = 4'shC; // 1100 (right-hand side) is sign-extended to 11111100
// even though u is an unsigned variable; GOTCHA
s = 4'shC; // 1100 (right-hand side) is sign-extended to 11111100

a = 4'hC;
u = a; // 1100 (right-hand side) is zero-extended to 00001100
s = a; // 1100 (right-hand side) is zero-extended to 00001100
// even though s is a signed variable; GOTCHA

b = 4'hC;
u = b; // 1100 (right-hand side) is sign-extended to 11111100
// even though u is an unsigned variable; GOTCHA
s = b; // 1100 (right-hand side) is sign-extended to 11111100

These simple examples illustrate two types of gotchas:

- Assigning to a signed variable does not cause sign extension. Sign
extension only occurs if the right-hand side expression is signed.

- Assigning to an unsigned variable can have sign extension. Sign
extension occurs if the right-hand side expression is signed.

In other words, it is the right-hand side of an assignment that determines
if sign extension will occur. The signed-ness of the left-hand side has no
bearing on sign extension.

These same assignment expansion rules apply when operations are performed on
the right-hand side of an assignment. However, whether zero extension or
sign extension will occur also depends on the type of operation. These
operation rules are covered in Sec 5.3.


4.5 Literal number Z and X extension backward compatibility

Gotcha: Verilog-2001 Z and X extension is not backward compatible
with Verilog-1995.

Verilog-1995 had a gotcha when assigning an unsized high-impedance value
('bz) to a bus that is greater than 32 bits. The default size of an unsized
number is 32 bits. The literal number expansion rules state the Z value
will extend through those 32 bits (see Sec 4.3). But, the assignment
extension rules state that this 32-bit value then zero-extends to the size
of the left-hand side of the assignment (see Sec 4.4). Therefore, with
Verilog-1995, only the lower 32 bits would be set to high-impedance, and the
upper bits would be set to 0. To set the entire bus to high-impedance
requires explicitly specifying the number of high impedance bits. Example:

//Verilog-1995 style:
parameter WIDTH = 64;
reg [WIDTH-1:0] data;

data = 'bz; // fills with 64'h00000000zzzzzzzz
data = 64'bz; // fills with 64'hzzzzzzzzzzzzzzzz

The fill rules in Verilog-1995 make it difficult to write models that scale
to new vector sizes. Redefinable parameters can be used to scale vector
widths, but the Verilog source code must still be modified to alter the
literal value widths used in assignment statements. (And yes, believe it or
not, there are still some companies primarily using Verilog-1995.) The
example above applies equally to assigning X's to a vector.

How to avoid this gotcha: One solution came with Verilog-2001, which changed
the rule for assignment expansion of unsized Z and X literal integers. The
unsized value of Z or X will automatically expand to fill the full width of
the vector on the left-hand side of the assignment.

//Verilog-2001style:
parameter WIDTH = 64;
reg [WIDTH-1:0] data;

data = 'bz; // fills with 64'hzzzzzzzzzzzzzzzz

The Verilog-2001 enhancement allows writing code that scales when vector
sizes are redefined. But, this solution is also a gotcha, because it is not
backward compatible w/ Verilog-1995. If maintaining backward compatibility
with Verilog-1995 is a requirement, then always specify the exact size of
literal Z and X values.

The best way to avoid these Z and X fill gotchas is to take advantage of a
new System Verilog literal number, as described in Sec 4.6.


4.6 Filling vectors

Gotcha: Verilog does not have a literal value that fills all bits
of a vector with 1's.

In Verilog-2001, assigning 'bx, 'bz, or 0 will fill a vector of any size
with all bits set to X, Z or zero, respectively. However, assigning 'b1 is
not orthogonal. It does not fill a vector with all bits set to one.

//Verilog-2001 style:
parameter WIDTH = 64;
reg [WIDTH-1:0] data;

data = 'b0; // fills with 64'h0000000000000000
data = 'bz; // fills with 64'hzzzzzzzzzzzzzzzz
data = 'bx; // fills with 64'hxxxxxxxxxxxxxxxx
data = 'b1; // fills with 64'h0000000000000001 -- GOTCHA!

In order to assign a vector of any size with all bits set to one, designers
must learn clever coding tricks involving various Verilog operators. These
tricks are not discussed in this paper, because there is a better way to
avoid this gotcha...

How to avoid this gotcha: System Verilog defines a consistent syntax for
filling any size of variable with all 1s, all 0s, all Xs or all Zs.

//System Verilog style:
parameter WIDTH = 64;
reg [WIDTH-1:0] data;

data = '1; // fills with 64'hffffffffffffffff
data = '0; // fills with 64'h0000000000000000
data = 'z; // fills with 64'hzzzzzzzzzzzzzzzz
data = 'x; // fills with 64'hxxxxxxxxxxxxxxxx

The syntax for this is just a simple assigning '.


4.7 Passing real (floating point) numbers through ports

Gotcha: Verilog does not allow real numbers to be passed directly
through ports.

In Verilog, the outputs of a module can be either net or variable types, but
the signals receiving values from module instantiations are required to be
of type net. Verilog also requires that input ports of a module be net
types. Verilog variables include the real type, which is a double-precision
floating point value, but there is no counterpart to a real variable for the
net data types. If outputs of a module can be variable types, but the
receiving side must be a net type, how are real values passed through
module ports?

The gotcha is it's illegal in Verilog to pass real numbers through ports.
A secret that many engineers don't know, however, is that Verilog has a pair
of built-in system functions that can be used to convert real numbers to a
format that can be passed through ports. The numbers are then converted
back to real in the receiving module. These functions are $realtobits and
$bitstoreal.

module top;
wire [63:0] net_real; // only net types used in netlist
real_out ro (.net_real_out(net_real));
real_in ri (.net_real_in(net_real));
endmodule

module real_out(output wire [63:0] net_real_out); // output is net type
real r;
assign net_real_out = $realtobits(r); // must convert real to a
// bit-vector to pass through
// module output port
...
endmodule

module real_in(input wire [63:0] net_real_in); // input is net type
real r;
always @(net_real_in)
r = $bitstoreal(net_real_in); // must use bit-vector on input
// port, then convert to real
...
endmodule

How to avoid this gotcha: While Verilog does provide a solution for
passing real numbers through ports, the solution is not well known, and is
awkward to use. System Verilog provides a much more elegant way to avoid
this gotcha. In System Verilog, real types can be passed directly through
ports System Verilog also allows both the sending and receiving side of
ports to be real variables. The example above can be coded much more
simply in System Verilog.

module top;
real r; // variable types can be used in netlist
real_out ro (.r);
real_in ri (.r);
endmodule

module real_out(output real r); // output is real variable type
...
endmodule

module real_in(input real r); // input is real variable type
...
endmodule


4.8 Port connection rules

Gotcha: The size of a port and the size of the net or variable
connected to it can be different.

The Verilog standard states that module ports are treated as continuous
assign statements that continuously transfer values into, and out of,
modules. This is not a gotcha that one can avoid, but rather a rule that
helps explain some gotchas relating to port connections.

In Verilog, the receiving side of an input or inout port can only be a net
type. The transmitting side of an output port can be either a net or a
variable. When considering ports as continuous assignment statements, it
becomes easier to understand why the receiving sides of ports are required
to be net data type signals, and why the driver (or source) side of ports
could be either net or variable. The receiving side of a port is the same
as the left hand side of a continuous assign statement, and the driver or
source side of a port is the same as the right hand side of a continuous
assign statement. In other words, the left hand side/right hand side rules
for continuous assignments apply directly to port assignments.

With this in mind, consider the 4 scenarios regarding port size connections
(3 of which can be gotchas if not well understood):

- The port size and the signal driving the port are the same size
- The signal driving the port has more bits than the port (a gotcha)
- The signal driving the port has fewer bits than the port (a gotcha)
- An input port is unconnected; no signal driving the port (a gotcha)

Applying continuous assignment size rules to ports gives the following
effects for these 4 scenarios:

1. If the size of the port and the size of the signal driving the
port match, then the value passes through the port with no change.

2. If the signal driving the port has more bits than the port's
receiving signal, then the upper bits of the driving signal are
truncated, including any sign bit.

3. If the signal driving the port has fewer bits than the port's
receiving signal, then the upper bits are extended, following
Verilog's assignment rules:

- If the driving signal is unsigned, the upper bits are
zero-extended to the size of the receiving signal.
- If the driving signal is signed, then the upper bits will
be sign-extended.

4. If an input port is unconnected, the value for the receiving
signal of the port will be the default uninitialized value for its
given data type. For the wire net type, the uninitialized value
is Z. For tri0 and tri1 net types, the uninitialized values are
0 and 1, respectively, with a pull-up strength.

Most often, any mismatch in port connection sizes is a design error. But,
it is not a syntax error. In Verilog, an incorrect size declaration is very
easy design error to make, especially when the modules that make up a design
are written by several different engineers, (and possibly even come from
outside sources). A simple typo in a netlist, or an incorrect parameter
redefinition, can also lead to port size mismatches. Typographical errors
in a netlist can also result in ports of a module instance unintentionally
left unconnected.

Verilog's rules for port connection mismatches are well defined, but the
simulation results are a gotcha! Trying to trace back to why some bits
disappeared from a vector, or additional bits suddenly appeared, can be
difficult. And that assumes that verification detected that there is a
problem! The following example illustrates how values are extended or
truncated when passed through a port of a different size than the value.

module top;
wire [3:0] data = 4'b1111; // decimal 15
wire [7:0] address = 8'b11111111; // decimal 255

block1 b1 (.data(data), // 4-bit wire connected to 8-bit port
.address(address)); // 8-bit wire connected to 4-bit port
// third port left unconnected
endmodule: top

module block1 (input [7:0] data,
input [3:0] address,
input [3:0] byte_en);

initial
#1 $display(" data = %b \n address = %b \n byte_en = %b\n",
data, address, byte_en);
endmodule: block1

The output from this code is:

data = 00001111
address = 1111
byte_en = zzzz

The example above shows how confusing unconnected or partially connected
ports can be. The value of data has mysteriously changed, gaining an extra
four bits. The value of address changed from 255 to 15 (decimal), and
byte_en is high-impedance instead of a valid logic value.

Most simulators generate warnings when code like this is elaborated, but
such warnings are not required by the Verilog standard, and engineers are
notorious for ignoring these warnings.

System Verilog has a great solution to this: implicit port connections using
either . or .* module instantiations. When using the . or the
.* module instantiation syntax, the driver and receiver port signals are
required to be the same size. If, for some reason, a driver/receiver signal
pair size mismatch is desired, the port must be explicitly connected. This
makes it very obvious in the code that the mismatch was intended.

module top;
wire [7:0] data;
wire [7:0] address;

block1 b1 (.data, // implicit port connections
.address);
endmodule: top

module block1 (input [7:0] data,
input [3:0] address,
input [3:0] byte_en);
...
endmodule: block1

In this example, the size of the wire called data has been corrected to be
8-bits wide, which is the same as the size of the data port in block1. The
. shortcut will infer that the wire called data is connected to the
port called data. However, there is still a typo in the declaration of the
wire called address. Instead of a port connection mismatch (a gotcha), an
elaboration error will occur because the signal at the top level is a
different size than the block1 port. The . will not infer connections
that do not match in size.

The . method will allow unconnected ports, such as the byte_en port in
the example above. Was this port left unconnected on purpose, or is it
another typo in the netlist? To catch all the size mismatches & unconnected
ports, using the .* shortcut is the best solution.

module top;
wire [7:0] data;
wire [7:0] address;

block1 b1 (.*, // implicit port connection
.address(address[3:0]), // explicit connection mismatch
.byte_en() ); // explicit unconnected port
endmodule: top

module block1 (input [7:0] data,
input [3:0] address,
input [3:0] byte_en);
...
endmodule: block1

The .* shortcut requires explicitly listing all unconnected ports and all
the signals with different sizes.


4.9 Back-driven input ports

Gotcha: Verilog allows input ports to be used as outputs.

One of the surprising gotchas in Verilog is that a module input port can be
used as an output. If a designer mistakenly assigns a value to a signal
declared as an input port, there will not be any warnings or errors.
Instead, Verilog simply treats the input port as if it were a bidirectional
inout port. The Verilog Language Reference Manual refers to this a port
coercion. In this paper, we refer to an input port being used as an output
as a back-driven port.

The following example illustrates this surprising gotcha:

module top;
wire w1;
backdrive bd(.a(w1)); // instance of a module with back-driven port
endmodule

module backdrive(input wire a); // "a" will be coerced to be an
output
wire b;
assign a = b; // GOTCHA! the intent was to have b = a, not a = b;
endmodule

Even though signal a is an input to module backdrive, it can still be
assigned a value within backdrive. This has the effect of a having two
drivers wired together. This is legal because, in Verilog, ports are
treated as continuous assignments. The code above is equivalent to:

module top;
wire w1;
wire a, b;
assign a = w1; // same as connecting "w1" to input port "a"
assign a = b; // a second continuous assignment to "a"
endmodule

How to avoid this gotcha: With System Verilog, input ports can be connected
to variables, instead of the wire type. System Verilog restricts variables
to only allow a single source. This is different than a wire type, where
multiple drivers are permitted (whether intentional, or not). In the
preceding example, if "a" had been declared as a logic type instead of a
wire type, the assignment of a = b would be a syntax error, because it would
represent a second source for "a". The authors recommend that all module
inputs and outputs be declared as variable types, unless it is intended to
have multiple drivers on the port (e.g. a bidirectional data bus).