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

RTLDebug

This is the top level specification for RTLDebug, an open specification for in-system debugging of RTL logic in FPGA and/or ASIC.

RTLDebug defines register interfaces and architecture only, multiple implementations are possible and should interoperate as long as they conform to this specification.

Overview

An RTLDebug system consists of the following base components:

  • A 32 bit memory mapped bus
    The choice of bus is implementation defined; plausible choices include AMBA APB, Avalon, or Wishbone.

    Registers in RTLDebug are all 32 bits in size, aligned to 32-bit boundaries (i.e. address base+0, base+4, base+8), and accessed as whole words only to provide maximum flexibility for different bus architectures.

    All debug components live on this single bus. The bus may be dedicated to debug or shared with other components.

  • A bridge to access this bus from a host PC
    Any mechanism which allows a PC to read and write registers via JTAG, UART, or another convenient transport can be used; host-side software should be designed in a modular fashion so that transports can be easily swapped out. Self-hosted debug is possible as well, if the system is a SoC containing a processor.

    The intent is to define our own open bridge standard with a freely licensed reference implementation, but to also support implementations which choose to use proprietary bridges such as an ARM JTAG-DP and MEM-AP.

    The bridge provides an implementation-defined mechanism for discovering the address of the top level RTLDebug descriptor ROM table.

  • A debug server on the PC
    The debug server connects to the hardware bridge block (which typically only supports one concurrent connection) and exposes an API for debug software on the PC to communicate with individual debug cores. The reference implementation of the debug server exposes a SCPI instrument server on a separate TCP port for each debug core however other designs are possible.

  • A top-level component descriptor ROM
    The ROM contains identifiers and pointers to other debug components on the bus so that the debug server can discover what debuggable components exist.

  • One or more debug cores
    Individual debug cores provide debug capabilities such as signal generation, waveform capture, etc.

Component Specifications

ROM table

The ROM table is the root component used to discover all remaining debug blocks in an RTLDebug system.

The ROM table's base address must be discoverable somehow so that debug software knows how to find it. Due to the variation in possible bridge and bus designs, we are not specifying the discovery mechanism in this document; the specification for each bridge interface must provide a discovery mechanism.

A ROM table can be at most 1 kB (256 words) in size. This means the maximum allowed size of a ROM is 127 descriptors plus the header. If more than 127 debug cores are needed in the SoC, multiple ROM tables can be chained in a linked list, with a "ROM_" entry from one table pointing to the next.

Addressing

Implementations MAY combine the ROM table with other ROMs, such as boot code or ILA probe manifests. The ROM table MUST be aligned on a 32-bit word boundary, but does not require a larger alignment (i.e. it can be placed at an arbitrary word offset within a larger shared ROM).

A ROM table consists of a 2-word header at offset 0x00, followed by zero or more descriptors starting at offset 0x08.

COUNT

** num_desc **: number of descriptors in this ROM table, not including the header.

Zero is a legal no-op value and causes this ROM table to be ignored.

PADDING

RFU / RAZ: Padding to allow descriptors to be aligned on 8-byte boundaries.

Reserved for future use; implementations MUST return 0x00000000 and debuggers MUST ignore this value until another function is defined.

Descriptor

FOURCC

Four-character code (FOURCC) uniquely identifying the debug block.

FOURCCs are packed into 32-bit registers with the leftmost character in the most-significant byte position, i.e. "ROM_" is encoded as the 32-bit value 0x5f4d4f52. If you are on a little-endian host system this will give correct byte ordering when casting a uint32 register to a char[4]. Big-endian systems will require a byte order swap.

POINTER

base_addr: 32-bit pointer to the base address of the debug block

FOURCC list

All entries other than those listed here are reserved for future use. All FOURCC's currently defined (other than padding) must consist only of printable ASCII characters as of this version of the specification, however this restriction MAY be relaxed in the future.

  • 0x00000000 A FOURCC consisting of four nul characters (not to be confused with the digit zero) is used for padding at the end of a ROM table. A null FOURCC MUST be paired with a null pointer (i.e. a descriptor consiting of eight zero bytes). Implementations MAY choose to stop reading the ROM after encountering a null FOURCC; all ROM table entries after a null descriptor MUST also be null descriptors.

  • !xxx All FOURCC's starting with a '!' character are reserved for implementation defined or testing purposes.

  • GPIO 32-bit bidirectional GPIO controller

  • ILA_ Internal logic analyzer (link TODO)

  • ROM_ Pointer to a second ROM table, as specified on this page. ROM tables can be chained in an arbitrarily long linked list if more than 127 debug cores are required in the SoC.

  • VIO_ Virtual IO (link TODO)

GPIO

[!IMPORTANT] This section describes the behavior of an existing, widely deployed block, and cannot be changed in incompatible ways.

The GPIO block uses FOURCC tag "GPIO" and provides a single bank of up to 32 general-purpose I/O pins, which may go to physical I/O pads or internal test points within the device as needed.

No symbol table is provided; this block is intended to be small and efficient rather than full-featured. If multi-bit ports or named signals are needed, use the VIO block instead.

Registers

Each GPIO is controlled by one bit each of the OUT, IN, and TRIS registers.

  • OUT: value to drive out the port when configured in output mode, ignored when in input mode
  • IN: value seen by the port when configured in input mode. The value when the pin is configured as an output is IMPLEMENTATION DEFINED.
  • TRIS: 1 for input, 0 for output

Notes

If these pins drive physical GPIO pads rather than internal nodes, I/O buffer configuration (pullup/pulldown, drive strength, etc) is provided by an IMPLEMENTATION DEFINED mechanism.

If the GPIO block is connected to internal nodes that do not support tristates, an implementation MUST ignore the value of the TRIS register. In this case, an implementation MAY choose to do any of the following:

  • Tie IN and OUT together for output-only ports
  • Tie IN to a constant value for output-only ports
  • Use IN and OUT as independent 32-bit unidirectional ports