From 88426ac89ab904aa50834bf17239ca90278d9d6e Mon Sep 17 00:00:00 2001 From: saji Date: Mon, 30 Sep 2024 10:20:17 -0500 Subject: [PATCH] cleanup tests, make data address combinational --- src/groovylight/hub75.py | 11 +-- src/groovylight/tests/test_hub75.py | 101 +++++++++++++++++++++------- 2 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/groovylight/hub75.py b/src/groovylight/hub75.py index a0278a5..43ac515 100644 --- a/src/groovylight/hub75.py +++ b/src/groovylight/hub75.py @@ -99,7 +99,7 @@ class DisplayClock(wiring.Component): { "start": In(1), "done": In(1), - "clk": Out(1), + "display_clk": Out(1), }, src_loc_at=src_loc_at, ) @@ -111,7 +111,8 @@ class DisplayClock(wiring.Component): with m.FSM(): with m.State("init"): - m.d.sync += [counter.eq(0), self.clk.eq(0)] + m.d.sync += [counter.eq(0)] + m.d.comb += self.display_clk.eq(0) with m.If(self.start == 1): m.next = "warmup" with m.State("warmup"): @@ -124,13 +125,13 @@ class DisplayClock(wiring.Component): with m.If(self.done == 1): m.next = "init" if self.double_fetch: + m.d.comb += self.display_clk.eq(~counter[1]) m.d.sync += [ - self.clk.eq(~counter[1]), counter.eq(counter + 1), ] else: + m.d.comb += (self.display_clk.eq(counter),) m.d.sync += [ - self.clk.eq(~counter), counter.eq(~counter), ] @@ -233,10 +234,10 @@ class Hub75DataDriver(wiring.Component): m.d.sync += [ self.data.rgb0.eq(ram_rgb_slice[0]), self.data.rgb1.eq(ram_rgb_slice[1]), + pixnum.eq(pixnum - 1), ] with m.If(counter[0] == 1): m.d.sync += [ - pixnum.eq(pixnum - 1), counter.eq(0), ] with m.If(pixnum == 0): diff --git a/src/groovylight/tests/test_hub75.py b/src/groovylight/tests/test_hub75.py index 3601330..ba2ca35 100644 --- a/src/groovylight/tests/test_hub75.py +++ b/src/groovylight/tests/test_hub75.py @@ -2,6 +2,8 @@ from amaranth import Module from amaranth.lib import wiring, data from amaranth.lib.memory import Memory from amaranth.sim import Simulator +import random +from random import randrange import pytest from groovylight.common import Rgb888Layout, Rgb666Layout @@ -13,6 +15,7 @@ from groovylight.hub75 import ( SwapBuffer, ) +random.seed() def test_swapbuffer(): dut = SwapBuffer(Rgb666Layout, 512) @@ -42,12 +45,29 @@ def test_swapbuffer(): sim.run_until(1e-6 * 1000) -def test_datadriver(): - # the string driver test must - # 1. finish - # 2. strobe through all of the data in the array - # 3. slice the correct bit from the data. - memdata = [{"red": x, "green": x, "blue": x} for x in range(256)] +def randcolor(nbits=8): + + return { + "red": randrange(2**nbits), + "green": randrange(2**nbits), + "blue": randrange(2**nbits), + } + + +def make_start(dut, bcm): + async def testbench(ctx): + # select a bit, strobe start, read values, test against known. + ctx.set(dut.bcm_select, bcm) + ctx.set(dut.start, 1) + await ctx.tick() + ctx.set(dut.start, 0) + assert ctx.get(dut.bram.en) == 1 + await ctx.tick().until(dut.done == 1) + return testbench + +@pytest.mark.parametrize("bcm", range(8)) +def test_datadriver(bcm): + memdata = [randcolor() for x in range(256)] m = Module() m.submodules.dut = dut = Hub75DataDriver() m.submodules.mem = mem = Memory(shape=Rgb888Layout, depth=256, init=memdata) @@ -57,35 +77,69 @@ def test_datadriver(): clocker.done.eq(dut.done), ] - port = mem.read_port() + wiring.connect(m, mem.read_port(), dut.bram) - wiring.connect(m, port, dut.bram) - - async def testbench(ctx): - # select a bit, strobe start, read values, test against known. - ctx.set(dut.bcm_select, 7) - ctx.set(dut.start, 1) - await ctx.tick() - ctx.set(dut.start, 0) - assert ctx.get(dut.bram.en) == 1 - await ctx.tick().until(dut.done == 1) + testbench = make_start(dut, bcm) async def rgbtest(ctx): await ctx.tick().until(dut.start == 1) counter = 127 - bitslice = 7 - async for _, rgb0, rgb1 in ctx.posedge(clocker.clk).sample(dut.data.rgb0, dut.data.rgb1): + async for _, rgb0, rgb1 in ctx.posedge(clocker.display_clk).sample( + dut.data.rgb0, dut.data.rgb1 + ): assert counter >= 0, "should not do more than 128 clocks" e0 = ctx.get(mem.data[counter << 1]) e1 = ctx.get(mem.data[(counter << 1) + 1]) print(counter) for r, e in [(rgb0, e0), (rgb1, e1)]: - assert r.red == (e.red >> bitslice) & 1 - assert r.green == (e.green >> bitslice) & 1 - assert r.blue == (e.blue >> bitslice) & 1 + assert r.red == (e.red >> bcm) & 1 + assert r.green == (e.green >> bcm) & 1 + assert r.blue == (e.blue >> bcm) & 1 + counter = counter - 1 + + sim = Simulator(m) + sim.add_clock(1e-6) + sim.add_testbench(testbench) + sim.add_testbench(rgbtest, background=True) + + with sim.write_vcd("output.vcd"): + sim.run() + + +@pytest.mark.parametrize("bcm", range(6)) +def test_datadriver_single(bcm): + memdata = [[randcolor(6), randcolor(6)] for x in range(128)] + m = Module() + m.submodules.dut = dut = Hub75DataDriver( + data_shape=Rgb666Layout, double_fetch=False + ) + mshape = data.ArrayLayout(Rgb666Layout, 2) + m.submodules.mem = mem = Memory(shape=mshape, depth=128, init=memdata) + m.submodules.clocker = clocker = DisplayClock(double_fetch = False) + m.d.comb += [ + clocker.start.eq(dut.start), + clocker.done.eq(dut.done), + ] + + wiring.connect(m, mem.read_port(), dut.bram) + + testbench = make_start(dut, bcm) + + async def rgbtest(ctx): + await ctx.tick().repeat(2) + counter = 127 + async for _, rgb0, rgb1 in ctx.posedge(clocker.display_clk).sample( + dut.data.rgb0, dut.data.rgb1 + ): + assert counter >= 0, "should not do more than 128 clocks" + e0, e1 = ctx.get(mem.data[counter]) + print(counter) + for r, e in [(rgb0, e0), (rgb1, e1)]: + assert r.red == (e.red >> bcm) & 1 + assert r.green == (e.green >> bcm) & 1 + assert r.blue == (e.blue >> bcm) & 1 counter = counter - 1 - sim = Simulator(m) sim.add_clock(1e-6) sim.add_testbench(testbench) @@ -93,7 +147,6 @@ def test_datadriver(): with sim.write_vcd("output.vcd"): sim.run() - # sim.run_until(1e-6 * 4000) @pytest.mark.skip()