can have more restrictive access mode, e.g. R/O fields can be
a part of an R/W register.
"""
- R = "r"
- W = "w"
+ R = "r"
+ W = "w"
RW = "rw"
def readable(self):
Write strobe. Registers should update their value or perform
the write side effect when this strobe is asserted.
"""
+
def __init__(self, width, access, *, name=None, src_loc_at=0):
if not isinstance(width, int) or width < 0:
raise ValueError("Width must be a non-negative integer, not {!r}"
.format(width))
- if not isinstance(access, Element.Access) and access not in ("r", "w", "rw"):
- raise ValueError("Access mode must be one of \"r\", \"w\", or \"rw\", not {!r}"
+ if not isinstance(access, Element.Access) and access not in (
+ "r", "w", "rw"):
+ raise ValueError("Access mode must be one of \"r\", "
+ "\"w\", or \"rw\", not {!r}"
.format(access))
- self.width = width
+ self.width = width
self.access = Element.Access(access)
layout = []
if self.access.readable():
layout += [
("r_data", width),
- ("r_stb", 1),
+ ("r_stb", 1),
]
if self.access.writable():
layout += [
("w_data", width),
- ("w_stb", 1),
+ ("w_stb", 1),
]
super().__init__(layout, name=name, src_loc_at=1)
.format(data_width))
self.addr_width = addr_width
self.data_width = data_width
- self.memory_map = MemoryMap(addr_width=addr_width, data_width=data_width,
+ self.memory_map = MemoryMap(addr_width=addr_width,
+ data_width=data_width,
alignment=alignment)
super().__init__([
- ("addr", addr_width),
- ("r_data", data_width),
- ("r_stb", 1),
- ("w_data", data_width),
- ("w_stb", 1),
+ ("addr", addr_width),
+ ("r_data", data_width),
+ ("r_stb", 1),
+ ("w_data", data_width),
+ ("w_stb", 1),
], name=name, src_loc_at=1)
bus : :class:`Interface`
CSR bus providing access to registers.
"""
+
def __init__(self, *, addr_width, data_width, alignment=0):
- self.bus = Interface(addr_width=addr_width, data_width=data_width, alignment=alignment,
- name="csr")
+ self.bus = Interface(addr_width=addr_width,
+ data_width=data_width,
+ alignment=alignment,
+ name="csr")
self._map = self.bus.memory_map
def align_to(self, alignment):
See :meth:`MemoryMap.add_resource` for details.
"""
if not isinstance(element, Element):
- raise TypeError("Element must be an instance of csr.Element, not {!r}"
- .format(element))
+ raise TypeError("Element must be an instance of csr.Element, "
+ "not {!r}" .format(element))
size = (element.width + self.bus.data_width - 1) // self.bus.data_width
- return self._map.add_resource(element, size=size, addr=addr, alignment=alignment)
+ return self._map.add_resource(
+ element, size=size, addr=addr, alignment=alignment)
def elaborate(self, platform):
m = Module()
for elem, (elem_start, elem_end) in self._map.resources():
shadow = Signal(elem.width, name="{}__shadow".format(elem.name))
if elem.access.readable():
- shadow_en = Signal(elem_end - elem_start, name="{}__shadow_en".format(elem.name))
+ shadow_en = Signal(
+ elem_end - elem_start,
+ name="{}__shadow_en".format(
+ elem.name))
m.d.sync += shadow_en.eq(0)
if elem.access.writable():
m.d.comb += elem.w_data.eq(shadow)
# carry chains for comparisons, even with a constant. (Register sizes don't have
# to be powers of 2.)
with m.Switch(self.bus.addr):
- for chunk_offset, chunk_addr in enumerate(range(elem_start, elem_end)):
- shadow_slice = shadow.word_select(chunk_offset, self.bus.data_width)
+ for chunk_offset, chunk_addr in enumerate(
+ range(elem_start, elem_end)):
+ shadow_slice = shadow.word_select(
+ chunk_offset, self.bus.data_width)
with m.Case(chunk_addr):
if elem.access.readable():
- r_data_fanin |= Mux(shadow_en[chunk_offset], shadow_slice, 0)
+ r_data_fanin |= Mux(
+ shadow_en[chunk_offset], shadow_slice, 0)
if chunk_addr == elem_start:
m.d.comb += elem.r_stb.eq(self.bus.r_stb)
with m.If(self.bus.r_stb):
m.d.sync += shadow.eq(elem.r_data)
# Delay by 1 cycle, allowing reads to be pipelined.
- m.d.sync += shadow_en.eq(self.bus.r_stb << chunk_offset)
+ m.d.sync += shadow_en.eq(self.bus.r_stb <<
+ chunk_offset)
if elem.access.writable():
if chunk_addr == elem_end - 1:
bus : :class:`Interface`
CSR bus providing access to subordinate buses.
"""
+
def __init__(self, *, addr_width, data_width, alignment=0):
- self.bus = Interface(addr_width=addr_width, data_width=data_width, alignment=alignment,
- name="csr")
- self._map = self.bus.memory_map
+ self.bus = Interface(addr_width=addr_width,
+ data_width=data_width,
+ alignment=alignment,
+ name="csr")
+ self._map = self.bus.memory_map
self._subs = dict()
def align_to(self, alignment):
See :meth:`MemoryMap.add_resource` for details.
"""
if not isinstance(sub_bus, Interface):
- raise TypeError("Subordinate bus must be an instance of csr.Interface, not {!r}"
- .format(sub_bus))
+ raise TypeError("Subordinate bus must be an instance of "
+ "csr.Interface, not {!r}" .format(sub_bus))
if sub_bus.data_width != self.bus.data_width:
- raise ValueError("Subordinate bus has data width {}, which is not the same as "
+ raise ValueError("Subordinate bus has data width {}, "
+ "which is not the same as "
"decoder data width {}"
.format(sub_bus.data_width, self.bus.data_width))
self._subs[sub_bus.memory_map] = sub_bus