Skip to content

How do you make a bounded up-down counter without modulo? #492

@BrettRD

Description

@BrettRD

Modulo operators for negative numbers are a known issue, and the operator is not implemented on stable.
What is the work around for a decrement to underflow around an arbitrary bounds?

This test shows the modulo producing strange results on decrement that disappear if you force the range into positive.

from nmigen import *
from nmigen.back.pysim import Simulator

class counter_thing(Elaboratable):
    def __init__(self, max_count, rst):
        self.dir = Signal(1)
        self.mod_pos = Signal(range(max_count), reset=rst)
        self.mod_neg = Signal(range(max_count), reset=rst)
    def elaborate(self, platform):
        m = Module()
        m.d.sync += self.mod_pos.eq((self.mod_pos + max_count - 1) % max_count)
        m.d.sync += self.mod_neg.eq((self.mod_neg - 1) % max_count)
        return m

def test():
    count = rst
    for _ in range(2*max_count):
        yield
        count = (count - 1) % max_count
        print(str((yield dut.mod_pos)) + ', ' + str((yield dut.mod_neg)) + ', ' + str(count))
        assert (yield dut.mod_pos) == count # passes
        assert (yield dut.mod_pos) == (yield dut.mod_neg) # fails after underflow

if __name__ == "__main__":
    max_count = 17
    rst = 13
    dut = counter_thing(max_count, rst)
    sim = Simulator(dut)
    sim.add_clock(1)
    sim.add_sync_process(test) # or sim.add_sync_process(process), see below
    sim.run()

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions