diff --git a/.gitignore b/.gitignore index 3bd993c..a61aa27 100644 --- a/.gitignore +++ b/.gitignore @@ -198,6 +198,7 @@ dmypy.json # Cython debug symbols cython_debug/ +.ruff_cache # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore diff --git a/groovylight/hub75.py b/groovylight/hub75.py deleted file mode 100644 index 0bd7eed..0000000 --- a/groovylight/hub75.py +++ /dev/null @@ -1,114 +0,0 @@ - - -# r0 g0 b0 gnd r1 g1 b1 e a b c d clk stb oe gnd -from litex.build.generic_platform import Signal, Subsignal, Pins -from litex.build.io import FSM, Module, Cat, Replicate -from litex.gen import ClockSignal, If, Instance, NextState, NextValue - -def make_hub75_iodevice(index, basename): - b = basename - signals = ("hub75_iodev", index, - Subsignal("r0", Pins(f"{b}:0")), - Subsignal("g0", Pins(f"{b}:1")), - Subsignal("b0", Pins(f"{b}:2")), - Subsignal("r1", Pins(f"{b}:4")), - Subsignal("g1", Pins(f"{b}:5")), - Subsignal("b1", Pins(f"{b}:6")), - Subsignal("addr", Pins(f"{b}:8 {b}:9 {b}:10 {b}:11 {b}:7")), - Subsignal("clk", Pins(f"{b}:12")), - Subsignal("stb", Pins(f"{b}:13")), - Subsignal("oe", Pins(f"{b}:14")), - ) - return [signals] - - - -class Hub75Driver(Module): - def __init__(self, base_freq=60e6, linedepth=128): - if base_freq // 2 > 30e6: - raise RuntimeError("hi") - - self.addr = Signal(5) - self.latch = Signal() - self.output_en = Signal() - color = Signal(24, reset=0xA0FF00) - self.rgb = Signal(6) - - self.clock_out = Signal() - - self.fsm = fsm = FSM() - self.submodules += self.fsm - bcm_value = Signal(3) - - counter = Signal(32) - - should_expose = (counter < (16 << bcm_value)) & (bcm_value != 0) - - - # this state both sets the OE low to drive the display with the previous frame - # while also loading the next row - # FIXME: there's a bug on the starting conditions right now, we are losing the lowest bit. - fsm.act("WRITEROW", - self.output_en.eq(~should_expose), - self.rgb[0].eq((color >> bcm_value) & 1), - self.rgb[3].eq((color >> bcm_value) & 1), - self.rgb[1].eq((color >> (bcm_value + 8)) & 1), - self.rgb[4].eq((color >> (bcm_value + 8)) & 1), - self.rgb[2].eq((color >> (bcm_value + 16)) & 1), - self.rgb[5].eq((color >> (bcm_value + 16)) & 1), - - NextValue(counter, counter + 1), - If(counter < linedepth * 2, - self.clock_out.eq(counter[0]), - ), - If(~(counter < linedepth * 2) & ~should_expose, - NextValue(counter, 0), - NextState("LATCH"), - ), - ) - - fsm.act("EXPOSE", - self.output_en.eq(0), - If(counter < (16 << bcm_value), - NextValue(counter, counter + 1), - ).Else( - NextValue(counter, 0), - NextState("LATCH"), - ), - ) - - fsm.act("LATCH", - self.latch.eq(1), - self.output_en.eq(1), - NextValue(counter, 0), - If(bcm_value == 7, - NextValue(bcm_value, 0), - NextValue(self.addr, self.addr + 1), - ).Else( - NextValue(bcm_value, bcm_value + 1), - ), - - NextState("WRITEROW"), - ) - - -class Hub75VerilogDriver(Module): - def __init__(self): - - self.o_addr = Signal(5) - self.o_display_clk = Signal() - self.o_latch = Signal() - self.o_out_enable = Signal() - self.o_panel_rgb0 = Signal(3) - self.o_panel_rgb1 = Signal(3) - - inst = Instance("coordinator", - i_clk = ClockSignal(), - o_panel_rgb0 = self.o_panel_rgb0, - o_panel_rgb1 = self.o_panel_rgb1, - o_latch = self.o_latch, - o_display_clk = self.o_display_clk, - o_out_enable = self.o_out_enable, - o_display_addr = self.o_addr, - ) - self.specials += inst diff --git a/groovylight/platform/colorlight_5a_75b_8_0.py b/groovylight/platform/colorlight_5a_75b_8_0.py deleted file mode 100644 index 7eb12f4..0000000 --- a/groovylight/platform/colorlight_5a_75b_8_0.py +++ /dev/null @@ -1,141 +0,0 @@ -# Board definition file for the Colorlight 5A-75B. -# Mostly copied from the litex-boards repo, but we didn't pull that in -from litex.build.generic_platform import Pins, IOStandard, Subsignal, Misc -from litex.build.lattice import LatticeECP5Platform -from litex.build.openfpgaloader import OpenFPGALoader -from litex.gen import LiteXModule, ClockDomain, ClockSignal -from litex.build.io import DDROutput -from litex.soc.cores.clock import ECP5PLL - -_io = [ - # Clk - ("clk25", 0, Pins("P6"), IOStandard("LVCMOS33")), - - # Led - ("user_led_n", 0, Pins("T6"), IOStandard("LVCMOS33")), - - # Button - ("user_btn_n", 0, Pins("R7"), IOStandard("LVCMOS33")), - - # serial - ("serial", 0, - Subsignal("tx", Pins("T6")), # led (J19 DATA_LED-) - Subsignal("rx", Pins("R7")), # btn (J19 KEY+) - IOStandard("LVCMOS33") - ), - # SDR SDRAM (M12L64322A) - ("sdram_clock", 0, Pins("C8"), IOStandard("LVCMOS33")), - ("sdram", 0, - Subsignal("a", Pins( - "A9 B9 B10 C10 D9 C9 E9 D8", - "E8 C7 B8")), - Subsignal("dq", Pins( - "B2 A2 C3 A3 B3 A4 B4 A5", - "E7 C6 D7 D6 E6 D5 C5 E5", - "A11 B11 B12 A13 B13 A14 B14 D14", - "D13 E11 C13 D11 C12 E10 C11 D10")), - Subsignal("we_n", Pins("B5")), - Subsignal("ras_n", Pins("B6")), - Subsignal("cas_n", Pins("A6")), - #Subsignal("cs_n", Pins("")), # gnd - #Subsignal("cke", Pins("")), # 3v3 - Subsignal("ba", Pins("B7 A8")), - #Subsignal("dm", Pins("")), # gnd - IOStandard("LVCMOS33"), - Misc("SLEWRATE=FAST") - ), - # RGMII Ethernet (RTL8211FD) - ("eth_clocks", 0, - Subsignal("tx", Pins("L1")), - Subsignal("rx", Pins("J1")), - IOStandard("LVCMOS33") - ), - ("eth", 0, - #Subsignal("rst_n", Pins("R6")), - Subsignal("mdio", Pins("T4")), - Subsignal("mdc", Pins("R5")), - Subsignal("rx_ctl", Pins("J2")), - Subsignal("rx_data", Pins("K2 J3 K1 K3")), - Subsignal("tx_ctl", Pins("L2")), - Subsignal("tx_data", Pins("M2 M1 P1 R1")), - IOStandard("LVCMOS33") - ), - ("eth_clocks", 1, - Subsignal("tx", Pins("J16")), - Subsignal("rx", Pins("M16")), - IOStandard("LVCMOS33") - ), - ("eth", 1, - #Subsignal("rst_n", Pins("R6")), - Subsignal("mdio", Pins("T4")), - Subsignal("mdc", Pins("R5")), - Subsignal("rx_ctl", Pins("P16")), - Subsignal("rx_data", Pins("M15 R16 L15 L16")), - Subsignal("tx_ctl", Pins("K14")), - Subsignal("tx_data", Pins("K16 J15 J14 K15")), - IOStandard("LVCMOS33") - ), -] - - -_connectors = [ - ("j1", "C4 D4 E4 - D3 F5 E3 N4 N5 N3 P3 P4 M3 N1 M4 -"), - ("j2", "F1 F2 G2 - G1 H2 H3 N4 N5 N3 P3 P4 M3 N1 M4 -"), - ("j3", "B1 C2 C1 - D1 E2 E1 N4 N5 N3 P3 P4 M3 N1 M4 -"), - ("j4", "P5 R3 P2 - R2 T2 N6 N4 N5 N3 P3 P4 M3 N1 M4 -"), - ("j5", "T13 R12 R13 - R14 T14 P12 N4 N5 N3 P3 P4 M3 N1 M4 -"), - ("j6", "R15 T15 P13 - P14 N14 H15 N4 N5 N3 P3 P4 M3 N1 M4 -"), - ("j7", "G16 H14 G15 - F15 F16 E16 N4 N5 N3 P3 P4 M3 N1 M4 -"), - ("j8", "D16 E15 C16 - B16 C15 B15 N4 N5 N3 P3 P4 M3 N1 M4 -"), -] - - -class _CRG(LiteXModule): - def __init__(self, platform, sys_clk_freq, with_reset = False): - self.cd_sys = ClockDomain("sys") - # self.cd_hub = ClockDomain("hub") - self.cd_sys_ps = ClockDomain("sys_ps") - # self.cd_sys2x = ClockDomain() - # self.cd_sys2x_ps = ClockDomain() - - # Clk / Rst. - clk25 = platform.request("clk25") - - - # PLL. - self.pll = pll = ECP5PLL() - - rst_n = platform.request("user_btn_n", 0) if with_reset else 1 - self.comb += pll.reset.eq(~rst_n) - pll.register_clkin(clk25, 25e6) - pll.create_clkout(self.cd_sys, sys_clk_freq) - # for the sdram - pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=180) - # pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq) - # pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180) - - # sdram_clk = ClockSignal("sys2x_ps") - sdram_clk = ClockSignal("sys_ps") - self.specials += DDROutput(1,0, platform.request("sdram_clock"), sdram_clk) - - -class Groovy1Platform(LatticeECP5Platform): - default_clk_name = "clk25" - default_clk_period = 1e9/25e6 - - def __init__(self, toolchain='trellis', **kwargs): - self.device = "LFE5U-25F-8BG256C" - LatticeECP5Platform.__init__(self, self.device, _io, connectors=_connectors, toolchain=toolchain, **kwargs) - - def create_programmer(self): - return OpenFPGALoader(cable="cmsisdap") - - def get_crg(self, sys_clk_freq) -> _CRG: - crg = _CRG(self, sys_clk_freq) - return crg - - def do_finalize(self, fragment, *args, **kwargs): - LatticeECP5Platform.do_finalize(self, fragment, *args, **kwargs) - self.add_period_constraint(self.lookup_request("clk25", loose=True), 1e9/25e6) - self.add_period_constraint(self.lookup_request("eth_clocks:rx", 0, loose=True), 1e9/125e6) - self.add_period_constraint(self.lookup_request("eth_clocks:rx", 1, loose=True), 1e9/125e6) diff --git a/groovylight/soc.py b/groovylight/soc.py deleted file mode 100644 index fe3f0f3..0000000 --- a/groovylight/soc.py +++ /dev/null @@ -1,97 +0,0 @@ -from migen import * - -from litex.gen import LiteXModule, ClockDomain, ClockSignal - -from litex.soc.cores.cpu import vexriscv -from litex.soc.integration.soc_core import SoCCore -from litex.soc.integration.builder import Builder, builder_argdict, builder_args -from litex.soc.integration.soc_core import soc_core_argdict, soc_core_args -from litex.build.lattice.trellis import trellis_argdict, trellis_args - -from litedram.modules import M12L64322A -from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY -from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII - -from platform.colorlight_5a_75b_8_0 import Groovy1Platform -from hub75 import Hub75Driver, make_hub75_iodevice, Hub75VerilogDriver - -class GroovySoC(SoCCore): - def __init__(self, platform, sys_clk_freq, - use_spi = False, - **kwargs): - - SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC for GroovyLight", **kwargs) - - - self.crg = platform.get_crg(sys_clk_freq) - self.submodules += self.crg - print(kwargs) - - # if not self.integrated_main_ram_size: - # self.sdrphy = GENSDRPHY(platform.request("sdram"), sys_clk_freq) - # self.add_sdram("sdram", - # phy = self.sdrphy, - # module = M12L64322A(sys_clk_freq, "1:1"), - # l2_cache_size = kwargs.get("l2_size", 8192), - # ) - # - # - # self.submodules.ethphy = LiteEthPHYRGMII( - # clock_pads= self.platform.request("eth_clocks", 0), - # pads = self.platform.request("eth", 0), - # tx_delay = 0e-9, # not sure what this is - # ) - # self.add_csr("ethphy") - # # self.add_etherbone(phy=self.ethphy, ip_address="192.168.0.36", mac_address = 0x10e2d5000001, data_width=32) - # if use_spi: - # from litespi.modules import W25Q32JV as SpiFlashModule - # from litespi.opcodes import SpiNorFlashOpCodes - # self.mem_map["spiflash"] = 0x20000000 - # mod = SpiFlashModule(SpiNorFlashOpCodes.READ_1_1_1) - # self.add_spi_flash(mode="1x", module=SpiFlashModule, with_master=False) - self.platform.add_extension(make_hub75_iodevice(0, "j8")) - hub_io = self.platform.request("hub75_iodev", 0) - self.submodules.hub75 = hub75 = Hub75VerilogDriver() - self.comb += [ - hub_io.r0.eq(hub75.o_panel_rgb0[0]), - hub_io.g0.eq(hub75.o_panel_rgb0[1]), - hub_io.b0.eq(hub75.o_panel_rgb0[2]), - hub_io.r1.eq(hub75.o_panel_rgb1[0]), - hub_io.g1.eq(hub75.o_panel_rgb1[1]), - hub_io.b1.eq(hub75.o_panel_rgb1[2]), - hub_io.clk.eq(hub75.o_display_clk), - hub_io.addr.eq(hub75.o_addr), - hub_io.oe.eq(hub75.o_out_enable), - hub_io.stb.eq(hub75.o_latch), - ] - platform.add_sources("./verilog/", "bitslicer.sv", "coordinator.sv", "hub75e.sv", "lineram.v", "pixgen.sv") - - - - - - -import argparse - -def main(): - parser = argparse.ArgumentParser(description="Groovylight builder") - - builder_arggroup = parser.add_argument_group("builder options") - soc_arggroup = parser.add_argument_group('SoC core options') - soc_arggroup.add_argument("--with-spiflash", action="store_true", help="Use built in SPI flash") - - builder_args(builder_arggroup) - soc_core_args(soc_arggroup) - trellis_args(parser.add_argument_group('Trellis options')) - args = parser.parse_args() - platform = Groovy1Platform() - soc = GroovySoC(platform, 120e6, **soc_core_argdict(args)) - - - builder = Builder(soc, **builder_argdict(args)) - - builder.build() - - -if __name__ == "__main__": - main()