Skip to content
VLSI Mentor

Wishbone · Module 6

Address Phase

Classic has one handshake, not an address channel. The address names a device and a register inside it, exists in three representations, and must stay coherent for the whole transfer.

Chapter 6.1 traced the read path and named the address as its first payload. That payload does two jobs at once, and the word "phase" invites an assumption from other protocols that is wrong here.

When does ADR_O identify the read target, and how long must that information stay coherent?

1. One Address, Two Jobs

A single value on ADR_O answers two different questions, resolved by two different pieces of logic.

Which device? The upper address bits select one slave. That decision belongs to the interconnect, and Chapter 3.5 built the general form.

Which register inside it? The lower bits become a local offset the slave indexes with. The slave knows nothing about where it sits in the system map.

A block diagram showing how a global word address is split. On the left the master drives a thirty-bit global word address. It feeds a decoder in the middle, which splits it two ways: the upper bits go to a comparator against the system address map and produce a one-hot slave select, while the lower bits pass through unchanged as a local offset. On the right, the selected slave receives both the strobe gated by its select line and the local offset, and uses the offset alone to index its register bank. The slave never sees the upper bits and has no knowledge of where it sits in the system map.MASTERADR_O — 30-bit word addressupper bitscompare vs the maplower bitspass through unchangedSLAVE SELECTone-hot; gates STBLOCAL OFFSETindexes the registers12
Figure 1 — one global word address, split into a device selection and a local offset.

The split is a system decision, not a protocol one. Wishbone defines neither the address map nor the decoding strategy — the specification's scope note leaves interconnect topology and address map to the integrator. Module 12 owns address decoding as a full subject; this chapter needs only enough to follow a read.

Why the slave is deliberately ignorant. A peripheral that knew its own base address could not be instantiated twice, or relocated, without editing its RTL. Giving it only a local offset is what makes it portable IP — which is the entire purpose of the Wishbone specification.

2. The Three Address Representations

A single read involves the same location expressed three ways, and confusing any two is a distinct bug.

RepresentationExample (ID)Lives inWidth
Byte offset0x10datasheets, drivers, softwarebyte-granular
Global word address0x0000_0004ADR_O on the busAW = 30
Local word offset0x4inside the slaveOFF_AW = 3

Byte → global is a right shift by two on a 32-bit port, plus the peripheral's base. Chapter 4.3 established why: the address array is ADR_O(n..2) and the two byte-offset bits are not on the bus at all.

Global → local is the decode of Figure 1.

All three are "the address of ID", and a debugging session that does not say which representation it is looking at will chase the wrong stage. Chapter 6.6 makes naming the representation an explicit step.

3. How Long the Address Must Stay Coherent

RULE 3.60"MASTER interfaces MUST qualify the following signals with [STB_O]: [ADR_O], [DAT_O()], [SEL_O()], [WE_O], and [TAGN_O]."

Qualified by STB_O means meaningful for as long as the strobe is asserted. Across a multi-cycle read that is an obligation to hold the value still, and Chapter 5.5 measured a master violating it for three of four cycles while reporting success.

Three consequences specific to reads.

A moving address redirects an outstanding read. The slave is still working; its ADR_I changes underneath it. Whether it serves the old or the new register depends on whether its decode is registered or combinational — and both slaves are conformant, because RULE 3.60 forbids the master from creating the situation at all.

No slave can defend against it. PERMISSION 3.10's slave is purely combinational with no storage. It cannot latch an address it was never told was new.

The interconnect cannot defend against it either. A decode that follows a changing address changes the slave select mid-transfer, so the strobe can move from one slave to another while a response is in flight — and Chapter 6.3 shows what that does to the return path.

4. RTL — The Decode

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// wb_read_decode — the interconnect's address stage for the running system.
//
// PURPOSE. Split one global word address into a one-hot slave select and a
// local offset, and gate each slave's STB with its own select line.
//
// This is stage 3 of Chapter 6.1's Figure 1. It is deliberately small:
// Module 12 owns address decoding properly, and everything here exists only
// to make a read reach the right register.
//
// MAP (word addresses; byte addresses are 4x these):
//   slave 0  REGS   base 0x0000_0000  8 words   (the running peripheral)
//   slave 1  SCRATCH base 0x0000_0008 8 words   (a second target, so that
//                                                "wrong slave" is possible)
//   anything else -> no select, and the default responder errors.
//
// Reset: none required — this block is purely combinational.
// ─────────────────────────────────────────────────────────────────────────
module wb_read_decode #(
  parameter int unsigned AW     = 30,      // global word address width
  parameter int unsigned OFF_AW = 3,       // local word offset width
  parameter int unsigned NSLV   = 2
) (
  // from the master
  input  logic [AW-1:0]     adr_i,
  input  logic              cyc_i,
  input  logic              stb_i,
  // to the slaves
  output logic [NSLV-1:0]   sel_slave_o,   // ONE-HOT, or all-zero
  output logic [NSLV-1:0]   stb_slave_o,   // per-slave strobe
  output logic [OFF_AW-1:0] off_o,         // local offset (shared)
  output logic              unmapped_o     // no slave claims this address
);
  // Each region is 2**OFF_AW words, so the region index is simply the
  // address with the offset bits removed. Keeping the regions uniform and
  // power-of-two sized makes the decode a comparison rather than a range
  // check — an EDUCATIONAL SIMPLIFICATION, not a Wishbone requirement.
  localparam int unsigned REGION_AW = AW - OFF_AW;

  logic [REGION_AW-1:0] region;
  assign region = adr_i[AW-1:OFF_AW];

  // ── LOCAL OFFSET ──────────────────────────────────────────────────────
  // The low bits pass through untouched. Every slave sees the same offset
  // value; only the gated strobe decides which one acts on it.
  assign off_o = adr_i[OFF_AW-1:0];

  // ── SLAVE SELECT ──────────────────────────────────────────────────────
  // One-hot by construction: `region` takes exactly one value, so at most
  // one comparison can be true. A decoder built from overlapping range
  // checks can produce two selects at once, and Section 7 gives the
  // evidence that identifies that failure.
  always_comb begin
    sel_slave_o = '0;
    unique case (region)
      REGION_AW'(0): sel_slave_o[0] = 1'b1;   // REGS    words 0..7
      REGION_AW'(1): sel_slave_o[1] = 1'b1;   // SCRATCH words 8..15
      default:       sel_slave_o    = '0;     // unmapped
    endcase
  end

  assign unmapped_o = (sel_slave_o == '0);

  // ── PER-SLAVE STROBE ──────────────────────────────────────────────────
  // RULE 3.30 forbids a slave from responding while CYC_I is negated, and
  // RULE 3.35 requires terminations to come from the AND of CYC_I and
  // STB_I. Gating the strobe with the select is what makes exactly one
  // slave see a qualified transfer.
  //
  // NOTE that CYC is BROADCAST to every slave (Chapter 3.5) while STB is
  // DECODED. That asymmetry is deliberate: CYC says a cycle is in
  // progress, STB says THIS transfer is for you.
  for (genvar i = 0; i < NSLV; i++) begin : g_stb
    assign stb_slave_o[i] = stb_i & cyc_i & sel_slave_o[i];
  end
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// wb_addr_walk_master — THE ADDRESS-STABILITY BUG, isolated.
//
// NOT A REFERENCE DESIGN. Identical to Chapter 6.1's wb_read_master except
// that adr_o is driven from a counter that advances every cycle the read is
// outstanding, instead of from a value latched once at acceptance.
//
// Against a zero-wait-state slave it is indistinguishable from a correct
// master: the transfer completes in the cycle it is presented, so the
// counter never gets a chance to move. Introduce ONE wait state and it
// reads a different register from the one that was requested.
// ─────────────────────────────────────────────────────────────────────────
module wb_addr_walk_master #(
  parameter int unsigned AW = 30,
  parameter int unsigned DW = 32
) (
  input  logic            clk_i,
  input  logic            rst_i,
  input  logic            req_i,
  input  logic [AW-1:0]   req_adr_i,
  input  logic [DW/8-1:0] req_sel_i,
  output logic            acc_o,
  output logic            busy_o,
  output logic            done_o,
  output logic [DW-1:0]   rdat_o,

  output logic            cyc_o,
  output logic            stb_o,
  output logic            we_o,
  output logic [AW-1:0]   adr_o,
  output logic [DW-1:0]   dat_o,
  output logic [DW/8-1:0] sel_o,
  input  logic [DW-1:0]   dat_i,
  input  logic            ack_i,
  input  logic            err_i,
  input  logic            rty_i
);
  logic          active_q;
  logic [AW-1:0] adr_q;
  logic [DW/8-1:0] sel_q;

  assign acc_o  = req_i & ~active_q;
  assign busy_o = active_q;
  assign cyc_o  = active_q;
  assign stb_o  = active_q;
  assign we_o   = 1'b0;
  assign dat_o  = '0;
  assign sel_o  = sel_q;

  // ── THE BUG ───────────────────────────────────────────────────────────
  // adr_o comes from a register that is INCREMENTED while waiting. RULE
  // 3.60 requires ADR_O to be qualified by STB_O — meaningful for the
  // strobe's whole duration — and this violates it from the second cycle
  // of any waited read onward.
  assign adr_o = adr_q;

  always_ff @(posedge clk_i) begin
    if (rst_i) begin
      active_q <= 1'b0;
      adr_q    <= '0;
      sel_q    <= '0;
      done_o   <= 1'b0;
      rdat_o   <= '0;
    end else begin
      done_o <= 1'b0;
      if (acc_o) begin
        active_q <= 1'b1;
        adr_q    <= req_adr_i;
        sel_q    <= req_sel_i;
      end else if (active_q) begin
        if (ack_i || err_i || rty_i) begin
          active_q <= 1'b0;
          done_o   <= 1'b1;
          if (ack_i) rdat_o <= dat_i;
        end else begin
          adr_q <= adr_q + AW'(1);      // <-- walks while waiting
        end
      end
    end
  end
endmodule

Reading the pair

Purpose. The decoder turns a global address into a selection and an offset; the walking master shows what happens when the address it decodes will not hold still.

Interface. The decoder is purely combinational, taking the master's address and qualifiers and producing per-slave strobes. The walking master presents Chapter 6.1's client contract exactly.

State. Decoder: none. Walking master: the outstanding flag and an address register that is rewritten while waiting — the single line that constitutes the bug.

Combinational logic. Decoder: region extraction, the one-hot select, the offset pass-through, and the per-slave strobe gating.

Sequential logic. Decoder: none, so no reset is required and none is present. That is worth noting explicitly, because a reviewer checking RULE 3.20 compliance should confirm a block has no state rather than look for a missing reset.

Read start. The decode is continuous — it produces a select whenever an address is present. What makes the selection meaningful is the gating with cyc_i & stb_i, so an idle bus selects nobody in any way that matters.

Address. off_o is driven to every slave unconditionally; only stb_slave_o differs between them. That is cheaper than routing per-slave address buses and is the standard shape.

Waiting. The decoder has no notion of waiting — it is a function of its inputs. If those inputs move, its outputs move, which is precisely why the master's stability obligation matters upstream of it.

Reset. Decoder: none needed. Walking master: synchronous active-high; active_q <= 0 negates both qualifiers per RULE 3.20.

Failure modes. Section 7.

Simplifications. Uniform power-of-two regions, two slaves, no default responder inside the decoder — unmapped_o is exported so a testbench or a wrapper can supply one. Chapter 3.5 discussed why a default responder matters; Module 12 owns real decoding.

5. Waveform — The Address That Walked

Address instability redirects an outstanding read

7 cycles
Seven clock cycles comparing a correct master and a walking master on a read of word address four from a slave that inserts one wait state. In cycle two both masters assert the cycle and strobe signals with write enable low and present word address four. The slave does not acknowledge in that cycle because it is inserting a wait state. In cycle three the correct master still presents word address four, but the walking master has incremented its address register and now presents word address five while its strobe is still asserted and the transfer is still outstanding. In cycle three the slave acknowledges. The correct master therefore receives the identification value belonging to word four, while the walking master receives the value at word five, which is a different register entirely.both present word 4both present word 4bad master now at word 5; ACKbad master now at word 5;ACKCLK_ICYC_OSTB_OWE_OADR_O (ok)----0x40x4----------------ADR_O (bad)----0x40x5----------------ACK_IDAT_I (ok)0x00x0574206010x00x00x00x0DAT_I (bad)0x00x00x00x00x00x00x0t0t1t2t3t4t5t6
Figure 2 — a one-wait read from a master whose address advances while waiting. Word 4 was requested; word 5 was served.

Cycle 2 is the violation. STB_O is asserted, the read is outstanding, and ADR_O changes. RULE 3.60 qualifies the address with the strobe precisely so a slave can rely on it for the strobe's whole duration.

The two masters diverge in what they receive. The correct one is served word 4 — ID, 0x57420601. The walking one is served word 5, which the running peripheral does not implement, so it gets zero and an error. In a peripheral with a denser map it would have received a plausible wrong register instead, which is far harder to notice.

Against a zero-wait slave both traces are identical. The transfer would complete in cycle 1 and the counter would never advance. That is what makes this bug latency-dependent and what makes a wait-state configuration mandatory in a master's unit testbench.

6. Simulation — Address Stability, Measured

Both masters read word 4 (ID) from the running peripheral behind a slave inserting two wait states, with the client advancing its own request input to a different address immediately after acceptance.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  === SIMULATION B - address stability (WAITS=2) ===
                                     correct      walking
    cycles the read was presented       3            3
    distinct ADR_O values on the bus    1            3
    ADR_O at the termination edge      0x4          0x6
    cycles ADR_O != requested (0x4)     0            2
    value captured                 0x57420601   0x00000000
    status                             OK           ERR

The correct master presented exactly one address value across all three cycles of the presented transfer, and received ID.

The walking master presented three, ending on word 6 — two words past the request. It received an error, because word 6 is unmapped in the running peripheral.

Note that the client changing its own inputs affected neither master. Both latch at acceptance; the walking master's bug is that it rewrites its latched copy afterwards. That distinction matters for diagnosis: an unlatched master (Chapter 5.5) follows the client, while this one diverges from both the client and the request. The distinct ADR_O values row separates them.

7. Failure Modes and Discriminating Evidence

Symptom: the read returns a different register's value than requested.

Candidate causes. Four stages can produce this, and they are separable in order.

Discriminating evidence. Check each representation in turn:

CheckIf wrong, the fault is
ADR_O vs the intended word addressthe master, or a byte/word conversion in software
ADR_O is 4× too largebyte offset used as a word address — conclusive
decoded sel_slavethe decoder's region comparison
off_o at the slavethe offset slice — an off-by-one or a width error
the slave's read-mux casethe slave (Chapter 6.3)

The 4× signature is the one to look for first, because it is unambiguous and by far the commonest. A decoder bug shows the correct address on the bus with the wrong slave selected; a byte/word bug shows a visibly wrong address.

Property. P1 in Section 8.

Symptom: the read works at zero wait states and returns the wrong register when latency is added.

Candidate causes. The master's address does not hold still — either rewritten while waiting, or driven from an unlatched client input.

Discriminating evidence. Watch ADR_O across the whole strobe assertion. Any change before termination is a RULE 3.60 violation. Then separate the two causes: if the bus address tracks the client's input it is an unlatched master (Chapter 5.5); if it diverges from both the client and the original request it is being rewritten internally.

Likely RTL location. The adr_o assignment, or the register feeding it.

Property. P1.

Symptom: two slaves respond to the same read.

Candidate causes. A decoder producing more than one select — typically built from overlapping range comparisons rather than a unique case on a region index.

Discriminating evidence. Probe every slave's STB_I in the same cycle. More than one asserted is conclusive, and the resulting merged read data and doubled acknowledge will otherwise look like a baffling slave bug.

Likely RTL location. The select generation.

Property. P2.

Symptom: an address in no slave's range hangs the bus.

Candidate causes. No slave selected and no default responder, so nothing terminates.

Discriminating evidence. unmapped_o asserted with the strobe held and no termination anywhere. Chapter 5.1 §5's probe sequence reaches this at P2 — the strobe arrives at no slave.

Likely RTL location. The interconnect, not any slave. RECOMMENDATION 3.10 suggests a watchdog in the INTERCON precisely because this failure is otherwise silent.

Symptom: the correct slave is selected but indexes the wrong register.

Candidate causes. The offset slice is too narrow or too wide, so the local offset carries region bits or drops address bits.

Discriminating evidence. Compare off_o against the low bits of ADR_O. A mismatch localises to the slice; a match moves the search into the slave's read multiplexer.

8. Verification

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// wb_addr_checker — address-phase properties.
//
// P1 is SPECIFICATION (RULE 3.60 read across a multi-cycle presentation)
// and is the property this chapter exists for. P2 and P3 are LOCAL DESIGN
// POLICY about this interconnect — the specification does not define
// address maps or decoding at all, so nothing here can be a Wishbone rule.
// ─────────────────────────────────────────────────────────────────────────
module wb_addr_checker #(
  parameter int unsigned AW     = 30,
  parameter int unsigned OFF_AW = 3,
  parameter int unsigned NSLV   = 2
) (
  input logic                clk_i,
  input logic                rst_i,
  input logic                cyc_o,
  input logic                stb_o,
  input logic [AW-1:0]       adr_o,
  input logic                ack_i,
  input logic                err_i,
  input logic                rty_i,
  input logic [NSLV-1:0]     sel_slave,     // white-box: decoder output
  input logic [OFF_AW-1:0]   off             // white-box: local offset
);
  default disable iff (rst_i);

  logic terminated;
  assign terminated = ack_i | err_i | rty_i;

  // P1 — SPECIFICATION (RULE 3.60). The address is stable for as long as
  //      the transfer is presented. The end boundary is the TERMINATION:
  //      omitting `!terminated` would forbid a master from presenting a
  //      different read the cycle after one completes, which is legal and
  //      normal — the over-strong-property trap of Chapter 4.6 Section 10.
  property p_address_stable_while_outstanding;
    @(posedge clk_i) (cyc_o && stb_o && !terminated) |=> $stable(adr_o);
  endproperty
  a_address_stable_while_outstanding :
    assert property (p_address_stable_while_outstanding)
    else $error("RULE 3.60: ADR_O moved while the read was outstanding");

  // P2 — LOCAL POLICY. The decoder selects at most one slave. $onehot0
  //      permits zero (an unmapped address) and forbids two.
  property p_select_onehot0;
    @(posedge clk_i) $onehot0(sel_slave);
  endproperty
  a_select_onehot0 : assert property (p_select_onehot0)
    else $error("LOCAL: more than one slave selected");

  // P3 — LOCAL POLICY. The local offset is exactly the low bits of the
  //      global address. Catches a mis-sized slice, which otherwise
  //      presents as a slave read-mux bug and sends the search one stage
  //      too far downstream.
  property p_offset_matches_low_bits;
    @(posedge clk_i) (cyc_o && stb_o) |-> (off == adr_o[OFF_AW-1:0]);
  endproperty
  a_offset_matches_low_bits : assert property (p_offset_matches_low_bits)
    else $error("LOCAL: local offset does not match ADR_O low bits");
endmodule

P1 is a conformance property and needs no white-box access — a passive monitor on the bus catches both the walking master and an unlatched one. That is a pleasant contrast with Chapter 5.3's repeated-side-effect bug, which no bus-level property could see.

P2 and P3 need decoder internals, and they encode decisions the specification does not make. Wishbone defines no address map and no decoding strategy, so there is no rule number available for either — labelling them LOCAL POLICY is not a formality, it is the accurate description.

Tooling limitation. Icarus Verilog has no SVA support and cannot execute any of these. They are reviewed by inspection; the synthesizable RTL is elaborated and the address-stability failure is simulated in Section 6.

9. Common Mistakes

"The address is accepted, so the master can move on."

Wrong mental model: an AXI-style address channel with independent handshaking.

Concrete bug: a master that presents an address, drops STB_O, and waits for data.

Observable evidence: a one-cycle strobe followed by a permanent hang — the slave saw the request vanish.

Correct model: Classic has one handshake. RULE 3.60 qualifies the address with STB_O for the transfer's whole duration, and a combinational slave has nothing to remember it with.

"The offset from the datasheet is the address to put on the bus."

Wrong mental model: one address representation.

Concrete bug: byte offset 0x10 driven onto ADR_O, reading word 16.

Observable evidence: ADR_O exactly 4× the intended word address — unmistakable once you look for it.

Correct model: three representations, converted at defined points. Chapter 4.3 explains why the bus is word-addressed.

"A slave should check that the address is in its range."

Wrong mental model: the slave knows where it lives.

Concrete bug: a peripheral with its base address hard-coded, which cannot be instantiated twice or relocated.

Observable evidence: not a runtime failure — an integration failure, discovered when the map changes.

Correct model: the interconnect decides which slave; the slave decides which of its own registers. That separation is what makes a core portable IP, which is the specification's stated purpose.

10. Interview Reasoning

Three checks in order, each eliminating one stage, using the three address representations.

First: is ADR_O on the bus the word address I intended? If it is exactly four times too large, the answer is immediate — a byte offset was driven where a word address belongs. Chapter 4.3 established that a 32-bit port carries ADR_O(n..2), so the two byte-offset bits are not on the bus and the conversion is a right shift by two. This is the commonest of the three and the cheapest to rule out, which is why it goes first.

Second: with the right address on the bus, is the right slave selected? Probe the decoder's select lines, or each slave's STB_I. Wrong slave means the decoder's region comparison is wrong. Two slaves selected at once means the decode was built from overlapping range checks rather than a mutually-exclusive region index — and that produces merged read data and a doubled acknowledge, which looks like a baffling slave bug if you start at the slave.

Third: with the right slave selected, is the local offset right, and does the read mux agree with it? Compare off_o against the low bits of ADR_O. A mismatch is a mis-sized slice. A match sends the search into the slave's multiplexer — a missing or wrong case arm.

Why the order matters more than the checks. All three produce the same user-visible symptom: a successful read of the wrong value. Nothing about the returned data says which stage failed, so guessing costs a full debug cycle each time. Each check is one probe and eliminates one stage definitively.

The assertion that would have caught the middle one for free is a $onehot0 on the select vector — cheap, always true in a correct system, and it fires at the moment of the fault rather than when someone notices a wrong value downstream.

11. Understanding Check

12. What's Next

The address is settled: one value doing two jobs, three representations, and an obligation to stay coherent for the whole transfer.

The forward path has now delivered its question to the right register. What comes back is a different problem — the return path is driven by whichever slave was selected, merged with every other slave's, and meaningful for exactly one cycle.

How does read data travel from peripheral state back to the requester, and when is it trustworthy?

Chapter 6.3 — Data Return answers it. The full path is on the Wishbone curriculum index.

Continue learning

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.