# Tri-state buffers and the shared bus

*Many drivers, one wire, one at a time*

A tri-state buffer can drive its output high, drive it low, or disconnect entirely into a high-impedance (Z) state. That third state lets many components share one bus by taking turns driving it, which is how a CPU moves data between blocks.

Group: Processor
URL: https://digiwleea.wleeaf.dev/learn/tristate/

So far every wire had exactly one driver. That was a hard rule back in [signals](https://digiwleea.wleeaf.dev/learn/signals/): two outputs fighting over one net, one pushing high and one low, is a short, and the net reads `X`. But a CPU has many blocks (registers, the ALU, memory) that all need to put their value on **one** shared [bus](https://digiwleea.wleeaf.dev/learn/buses/). They cannot all drive it at once. The fix is a third output state: not just `0` and `1`, but also **off**, electrically disconnected. A gate with that ability is a **tri-state buffer**.

## Three states: 0, 1, and high-Z

A tri-state buffer has a data input `IN` and an **enable** `EN`. When `EN = 1` it acts like a plain wire: `OUT` follows `IN`. When `EN = 0` it stops driving entirely and `OUT` goes to **high-Z** (`Z`), the floating state from the [signals](https://digiwleea.wleeaf.dev/learn/signals/) lesson. The key is that a `Z` output is not a `0`; it is *nothing*, so it does not fight whatever else is on the wire.

| EN | IN | OUT |
| --- | --- | --- |
| 0 | 0 | Z |
| 0 | 1 | Z |
| 1 | 0 | 0 |
| 1 | 1 | 1 |

_When EN = 0 the output is Z (disconnected) regardless of IN. When EN = 1 the output simply follows IN. The buffer either drives the wire or lets go of it._

In this switch-level simulator a tri-state buffer is a single **transmission gate**: an NMOS and a PMOS in parallel, their gates driven by `EN` and `NOT EN`, passing `IN` to `OUT`. When enabled both transistors conduct and the value flows; when disabled both are off and the path is open, so `OUT` floats. You met exactly these transistors in the very first lessons; here they make a controllable connection.

## Sharing one bus

Now put several tri-state buffers on the **same** output wire, each with its own data source and its own enable. As long as the control logic raises **exactly one** enable at a time, only that buffer drives the bus; all the others are in high-Z and stay out of the way. The bus carries the chosen source. Raise a different enable and a different value appears, all on the same wire.

> **TIP:** An analogy: a shared bus is a **conference call**. Everyone is connected to the same line, but if two people talk at once it is noise (`X`). The enable is each person's mute button: as long as exactly one speaker is unmuted at a time, the line carries that one voice clearly. High-Z is the muted state, present on the line but adding nothing.

_Circuit diagram: Two tri-state buffers sharing one BUS node. With both enables low (the default here) the bus reads Z, nobody is driving it. Open it in the lab, raise ENA to put A on the bus, then drop it and raise ENB to put B on instead. Raising both at once with different values is the short (X) you must avoid._

**Q (Try it):** On the two-buffer bus, what does `BUS` read when both `ENA` and `ENB` are `0`? What if you raise `ENA = 1` with `A = 1`? And what happens if you raise both enables with `A = 1, B = 0`?

**A:** Both enables low: nobody drives the bus, so it reads `Z` (floating). `ENA = 1, A = 1`: buffer A drives, so `BUS = 1`. Both enabled with opposite values: two drivers fight, so `BUS = X`, a short. Exactly one enable at a time is the rule.

> **WARN:** The one-driver rule from [signals](https://digiwleea.wleeaf.dev/learn/signals/) has not gone away; tri-state just lets you *schedule* who drives the bus. If two enabled buffers push opposite values at the same time, the bus shorts to `X`, exactly as before. Guaranteeing one enable at a time is the job of the [control unit](https://digiwleea.wleeaf.dev/learn/control/); get that wrong and the bus fights itself.

> **KEY:** The shared bus plus tri-state outputs is the backbone of the whole machine. Every block hangs off one common bus and is gated onto it by a control line. The first place this pays off is [memory](https://digiwleea.wleeaf.dev/learn/ram/): many storage cells, one data bus, a [decoder](https://digiwleea.wleeaf.dev/learn/decoder/) raising one cell's tri-state at a time.

**Spot the fault** (Float (Z)): ENA=0, ENB=0, A=1, B=0, BUS=Z. Look at BUS.

Both tri-state enables are `0`, so neither buffer is driving the shared wire. With no driver at all the bus floats to `Z`, not `0`. Raise exactly one enable to put that source's value on the bus.

### FAQ

**Q:** What is a tri-state buffer?

**A:** A **tri-state buffer** has three output states: `0`, `1`, and `Z` (high-impedance, electrically disconnected). It has a data input `IN` and an **enable** `EN`: when `EN = 1` it acts like a plain wire (`OUT` follows `IN`), and when `EN = 0` it stops driving entirely and `OUT` floats to `Z`.

**Q:** How is the Z state different from a normal 0 or 1 output?

**A:** A `Z` output is not a `0`; it is **nothing**, the floating state where the buffer has electrically let go of the wire. Because it drives no value, it does not fight whatever else is on the wire, which is exactly what a normal `0` or `1` output would do.

**Q:** How do tri-state buffers let many devices share one bus?

**A:** Put several tri-state buffers on the same wire, each with its own source and enable. As long as the control logic raises **exactly one** enable at a time, only that buffer drives the [bus](https://digiwleea.wleeaf.dev/learn/buses/) while the rest sit in high-`Z` and stay out of the way. Raise a different enable and a different value appears, all on one wire.

**Q:** What happens if two tri-state buffers drive a bus at once?

**A:** The bus shorts to `X`, exactly the one-driver violation from [signals](https://digiwleea.wleeaf.dev/learn/signals/). Tri-state does not repeal that rule; it just lets you *schedule* who drives the bus. Guaranteeing exactly one enable at a time is the job of the [control unit](https://digiwleea.wleeaf.dev/learn/control/).
