resolve WBDownConvert ack issues when stall is active
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 15 Feb 2022 01:35:06 +0000 (01:35 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 15 Feb 2022 01:35:06 +0000 (01:35 +0000)
src/soc/bus/wb_downconvert.py

index c6f23a16750571c5d8f5cae5eb5b079f0241a399..27b6e3c2ed5cd7437af7cefad962278e676c4d00 100644 (file)
@@ -42,9 +42,7 @@ class WishboneDownConvert(Elaboratable):
 
         read = Signal()
         write = Signal()
-
-        cached_data = Signal(dw_from)
-        shift_reg = Signal(dw_from)
+        dat_r = Signal(dw_from)
 
         counter = Signal(log2_int(ratio, False))
         counter_reset = Signal()
@@ -61,8 +59,11 @@ class WishboneDownConvert(Elaboratable):
         with m.FSM() as fsm:
             with m.State("IDLE"):
                 comb += counter_reset.eq(1)
-                sync += cached_data.eq(0)
+                sync += dat_r.eq(0)
+                sync += master.ack.eq(0)
                 with m.If(master.stb & master.cyc):
+                    if hasattr(master, 'stall'):
+                        comb += master.stall.eq(1)
                     with m.If(master.we):
                         m.next = "WRITE"
                     with m.Else():
@@ -73,11 +74,19 @@ class WishboneDownConvert(Elaboratable):
                 comb += slave.we.eq(1)
                 comb += slave.cyc.eq(1)
                 with m.If(master.stb & master.cyc):
-                    comb += slave.stb.eq(1)
+                    if hasattr(master, 'stall'):
+                        comb += master.stall.eq(1)
+                    if hasattr(slave, 'stall'):
+                        with m.If(~slave.stall):
+                            comb += slave.stb.eq(1)
+                    else:
+                        comb += slave.stb.eq(1)
                     with m.If(slave.ack):
                         comb += counter_ce.eq(1)
                         with m.If(counter_done):
-                            comb += master.ack.eq(1)
+                            if hasattr(master, 'stall'):
+                                comb += master.stall.eq(0)
+                            sync += master.ack.eq(1)
                             m.next = "IDLE"
                 with m.Elif(~master.cyc):
                     m.next = "IDLE"
@@ -86,12 +95,19 @@ class WishboneDownConvert(Elaboratable):
                 comb += read.eq(1)
                 comb += slave.cyc.eq(1)
                 with m.If(master.stb & master.cyc):
-                    comb += slave.stb.eq(1)
+                    if hasattr(master, 'stall'):
+                        comb += master.stall.eq(1)
+                    if hasattr(slave, 'stall'):
+                        with m.If(~slave.stall):
+                            comb += slave.stb.eq(1)
+                    else:
+                        comb += slave.stb.eq(1)
                     with m.If(slave.ack):
                         comb += counter_ce.eq(1)
                         with m.If(counter_done):
-                            comb += master.ack.eq(1)
-                            comb += master.dat_r.eq(shift_reg)
+                            if hasattr(master, 'stall'):
+                                comb += master.stall.eq(0)
+                            sync += master.ack.eq(1)
                             m.next = "IDLE"
                 with m.Elif(~master.cyc):
                     m.next = "IDLE"
@@ -104,10 +120,6 @@ class WishboneDownConvert(Elaboratable):
                 comb += slave.cti.eq(2)
         comb += slave.adr.eq(Cat(counter, master.adr))
 
-        # stall
-        if hasattr(slave, 'stall'):
-            comb += master.stall.eq(slave.stall)
-
         # write Datapath - select fragments of data, depending on "counter"
         with m.Switch(counter):
             slen = slave.sel.width
@@ -120,9 +132,8 @@ class WishboneDownConvert(Elaboratable):
 
         # read Datapath - uses cached_data and master.dat_r as a shift-register.
         # by the time "counter" is done (counter_done) this is complete
-        comb += shift_reg.eq(Cat(cached_data[dw_to:], slave.dat_r))
-        with m.If(read & counter_ce):
-            sync += cached_data.eq(shift_reg)
-
+        comb += master.dat_r.eq(Cat(dat_r[dw_to:], slave.dat_r))
+        with m.If(read & slave.ack):
+            sync += dat_r.eq(master.dat_r)
 
         return m