from amaranth.build import Platform
from amaranth import *

class Debouncer(Elaboratable):

    def __init__(self, cycles: int):
        #signals
        self.i = Signal()
        self.o = Signal()

        #state
        self.count = Signal(range(0, cycles+1), reset=cycles)
        self.state = Signal()
        self.prevInValid = Signal()
        self.prevIn = Signal()

    def elaborate(self, platform: Platform):
        m = Module()

        with m.If(self.prevInValid):
            with m.If(self.count == 0):
                with m.If(self.prevIn ^ self.i):
                    m.d.sync += self.count.eq(self.count.reset)
                m.d.sync += self.state.eq(self.i)
            with m.Elif(self.i == self.state):
                m.d.sync += self.count.eq(self.count.reset)
                m.d.sync += self.state.eq(self.i)
            with m.Else():
                m.d.sync += self.count.eq(self.count - 1)        
        with m.Else():
            m.d.sync += self.count.eq(0)
            m.d.sync += self.prevInValid.eq(Const(1))
            m.d.sync += self.state.eq(self.i)

        m.d.sync += self.prevIn.eq(self.i)
        m.d.comb += self.o.eq(self.state)

        return m