--- /dev/null
+#from nmigen import *
+from nmigen import Signal, Value, Elaboratable, Module, Cat, Const
+#from nmigen import ClockDomain, ClockSignal
+from nmigen.build import Platform
+#from nmigen.cli import main_parser, main_runner
+#from nmigen.asserts import Assert, Assume, Cover, Past
+
+# --- CONVERT ---
+from nmigen.back import verilog
+
+from nmigen.sim import Simulator, Delay, Settle, Tick, Passive
+
+from nmutil.gtkw import write_gtkw
+
+
+class UpCounter(Elaboratable):
+ """
+ A 16-bit up counter with a fixed limit.
+
+ Parameters
+ ----------
+ limit : int
+ The value at which the counter overflows.
+
+ Attributes
+ ----------
+ en : Signal, in
+ The counter is incremented if ``en`` is asserted, and retains
+ its value otherwise.
+ ovf : Signal, out
+ ``ovf`` is asserted when the counter reaches its limit.
+ """
+ def __init__(self, limit):
+ self.limit = limit
+
+ # Ports
+ self.en = Signal()
+ self.ovf = Signal()
+
+ # State
+ self.count = Signal(16)
+
+ def elaborate(self, platform):
+ m = Module()
+
+ m.d.comb += self.ovf.eq(self.count == self.limit)
+
+ with m.If(self.en):
+ with m.If(self.ovf):
+ m.d.sync += self.count.eq(0)
+ with m.Else():
+ m.d.sync += self.count.eq(self.count + 1)
+
+ return m
+# --- TEST ---
+from nmigen.sim import Simulator
+
+
+dut = UpCounter(25)
+def bench():
+ # Disabled counter should not overflow.
+ yield dut.en.eq(0)
+ for _ in range(30):
+ yield
+ assert not (yield dut.ovf)
+
+ # Once enabled, the counter should overflow in 25 cycles.
+ yield dut.en.eq(1)
+ for _ in range(25):
+ yield
+ assert not (yield dut.ovf)
+ yield
+ assert (yield dut.ovf)
+
+ # The overflow should clear in one cycle.
+ yield
+ assert not (yield dut.ovf)
+
+
+sim = Simulator(dut)
+sim.add_clock(1e-6) # 1 MHz
+sim.add_sync_process(bench)
+with sim.write_vcd("up_counter.vcd"):
+ sim.run()
+
+# GTKWave doc generation
+style = {
+ '': {'base': 'dec'},
+ 'in': {'color': 'orange'},
+ 'out': {'color': 'yellow'},
+ 'pad_i': {'color': 'orange'},
+ 'pad_o': {'color': 'yellow'},
+ 'core_i': {'color': 'indigo'},
+ 'core_o': {'color': 'blue'},
+ 'debug': {'module': 'top', 'color': 'red'}
+}
+traces = [
+ ('Counter', [
+ ('clk', 'in'),
+ ('en', 'in'),
+ ('ovf', 'in'),
+ ('rst', 'in'),
+ ('count[15:0]', 'out')
+ ])
+]
+
+write_gtkw("up_counter.gtkw", "up_counter.vcd", traces, style, module="bench.top")
+
+top = UpCounter(25)
+with open("up_counter.v", "w") as f:
+ f.write(verilog.convert(top, ports=[top.en, top.ovf]))