Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 72039b607283
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 597d778cf6cb
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Dec 26, 2018

  1. examples: add an FSM usage example (UART receiver).

    whitequark committed Dec 26, 2018
    Copy the full SHA
    597d778 View commit details
Showing with 61 additions and 1 deletion.
  1. +60 −0 examples/fsm.py
  2. +1 −1 nmigen/hdl/dsl.py
60 changes: 60 additions & 0 deletions examples/fsm.py
Original file line number Diff line number Diff line change
@@ -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])
2 changes: 1 addition & 1 deletion nmigen/hdl/dsl.py
Original file line number Diff line number Diff line change
@@ -299,7 +299,7 @@ def _pop_ctrl(self):
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())))