Description
Peripherals are a currently missing building block from nmigen-soc.
They would provide wrappers to cores by means of a CSR interface (also interrupts, but handling these could be the subject of a separate issue).
For example, an AsyncSerialPeripheral
wrapper in nmigen-soc would provide access to an AsyncSerial
core in nmigen-stdio. Baudrate, RX/TX data, strobes etc. would be accessed through CSRs.
Integration would be straightforward for peripherals that provide nothing more than CSRs:
- CSRs are gathered behind a
csr.Multiplexer
, whose bus interface is exposed by the peripheral - all peripheral interfaces are gathered behind a single
csr.Decoder
- the
csr.Decoder
bus interface is bridged to the SoC interconnect
But what about peripherals that also provide a memory interface ? (e.g. DRAM controllers, flash controllers, etc.)
I see two possible approaches:
Approach A: exposing two separate bus interfaces for CSRs and memories
CSRs would be handled the same way as described above, but the peripheral would also provide a separate bus interface to access its memories (e.g. WB4). I think LiteX follows a similar approach.
This has the consequence of locating the CSRs and memories of a given peripheral in separate regions of the SoC address space.
pros:
- lower resource consumption; all the CSRs of the SoC are still pooled behind a single
csr.Decoder
, and the WB4 interface of a peripheral is directly connected to its logic.
cons:
- transactions may be reordered if e.g. the WB4 interface sits behind a FIFO, but not the CSR interface.
Approach B: exposing a single bus interface for both CSRs and memories
Instead of two separate interfaces, a memory-capable peripheral would expose a single bus interface like WB4 or AXI4. This has the consequence of locating all the resources of a peripheral in the same address space region.
- peripherals would have a local
wishbone.Decoder
, whose bus interface would be exposed - memory interfaces would be added to the decoder
- CSRs would be grouped into banks, each bank would be bridged to the same decoder
(e.g.csr.Multiplexer
->WishoneCSRBridge
->wishbone.Decoder
)
pros:
- peripherals with single standard bus interface are easier to integrate when instantiated alone
(counterargument: users may prefer just using the bare nmigen-stdio cores instead, if available) - the address space layout of a peripheral would be flexible to the point where one could mimick the peripherals of another SoC. This could facilitate porting/reusing drivers.
cons:
- some layouts may consume significantly more resources, e.g. if many CSR banks are requested.
(although I assume that the general case consists of a single CSR bank)
Any thoughts on this ?
cc @whitequark @awygle @enjoy-digital and others