crc: modify CRCChecker to remove CRC and clean up
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 17 Dec 2014 08:22:08 +0000 (09:22 +0100)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sun, 21 Dec 2014 09:24:52 +0000 (17:24 +0800)
migen/actorlib/crc.py
migen/genlib/crc.py

index 2e42344be7367203f3e9753cdb44be17d5b3f797..25e696d4369fa77544fcb5273e5bde02be61328a 100644 (file)
@@ -4,6 +4,7 @@ from migen.genlib.record import *
 from migen.genlib.misc import chooser
 from migen.genlib.crc import *
 from migen.flow.actor import Sink, Source
+from migen.actorlib.fifo import SyncFIFO
 
 class CRCInserter(Module):
        """CRC Inserter
@@ -30,11 +31,12 @@ class CRCInserter(Module):
                ###
 
                dw = flen(sink.d)
-               self.submodules.crc = crc_class(dw)
-               self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+               crc = crc_class(dw)
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += crc, fsm
 
                fsm.act("IDLE",
-                       self.crc.reset.eq(1),
+                       crc.reset.eq(1),
                        sink.ack.eq(1),
                        If(sink.stb & sink.sop,
                                sink.ack.eq(0),
@@ -42,32 +44,40 @@ class CRCInserter(Module):
                        )
                )
                fsm.act("COPY",
-                       self.crc.ce.eq(sink.stb & source.ack),
-                       self.crc.d.eq(sink.d),
+                       crc.ce.eq(sink.stb & source.ack),
+                       crc.d.eq(sink.d),
                        Record.connect(sink, source),
                        source.eop.eq(0),
                        If(sink.stb & sink.eop & source.ack,
                                NextState("INSERT"),
                        )
                )
-               ratio = self.crc.width//dw
-               cnt = Signal(max=ratio, reset=ratio-1)
-               cnt_done = Signal()
-               fsm.act("INSERT",
-                       source.stb.eq(1),
-                       chooser(self.crc.value, cnt, source.d, reverse=True),
-                       If(cnt_done,
+               ratio = crc.width//dw
+               if ratio > 1:
+                       cnt = Signal(max=ratio, reset=ratio-1)
+                       cnt_done = Signal()
+                       fsm.act("INSERT",
+                               source.stb.eq(1),
+                               chooser(crc.value, cnt, source.d, reverse=True),
+                               If(cnt_done,
+                                       source.eop.eq(1),
+                                       If(source.ack, NextState("IDLE"))
+                               )
+                       )
+                       self.comb += cnt_done.eq(cnt == 0)
+                       self.sync += \
+                               If(fsm.ongoing("IDLE"),
+                                       cnt.eq(cnt.reset)
+                               ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
+                                       cnt.eq(cnt - source.ack)
+                               )
+               else:
+                       fsm.act("INSERT",
+                               source.stb.eq(1),
                                source.eop.eq(1),
+                               source.d.eq(crc.value),
                                If(source.ack, NextState("IDLE"))
                        )
-               )
-               self.comb += cnt_done.eq(cnt == 0)
-               self.sync += \
-                       If(fsm.ongoing("IDLE"),
-                               cnt.eq(cnt.reset)
-                       ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
-                               cnt.eq(cnt - source.ack)
-                       )
                self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
 
 class CRC32Inserter(CRCInserter):
@@ -89,7 +99,7 @@ class CRCChecker(Module):
        sink : in
                Packets input with CRC.
        source : out
-               Packets output with CRC and "error" set to 0
+               Packets output without CRC and "error" set to 0
                on eop when CRC OK / set to 1 when CRC KO.
        """
        def __init__(self, crc_class, layout):
@@ -100,32 +110,58 @@ class CRCChecker(Module):
                ###
 
                dw = flen(sink.d)
-               self.submodules.crc = crc_class(dw)
+               crc = crc_class(dw)
+               self.submodules += crc
+               ratio = crc.width//dw
 
-               fsm = FSM(reset_state="RESET_CRC")
+               error = Signal()
+               fifo = InsertReset(SyncFIFO(layout, ratio + 1))
+               self.submodules += fifo
+
+               fsm = FSM(reset_state="RESET")
                self.submodules += fsm
 
-               fsm.act("RESET_CRC",
-                       sink.ack.eq(0),
-                       self.crc.reset.eq(1),
-                       NextState("IDLE")
+               fifo_in = Signal()
+               fifo_out = Signal()
+               fifo_full = Signal()
+
+               self.comb += [
+                       fifo_full.eq(fifo.fifo.level == ratio),
+                       fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
+                       fifo_out.eq(source.stb & source.ack),
+
+                       Record.connect(sink, fifo.sink),
+                       fifo.sink.stb.eq(fifo_in),
+                       self.sink.ack.eq(fifo_in),
+
+                       source.stb.eq(sink.stb & fifo_full),
+                       source.sop.eq(fifo.source.sop),
+                       source.eop.eq(sink.eop),
+                       fifo.source.ack.eq(fifo_out),
+                       source.payload.eq(fifo.source.payload),
+
+                       source.error.eq(sink.error | crc.error),
+               ]
+
+               fsm.act("RESET",
+                       crc.reset.eq(1),
+                       fifo.reset.eq(1),
+                       NextState("IDLE"),
                )
                fsm.act("IDLE",
-                       sink.ack.eq(sink.stb),
-                       If(sink.stb & sink.sop,
-                               Record.connect(sink, source),
-                               self.crc.ce.eq(sink.ack),
-                               self.crc.d.eq(sink.d),
+                       crc.d.eq(sink.d),
+                       If(sink.stb & sink.sop & sink.ack,
+                               crc.ce.eq(1),
                                NextState("COPY")
                        )
                )
                fsm.act("COPY",
-                       Record.connect(sink, source),
-                       self.crc.ce.eq(sink.stb & sink.ack),
-                       self.crc.d.eq(sink.d),
-                       source.error.eq(sink.eop & self.crc.error),
-                       If(sink.stb & sink.ack & sink.eop,
-                               NextState("RESET_CRC")
+                       crc.d.eq(sink.d),
+                       If(sink.stb & sink.ack,
+                               crc.ce.eq(1),
+                               If(sink.eop,
+                                       NextState("RESET")
+                               )
                        )
                )
                self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
index e0a6672c0e93b068cb64162d1a7a6ff5596bfb0c..51a9ab1088bebcc4dd861e2f9d9a1a873a23e158 100644 (file)
@@ -53,11 +53,11 @@ class CRCEngine(Module):
                curval = [[("state", i)] for i in range(width)]
                for i in range(dat_width):
                        feedback = curval.pop() + [("din", i)]
-                       curval.insert(0, feedback)
-                       for j in range(1, width-1):
-                               if (polynom&(1<<j)):
+                       for j in range(width-1):
+                               if (polynom & (1<<(j+1))):
                                        curval[j] += feedback
                                curval[j] = _optimize_eq(curval[j])
+                       curval.insert(0, feedback)
 
                # implement logic
                for i in range(width):
@@ -92,6 +92,7 @@ class CRC32(Module):
        """
        width = 32
        polynom = 0x04C11DB7
+       init = 2**width-1
        check = 0xC704DD7B
        def __init__(self, dat_width):
                self.d = Signal(dat_width)
@@ -101,7 +102,7 @@ class CRC32(Module):
                ###
 
                self.submodules.engine = CRCEngine(dat_width, self.width, self.polynom)
-               reg = Signal(self.width, reset=2**self.width-1)
+               reg = Signal(self.width, reset=self.init)
                self.sync += reg.eq(self.engine.next)
                self.comb += [
                        self.engine.d.eq(self.d),