Logic Values


As I touched upon in my earlier column on metastability, a VHDL signal that uses the “std_logic_1164 package” can undertake one of nine different values.

This may come as a shock to newer FPGA designers, who might wonder why a signal that spends the majority of its time as a 0 or 1 needs seven other values to accurately represent its behavior. As with a lot of these things, there is an interesting history as to why we ended up with this nine-value system.

These nine values are defined by the IEEE standard 1164, which was introduced in 1993. This replaced the earlier IEEE 1076-1987 standard, whose logical type — the “bit” — could assume one of only two values: 0 or 1. Sadly the “bit” type’s limited value system caused issues with models of buses, in which multiple tri-state drive gates may be connected to the same signal.

In order to address this problem, the multi-valued logic system defined by the IEEE 1164 standard not only introduced a set of new values, but it also defined an order of precedence. This order of precedence is very important to ensure that the simulator can correctly resolve the value on a signal.


Another way of visualizing this graphically is illustrated below. What this image tells us is that a conflict between a signal carrying a “U” (Uninitialized) value — for example, a register that has not been loaded with a 0 or 1 — and any other value will result in a “U.” A conflict between a “-” (Don’t Care) value and any other value (apart from a “U”) will result in an “X.” A conflict between a “0” and a “1” will result in an “X.” A conflict between a “0” and an “L,” “W,”, or “H” will result in a “0.” And so on and so forth…


It’s important to note that not all of these values can be assigned in synthesizable code, but they may be used in modeling and — in the case of the “U” (Uninitialized”) value, for example — they may be seen as the initial values on signals and registers during simulation.

While the meanings of the “0,” “1,” and “Z” — which are typically used to model the behavior of both signals and buses — are reasonably straightforward (doing what the “bit” type could not), the uses of the other values might not be immediately apparent. The “H” (Weak High) and “L” (Weak Low) states are used to model high-value pull-up and pull-down resistance values on a signal, respectively. These can subsequently be used to accurately represent the actions of wired-AND and wired-OR circuits during simulation. In turn, this lead to the “W” (Weak Unknown”), which represents the case where a signal is being driven by both “L” and “H” values from two different drivers.

The “-” (Don’t Care) value is not intended to be used for branch or loop selection such as “IF signal_a = ‘-‘ THEN…” as this will not be true unless “signal_a” actually is “-“; instead, the “-” value is intended to be used for defining outputs; for example:


You may have noticed my mentioning that the simulator resolves the signal to the correct value. In fact, two base types are defined within the 1164 package: “std_ulogic” and “std_logic.” Both of these types use the same nine-value logic system; however, “std_logic” is resolved while “std_ulogic” is unresolved. What this means is that — when using “std_logic” — if multiple drivers are present the simulator is capable of resolving the situation and determining the resultant state of the signal using the resolution table below:


Of course, this does not mean that the resolved signal will be one the engineer expects and/or one that is useable in the final design. Frequently, if the engineer has inadvertently connected multiple drivers together, the result will be an “X” (Forcing Unknown).

This problem is somewhat solved by using the “std_ulogic” type, because this will cause the simulator to report an error if multiple drivers are present (generally speaking, most signals in logic designs should have only one driver).

The “std_ulogic” type is not commonly used with FPGA designs (although this depends on each company’s coding rules). However, this type is very popular with ASIC designs where inadvertent multiple drivers can have a serious effect on the ensuing silicon realization