I was wondering about the 'buffer' i/o option for entities in the VHDL language. I have found that my code is much cleaner if I use the 'buffer' option instead of 'out' in any circumstance where I want to act on the outgoing signal somewhere within the entity. I find that I can think of very few reasons to use 'out' ever and I'm tempted to just always use 'buffer' in every case. So, my question is, under what circumstances should I set my outputs as 'out' (even when that means I have to add an extra signal declaration and assignment) and when is it ok to use 'buffer'?
2 Answers
One case, that probably doesn't apply, is if you're using a standard older than VHDL-2002. Before than, buffer
could not connect directly to out
. So in a hierarchical design, the signal path would need to be declared as a buffer
on all levels. Also, when adhering to these older standards, some tools have problems synthesizing buffer
s correctly. They may or may not warn you about this.
These should no longer be an issue if you're using a newer standard. From the VHDL-2002 Standard:
a) For a formal port of mode in, the associated actual must be a port of mode in, inout, or buffer.
b) For a formal port of mode out, the associated actual must be a port of mode out, inout, or buffer.
c) For a formal port of mode inout, the associated actual must be a port of mode inout, or buffer.
d) For a formal port of mode buffer, the associated actual must be a port of mode out, inout, or buffer.
e) For a formal port of mode linkage, the associated actual may be a port of any mode.
I also often see advice stating that a buffer
should never be tri-stated. If you need the ability to tri-state a bus, then you would need to use out
. I could find no direct reference to how buffer
s handled tri-stating in the standard. But it is probably good advice to follow. Again, your tools may or may not complain if you attempt to synthesis a tri-stated buffer.
-
1\$\begingroup\$ Additionally you could note that in the pre-2002 case a buffer can have at most one source. \$\endgroup\$– user8352Jul 30, 2014 at 0:36
-
\$\begingroup\$ @DavidKoontz I actually had a similar statement in my answer to begin with, but took it out because I could find no explicit reference in the standard to allowing multiple drivers to a
buffer
. But that is also good information to have. \$\endgroup\$ Jul 30, 2014 at 13:07
I'm not going to restate embedded.kyle's very nice answer, but I will clarify the "buffer
should never be tri-stated" bit.
First, IEEE 1164 std_logic is a resolved version of std_ulogic which is just an enum with values of 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H' and '-'. Due to the way VHDL handles enums of chars you can get arrays of enums by using strings. TL;DL: VHDL does not treat IEEE types specially, synthesis tools might, but the standard does not.
Second, the tri-state signal has no special importance. It simply has a line in the resolution table (again defined by IEEE 1164, not VHDL) that corresponds more or less to the other values. The '-' uninitialized value together with 'Z' actually goes to 'X', but all other values just get maintained when combined with 'Z'.
Finally, taking those into account, what actually matter is whether the port is "read" into the inside context from the instantiating context. IN
, INOUT
and LINKAGE
(not used in the port interface) do read values, BUFFER
does not. What this means is that if you write a value to a buffer, it will not get resolved with external signals. So if you write a '1', something outside writes a '0', you will not see the 'X'. Similarly, writing a 'Z' to it will not grant you access to the external signal. In this sense you need to think of it either like a real buffer (in the sense that nothing that happens outside the circuit can get back through the buffer) or just think of it as programming instead of as a circuit and realize that BUFFER
means that the signal goes out and allows reading inside but doesn't pull in from the outside.
From section 4.3.2:
The value of an object is said to be read when one of the following conditions is satisfied:
— When the object is evaluated, and also (indirectly) when the object is associated with an interfac eobject of the modes in, inout, or linkage
The value of an object is said to be updated when one of the following conditions is satisfied:
— When it is the target of an assignment, and also (indirectly) when the object is associated with an interface object of the modes out, buffer, inout, or linkage
buffer
are: (1) mixingout
on one hierarchical level withbuffer
on another is disallowed (one way round; can't remember which!) and (2) Some tools produce reams of fussy but meaningless warnings aboutbuffer
(but still work anyway!). Buffer is absolutely fine. \$\endgroup\$