Skip to content
VLSI Mentor

Wishbone · Module 24

Register Maps

RULE 2.15 demands port size, granularity, operand size and endianness — and none of them describe a map. Holes, mixed widths and alignment are the slave's own contract, and an alignment rule that looked right made single-lane writes illegal.

Chapter 23.3 built a register bank from a table of access policies, and that table was the right idea. It also quietly assumed three things that no real map gets to assume:

  1. every offset below N exists — real maps have holes
  2. every register is the full port size — real maps mix 8, 16 and 32-bit
  3. any [SEL_O()] pattern is acceptable — real maps have alignment rules

This chapter is about the map itself rather than the registers in it: a document that says what is at each offset, how wide it is, and what happens at the addresses where nothing is. Module 25's DMA engine will be a client of exactly such a document, and so is every driver ever written.

A register map is the only part of a peripheral that another human being has to read. Everything else can be inferred from behaviour; the map cannot, because the parts that matter most are the parts that do nothing.

1. What B3 Requires, And What It Leaves You

RULE 2.00 makes a datasheet mandatory. RULE 2.15 then lists twelve things it must contain, and five of them touch this chapter:

RULE 2.15 item 7"The WISHBONE DATASHEET MUST indicate the port size. MUST be indicated as: 8-bit, 16-bit, 32-bit or 64-bit."

item 8"...MUST indicate the port granularity..."

item 9"...MUST indicate the maximum operand size. ...If the maximum operand size is unknown, then the maximum operand size shall be the same as the granularity."

item 10"...MUST indicate the data transfer ordering. The ordering MUST be indicated as BIG ENDIAN or LITTLE ENDIAN."

item 11"...MUST indicate the sequence of data transfer through the port. If the sequence of data transfer is not known, then the datasheet MUST indicate it as UNDEFINED."

Read those five together and notice what is missing. They describe the port. Not one of them says which offsets exist, what is at offset 4, or what happens if you write to offset 9. B3 specifies the pipe and says nothing about what is on the other end of it.

Two rules do touch data layout, and they are narrower than they look:

RULE 3.100"Data organization on 32-bit ports MUST conform to organization32."

RULE 3.90"Data organization MUST conform to the ordering indicated in operands."

Those fix which byte lane a byte lives in. They say nothing about whether a 16-bit register may be read with a 32-bit access, because B3 has no concept of a register at all.

the questionwho answers it
which lane does byte 2 occupy?RULE 3.100
is this port big or little endian?RULE 2.15 item 10 — you must say
which offsets exist?you, and nothing checks you
what does a hole do?you
may a 32-bit access hit a 16-bit register?you
what is the maximum operand size?RULE 2.15 item 9 — you must say

2. The Running Map

Every rig in Module 24 uses one map, so that one document describes every measurement:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
//   offset  policy  width  source     what it is
//     0      RW     32     reg        a plain control word
//     1      RO     32     counter    a free-running counter
//     2      W1C     8     status     an interrupt flag word
//     3      WO     32     reg        a command strobe
//     4      RW     16     reg        a narrow config word
//     5      --     --     --         RESERVED
//     6      RW      8     fifo       a byte-wide data port
//     7      RO     16     reg        a narrow identity word
//    8-15    --     --     --         RESERVED

Offset 5 is a hole in the middle, not at the end. That is deliberate. A map whose reserved space is all at the top is the easy case; a hole between two live registers is where decode logic and documentation drift apart.

The encoding packs width and policy into four bits per offset:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// entry = {width[1:0], policy[1:0]}   W8=0 W16=1 W32=2 RSVD=3
//                                     RW=0 RO=1  W1C=2 WO=3

A hole is encoded as a width, not as a fifth policy. That is a design decision worth stating: reserved and zero bytes wide are the same statement, and putting them in the same field makes it impossible to write a table entry that is reserved and also read-write.

The register map as a lookup. An incoming address is reduced to a four-bit offset by partial address decoding, the remaining upper bits having been decoded by the interconnect. The offset indexes a packed table that yields two fields: a two-bit access policy and a two-bit width code. The width code doubles as the presence flag, because a width of RSVD marks the offset as a hole. Three outputs follow. Presence and reserved drive the termination decision. The width drives a lane mask describing which byte lanes the register actually occupies. The lane mask combined with the master's byte selects drives the alignment verdict, which decides whether the access stays inside the register it addressed.ADR_Iupper bits already decodedoffsetADR_I[3:0] — partial decodeMAP table4 bits per offset, packedpresent / reserveda hole is a width, not apolicypolicyRW / RO / W1C / WOlane maskwhich lanes the registerowns12

3. Every Offset Is Accounted For

The sweep is the completeness proof, and the total is the point of it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
      off  present  policy  width  lanes   what
       0     yes      RW      32    1111   implemented
       1     yes      RO      32    1111   implemented
       2     yes      W1C     8     0001   implemented
       3     yes      WO      32    1111   implemented
       4     yes      RW      16    0011   implemented
       5     NO       --      --    0000      RESERVED
       6     yes      RW      8     0001   implemented
       7     yes      RO      16    0011   implemented
       8     NO       --      --    0000      RESERVED

      implemented 7   reserved 9   total 16
      -> EVERY OFFSET IN THE WINDOW IS ACCOUNTED FOR.
         That is not automatic. A map that simply stops
         at the last implemented register leaves the rest
         of its own window undefined, and the integrator
         finds out by writing there.

7 + 9 = 16. Not "7 registers and some spare room" — sixteen offsets, each with a defined answer.

A map that describes only what exists is half a map. The addresses where nothing exists are the ones a driver reaches by accident, and they are the only part of the document that a reader cannot discover by experiment without risking the very side effects the map is supposed to warn them about.

4. The Three Policies For A Hole

B3 says nothing about an offset inside your window that you did not implement. Three answers exist:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
//   1. alias it        - mirror a real register. Cheap decode, and the
//                        integrator discovers it by accident in year two.
//   2. read 0 / ack    - silent. Writes vanish, reads look plausible.
//   3. read 0 / ERR    - reported.            <-- THIS MODULE

Policy 1 is the cheapest and the most dangerous. Decoding only the bits you need means offset 9 lands on offset 1, and the aliasing is invisible until somebody's driver writes a "harmless" scratch location and stops a timer. It is not a bug in any rule — B3's own Partial Address Decoding model encourages decoding only what you need:

"each SLAVE decodes only the range of addresses that it requires... The remaining address bits are decoded by the interconnection system."

Policy 2 is what most silicon does, and it is why "I wrote it and it didn't take" is a permanent fixture of peripheral bring-up.

Policy 3 is the only one that tells anybody, and it costs an [ERR_O] the master may not have a pin for — which Chapter 24.5 shows is its own failure mode. There is no free choice here, only a documented one.

5. Alignment, And A Rule I Got Wrong

Here is the version of the alignment rule this module shipped first, and it is wrong:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─── DO NOT SHIP THIS ───────────────────────────────────────────────
// The first alignment rule this module shipped. It is internally
// consistent, it reads correctly, and it makes a single-byte write to a
// 32-bit register ILLEGAL - which is the one thing RULE 3.60 puts
// [SEL_O()] on the bus to express. SIM D caught it on its first run.
  // "a register must be accessed at its own width"
  assign strict_ok = (width_o == W32) ? (sel_i == 4'b1111) :
                     (width_o == W16) ? ((sel_i == 4'b0011) ||
                                         (sel_i == 4'b1100)) :
                     (width_o == W8)  ? (sel_i == 4'b0001) : 1'b0;

It reads correctly. It is internally consistent. And it makes a single-byte write to a 32-bit register illegal — which is precisely the thing [SEL_O()] exists to express. RULE 3.60 puts [SEL_O()] on the bus so a master can say "change one byte"; a slave that refuses is not enforcing a contract, it is breaking one.

SIM D found it on its first run: a lane-1 write to offset 0 came back as a misalignment error.

The correct question is not does the access match the register's width but does the access stay inside the register:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  //   sel_i & ~lanes  is the set of lanes the master asked for that this
  //                   register does not own. It must be empty.
  logic in_own, nonzero;
  assign in_own  = ((sel_i & ~own) == {SW{1'b0}});
  assign nonzero = (sel_i != {SW{1'b0}});

Subset, not equality. The table becomes:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
      off  width  SEL_I   strict  loose
       0    32    1111     ok      ok
       0    32    0011     ok      ok
       0    32    0001     ok      ok
       2    8     1111     ERR     ok
       2    8     0001     ok      ok
       4    16    1111     ERR     ok
       4    16    0011     ok      ok
       4    16    0001     ok      ok

A 32-bit register accepts any sub-pattern; a narrow register refuses anything reaching past it. That preserves RULE 3.60's purpose and still catches the access that would read bytes the register does not have.

6. What A Loose Map Costs

STRICT_ALIGN off accepts any non-zero select and lets the lane mask clip it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
      offset 4 is 16 bits wide. A 32-bit access:
        STRICT_ALIGN=1  aligned=0  -> the slave ERRORs it
        STRICT_ALIGN=0  aligned=1  -> the slave accepts it
        lanes the register occupies: 0011

      -> THE LOOSE MAP RETURNS HALF A REGISTER AND SAYS
         NOTHING. The lane mask clips the access to 0011,
         so the upper two bytes read as zero - which is
         indistinguishable from a register whose upper
         half is genuinely zero. Neither choice is more
         conformant; RULE 2.15 item 9 obliges you to
         state the maximum operand size either way.

That last sentence is the whole argument. A driver reading 0x0000BEEF from a 32-bit access cannot tell whether the upper half is zero because the register is narrow or because the field is clear. The strict map turns that ambiguity into an error; the loose map turns it into a plausible number.

Neither is more conformant. RULE 2.15 item 9 obliges you to state the maximum operand size either way, and a datasheet that says maximum operand size: 16-bit has told the reader everything the strict check would have enforced — if they read it.

STRICT_ALIGN = 1STRICT_ALIGN = 0
32-bit access to a 16-bit register[ERR_O]succeeds, returns half
single-lane write to a 32-bit registersucceedssucceeds
costan [ERR_O] path and a comparatorsilence
what the datasheet must still sayoperand size (item 9)operand size (item 9)
failure modea driver that worked elsewhere now errorsa field that reads as zero forever

7. Where The Map Is Not The Decoder

One boundary worth drawing, because these two jobs look alike and belong in different modules.

Chapter 23.5's decoder answers which slave. This map answers what is inside one slave. The decoder works on a base/mask table across a whole address space; the map works on four address bits after the interconnect has already chosen this slave.

They fail differently, too. A decoder hole means no slave answers — a hang, unless a default port exists. A map hole means this slave answers and refuses. The first is an interconnect problem and the second is a datasheet problem, and conflating them produces a peripheral that hangs the bus instead of reporting a bad offset.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  // Compared at FIVE bits, not four. N may legitimately be 16, and
  // N[3:0] is then zero - a truncation that makes every offset fall
  // outside the window and the whole map read as unimplemented. SIM A
  // found this on its first run.
  logic in_window;
  assign in_window = ({1'b0, off_o} < N[4:0]);

That comment records a real bug and the sim that caught it. N is 16 and N[3:0] is 0, so the first version of this module reported every offset as unimplemented and the whole map came back empty. A width truncation in a comparison is silent in every tool that will ever look at it.

8. The Datasheet This Map Produces

RULE 2.15 itemvalue
1 revision levelB3
2 interface typeSLAVE
7 port size32-bit
8 granularity8-bit
9 maximum operand size32-bit
10 data orderingLITTLE ENDIAN
11 transfer sequenceUNDEFINED — SINGLE cycles only
— signal polarityactive high, per RULE 2.30
— reserved offsetsread 0, write [ERR_O] — local policy
— alignmentsubset of the register's lanes — local policy

RULE 2.30 is worth its line: "All WISHBONE interface signals MUST use active high logic." It is the one rule in this chapter that requires no judgement at all, and it is there because some tools and some houses default the other way.

9. What This Chapter Did Not Build

  • No register behaviour. The map says a register is W1C; Chapter 24.3 makes clearing work.
  • No read multiplexing. The map says offset 6 is a FIFO; Chapter 24.2 connects one.
  • No termination. Nothing here drives [ACK_O]. The map is combinational and has no clock at all — it is a document that happens to be synthesisable.
  • No runtime reconfiguration. The table is a parameter.
  • No 64-bit port. RULE 3.95 governs that layout and this module is 32-bit throughout.

Next: Chapter 24.2 — Read Logic connects four different sources to one [DAT_O()], and runs into a rule no chapter in this curriculum has cited before — the one that says a read's data is only meaningful on the clock it is answered, and therefore so is everything the read caused.

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.