In an interview you are handed a marker and asked to draw an APB write with one wait state. You draw the clock, PSEL, PENABLE, the address and PREADY. The interviewer points at one clock edge and asks: "Did the write happen here, or one cycle later?" You realise you drew the signals, but you cannot say which edge the transfer completes on.
How do you read a timing diagram so that every edge has a definite meaning?
Most people read a waveform the way they read a graph: scan left to right and notice where signals go high and low. That shows that things happen, not when they count. In synchronous logic, nothing counts between edges. A value matters only at the rising edge where a register samples it, and the waveform you see between edges is just the value that will be sampled at the next one. Read a diagram as a smooth picture and you will misplace events by a cycle, which is exactly the interviewer's trap.
Read a synchronous timing diagram as a sequence of clock edges, and at each edge ask three questions:
What values are present just before this edge? These are what every register samples.
Does any rule fire at this edge? For example, "a transfer completes on an edge where PSEL, PENABLE and PREADY are all high".
What must stay unchanged across this edge? For example, address and data during a stall.
The course's waveforms are drawn one slot per clock cycle, each slot showing the values just after a rising edge, which are the values that will be sampled at the next edge. So when a rule needs signals to be high "on an edge", look for a slot in which they are all high: the transfer completes at the edge that ends that slot.
Symbol in a diagram | Meaning |
|---|---|
Rising edge of the clock | The only moment registers sample |
A high or low single-bit lane | The value during that cycle |
A bus lane with a value in a box | The value held during those cycles; a new box only when it changes |
Hatched or grey region (in many specs) | Don't care: any value is allowed and must be ignored |
Arrow from one signal's change to another's (in many specs) | Causality: the second change happens because of the first |
The testbench below drives a real APB transfer: a write of a5 to register address 4 with one wait state, then a read of the same register with none. A checker confirms that the address and data stay constant through the access phase and that the read returns a5. The waveform after it is the simulation output.
// An APB write with one wait state, then a read of the same register with none.
// Setup phase: PSEL = 1, PENABLE = 0 for exactly one cycle. Access phase: PENABLE = 1
// until the completer drives PREADY = 1; the transfer completes on that edge. The
// checker confirms the address and data stay constant through the access phase and
// that the read returns the value written.
module tb;
reg clk = 0;
always #5 clk = ~clk;
reg rst_n = 0;
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, tb);
#12 rst_n = 1;
end
// Requester (drives the bus from a fixed script, one step per cycle)
reg psel = 0, penable = 0, pwrite = 0;
reg [7:0] paddr = 0, pwdata = 0;
reg [3:0] step = 0;
wire pready; // driven by the completer below
wire done = psel && penable && pready; // a transfer completes on this edge
always @(posedge clk) if (rst_n) begin
case (step)
0: begin psel <= 1; penable <= 0; pwrite <= 1; paddr <= 8'h04; pwdata <= 8'hA5; step <= 1; end // setup (write)
1: begin penable <= 1; step <= 2; end // access
2: if (done) begin psel <= 1; penable <= 0; pwrite <= 0; pwdata <= 0; step <= 3; end // next setup (read)
3: begin penable <= 1; step <= 4; end // access
4: if (done) begin psel <= 0; penable <= 0; step <= 5; end // back to idle
default: ;
endcase
end
// Completer: four 8-bit registers. Writes take one wait state; reads take none.
reg [7:0] regs [0:3];
reg waited = 0;
assign pready = !pwrite || waited;
wire [7:0] prdata = (psel && !pwrite) ? regs[paddr[3:2]] : 8'h00;
always @(posedge clk) begin
waited <= psel && penable && pwrite && !waited; // first access cycle of a write: wait
if (done && pwrite) regs[paddr[3:2]] <= pwdata;
end
// Checker
integer errors = 0;
reg [7:0] held_addr, held_data;
always @(posedge clk) if (rst_n) begin
if (psel && !penable) begin held_addr <= paddr; held_data <= pwdata; end
if (psel && penable && (paddr != held_addr || (pwrite && pwdata != held_data))) begin
$display("ERROR: address or write data changed during the access phase");
errors = errors + 1;
end
if (done && !pwrite && prdata != 8'hA5) begin
$display("ERROR: read returned %h, expected a5", prdata);
errors = errors + 1;
end
end
initial begin
#110;
if (errors == 0 && step == 5) $display("PASS: write with one wait state, then read back a5 with none");
else $display("FAIL: %0d errors, step %0d", errors, step);
$finish;
end
endmoduleWalk through it slot by slot and apply the three questions:
Slot 0: idle. psel is low, so nothing on the bus means anything. pready happens to be 1 here, but PREADY only matters in an access phase.
Slot 1: setup phase of the write. psel = 1, penable = 0, pwrite = 1, paddr = 4, pwdata = a5. At the edge that ends this slot, nothing completes; the setup phase always lasts exactly one cycle.
Slot 2: first access cycle. penable = 1, but the completer drives pready = 0: a wait state. The rule "PSEL, PENABLE and PREADY all high" does not fire at the edge ending this slot, so the write has not happened. Address and data must stay exactly as they were, and they do.
Slot 3: second access cycle. Now pready = 1, and all three are high. The write completes at the edge that ends slot 3. That is the answer to the interviewer's question.
Slot 4: setup phase of the read. pwrite = 0, penable = 0. The completer already shows a5 on prdata, but nothing completes yet.
Slot 5: access phase of the read. All three are high in the same slot, so the read completes at the edge ending slot 5, and the requester samples prdata = a5 there.
Slot 6 onwards: idle.
When you draw a timing diagram yourself, especially in an interview, follow this order. It keeps you from drawing a picture that cannot happen:
Draw the clock first, with numbered cycles. Every later mark aligns to it.
Draw the signals that start the transfer (here PSEL, PWRITE, address, data), changing just after an edge.
Draw the signal that ends each phase (PENABLE for setup, PREADY for access).
Mark the completion edge with an arrow and say the rule out loud.
Shade what must stay stable while waiting, and mark don't-care regions.
Drawing signals changing just after a rising edge, never exactly on it, makes it obvious which value each edge samples.
A timing diagram is good at | A timing diagram cannot |
|---|---|
Showing one concrete transfer, cycle by cycle | Show every case: a diagram is an example, not a rule |
Building intuition for phases and stalls | Say what happens in cases it does not draw (errors, reset, long stalls) |
Settling "which edge" questions for the case drawn | Prove a rule holds in general; that needs a checker or a proof |
That is why the listing above includes a checker. The waveform shows one run; the checker enforces the rule (address and data stable through the access phase) on every cycle of every run it is given.
Protocol | Its completion rule, read from a diagram |
|---|---|
APB | A transfer completes on a rising edge with PSEL, PENABLE and PREADY all high, after exactly one setup cycle. |
AXI | A transfer on any channel happens on an edge where its VALID and READY are both high. |
I2C | Not edge-based on a system clock: data bits are sampled while SCL is high, and SDA changing while SCL is high marks START or STOP instead. |
The first two are synchronous: find the edge. I2C shows the other family, where the protocol's own clock line (SCL) defines when data counts, which is the subject of Part 1.
A verification engineer writes a monitor that samples PRDATA in the first cycle that PENABLE is high (illustrative). It works against a completer with no wait states. Against a slower completer it captures PRDATA in the wait-state cycle, before the data is valid, and reports read mismatches that look like data corruption. The design is fine; the monitor applied a picture ("data comes with PENABLE") instead of the rule ("data is sampled at the edge where PSEL, PENABLE and PREADY are all high"). The fix is one extra condition, and the lasting lesson is to write monitors from rules, not from example waveforms.
PREADY is low in slot 2. The completion rule needs PSEL, PENABLE and PREADY all high in the same slot; that first happens in slot 3.
No. Slot 4 is the setup phase (PENABLE low). The read completes at the edge ending slot 5, the first slot with PSEL, PENABLE and PREADY all high; only then does the requester sample PRDATA.
Because a register samples the value present just before the edge. Drawing changes slightly after the edge makes it unambiguous which value each edge captures.
Read synchronous timing diagrams edge by edge: only values present just before a rising edge count.
A transfer completes at the edge ending the first slot where every condition of the completion rule is true.
A diagram is an example, not a rule; write monitors and checks from the rules.