csr: add we signal to CSR, CSRStatus
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 24 Sep 2019 15:51:06 +0000 (17:51 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 24 Sep 2019 15:51:06 +0000 (17:51 +0200)
Doing actions on register read is generally not a good design practice (it's
better to do separate register write to trigger actions) but in some very
specific cases being able to know that register has been read can solve cases
that are difficult to do with the recommended practives and that can justify
doing an exception.

This commit add a we signal to CSR, CSRStatus and this allow the logic to know
when the CSR, CSRStatus is read.

litex/soc/interconnect/csr.py
litex/soc/interconnect/csr_bus.py

index 228290fa6f0fb0087e409ad9a457086dfd177300..a7defd0afbceab3b14bd73b2f42a580e68571de8 100644 (file)
@@ -94,17 +94,26 @@ class CSR(_CSRBase):
     w : Signal(size), in
         The value to be read from the bus.
         Must be provided at all times.
+
+    we : Signal(), out
+        The strobe signal for ``w``.
+        It is active for one cycle, after or during a read from the bus.
     """
 
     def __init__(self, size=1, name=None):
         _CSRBase.__init__(self, size, name)
         self.re = Signal(name=self.name + "_re")
-        self.r = Signal(self.size, name=self.name + "_r")
-        self.w = Signal(self.size, name=self.name + "_w")
+        self.r  = Signal(self.size, name=self.name + "_r")
+        self.we = Signal(name=self.name + "_we")
+        self.w  = Signal(self.size, name=self.name + "_w")
 
     def read(self):
         """Read method for simulation."""
-        return (yield self.w)
+        yield self.we.eq(1)
+        value = (yield self.w)
+        yield
+        yield self.we.eq(0)
+        return value
 
     def write(self, value):
         """Write method for simulation."""
@@ -282,6 +291,7 @@ class CSRStatus(_CompoundCSR):
         _CompoundCSR.__init__(self, size, name)
         self.description = description
         self.status = Signal(self.size, reset=reset)
+        self.we = Signal()
         for field in fields:
             self.comb += self.status[field.offset:field.offset + field.size].eq(getattr(self.fields, field.name))
 
@@ -292,10 +302,15 @@ class CSRStatus(_CompoundCSR):
             sc = CSR(nbits, self.name + str(i) if nwords > 1 else self.name)
             self.comb += sc.w.eq(self.status[i*busword:i*busword+nbits])
             self.simple_csrs.append(sc)
+        self.comb += self.we.eq(sc.we)
 
     def read(self):
         """Read method for simulation."""
-        return (yield self.status)
+        yield self.we.eq(1)
+        value = (yield self.status)
+        yield
+        yield self.we.eq(0)
+        return value
 
 # CSRStorage ---------------------------------------------------------------------------------------
 
index 038cdd596ef82b5fec71195f972b68d36fb977da..dac45972bd454955d35bc5b32ad37dcff27adf3f 100644 (file)
@@ -171,7 +171,10 @@ class CSRBank(csr.GenericBank):
                 c.r.eq(self.bus.dat_w[:c.size]),
                 c.re.eq(sel & \
                     self.bus.we & \
-                    (self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i))
+                    (self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i)),
+                c.we.eq(sel & \
+                    ~self.bus.we & \
+                    (self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i)),
             ]
 
         brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs))