"""Test pattern generator for digital capture emulation. Generates configurable test patterns to serve as fake sample data when no real probes are connected. Patterns include: - Free-running counter (default) - Square wave at configurable frequency - Walking ones/zeros """ from amaranth import * class TestPatternGenerator(Elaboratable): """Generates test pattern samples on each clock cycle. Parameters ---------- width : int Number of digital channels (default 8). Attributes ---------- sample : Signal(width), output Current sample value. valid : Signal(), output High when sample is valid (always high for test patterns). pattern : Signal(3), input Pattern select: 0=counter, 1=square, 2=walking1, 3=walking0. divider : Signal(16), input Clock divider for square/walking patterns (0 = every cycle). """ def __init__(self, width=8): self.width = width self.sample = Signal(width) self.valid = Signal(reset=1) self.pattern = Signal(3) self.divider = Signal(16) def elaborate(self, platform): m = Module() counter = Signal(self.width) div_counter = Signal(16) tick = Signal() # Divider logic with m.If(div_counter >= self.divider): m.d.sync += div_counter.eq(0) m.d.comb += tick.eq(1) with m.Else(): m.d.sync += div_counter.eq(div_counter + 1) with m.Switch(self.pattern): with m.Case(0): # Free-running counter m.d.sync += counter.eq(counter + 1) with m.Case(1): # Square wave with m.If(tick): m.d.sync += counter.eq(~counter) with m.Case(2): # Walking ones with m.If(tick): with m.If(counter == 0): m.d.sync += counter.eq(1) with m.Else(): m.d.sync += counter.eq(counter << 1) with m.Case(3): # Walking zeros (inverted walking ones) with m.If(tick): with m.If(counter == 0): m.d.sync += counter.eq(~C(1, self.width)) with m.Else(): m.d.sync += counter.eq(counter >> 1) with m.Default(): m.d.sync += counter.eq(counter + 1) m.d.comb += [ self.sample.eq(counter), self.valid.eq(1), ] return m