Sign in

Learn

0/8
0/6
0/6
0/6

Practice

Port Directions

Every port in Anatomy of a Component answered three questions: name, direction, type. This lesson is about the middle one. A direction is not decoration: it is a contract about who drives the wire. Getting it wrong means either a compile error or two drivers fighting over one signal.

in: the outside drives, you read

An in port is read-only from inside the component. Read it in as many statements as you like (that's the fan-out from lesson 1), but never assign to it. The driver lives outside.

CAUTION

Common Mistake: driving your own input. VHDL refuses to compile: GHDL stops with port "line_in" can't be assigned.

out: you drive, the outside reads

An out port is the mirror image: your component must drive it, and the outside world reads it. Inside the architecture or module body, it behaves like any signal you own: drive it from exactly one statement.

In older VHDL you couldn't even read your own out port inside the architecture. Designers kept an internal copy signal or used the buffer direction as a workaround, and you will still meet both in older code. VHDL-2008, the standard this platform uses, removed the restriction: reading your own output is fine.

inout: taking turns on a shared wire

Some wires genuinely have more than one legitimate driver. A memory chip's data pins carry write data into the chip one moment and read data out of it the next. The data line of an I2C bus is shared by every chip on it (the I2C lesson builds one). One wire, several components attached: that's what inout is for. The contract: at most one component drives at a time; everyone else lets go.

"Letting go" is a value of its own: 'Z', high impedance, meaning electrically disconnected, "not driving".

It's one of the values a std_logic wire can carry.

The Tri-State Recipe

To drive the pin on your turn and let go otherwise, use this pattern as-is; these two lines are from this lesson's example, line_driver:

-- drive on your turn, let go otherwise
line <= value when enable = '1' else 'Z';
-- reading the pin needs nothing special
seen <= line;

Parts of this recipe run ahead of this topic; take them on faith for now.

The conditional form (when/else) is taught properly in Concurrent Statements, which revisits this exact recipe and explains the mechanism behind it. Until then, read it as: while enable is '1' the pin carries value; otherwise the component disconnects itself.

What if two components break the contract and drive opposite values at once? The wire resolves to 'X', unknown, and the waveform shows it. You won't see an 'X' in this lesson's example: its two drivers take turns by design, which is exactly the discipline inout exists to support.

WARNING

Two enabled drivers on one wire is bus contention: in simulation an 'X', on real hardware two output stages fighting and heating up. Designs guarantee turn-taking structurally: one enable per driver, never two active at once. Building and arbitrating tri-state buses hands-on comes in Combinational Building Blocks.

In the Example

The example panel on the right wires two copies of line_driver, card A and card B, to one shared wire. Follow status_line in the waveform, left to right. It opens at 'Z': nobody has taken a turn yet, so the wire starts out floating. 'Z' is a value like any other, there from the first instant. Then A drives '1', then '0', while B just listens; b_seen mirrors everything A puts on the wire. Then A releases and the line returns to 'Z': again nobody is driving. B takes its turn driving '1' (now a_seen does the mirroring), and finally both release and the line parks at 'Z' once more. The 'Z' stretches are the wire floating: harmless in simulation, and real boards usually add a pull-up resistor so a floating bus still has a defined level.

Key Takeaways

  • in and out are one-driver contracts: the parent drives an in, you drive an out.
  • inout is for shared wires: drive on your turn, 'Z' otherwise. Use the tri-state recipe as-is until Concurrent Statements explains it.
  • 'Z' means nobody is driving; 'X' means two drivers are fighting.
Loading editor...
Waveform not yet available. Run sync-content --examples to generate.