# Signals and std_logic

*The four values a wire can carry*

std_logic is VHDL's standard wire type, holding the values '0', '1', 'Z' (high-impedance) and 'X' (unknown/contention), the same four logic values a probe reads in digiwleea, used for both ports and internal signals.

Group: HDL
URL: https://digiwleea.wleeaf.dev/learn/vhdl-signals/

An [entity's](https://digiwleea.wleeaf.dev/learn/vhdl-entity/) ports each had a type: `std_logic`. That type is not an accident, it carries exactly the four values you have been metering all along. Recall from your circuit work that a wire is never just "on or off": a probe can read `0`, `1`, the floating `Z` (driven by nothing), or the contention `X` (driven two ways at once). `std_logic` is the VHDL type that models that same four-value wire.

## std_logic: a wire, not a boolean

A software boolean is just true/false. A real wire is richer, and `std_logic` captures it. Its values are written in single quotes (a VHDL detail): `'0'` and `'1'` are the driven logic levels, `'Z'` is high-impedance (the wire is let go, what a [tri-state](https://digiwleea.wleeaf.dev/learn/tristate/) buffer outputs when disabled), and `'X'` is unknown, the synthesis/simulation flag for a wire driven to conflicting values at once. They line up one-for-one with the values your probes show.

| std_logic value | What it means on a wire |
| --- | --- |
| '0' | driven low (logic 0, tied to GND) |
| '1' | driven high (logic 1, tied to VCC) |
| 'Z' | high-impedance, floating, nothing driving it |
| 'X' | unknown / contention, driven two ways at once |

_The four std_logic values that matter day to day, and their direct match to the 0/1/Z/X a digiwleea probe reads. (The full type has a few more rare values, but these four are the ones you use.)_

> **TIP:** Why single quotes? `'1'` is one `std_logic` **bit**; `"1010"` (double quotes) is a `std_logic_vector`, a **bus** of several bits, the textual form of a multi-bit [bus](https://digiwleea.wleeaf.dev/learn/buses/). One wire uses single quotes; a bundle of wires uses double quotes. The next track lessons stick to single-bit signals.

## Ports versus internal signals

There are two places `std_logic` shows up. A **port** (declared in the entity, `in` or `out`) is a wire that crosses the block's boundary, a pin. An internal **signal** (declared inside the architecture, before `begin`) is a wire that lives entirely inside the block, used to name an intermediate result. A signal has no direction because it is not on the boundary; it is just a named net you can drive and read freely, like a wire stub between two gates on your canvas that no probe sits on.

```vhdl
architecture rtl of and3 is
  signal t : std_logic;          -- internal wire, no direction
begin
  t <= A and B;                  -- first gate drives the internal net
  F <= t and C;                  -- second gate reads it
end architecture;
```

_An internal signal t names the output of the first gate so the second can use it. t is not a port: it never leaves the block, it is a wire between two internal gates._

> **WARN:** Do not confuse port mode with signal: an `in` port can be read but not driven inside the architecture, an `out` port can be driven but (in classic VHDL) not read back, and an internal `signal` can be both driven and read but never appears on the boundary. Mixing these up is the most common beginner error. If you need to both drive a value and read it elsewhere, use an internal signal and assign it to the output port.

> **KEY:** Why this matters: because `std_logic` is a genuine four-value wire and not a boolean, VHDL can describe things software types cannot, a [tri-state](https://digiwleea.wleeaf.dev/learn/tristate/) driver letting go to `'Z'`, or a tool flagging a bus short as `'X'`. The type system is modelling real electrical behavior, which is exactly the behavior you metered building circuits by hand.

**Q (Check yourself):** A signal `bus_line` is currently `'Z'` in simulation. What does that tell you about who is driving it right now, and what should drive it to a `'0'` or `'1'`?

**A:** `'Z'` means **nothing is driving** `bus_line` at this instant; it is floating, electrically let go. To give it a defined value, exactly one driver must be enabled, for example a [tri-state](https://digiwleea.wleeaf.dev/learn/tristate/) buffer whose enable is asserted, pushing a `'0'` or `'1'` onto it. If *two* drivers turn on at once you would instead see `'X'` (contention). This is the same shared-bus discipline you used with tri-state on the canvas.

### FAQ

**Q:** What is std_logic in VHDL?

**A:** std_logic is VHDL's standard single-bit wire type. It holds '0', '1', 'Z' (high-impedance/floating), and 'X' (unknown/contention), among a few rarer values, so it models a real wire's possible states rather than just a true/false boolean.

**Q:** What do the std_logic values 0, 1, Z, and X mean?

**A:** '0' and '1' are driven logic levels (tied to ground or power). 'Z' is high-impedance: the wire is floating with nothing driving it, what a disabled tri-state buffer outputs. 'X' is unknown or contention: the wire is being driven two conflicting ways at once. They match the four values a digiwleea probe reads.

**Q:** What is the difference between a port and a signal in VHDL?

**A:** A port is declared in the entity, has a direction (in or out), and is a wire that crosses the block's boundary (a pin). An internal signal is declared inside the architecture, has no direction, and is a wire that stays entirely inside the block to name an intermediate value.

**Q:** Why does std_logic use single quotes like '1'?

**A:** Single quotes denote one std_logic bit, such as '0' or '1'. Double quotes like "1010" denote a std_logic_vector, a multi-bit bus. So a single wire uses single quotes and a bundle of wires uses double quotes.
