from amaranth import * from amaranth.lib import wiring from amaranth.lib.wiring import In, Out class UpCounter(wiring.Component): """ 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. """ en: In(1) ovf: Out(1) def __init__(self, limit): self.limit = limit self.count = Signal(16) super().__init__() 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 amaranth.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() # --- CONVERT --- from amaranth.back import verilog top = UpCounter(25) with open("up_counter.v", "w") as f: f.write(verilog.convert(top))