SPI · Module 6
Read Waveform Analysis
Decode an unlabelled read capture including the dummy phase: why the MISO tri-state transition is the most informative event on the bus, how to measure read latency without a datasheet, and checking versus discovery.
Chapter 5.4 decoded a write capture and found a hard limit: signalling is fully recoverable, meaning is not. A read capture contains something a write capture does not, and it moves that limit.
A read capture has a moment where the bus changes hands. What does that single transition let you measure that a write capture never could?
The answer is the device's read latency — a number you would normally take from a datasheet, recoverable from a capture alone. That makes this the most practically valuable analysis chapter in the track, and it also forces a distinction the previous chapters deliberately avoided.
1. What a Read Capture Adds
A write capture is one-directional: MOSI carries everything and MISO carries nothing (Chapter 5.4 §5). Every structural question — where the address ends, where the data begins — is unanswerable because nothing on the wire marks it.
A read capture has an event the write lacks. At some point the device takes MISO — the line stops being high impedance and starts being driven (Chapter 6.1 §4). That transition is:
- Observable on any capture with a pull-up or a differential probe.
- Generated by the device, not the master, so it reports the device's internal state rather than the master's intent.
- Positioned exactly at the end of the dummy phase, because that is when the data phase opens.
So the read capture contains one genuine boundary marker — the only one an SPI bus ever produces. Everything in this chapter follows from exploiting it.
2. The Tri-State Transition Is the Evidence
MISO stops floating — the one boundary the bus reveals
10 cyclesTwo cautions about reading this on real equipment, both of which cost people hours.
High impedance and logic low look identical on a single-ended capture of an undriven line (Chapter 5.4 §5). If MISO has no pull-up, an idle line may sit anywhere and a floating-to-low transition may be invisible. Fit a pull-up — or probe with a high-impedance scope and look for the characteristic slow, undriven drift before the transition and the crisp driven edges after.
The transition is an analogue event with a duration. The output enable asserts, the pad ramps, and the line settles — over a nanosecond or more on a real device. At high SCLK that ramp can span an appreciable fraction of a bit period, which matters when you are counting cycles to the nearest one.
3. Measuring Read Latency From the Capture
This is the chapter's payoff, and the procedure is short.
- Find CS falling — the frame's origin, and the point both endpoints count from.
- Count active SCLK edges from CS falling to the edge at which MISO becomes driven.
- That count is the device's total pre-data latency in cycles: command plus address plus dummy.
- Subtract the command and address if you know them, and the remainder is the dummy count.
Worked on Figure 1's shape, extended to a realistic transaction:
edges from CS↓ to MISO driven ........ 40
command (1 byte, from the capture) .. 8
address (3 bytes, from the capture) . 24
────────────────────────────────────────
dummy cycles ......................... 8That number — 8 — is a datasheet fact, recovered without the datasheet.
And the reason it works is worth stating: the device's output enable is driven by its own phase sequencer (Chapter 6.1 §6), so the transition is the device telling you where it thinks the data phase begins. If the master disagrees, the disagreement is visible as a mismatch between where MISO goes live and where the master starts collecting — which is Chapter 6.4's alignment error, made observable.
What if you do not know the command and address lengths? Then the capture gives you the total and not the split, exactly as in Chapter 5.4 §4. But the total is often the more useful number, because it is precisely the skip_bits a master needs (Chapter 6.4 §3) — and a master does not care how that total divides.
4. The Full Procedure
Steps 1 through 5 are Chapter 5.4's, unchanged. The read adds steps 6 and 7.
- Idle level →
CPOL, requiring no interpretation. - CS edges → the frame.
- Which edge data is stable across → the sampling edge, and therefore
CPHA. - Edge count → total bits.
- Segment → byte values on each line.
- MISO's tri-state transition → the pre-data latency, in cycles.
- Compare where MISO goes live against where the master's decode begins → whether the two ends agree.
Step 7 is the diagnostic one and has no analogue in a write capture. A write gives you no way to tell whether the device interpreted the frame as you intended; a read tells you directly, because the device's answer starts somewhere, and where it starts is its own statement about the transaction's structure.
5. An Unlabelled Read
Six byte times, one of them a response
8 cyclesWhat is certain. One frame, six byte times, the MOSI values as shown, and the device driving for exactly the final byte time. Forty active edges elapsed before MISO went live.
What is near-certain. This is a read: MISO is silent while the master transmits and active afterwards (Chapter 6.2 §1). The 0x00 bytes on MOSI during the response are filler, not data — a master with nothing left to say (Chapter 5.2 §3).
What is measurable. The pre-data latency is 40 cycles. If byte 1 is an opcode and bytes 2–4 are an address — the most plausible reading — the dummy phase is 40 − 8 − 24 = 8 cycles.
What remains ambiguous. The same ambiguity as always: a 2-byte address with a 16-cycle dummy phase fits the identical capture, as does a 4-byte address with no dummy phase at all. The total is certain; the split is not.
And the practical point. For a master, the total is what matters. A driver configured with skip_bits = 40 works regardless of how those 40 cycles divide internally — which is why Chapter 6.4's module takes one number rather than four.
6. Checking Versus Discovery
Chapter 5.4 §7 stated firmly that a monitor must be told the configuration and must never infer it, because a monitor that adapts to the DUT can never detect a disagreement with it. This chapter has just spent four sections inferring configuration from a capture. Those are not in conflict, and the distinction is worth making explicit because it is a genuine design principle.
A checker must be told. Its job is to compare observed behaviour against a specification. If it derives the specification from the observation, it is comparing something against itself and will agree with any behaviour whatsoever. This is Chapter 3.8 §6's point and Chapter 6.4 §7's independent-predictor discipline.
A discovery tool must infer. Its job is to characterise an unknown device — during bring-up, when reverse-engineering an undocumented part, or when a datasheet is wrong. Inference is the entire point, and being told the answer would defeat it.
The error is not doing either; it is building one and using it as the other. A characterisation tool promoted into a regression suite becomes a checker that agrees with everything. Keeping them separate — and naming them differently — is the practical safeguard.
// NOT a monitor and NOT a scoreboard. This measures an unknown device's
// pre-data latency by watching when it takes MISO. It INFERS, which is
// exactly what a checker must never do -- hence the name and this comment.
//
// Use during bring-up to find the number, then CONFIGURE the checker with
// it. Never wire this into a pass/fail path.
class spi_latency_probe extends uvm_component;
`uvm_component_utils(spi_latency_probe)
virtual spi_if vif;
int unsigned last_measured_cycles;
task run_phase(uvm_phase phase);
forever begin
int unsigned edges;
@(negedge vif.cs_n); // step 1: frame origin
edges = 0;
fork : measure
forever begin
@(active_edge()); // step 2: count edges
edges++;
end
begin
// step 3: wait for the device to take the line.
// `miso_driven` is a physical-layer observation --
// a pull-up plus a threshold, or a scope channel --
// NOT something recoverable from a 0/1 abstraction.
@(posedge vif.miso_driven);
end
@(posedge vif.cs_n); // frame ended with no response
join_any
disable measure;
if (vif.miso_driven) begin
last_measured_cycles = edges;
`uvm_info("PROBE", $sformatf(
"pre-data latency measured: %0d cycles", edges), UVM_LOW)
end else begin
`uvm_info("PROBE",
"frame closed with no response -- a write, or an ignored command",
UVM_LOW)
end
end
endtask
endclassThe miso_driven signal in that code is doing real work and is worth flagging. In simulation a tri-state is z and the distinction is free. On hardware it is not — §2's caution — and a probe that assumes it can tell driven-low from floating will silently measure the wrong thing on a board with no pull-up. The honest version of this tool requires either a pull-up or an analogue observation, and saying so is part of the tool.
7. Why This Chapter Has No RTL
Deliberate, and for the same reason as Chapter 5.4 §6.
This chapter teaches a procedure performed on a capture. No device has this problem: a slave knows its own latency by construction and a master is configured with it. Hardware that "discovers an unknown device's dummy count" would be solving a problem no shipping design has.
What is buildable is the verification-side form, and §6 builds it — with the deliberate caveat that it is a discovery tool rather than a checker, which is itself the chapter's most transferable idea.
The RTL this chapter depends on already exists: Chapter 6.1's output enable is what creates the observable transition, and Chapter 6.4's aligner is what consumes the number the procedure recovers.
8. Coverage of the Analysis
covergroup spi_read_capture_cg @(posedge cs_rose);
// §5: where MISO goes live relative to the frame. A suite that only
// ever runs one latency has never tested the boundary detection.
cp_turnaround : coverpoint pre_data_cycles {
bins immediate = {0}; // device drives from bit 0
bins short = {[1:15]};
bins typical = {[16:47]}; // cmd + addr + dummy
bins long = {[48:$]};
}
// The case with no response at all must be distinguishable from a
// read whose response is all zeros -- §2's hardware caution, as a bin.
cp_response : coverpoint response_kind {
bins never_driven = {NONE}; // a write, or an ignored command
bins driven_zeros = {ZEROS}; // driven, but all-zero data
bins driven_data = {DATA};
}
// Whether the dummy phase landed on a byte boundary. A decoder that
// assumes byte alignment breaks on a 6- or 10-cycle dummy.
cp_align : coverpoint (pre_data_cycles % 8 == 0) {
bins byte_aligned = {1};
bins mid_byte = {0}; // the case that breaks assumptions
}
x_turn_resp : cross cp_turnaround, cp_response;
endgroupcp_response.driven_zeros is the bin worth insisting on. A device driving 0x00 and a device driving nothing at all produce identical byte lists and are distinguishable only by the tri-state observation — so a suite that never exercises a driven-zero response has never verified that the analysis tells them apart.
9. Failure Signature — The Capture Shows a Response the Driver Never Receives
Symptom. A logic analyzer clearly shows the device driving MISO with plausible data. The driver receives zeros, or the first byte only, or garbage. Both observations are stable and repeatable.
What the visible response establishes. A great deal, and quickly. The device received the command, understood it, fetched data and drove it onto the bus. So the mode, framing, command decode and address handling are all correct — the request half of the transaction worked. The fault is entirely in the master's reception.
Plausible mechanisms.
- The master's
skip_bitsis wrong, so it discards payload or collects filler (Chapter 6.4 §9). - The master's sampling point is outside the valid window, so captures return the adjacent bit (Chapter 6.3 §2).
- The master stopped clocking before the response completed — collecting one byte and closing the frame.
- The driver reads the wrong buffer, with no hardware fault at all.
The discriminating observation, and it is what this chapter exists to enable. Measure, on the capture, the cycle count from CS falling to MISO going live. Compare it against the master's configured skip_bits. If they differ, the diagnosis is complete and the direction of the correction is known — and the comparison uses only the capture and one driver constant.
If they agree, alignment is right and the fault is the sampling point or the clocking, which Chapter 6.3 §9's frequency test then separates.
Why the investigation goes wrong. Because "the analyzer shows the right data" is read as proof the link works, when it proves only that the device worked. The analyzer sits on the wire and sees what the device drove; the master's capture is a separate act with its own timing and its own accounting. A read has two independent halves, and a capture that validates one says nothing about the other.
10. Common Misconceptions
11. Reason It Through
Work this before reading the answer.
An undocumented sensor is captured. SCLK idles low. One frame contains 64 active edges. MOSI carries
0x9F 0x00 0x00 0x00 0x00 0x00 0x00 0x00. MISO is undriven for the first 16 edges and then carries0xEF 0x40 0x18 0x00 0x00 0x00across the remainder.What can you establish, and what would you do next?
Mode, immediately. SCLK idles low, so CPOL = 0. Determining CPHA needs the transition clustering (Chapter 5.4 §2), which is not given here — but it is recoverable from the same capture, and it is the first thing to read off before trusting any byte value.
Framing. 64 edges is a multiple of 8, so 8-bit framing is consistent: eight byte times.
Direction and structure. MISO is undriven for 16 edges and then driven. So the pre-data latency is 16 cycles — exactly two byte times. MOSI's first byte is 0x9F and the remaining seven are 0x00, which is filler (Chapter 5.2 §3).
Now the interesting part: where do those 16 cycles go? MOSI carries one meaningful byte, so the command is 8 cycles. That leaves 8 cycles unaccounted for, and they are either an address byte the master sent as 0x00, or a dummy phase. Both fit the capture exactly.
Which is more likely, and why? The command 0x9F is a strong clue. It is the widespread convention for a read-ID command in serial flash and flash-like devices — a command that takes no address, because "tell me what you are" has no location. That makes the 8 unaccounted cycles a dummy phase, not an address.
That inference is pattern-matching against devices previously seen, which is exactly the kind of reasoning Chapter 4.1 §11 classified as guessable but not determinable. It is legitimate and useful, and it must be labelled as a hypothesis rather than a reading.
What does the response suggest? 0xEF 0x40 0x18 followed by zeros is the shape of a three-byte identification: a manufacturer byte, then a device-type and capacity pair. The trailing zeros are the device continuing to drive after its ID is exhausted — very common, and a reminder that a response's length is set by how long the master clocks, not by the device (Chapter 5.3 §1 in reverse).
What would you do next? Two cheap, high-value actions.
Look up the first response byte. Manufacturer identification codes are published and 0xEF is a well-known one. Identifying the manufacturer usually identifies the part family, at which point the real datasheet replaces every inference here.
Re-capture with a shorter frame. Clock only 32 edges instead of 64 and see whether the response is truncated at the same values. That confirms the trailing zeros are padding rather than data, and it confirms the latency measurement is stable rather than an artifact of one capture.
The general lesson. A read capture yields the mode, the framing, the direction and the total pre-data latency as facts. The division of that latency into address and dummy, and the meaning of the response, are hypotheses — well-founded ones, drawn from convention, and worth acting on precisely as long as you remember which is which.
12. Understanding Check
13. Summary
A read capture contains one thing a write capture never does: the moment the device takes MISO. That transition is generated by the device's output enable rather than by counting, so it is the only boundary marker an SPI bus produces — and it sits exactly where the data phase opens.
Exploiting it gives a procedure that recovers a datasheet fact without the datasheet: count active edges from CS falling to MISO going live, and that is the device's total pre-data latency. Subtract the command and address bits and the remainder is the dummy count.
For a master, the total is sufficient — the receive alignment takes one number, and how those cycles divide internally does not change it.
The full procedure extends Chapter 5.4's by two steps: the tri-state transition gives the latency, and comparing it against where the master begins collecting reveals whether the two ends agree — a diagnostic with no analogue in a write capture.
Two hardware cautions bound the method. Driven-low and undriven look identical without a pull-up, and the transition is an analogue ramp with real duration.
This chapter also resolves an apparent contradiction. A checker must be told its configuration, or it compares something against itself. A discovery tool must infer, because characterising an unknown device is its purpose. Both are correct; the error is building one and deploying it as the other.
And when a capture shows the device answering correctly while the driver receives nothing useful, the capture has validated only half the transaction. Comparing the measured turnaround against the master's configured skip settles which half is wrong.
14. What Comes Next
That closes Module 6. The read path is complete: its four phases and the slave's continuous obligation, why every read is a write first, when returned data may be trusted, what the whole thing costs in cycles, and the analysis that reads any of it off a screen.
Modules 5 and 6 each followed a single transaction end to end. Module 7 asks what happens when transactions stop being single: multi-byte bursts, continuous transfer modes that keep a device streaming across many words, and the throughput arithmetic that decides whether a design is limited by its bus, its device, or its software. The efficiency ratios that appeared repeatedly in this module become the central subject there.
Browse the path on the SPI curriculum index, or revisit Read Latency Accounting for the arithmetic this chapter inverts into a measurement.
Continue learning
Related tutorials
- Related topic
Write Waveform Analysis
Reconstruct a transaction from four unlabelled signals: recover the mode from the idle level and transitions, find the frame, segment the bytes, and see where decoding stops and the datasheet takes over.
- Related topic
Mode Mismatch and Its Failure Signature
What happens when the two ends disagree about the mode. The distinct signature each mismatch produces, how to tell polarity from phase disagreement from the data alone, and the monitor and coverage work that catches it.
- Related topic
MISO Contention and Multiple Slaves Selected
What two active drivers do to a shared net: why the level is undefined rather than wrong, how much current flows, why damage ranges from a corrupted bit to a destroyed output stage, and why contention can be detected but never implemented.
- Related topic
Bit Ordering — MSB-First and LSB-First
Which end of the shift register goes out first, the two multiplexers that make the order configurable in three HDLs, and why a bit-order bug is perfectly deterministic and yet invisible on certain data.
