Skip to content
{{ message }}

# amaranth-lang / amaranth Public

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
opened this issue Aug 27, 2020 · 4 comments
Closed

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

opened this issue Aug 27, 2020 · 4 comments
Labels

## Comments

### BrettRD commented Aug 27, 2020

 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() `````` The text was updated successfully, but these errors were encountered:

### whitequark commented Aug 29, 2020 • edited

 What is the work around for a decrement to underflow around an arbitrary bounds? Assuming you are interested in a counter that increments or decrements by 1 each cycle, something like this would give you arbitrary overflow bounds: ```class BoundedCounter(Elaboratable): def __init__(self, min, max): self.min = min self.max = max self.up = Signal(1) self.count = Signal(range(min, max + 1)) def elaborate(self, platform): m = Module() with m.If(self.up): with m.If(self.count == max): m.d.sync += self.count.eq(min) with m.Else(): m.d.sync += self.count.eq(self.count + 1) with m.Else(): with m.If(self.count == min): m.d.sync += self.count.eq(max) with m.Else(): m.d.sync += self.count.eq(self.count - 1) return m```

### whitequark commented Sep 4, 2020

 Does this answer your question?

### DaKnig commented Sep 4, 2020

 I'd suggest to avoid the % and / operators in hardware design (when you divide by a number that is not a power of 2). division is slow and expensive in hardware, it would take more than one clock at a rate users usually want to work, that is why usually backends don't implement that in synthesizable code regardless of what language you would use.

### BrettRD commented Sep 4, 2020

 This answers my question, Thanks.

closed this Sep 4, 2020
to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants