Skip to content

Commit

Permalink
csr.reg: implement amaranth-lang/rfcs#16.
Browse files Browse the repository at this point in the history
  • Loading branch information
jfng committed Sep 1, 2023
1 parent 9ca5fe5 commit 0181c95
Show file tree
Hide file tree
Showing 5 changed files with 1,891 additions and 0 deletions.
1 change: 1 addition & 0 deletions amaranth_soc/csr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .bus import *
from .event import *
from .reg import *
188 changes: 188 additions & 0 deletions amaranth_soc/csr/field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
from amaranth import *

from .reg import Field


__all__ = ["R", "W", "RW", "RW1C", "RW1S"]


class R(Field):
__doc__ = Field._doc_template.format(
description="""
A read-only field.
""".strip(),
parameters="",
attributes="""
r_data : Signal(shape)
Read data. Drives the :attr:`~FieldPort.r_data` signal of ``port``.
""".strip())

def __init__(self, shape):
super().__init__(shape, access="r")
self.r_data = Signal(shape)

def elaborate(self, platform):
m = Module()
m.d.comb += self.port.r_data.eq(self.r_data)
return m


class W(Field):
__doc__ = Field._doc_template.format(
description="""
A write-only field.
""".strip(),
parameters="",
attributes="""
w_data : Signal(shape)
Write data. Driven by the :attr:`~FieldPort.w_data` signal of ``port``.
""".strip())

def __init__(self, shape):
super().__init__(shape, access="w")
self.w_data = Signal(shape)

def elaborate(self, platform):
m = Module()
m.d.comb += self.w_data.eq(self.port.w_data)
return m


class RW(Field):
__doc__ = Field._doc_template.format(
description="""
A read/write field with built-in storage.
Storage is updated with the value of ``port.w_data`` one clock cycle after ``port.w_stb`` is
asserted.
""".strip(),
parameters="""
reset : :class:`int`
Storage reset value.
""",
attributes="""
data : Signal(shape)
Storage output.
""".strip())

def __init__(self, shape, *, reset=0):
super().__init__(shape, access="rw")
self.data = Signal(shape)
self._storage = Signal(shape, reset=reset)
self._reset = reset

@property
def reset(self):
return self._reset

def elaborate(self, platform):
m = Module()

with m.If(self.port.w_stb):
m.d.sync += self._storage.eq(self.port.w_data)

m.d.comb += [
self.port.r_data.eq(self._storage),
self.data.eq(self._storage),
]

return m


class RW1C(Field):
__doc__ = Field._doc_template.format(
description="""
A read/write-one-to-clear field with built-in storage.
Storage bits are:
* cleared by high bits in ``port.w_data``, one clock cycle after ``port.w_stb`` is asserted;
* set by high bits in ``set``, one clock cycle after they are asserted.
If a storage bit is set and cleared on the same clock cycle, setting it has precedence.
""".strip(),
parameters="""
reset : :class:`int`
Storage reset value.
""",
attributes="""
data : Signal(shape)
Storage output.
set : Signal(shape)
Mask to set storage bits.
""".strip())

def __init__(self, shape, *, reset=0):
super().__init__(shape, access="rw")
self.data = Signal(shape)
self.set = Signal(shape)
self._storage = Signal(shape, reset=reset)
self._reset = reset

@property
def reset(self):
return self._reset

def elaborate(self, platform):
m = Module()

for i, storage_bit in enumerate(self._storage):
with m.If(self.port.w_stb & self.port.w_data[i]):
m.d.sync += storage_bit.eq(0)
with m.If(self.set[i]):
m.d.sync += storage_bit.eq(1)

m.d.comb += [
self.port.r_data.eq(self._storage),
self.data.eq(self._storage),
]

return m


class RW1S(Field):
__doc__ = Field._doc_template.format(
description="""
A read/write-one-to-set field with built-in storage.
Storage bits are:
* set by high bits in ``port.w_data``, one clock cycle after ``port.w_stb`` is asserted;
* cleared by high bits in ``clear``, one clock cycle after they are asserted.
If a storage bit is set and cleared on the same clock cycle, setting it has precedence.
""".strip(),
parameters="""
reset : :class:`int`
Storage reset value.
""",
attributes="""
data : Signal(shape)
Storage output.
clear : Signal(shape)
Mask to clear storage bits.
""".strip())
def __init__(self, shape, *, reset=0):
super().__init__(shape, access="rw")
self.data = Signal(shape)
self.clear = Signal(shape)
self._storage = Signal(shape, reset=reset)
self._reset = reset

@property
def reset(self):
return self._reset

def elaborate(self, platform):
m = Module()

for i, storage_bit in enumerate(self._storage):
with m.If(self.clear[i]):
m.d.sync += storage_bit.eq(0)
with m.If(self.port.w_stb & self.port.w_data[i]):
m.d.sync += storage_bit.eq(1)

m.d.comb += [
self.port.r_data.eq(self._storage),
self.data.eq(self._storage),
]

return m
Loading

0 comments on commit 0181c95

Please sign in to comment.