Wishbone · Module 22
Throughput
Bytes per clock is a count and is published; bytes per second needs a clock period and a clock period needs synthesis — which is also where B3 says Wishbone's real timing limit lives.
This module is called Performance Analysis, and the first thing it owes you is the line it will not cross.
Bytes per clock is computable and is published. Bytes per second is not, because it needs a clock period, and a clock period needs synthesis.
1. What Is Published And What Is Refused
No synthesis tool was run on any RTL in this module. No place-and-route, no timing analysis, no library, no netlist. So:
| published — a pure count | refused — needs silicon |
|---|---|
| transfers per clock | MB/s, GB/s, any absolute bandwidth |
| bytes per clock = transfers/clock × bytes/transfer | fmax, "runs at N MHz" |
| clocks per transfer | gate count, LUT count, area |
| efficiency = useful clocks ÷ total clocks | power |
| latency in clocks, decomposed by cause | "Wishbone is faster than X", unqualified |
| arbitration overhead in clocks | any number carrying a time unit |
If you want bytes per second, multiply a number from the left column by a clock frequency you have established for your own design. That multiplication is yours to make. Establishing the frequency is the step this module cannot take — and §2 is about why that step is harder than it looks.
2. Where Wishbone's Frequency Limit Actually Comes From
B3 answers the question this module cannot measure, in a chapter no module in this curriculum has cited before — 04_registered.rst, 824 lines, 22 numbered identifiers, none of them used until now.
"To achieve the highest possible throughput, WISHBONE Classic requires asynchronous cycle termination signals. This results in an asynchronous loop from the MASTER, through the INTERCONN to the SLAVE, and then from the SLAVE through the INTERCONN back to the MASTER... In large System-on-Chip devices this routing delay between MASTER and SLAVE is the dominant timing factor. This is especially true for deep sub-micron technologies." — B3, §4.1
3. The Formula, Derived Before Anything Was Simulated
This module's method is: derive, predict, measure, and hunt for where the prediction breaks.
The derivation for a single-transfer master against a wait-stated slave, with a rule cited for each term:
| term | value | why |
|---|---|---|
| clocks a request is presented | 1 + W | [STB_O] is asserted until a termination arrives; the slave withholds [ACK_O] for W clocks first |
| terminations per transfer | exactly 1 | RULE 3.45 — "the SLAVE MUST NOT assert more than one of the following signals at any time: [ACK_O], [ERR_O] or [RTY_O]" |
| transfers in flight | 1 | RULE 3.35 — the termination is "generated in response to the logical AND of [CYC_I] and [STB_I]", and RULE 3.60 qualifies the whole request context with [STB_O] |
clocks(N, W) = N × (1 + W)
That formula is written into the testbench as a localparam, as a literal, before the simulation runs. Nothing computes it from a measurement — Chapter 22.5 §6 shows what happens to a checker that does.
// run_clocks(N, W) = N * (1 + W) for N transfers, back to back
//
// The workload is 16 records. These are LITERALS. Nothing below reads
// a measured value to form them, which is what makes the comparison in
// SIM B a test rather than a restatement.
localparam int unsigned NXFER = 16;
localparam int unsigned PRED_W0 = NXFER * (1 + 0); // 16
localparam int unsigned PRED_W1 = NXFER * (1 + 1); // 32
localparam int unsigned PRED_W2 = NXFER * (1 + 2); // 48
localparam int unsigned PRED_W4 = NXFER * (1 + 4); // 80
localparam int unsigned PRED_W8 = NXFER * (1 + 8); // 144
// waits scheme dbl wu al
`SEQRIG(z, 0, 0, 1'b0, 1'b0, 1'b0)
`SEQRIG(o, 1, 0, 1'b0, 1'b0, 1'b0)
`SEQRIG(t, 2, 0, 1'b0, 1'b0, 1'b0)
`SEQRIG(f, 4, 0, 1'b0, 1'b0, 1'b0)
`SEQRIG(e, 8, 0, 1'b0, 1'b0, 1'b0)4. One Transfer, Every Clock Named
=== SIM A - one transfer, every clock attributed ===
zero wait states, asynchronous termination. Four named
components, and every clock lands in exactly one.
clk want CYC STB ACK component
2 1 0 0 0 ISSUE - master forming request
3 1 1 1 1 ANSWER - the transfer completes
4 1 0 0 0 ISSUE - master forming request
5 1 1 1 1 ANSWER - the transfer completes
6 1 0 0 0 ISSUE - master forming request
7 1 1 1 1 ANSWER - the transfer completes
over the whole 16-record run at zero wait states
ISSUE clocks the master spent forming requests 1
PRESENT clocks a request stood unanswered 0
ANSWER clocks a transfer completed 16
RECOVER clocks after a transfer before the next 15
------------------------------------------------------
sum of components 32
total clocks the master had work 32
-> EVERY CLOCK COUNTED EXACTLY ONCE. RULE 3.45 makes
ANSWER exactly one clock per transfer: "the SLAVE
MUST NOT assert more than one of the following
signals at any time: [ACK_O], [ERR_O] or [RTY_O]".Four components, and every clock lands in exactly one. The instrument that produces them is built so the sum is checkable:
//
// ISSUE clocks from the master having work to [STB_O] rising.
// Owned by the MASTER. A master that registers its request
// spends one here; a combinational one spends none.
//
// PRESENT clocks with [STB_O] asserted and no termination.
// Owned by the SLAVE. These are wait states, and B3 calls
// them exactly that.
//
// ANSWER the clock on which the termination is asserted.
// Always exactly one, by RULE 3.45 - "the SLAVE MUST NOT
// assert more than one of the following signals at any
// time: [ACK_O], [ERR_O] or [RTY_O]."
//
// RECOVER clocks after termination before the next [STB_O] can
// rise. Owned by the MASTER. Zero for a back-to-back
// master; one or more for a master that returns to idle.
//
// ── EVERY CLOCK IS COUNTED EXACTLY ONCE ─────────────────────────────────
// The four are mutually exclusive by construction: the state register
// below is in exactly one of them on every clock, and total_o is
// incremented from the same place. SIM J checks
// issue + present + answer + recover == total
// and the negative control DOUBLE_COUNT breaks it deliberately, because
// an attribution that cannot fail has not been shown to attribute.
//5. The Clock No Rule Requires
THE STATE-MACHINE CLOCK AUDIT - read this before any
number in this module is quoted.
RECOVER is 15 clocks over 16 transfers. That is one
clock per transfer, after the first, during which the
master has work and is not asserting [STB_O].
NO RULE IN B3 REQUIRES IT. It is wb_master_seq
registering its next request - the same reused master
Chapters 20 and 21 measured with. A master that drove
[STB_O] combinationally from its request queue would
spend zero here and be harder to time-close.
SO TWO DIFFERENT TRUE NUMBERS EXIST FOR THIS RUN:
clocks with [STB_O] asserted 16
clocks from start to finish 32
The formula in SIM B predicts the FIRST. It is a
property of the protocol. The second is a property of
this master, and Module 21 found the same class of
clock making APB look 50% worse than it was.
Every clocks-per-transfer figure in Module 22 is
[STB_O] clocks and says so.6. Prediction Against Measurement
=== SIM B - prediction against measurement ===
The prediction is a localparam in this testbench,
derived by hand from B3 Table 4-1 before the simulation
was run:
"Asynchronous cycle termination requires only one
cycle per transfer" (B3, 04_registered.rst, T4-1)
clocks_of_stb(W) = 1 + W
run_clocks(N, W) = N * (1 + W)
tolerance 0 clocks - Table 4-1 gives exact integers.
case predicted measured res verdict
N=16 W=0 asynchronous 16 16 0 MATCH7. Bytes Per Clock
=== SIM C - bytes per clock, and what SEL_O does to it ===
The workload is 16 records: 9 reads and 7 writes, three
of the writes sub-word. Payload counts ONLY the byte
lanes asserted in SEL_O, because a byte write moves one
byte and not four.
transfers completed 16
byte lanes actually moved 54
clocks the master had work 32
bytes per transfer 3.38
BYTES PER CLOCK 1.69
A 32-bit port moving only full words would read 4.00
bytes per transfer. This workload reads 3.38 because
three of its writes assert fewer than four lanes.
THAT NUMBER CARRIES NO TIME UNIT AND THAT IS
DELIBERATE. Multiply it by a clock frequency you have
established for your own design and you have bytes
per second. This module does not establish one.Payload counts only the byte lanes actually asserted in [SEL_O()], because a byte write moves one byte and not four. B3 makes those lanes the definition of what is being transferred — [SEL_O()]'s own description says "The array boundaries are determined by the granularity of a port."
// ── BYTES, NOT TRANSFERS ────────────────────────────────────────────────
// payload_o counts only the byte lanes actually asserted in [SEL_O()],
// because a byte write moves one byte and not four. B3's SEL_O
// description makes those lanes the definition of what is being
// transferred: "The array boundaries are determined by the granularity
// of a port."
//
// bytes-per-clock is then payload_o / total_o, computed in the testbench
// where it can be printed as a ratio. THAT NUMBER IS THE MODULE'S
// HEADLINE and it carries no time unit, which is the whole point -
// multiply it by a clock frequency you have established yourself and youThe alternative — counting the full bus width on every transfer — would flatter every wide bus and is one of this module's seeded instrument defects. Chapter 22.5 §6 runs it.
8. The Formula At Five Latencies
=== SIM D - the formula at five wait-state settings ===
case predicted measured res verdict
N=16 W=0 16 16 0 MATCH
N=16 W=1 32 32 0 MATCH
N=16 W=2 48 48 0 MATCH
N=16 W=4 80 80 0 MATCH
N=16 W=8 144 144 0 MATCH
checks run 6 failures 0
THE FORMULA HELD AT EVERY SETTING, exactly, with zero
tolerance. That is worth stating plainly: a
single-transfer Wishbone master against a
wait-stated slave has no behaviour the arithmetic
does not already describe.
Chapters 22.4 and 22.5 are where it stops holding.Zero residual at every setting, with zero tolerance. That is worth stating plainly rather than celebrating: a single-transfer Wishbone master against a wait-stated slave has no behaviour the arithmetic does not already describe.
A formula that always matches has not been tested, which is why this module keeps going. Chapter 22.4 adds a second master and Chapter 22.5 changes the termination scheme, and both are places the formula stops holding.
9. Where This Module Goes
| chapter | the question |
|---|---|
| 22.2 Latency | the four components, drawn and traced |
| 22.3 Wait-State Impact | what a wait state costs, and what efficiency even means |
| 22.4 Arbitration Cost | handover clocks, isolated from slave clocks |
| 22.5 Design Optimization | registered feedback, B3's own throughput table, measured |
Continue learning
Related tutorials
- Related topic
Throughput Improvements
The saving from retaining CYC is a constant; slave latency is a multiplier. Measured: 1.6x decaying to 1.18x with nothing in either design changing.
- Related topic
Throughput
APB's extra clock costs 2x with fast slaves and 1.2x with slow ones. The ratio narrows, the absolute gap never moves, and the shape of that result is what a single benchmark number would have destroyed.
- Related topic
Performance Considerations
A block cycle saves exactly N-1 clocks over N single cycles, independent of slave latency — and that saving vanishes if the master throttles. Measured, including the latency it costs every other master.
- Related topic
SEL Signals
The address names a word; SEL names which bytes of it take part. The lane binding is normative, the byte numbering is not, and confusing the two is the expensive mistake.
Standards & specifications
- Governing standard
- Wishbone SoC Interconnection Architecture (OpenCores)(opens OpenCores in a new tab)
Defines the Wishbone signal set, the bus cycles built from it and the interface rules a portable IP core must follow. It deliberately leaves interconnect topology, address map and arbitration policy to the integrator, so those are system decisions rather than requirements of the specification.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the Wishbone curriculum.
