examples: add an FSM usage example (UART receiver).
authorwhitequark <whitequark@whitequark.org>
Wed, 26 Dec 2018 10:10:27 +0000 (10:10 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 26 Dec 2018 10:10:27 +0000 (10:10 +0000)
examples/fsm.py [new file with mode: 0644]
nmigen/hdl/dsl.py

diff --git a/examples/fsm.py b/examples/fsm.py
new file mode 100644 (file)
index 0000000..2f7ed50
--- /dev/null
@@ -0,0 +1,60 @@
+from nmigen import *
+from nmigen.cli import main
+
+
+class UARTReceiver:
+    def __init__(self, divisor):
+        self.divisor = divisor
+
+        self.i    = Signal()
+        self.data = Signal(8)
+        self.rdy  = Signal()
+        self.ack  = Signal()
+        self.err  = Signal()
+
+    def get_fragment(self, platform):
+        m = Module()
+
+        ctr = Signal(max=self.divisor)
+        stb = Signal()
+        with m.If(ctr == 0):
+            m.d.sync += ctr.eq(self.divisor - 1)
+            m.d.comb += stb.eq(1)
+        with m.Else():
+            m.d.sync += ctr.eq(ctr - 1)
+
+        bit = Signal(3)
+        with m.FSM():
+            with m.State("START"):
+                with m.If(~self.i):
+                    m.next = "DATA"
+                    m.d.sync += [
+                        ctr.eq(self.divisor // 2),
+                        bit.eq(7),
+                    ]
+            with m.State("DATA"):
+                with m.If(stb):
+                    m.d.sync += [
+                        bit.eq(bit - 1),
+                        self.data.eq(Cat(self.i, self.data))
+                    ]
+                    with m.If(bit == 0):
+                        m.next = "STOP"
+            with m.State("STOP"):
+                with m.If(stb):
+                    with m.If(self.i):
+                        m.next = "DONE"
+                    with m.Else():
+                        m.next = "ERROR"
+            with m.State("DONE"):
+                m.d.comb += self.rdy.eq(1)
+                with m.If(self.ack):
+                    m.next = "START"
+            with m.State("ERROR"):
+                m.d.comb += self.err.eq(1)
+        return m.lower(platform)
+
+
+if __name__ == "__main__":
+    rx = UARTReceiver(20)
+    main(rx, ports=[rx.i, rx.data, rx.rdy, rx.ack, rx.err])
index 7a531a7eeb0505d20574cf58bf7cb5206729ff86..eec3f6ea55c9eef2afbc28923af5f6114d14efdc 100644 (file)
@@ -299,7 +299,7 @@ class Module(_ModuleBuilderRoot):
             fsm_signal.nbits = bits_for(len(fsm_encoding) - 1)
             # The FSM is encoded such that the state with encoding 0 is always the reset state.
             fsm_decoding = {n: s for s, n in fsm_encoding.items()}
-            fsm_signal.decoder = lambda v: "{}/{}".format(fsm_decoding[n], n)
+            fsm_signal.decoder = lambda n: "{}/{}".format(fsm_decoding[n], n)
             self._statements.append(Switch(fsm_signal,
                 OrderedDict((fsm_encoding[name], stmts) for name, stmts in fsm_states.items())))