Skip to content
VLSI Mentor

Wishbone · Module 19

RISC-V SoCs

Wishbone B3 contains the word CPU zero times and no interrupt signal at all — so this chapter builds the two seams that a conformant bus and a conformant processor still do not give you, and measures one whole system running across both.

Eighteen chapters of this module have built a bus. This one attaches a processor to it, and the first thing to establish is that the specification you have been reading does not describe how.

RISC-V specifies instructions. Wishbone specifies a bus. Neither specifies the wire between them — and that wire is where the work is.

1. Four Things People Call "The Bus" That Are Not The Bus

When an engineer says "the RISC-V core is on the Wishbone bus," four separate things are being asserted, and only one of them is in B3.

what was saidwhat it actually isspecified by
the core fetches instructions over Wishbonea request interface on the core, convertednobody
the core takes a trap when a load failsan exception model in the ISA, triggered by a bus signalRISC-V, but the trigger is undictated
the timer interrupts the corea wire that is not part of Wishbone at allnobody
the core writes a peripheral registerthis one — a Wishbone WRITE cycleB3

Three of the four are yours. The fourth is the only one where quoting a rule number settles an argument.

2. The Two Seams

Every system in this chapter has exactly two boundaries that matter, and confusing them is the single most productive source of integration bugs in this whole curriculum.

A RISC-V style core attached to a Wishbone system through two seams. On the left the core drives two native request ports, instruction fetch and load/store. Each passes through its own adapter, which is seam one: the boundary between the core's request interface and Wishbone, described by no specification. The adapters drive a Wishbone arbiter and address-split tree reused unchanged from Modules 16 and 17. On the right sit five slaves: boot ROM, RAM, and a peripheral group of timer, GPIO and CSR bank whose register behaviour is seam two, also described by no specification. A separate interrupt wire runs from the peripherals back to the core without touching the bus.corefetch + load/storeifetch adapterSEAM 1dbus adapterSEAM 1arbiter +splitModules 16-17boot ROMword 0x000RAMword 0x400timer GPIO CSRSEAM 2valid / ready+ sizeCYC STB SEL WEirq12

Everything in the middle column is published RTL from Modules 16 and 17, instantiated byte-for-byte unchanged. The irq edge crosses the whole figure because it crosses nothing on the bus.

SEAM 1 is the core's native request interface meeting Wishbone. No specification describes it. The core's designer documented their side; B3 documents the other side; the converter between them is a module somebody has to write, and this module writes two of them.

SEAM 2 is a peripheral's registers meeting Wishbone. B3 describes the cycle. It says nothing about what a register does when you write it — whether a bit is read-only, whether writing a one clears it, whether the write has a side effect, or which byte lanes reach which field.

The bus in the middle is the part that is finished. Chapter 17.5's arbiter and Chapter 16.4's split tree are instantiated here unchanged, byte for byte, and neither is touched again.

3. The System This Module Measures

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// m19_soc — the teaching SoC. Two seams, one bus, five slaves.
//
//   core ifetch ─ wb_ifetch_adapter ─┐
//   core dbus   ─ wb_dbus_adapter  ──┼─ wb_owner_arb3 ─ wb_split2 tree
//   DMA         ────────────────────┘        (M17)         (M16)
//
//                                      ├── boot ROM   word 0x000..0x0FF
//                                      ├── RAM        word 0x400..0x4FF
//                                      ├── timer      word 0x800..0x803
//                                      ├── GPIO       word 0xA00..0xA03
//                                      └── CSR bank   word 0xC00..0xC03
//
//   timer irq ──┐
//   GPIO  irq ──┴──────────────────── core irq_i   NOT ON THE BUS
//
// Everything between the adapters and the slaves is published RTL from
// earlier modules, reused unchanged: wb_owner_arb3 from Chapter 17.5,
// wb_split2 from Chapter 16.4, wb_teaching_dma from Chapter 16.1. Module 19
// adds the two adapters at one seam and the register-bearing slaves at the
// other, and touches nothing in between.

Five slaves, three masters, and a byte-to-word boundary that exists in exactly two files.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ── BYTE ADDRESSES ABOVE, WORD ADDRESSES BELOW ──────────────────────────
// The core issues 32-bit BYTE addresses. The bus is WORD-addressed with
// AW = 12, which is Chapter 12.1's convention and, as it happens, LiteX's
// default too - its Wishbone Interface declares adr_width=30 for a 32-bit
// data width. The adapters divide by four. The boundary is in exactly two
// modules and nowhere else.
//
//   byte 0x0000..0x03FF  ->  word 0x000..0x0FF   boot ROM
//   byte 0x1000..0x13FF  ->  word 0x400..0x4FF   RAM
//   byte 0x2000..0x200F  ->  word 0x800..0x803   timer
//   byte 0x2800..0x280F  ->  word 0xA00..0xA03   GPIO
//   byte 0x3000..0x300F  ->  word 0xC00..0xC03   CSR bank
//
// ── THERE IS NO UNMAPPED REGION, AND THAT IS A CHOICE ───────────────────
// The split tree is a dense binary decode: every address reaches some
// slave. A sparse map with holes needs a default slave, which is
// Chapter 12.6's subject and is not rebuilt here. The error cases in this
// module come from slaves refusing requests that are wrong for them - a
// write to the ROM, a write to a read-only register - which is where a
// real error usually comes from anyway.

4. One Request, One Transfer

The smallest claim worth making about a seam is that it does not invent or destroy work. A core asks for one instruction; the bus performs one transfer; one answer comes back.

SIM A measures exactly that, and the ROM is written so the value returned names the word the fetch actually reached — ROM[i] = 0x10000000 + i. A fetch that lands on the wrong word returns a number that says so.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  === SIM A - one bus transfer per instruction fetch ===
    boot ROM at byte 0x0000, word 0x000. ROM[i] = 0x10000000+i,
    so the value names the word the fetch actually reached.

      fetch byte addr   word addr   data returned
        0x00000000        0x000     0x10000000
        0x00000004        0x001     0x10000001
        0x00000008        0x002     0x10000002
        0x0000000c        0x003     0x10000003

    SEAM 1, instruction port
      core requests accepted      4
      bus transfers terminated    4
      answers returned to core    4
      requests dropped            0
      request moved while pending 0
      SEL did not match the size  0
      word address != byte/4      0
      trap without error, or back 0
    ROM reads 4   ROM writes refused 0

Every violation counter is zero, and each of them is a separate accusation the instrument was capable of making. The wb_seam_probe that produced those lines recomputes SEL from the core's own request and compares it with what the adapter drove; it recomputes the word address as byte/4 and compares; it watches for a request that was accepted and then withdrawn. Section 7 of Chapter 19.5 runs the same probe against six systems in which those counters are not zero.

5. The Core Is Two Masters, Not One

A processor that fetches instructions and performs loads is two independent requesters, and on a single shared bus they compete.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  === SIM B - fetch and data, two masters, one bus ===
    the core asks for an instruction and a load on the same
    clock. They are two Wishbone masters and Chapter 17.5's
    arbiter decides between them.

      clk  ifetch busy  dbus busy  owner  bus adr  ACK
        1       0           0      -      0x000    0
        2       0           0      -      0x000    0
        3       1           1      -      0x000    0
        4       1           1      -      0x000    0
        5       1           1      DBUS   0x402    1
        6       1           0      DBUS   0x402    0
        7       1           0      IF     0x004    1
        8       0           0      IF     0x004    0
        9       0           0      -      0x000    0

    instruction returned 0x10000004   from the ROM
    load returned        0xaaaa0002   from the RAM
    seam violations  ifetch 0   dbus 0
    transfers        ifetch 1   dbus 1
    -> two streams, two signatures, neither corrupted the
       other. The interconnect is Module 17's, unchanged.

Look at clocks 3 through 8. Both ports go busy on the same clock. The data port wins clock 5, the fetch port gets clock 7, and neither request was damaged by the delay. Nothing in this chapter arbitrates anything — that is wb_owner_arb3 from Chapter 17.5, instantiated and left alone.

This is also why the word "the CPU's bus interface" is misleading in the singular. Most RISC-V cores expose their fetch and data paths separately, and the ones that do not have multiplexed them internally, which is the same decision made one level up.

6. What a Whole Run Looks Like

Here is the system in §3 doing a plausible day's work in one simulation: boot from ROM, fill RAM, configure and start a DMA, keep fetching and writing registers while the DMA copies, take a timer interrupt, and service it.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  === SIM I - the whole system, one run ===
    three masters: instruction fetch, load/store, DMA.
    five slaves behind a split tree. ROM answers with one
    wait state, the peripheral leg with two.

    boot   fetched 4 words from ROM: 0x10000000 0x10000001 0x10000002 0x10000003
    fill   wrote 4 words to RAM      RAM writes so far 4
    timer  RELOAD 40, CTRL enable+irq_en   reloads 1
    dma    src word 0x400 dst word 0x408 len 4, started
    work   6 more fetches and 6 CSR writes issued while
           the DMA was moving words  (dma words 4)
    dma    done, 4 words copied

    IRQ    raised at bus clock 570, with no transfer of any
           kind required to deliver it.  irqs seen by the
           core: 1   timer expiries: 1
    svc    read STATUS  0x00000001
    svc    wrote 1 to bit 0 at bus clock 586   irq now 0

    check  destination words, read back by the core
             0xd0000000  expected 0xd0000000
             0xd0000001  expected 0xd0000001
             0xd0000002  expected 0xd0000002
             0xd0000003  expected 0xd0000003

Three numbers in there are the whole module.

The interrupt arrived at bus clock 570 with no transfer required to deliver it. Servicing it took two ordinary Wishbone accesses — a read of STATUS and a write of a one to bit zero — and the line went down. And the DMA moved four words that the core then read back correctly, while the core was itself using the bus throughout.

7. What RISC-V Actually Specifies, and What It Does Not

RISC-V specifies an instruction set and a memory model. It does not specify a bus, a bus width, a byte-enable encoding, an address map, a reset vector value, an interrupt wire, or a peripheral. A conformant RISC-V core and a conformant Wishbone slave can be wired together and not work, with neither of them wrong.

This is not a defect in either specification. It is the division of labour that makes both of them reusable. But it has a consequence that the rest of this module is about: the correctness argument for the join lives in your design, not in a rule number — and therefore it has to be measured, because there is nothing to cite.

8. Where This Module Goes

chapterseamthe question
19.2 LiteXbothwhat a generator decides for you, and what it leaves open
19.3 Open hardware systems1three real cores, three different native interfaces, each documented only by itself
19.4 CPU integration1byte enables, misalignment, errors, stall-versus-wait, and the interrupt
19.5 Peripheral integration2register policies, side effects, decode, and the DATASHEET obligation

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.