CSRs
Bus
- class torii.lib.soc.csr.bus.Element(width: int, access: Access, *, name: str | None = None, src_loc_at: int = 0)
- class torii.lib.soc.csr.bus.Interface(*, addr_width: int, data_width: int, name: str | None = None)
CPU-side CSR interface.
A low-level interface to a set of atomically readable and writable peripheral CSR registers.
Operation
CSR registers mapped to the CSR bus are split into chunks according to the bus data width. Each chunk is assigned a consecutive address on the bus. This allows accessing CSRs of any size using any datapath width.
When the first chunk of a register is read, the value of a register is captured, and reads from subsequent chunks of the same register return the captured values. When any chunk except the last chunk of a register is written, the written value is captured; a write to the last chunk writes the captured value to the register. This allows atomically accessing CSRs larger than datapath width.
- param addr_width:
Address width. At most
(2 ** addr_width) * data_width
register bits will be available.- type addr_width:
int
- param data_width:
Data width. Registers are accessed in
data_width
sized chunks.- type data_width:
int
- param name:
Name of the underlying record.
- type name:
str
- ivar memory_map:
Map of the bus.
- vartype memory_map:
MemoryMap
- ivar addr:
Address for reads and writes.
- vartype addr:
Signal(addr_width)
- ivar r_data:
Read data. Valid on the next cycle after
r_stb
is asserted. Otherwise, zero. (Keeping read data of an unused interface at zero simplifies multiplexers.)- vartype r_data:
Signal(data_width)
- ivar r_stb:
Read strobe. If
addr
points to the first chunk of a register, captures register value and causes read side effects to be performed (if any). Ifaddr
points to any chunk of a register, latches the captured value tor_data
. Otherwise, latches zero tor_data
.- vartype r_stb:
Signal()
- ivar w_data:
Write data. Must be valid when
w_stb
is asserted.- vartype w_data:
Signal(data_width)
- ivar w_stb:
Write strobe. If
addr
points to the last chunk of a register, writes captured value to the register and causes write side effects to be performed (if any). Ifaddr
points to any chunk of a register, latchesw_data
to the captured value. Otherwise, does nothing.- vartype w_stb:
Signal()
- class torii.lib.soc.csr.bus.Decoder(*args, src_loc_at: int = 0, **kwargs)
CSR bus decoder.
An address decoder for subordinate CSR buses.
Usage
Although there is no functional difference between adding a set of registers directly to a
Multiplexer
and adding a set of registers to multipleMultiplexer`s that are aggregated with a :class:`Decoder
, hierarchical CSR buses are useful for organizing a hierarchical design. If many peripherals are directly served by a singleMultiplexer
, a very large amount of ports will connect the peripheral registers with the decoder, and the cost of decoding logic would not be attributed to specific peripherals. With a decoder, only five signals per peripheral will be used, and the logic could be kept together with the peripheral.- param addr_width:
Address width. See
Interface
.- type addr_width:
int
- param data_width:
Data width. See
Interface
.- type data_width:
int
- param alignment:
Window alignment. See
memory.MemoryMap
.- type alignment:
log2 of int
- param name:
Window name. Optional.
- type name:
str
- ivar bus:
CSR bus providing access to subordinate buses.
- vartype bus:
- class torii.lib.soc.csr.bus.Multiplexer(*args, src_loc_at: int = 0, **kwargs)
CSR register multiplexer.
An address-based multiplexer for CSR registers implementing atomic updates.
Latency
Writes are registered, and are performed 1 cycle after
w_stb
is asserted.Alignment
Because the CSR bus conserves logic and routing resources, it is common to e.g. access a CSR bus with an n-bit data path from a CPU with a k-bit datapath (k>n) in cases where CSR access latency is less important than resource usage. In this case, two strategies are possible for connecting the CSR bus to the CPU:
The CPU could access the CSR bus directly (with no intervening logic other than simple translation of control signals). In this case, the register alignment should be set to 1 (i.e. alignment should be set to 0), and each w-bit register would occupy ceil(w/n) addresses from the CPU perspective, requiring the same amount of memory instructions to access.
The CPU could also access the CSR bus through a width down-converter, which would issue k/n CSR accesses for each CPU access. In this case, the register alignment should be set to k/n, and each w-bit register would occupy ceil(w/k) addresses from the CPU perspective, requiring the same amount of memory instructions to access.
If the register alignment (i.e. 2 ** alignment) is greater than 1, it affects which CSR bus write is considered a write to the last register chunk. For example, if a 24-bit register is used with a 8-bit CSR bus and a CPU with a 32-bit datapath, a write to this register requires 4 CSR bus writes to complete and the 4th write is the one that actually writes the value to the register. This allows determining write latency solely from the amount of addresses the register occupies in the CPU address space, and the width of the CSR bus.
- param addr_width:
Address width. See
Interface
.- type addr_width:
int
- param data_width:
Data width. See
Interface
.- type data_width:
int
- param alignment:
Register alignment. See
memory.MemoryMap
.- type alignment:
log2 of int
- param name:
Window name. Optional.
- type name:
str
- ivar bus:
CSR bus providing access to registers.
- vartype bus:
Events
- class torii.lib.soc.csr.event.EventMonitor(*args, src_loc_at: int = 0, **kwargs)
Event monitor.
A monitor for subordinate event sources, with a CSR bus interface.
CSR registers
- enable
self.src.event_map.size
, read/write Enabled events. See
event.EventMap.sources()
for layout.- pending
self.src.event_map.size
, read/clear Pending events. See
event.EventMap.sources()
for layout.
- param data_width:
CSR bus data width. See
csr.Interface
.- type data_width:
int
- param alignment:
CSR address alignment. See
memory.MemoryMap
.- type alignment:
int
- param trigger:
Trigger mode. See
event.Source
.- type trigger:
event.Source.Trigger
- enable
Wishbone
- class torii.lib.soc.csr.wishbone.WishboneCSRBridge(*args, src_loc_at: int = 0, **kwargs)
Wishbone to CSR bridge.
A bus bridge for accessing CSR registers from Wishbone. This bridge supports any Wishbone data width greater or equal to CSR data width and performs appropriate address translation.
Latency
Reads and writes always take
self.data_width // csr_bus.data_width + 1
cycles to complete, regardless of the select inputs. Write side effects occur simultaneously with acknowledgement.- param csr_bus:
CSR bus driven by the bridge.
- type csr_bus:
csr.Interface
- param data_width:
Wishbone bus data width. If not specified, defaults to
csr_bus.data_width
.- type data_width:
int or None
- param name:
Window name. Optional.
- type name:
str
- ivar wb_bus:
Wishbone bus provided by the bridge.
- vartype wb_bus:
wishbone.Interface