From 472beee1b20ada92578e31b446b4d81c2d88a07c Mon Sep 17 00:00:00 2001 From: Andrey Miroshnikov Date: Sun, 24 Sep 2023 13:08:11 +0000 Subject: [PATCH] Adding README and counter example. --- README.md | 13 +++++ up_counter/up_counter.py | 111 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 README.md create mode 100644 up_counter/up_counter.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6491cf --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# nMigen Examples (To be used with Libre-SOC flow) + +See the Libre-SOC nMigen [tutorial page](https://libre-soc.org/docs/learning_nmigen/) + +## Counter example + +Example modified from [original in nMigen repo](https://gitlab.com/nmigen/nmigen/blob/master/docs/start.rst). + +Includes gtkw nmutils lib for generating the .gtkw trace file. + +To run: + + python3 up_counter.py diff --git a/up_counter/up_counter.py b/up_counter/up_counter.py new file mode 100644 index 0000000..110a5fd --- /dev/null +++ b/up_counter/up_counter.py @@ -0,0 +1,111 @@ +#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])) -- 2.30.2