Bidirectional bus in vhdl

bidirectionalbusfpgavhdl

I need to understand the concept of bidirectional bus. What i want to do is connect a memory with ports din and dout to a inout port named data. So along with memory i use a tristate buffer as component. One tristate buffer has rd signal as enable while the other will have (not read) as enable meaning write.so when i write (read=0) , value flows from data into din(at this time read =0 disables other tristate buffer) so there is no driving of multiple signals in this case. similarly when read =1 the vice versa happens. value flows from memory to data line. So the read signal itself takes care of the direction.
1)During read can there be contention of value coming out of memory and input data ?
as the buffer that takes value from data to memory is disabled.
2) In testbench when i read the memory why is there a need to give data <= 'Z' ? Isnt it already taken care when i connect the components using port map ?

Best Answer

Take the following VHDL design description:

library ieee;
use ieee.std_logic_1164.all;

entity bidir is
    port (
        Z  : inout std_logic;
        Y  : out   std_logic;
        OE : in    std_logic;
        A  : in    std_logic
        );
end;

architecture behave of bidir is
begin

    Z <= A when OE = '1' else
         'Z' when OE = '0' else
         'X';

    Z <= 'H';                           -- pullup

    Y <= TO_X01(Z);

end behave;

There are potentially three or more drivers for the net connected to the mode inout port Z. There are two local drivers - the two concurrent signal assigments one driving from port A depending on the output enable OE (and propagating unknowns), the other a pullup.

There can be some some number of external drivers on the net Z is connected to, potentially none. The value of that signal net is determined by a resolution function.

This introduces the distinction between the driven value from a driver and the effective value of signal net. The value of the signal net in an expression is the output of the resolution function, and not the nearest driver.

In a timed simulation, or in the case of the output enables of two of these buffers with the output enable being delivered on different delta cycles (a second signal for one of the output enables derived from the other by a signal assignment), there can be overlap between active drivers. You typically logically AND a chip select with the output enable to prevent overlapped enables on multiple drivers. If the driven values of the multiple drivers are different (e.g. one '1', the other '0') you'll see a resolution of 'X' during VHDL simulation for the overlap.

The pullup implies that the default value of the signal net is 'H' when there are no 'active' drivers providing strong values ('1' or '0'). You'd typically 'filter' the 'H' to a '1' by using a conversion function (e.g. TO_XO1) on the signal being used internally on the theory that un-driven signals floating in the switching region for an input buffer is a bad thing, potentially causing high transient current loads and potential latch up.

With std_logic there are two ways to insure a driver doesn't interfere with another driver. std_logic is a resolved type, using a resolution table to determine the effective value, taking two signals at a time (a result value and each driver in turn, the result initialized to 'Z.

  constant resolution_table : stdlogic_table := (
    --      ---------------------------------------------------------
    --      |  U    X    0    1    Z    W    L    H    -        |   |  
    --      ---------------------------------------------------------
             ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'),  -- | U |
             ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'),  -- | X |
             ('U', 'X', '0', 'X', '0', '0', '0', '0', 'X'),  -- | 0 |
             ('U', 'X', 'X', '1', '1', '1', '1', '1', 'X'),  -- | 1 |
             ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X'),  -- | Z |
             ('U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X'),  -- | W |
             ('U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X'),  -- | L |
             ('U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X'),  -- | H |
             ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X')   -- | - |
             );

The two axis of the resolution table are the two inputs. You might note that every intersection of 'Z' on one input results in the unchanged value of the other input. 'Z' is a safe value.

Specifying a 'Z' output for an 'inactive' driver is the correct thing to do for a pure behavioral model.

A structural model can use a disconnection specification on a guarded signal, specifying how long after an event a signal is driven. When it's not driven (disconnected) it's not involved in resolution.

Without disconnecting a driver the only way to have a driver uninvolved in the resolution value for a multi driver net is to drive it to 'Z'.