From 92f5a9f0e6599c21b9107246f6e6283ed7f69f3f Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 12 Dec 2021 15:18:24 +0100 Subject: [PATCH] soc/cores/led/WS2812: Add Bus Mastering capability. Useful on small FPGAs to reduce resource usage: When enabling bus mastering, the core is able to automatically read led values from the bus and can then avoid the internal memory. This is particularly useful when reading values from SPI Flash with a small "Player" core just updating the base address. --- litex/soc/cores/led.py | 68 ++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/litex/soc/cores/led.py b/litex/soc/cores/led.py index c9a1f6024..05eaf3427 100644 --- a/litex/soc/cores/led.py +++ b/litex/soc/cores/led.py @@ -117,19 +117,23 @@ class WS2812(Module): sys_clk_freq: int, in System Clk Frequency. """ - def __init__(self, pad, nleds, sys_clk_freq): - # Memory. - mem = Memory(32, nleds) - port = mem.get_port() - self.specials += mem, port + def __init__(self, pad, nleds, sys_clk_freq, bus_mastering=False, bus_base=None): + if bus_mastering: + self.bus = bus = wishbone.Interface(data_width=32) + else: + # Memory. + mem = Memory(32, nleds) + port = mem.get_port() + self.specials += mem, port + + # Wishone Memory. + self.submodules.wb_mem = wishbone.SRAM( + mem_or_size = mem, + read_only = False, + bus = wishbone.Interface(data_width=32) + ) + self.bus = self.wb_mem.bus - # Wishone Memory. - self.submodules.wb_mem = wishbone.SRAM( - mem_or_size = mem, - read_only = False, - bus = wishbone.Interface(data_width=32) - ) - self.bus = self.wb_mem.bus # Internal Signals. led_data = Signal(24) @@ -164,17 +168,37 @@ class WS2812(Module): NextState("LED-SHIFT") ) ) - self.comb += port.adr.eq(led_count) - fsm.act("LED-SHIFT", - NextValue(bit_count, 24-1), - NextValue(led_data, port.dat_r), - NextValue(led_count, led_count + 1), - If(led_count == (nleds-1), - NextState("RST") - ).Else( - NextState("BIT-TEST") + if bus_mastering: + fsm.act("LED-SHIFT", + bus.stb.eq(1), + bus.cyc.eq(1), + bus.we.eq(0), + bus.sel.eq(2**(bus.data_width//8)-1), + bus.adr.eq(bus_base[2:] + led_count), + If(bus.ack, + NextValue(bit_count, 24-1), + NextValue(led_data, bus.dat_r), + NextValue(led_count, led_count + 1), + If(led_count == (nleds-1), + NextState("RST") + ).Else( + NextState("BIT-TEST") + ) + ) ) - ) + else: + self.comb += port.adr.eq(led_count) + fsm.act("LED-SHIFT", + NextValue(bit_count, 24-1), + NextValue(led_data, port.dat_r), + NextValue(led_count, led_count + 1), + If(led_count == (nleds-1), + NextState("RST") + ).Else( + NextState("BIT-TEST") + ) + ) + fsm.act("BIT-TEST", If(led_data[-1] == 0, NextState("ZERO-SEND"),