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.
This commit is contained in:
Florent Kermarrec 2021-12-12 15:18:24 +01:00
parent 649c45e962
commit 92f5a9f0e6

View file

@ -117,7 +117,10 @@ class WS2812(Module):
sys_clk_freq: int, in sys_clk_freq: int, in
System Clk Frequency. System Clk Frequency.
""" """
def __init__(self, pad, nleds, sys_clk_freq): 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. # Memory.
mem = Memory(32, nleds) mem = Memory(32, nleds)
port = mem.get_port() port = mem.get_port()
@ -131,6 +134,7 @@ class WS2812(Module):
) )
self.bus = self.wb_mem.bus self.bus = self.wb_mem.bus
# Internal Signals. # Internal Signals.
led_data = Signal(24) led_data = Signal(24)
bit_count = Signal(8) bit_count = Signal(8)
@ -164,6 +168,25 @@ class WS2812(Module):
NextState("LED-SHIFT") NextState("LED-SHIFT")
) )
) )
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) self.comb += port.adr.eq(led_count)
fsm.act("LED-SHIFT", fsm.act("LED-SHIFT",
NextValue(bit_count, 24-1), NextValue(bit_count, 24-1),
@ -175,6 +198,7 @@ class WS2812(Module):
NextState("BIT-TEST") NextState("BIT-TEST")
) )
) )
fsm.act("BIT-TEST", fsm.act("BIT-TEST",
If(led_data[-1] == 0, If(led_data[-1] == 0,
NextState("ZERO-SEND"), NextState("ZERO-SEND"),