examples: add an FSM usage example (UART receiver).
This commit is contained in:
parent
72039b6072
commit
597d778cf6
60
examples/fsm.py
Normal file
60
examples/fsm.py
Normal file
|
@ -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])
|
|
@ -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())))
|
||||
|
||||
|
|
Loading…
Reference in a new issue