A video pipeline passes frames from a camera block through a scaler to an encoder. The first design gives every block a memory-mapped port: the camera writes each frame to memory, the scaler reads it back, writes its output, and the encoder reads that. It works, and it uses three times the memory bandwidth the data needs. A second design connects the blocks directly, frame data flowing from one to the next with no addresses at all. Same blocks, same data, very different protocols.
What are the basic ways two blocks can communicate, and how do you choose?
The common reflex is to make everything memory-mapped: every block gets a port on the fabric with an address range, and communication means reading and writing addresses. It is universal and software understands it. But it forces every transfer through an address, a target and often a trip to memory, even when the data only ever goes from one block to the next. It also forces the receiver to discover, somehow, that new data has arrived. Memory-mapped is one model among three, and it is the wrong one for some traffic.
Model | What a transfer is | Addressing | How the receiver knows something arrived |
|---|---|---|---|
Memory (load/store) | Read or write a location | Every transfer names an address | It does not, by itself: it must poll, or be told separately (an interrupt or a flag) |
Message | Deliver a self-contained unit to a destination | Names a destination (and a type), not a location | The message's arrival is the event |
Stream | An ordered flow of data from one producer to one consumer | None: the connection is the address | Data keeps arriving, with markers for boundaries (such as end of packet) |
The models differ most in three properties:
Shared state. Memory semantics share locations, so two agents can read and write the same data, which brings ordering and coherence questions (Parts 7 and 13). Messages and streams hand data over: once sent, it belongs to the receiver.
Notification. A write to memory is silent; the reader needs a separate signal. A message or stream carries its own notification.
Flow control. A memory target must accept or stall every access. A stream has natural back-pressure from consumer to producer. Messages need buffering at the destination and a way to stop senders when it fills (Part 4).
Take the camera-to-scaler link from the opening and count what each model costs per frame (illustrative frame of 8 MB):
Model | Memory traffic per frame on this link | Extra machinery |
|---|---|---|
Memory: camera writes, scaler reads back | 16 MB (8 MB written, 8 MB read) | A notification that the frame is complete; buffer management so the camera does not overwrite a frame being read |
Message: one message per line of the frame | 0 MB (the data travels in the messages) | Buffering at the scaler for incoming messages; a way to stop the camera when it is full |
Stream: pixels flow straight through | 0 MB | Back-pressure from scaler to camera; end-of-line and end-of-frame markers |
The stream wins for this link, because the data goes from one producer to one consumer, in order, exactly once. But the encoder may need to look at earlier frames (reference frames for compression), which requires going back to data that has already passed: that is a memory access pattern. Real designs mix the models: stream where data flows, memory where it must be revisited or shared.
Model | Wins when | Costs |
|---|---|---|
Memory | Data is shared, revisited, accessed out of order, or needs to be visible to software | Address traffic, notification, ordering and coherence rules |
Message | Agents exchange self-contained requests or events, possibly many-to-many | Destination buffering, message formats, flow control per destination |
Stream | Data flows one way, in order, from one producer to one consumer | No random access; the consumer must keep up or push back |
A common hybrid is the descriptor ring with a doorbell (lesson 5.16): bulk data sits in memory, and a small message (the doorbell) tells the consumer where to find it. It combines memory's random access with a message's notification.
Protocol | Model | What that implies |
|---|---|---|
AXI | Memory: every read and write carries an address | Needs separate notification (interrupts or flags) and ordering rules for when writes become visible |
AXI-Stream | Stream: no address; TLAST marks packet ends | Back-pressure through TVALID/TREADY; ideal for data pipelines |
PCI Express | Mainly memory: most transactions carry addresses; it also defines message transactions, for example for error reporting, power management and emulating legacy interrupt wires | Combines memory-mapped data movement with message-based notification on one link |
A design uses memory semantics between a producer and a consumer and signals completion by writing a flag in memory after writing the data (illustrative). On the first chip it works. On the next, the fabric has two paths to memory, and the flag write occasionally overtakes the last data write. The consumer sees the flag, reads the buffer, and gets part of the previous frame. Nothing is wrong with either block; the bug is that memory semantics separate data from notification, and the design relied on an ordering the fabric never promised. Part 7 is entirely about this problem. A stream would not have had it: the end-of-frame marker travels in the same ordered flow as the data.
A write to memory is silent: the consumer cannot tell it happened. The producer needs a notification (an interrupt, a flag write or a doorbell message), and the protocol must guarantee the notification is not seen before the data.
Not on its own: a stream passes each frame once. It must either buffer previous frames itself or fetch them from memory, which is a memory access pattern. Such blocks typically combine a stream input with memory access for references.
The memory model, because only it lets several agents hold and update copies of the same location. Messages and streams hand data over instead of sharing it.
Blocks communicate by memory (read and write locations), messages (deliver self-contained units) or streams (ordered flows with no addresses).
Memory semantics share data and need separate notification and ordering rules; messages and streams carry their own notification.
Choose per link: stream for one-way ordered flows, memory for shared or revisited data, messages for requests and events.