Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Standard Debug Spec Milestone

Below are milestones planned in the project :

Phase 1 adds missing features in DebugModule from ratified RISC-V Debug Specification.

Phase 2 adds a target-side Arm Serial Wire Debug (SWD) front-end that still drives the same RISC-V DebugBus used by the JTAG DTM. The Arm specification is at ADIv5.0–ADIv5.2 (IHI0031).

Host (SWCLK / SWDIO)
        │
   ┌────▼────┐
   │ SwdPhy  │  Phase 2A — wire protocol (framing, turnaround, line reset)
   └────┬────┘
        │ SwdDpCmd / SwdDpRsp / SwdDpWrite
   ┌────▼────┐
   │  SwdDp  │  Phase 2B — DP registers + ACK policy (OK / WAIT / FAULT)
   └────┬────┘
        │ SwdApCmd / SwdApRsp
   ┌────▼──────────┐
   │ SwdDmiGateway │  Phase 2C — custom DMI AP + SWCLK↔debug CDC
   └────┬──────────┘
        │ DebugBus (same as JTAG DTM)
   ┌────▼────────┐
   │ DebugModule │  Phases 1B–1D
   └─────────────┘

How the SWD protocol works

What SWD is

Serial Wire Debug is a 2-wire, synchronous, packet-based host↔target link:

SignalRole
SWCLKClock (usually driven by the probe/host)
SWDIOBidirectional data (one bit per clock)

There is no separate reset pin. Recovery uses a line reset on SWDIO.

Logically, SWD talks to a Debug Port (DP). The DP either answers for itself (DP registers) or forwards accesses to an Access Port (AP) that reaches the real debug resource. In this project the AP is a custom RISC-V DMI gateway, which drives the existing DebugBus into the Debug Module.

One transaction on the wire

Every SWD access is request → ACK → (optional data).

Packet request (host → target, 8 bits)

After optional idle cycles (SWDIO low), the host sends:

Bit(s)NameMeaning
1StartAlways 1
1APnDP0 = DP register, 1 = AP register
1RnW0 = write, 1 = read
2A[2:3]Register address bits A[3:2] (LSB-first on the wire)
1ParityEven parity over APnDP, RnW, A[2], A[3]
1StopAlways 0
1ParkHost drives 1, then releases the line

All multi-bit fields are LSB first.

Turnaround (Trn)

When drive ownership changes, neither side should drive for a short period (default 1 SWCLK). That prevents bus fight on SWDIO.

ACK (target → host, 3 bits)

Encoding (value)NameWire order (LSB first)
0b001OK1, 0, 0
0b010WAIT0, 1, 0
0b100FAULT0, 0, 1

The numeric value and the bit order on the wire are easy to confuse: OK is value 001, so the first driven bit is 1.

Data phase (only if ACK = OK in this implementation)

DirectionWhenFormat
WriteAfter OK + second turnaround32-bit WDATA + even parity (host → target)
ReadAfter OK, no turnaround (target keeps the line)32-bit RDATA + even parity (target → host)

Errors and special sequences

ConditionTarget behaviour
Protocol error (bad request parity / Stop / Park)Do not drive ACK; stay silent until line reset
WDATA parity failACK already sent; DP sets WDATAERR and drops the write (not a line silence)
WAITBusy (e.g. previous AP access outstanding); host typically retries
FAULTSticky error set; host clears via ABORT
Line resetSWDIO HIGH for ≥ 50 SWCLK, then ≥ 2 idle (LOW)
IdleSWDIO low between frames, or back-to-back Start with zero idle

Clock and pins

Clock domain = SWCLK (probe-driven)

swdio.i  ← host/probe (or pad input)
swdio.o  → pad output value when target drives
swdio.oe → pad output enable
  • Target samples i and updates o/oe on rising SWCLK (OpenOCD bitbang model).

Minimal mental model (one frame)

  1. Host clocks an 8-bit header (Start…Park).
  2. Phy validates it; if bad → silence until line reset.
  3. If good → phy fires cmd and needs rsp.ack for the next few clocks.
  4. Phy drives ACK (value chosen by Phase 2B).
  5. If OK and read → phy streams rdata + parity from the DP.
  6. If OK and write → phy releases the line, samples wdata + parity, fires wr.
  7. If WAIT/FAULT → phy stops after ACK (no data phase here).
  8. Host may retry, clear sticky via ABORT or line-reset.