You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
481 lines
23 KiB
481 lines
23 KiB
#!/usr/bin/env python3 |
|
|
|
# |
|
# neopixelar.py |
|
# |
|
# This file has been derived from LiteX-Boards/colorlight_5b_75x.py |
|
# Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr> |
|
# SPDX-License-Identifier: BSD-2-Clause |
|
# |
|
# Disclaimer: Still a proof of concept with large timings violations on the IP/UDP and |
|
# Etherbone stack that need to be optimized. It was initially just used to validate the reversed |
|
# pinout but happens to work on hardware... |
|
# |
|
# History: |
|
# -------- |
|
# 14.09.20/KQ Initial version, some output ports activated (user_led, J4) for testing |
|
# 15.09.20/KQ Own logic exported to external module (neopixelprotocol.py - now neopixelengine.py) |
|
# 19.09.20/KQ Project renamed 'NeoPixelar' (swedish plural for NeoPixel ...) |
|
# 20.11.20/KQ Input provided: U28 -> J1 (1, 2, 3, [4=GND], 5, 6, 7), J2 (1, 2, [4=GND]) |
|
# (U15 -> J7 ([4=GND], 5, 7), J8 (1, 2, 3, [4=GND], 5, 6, 7)) |
|
# 02.01.21/KQ DMA DRAM access integration started |
|
# |
|
# Build/Use ---------------------------------------------------------------------------------------- |
|
# - 'python3 neopixelar.py --build --revision=7.0 --uart-name=crossover --with-etherbone --ip-address=192.168.1.20 --csr-csv=build/csr.csv' |
|
# to generate |
|
# - 'python3 neopixelar.py --load' to download to FPGA |
|
# - 'ping 192.168.1.20' to verify ethernet connection - via LEFT(!) RJ45 port |
|
# - 'wishbone-tool --ethernet-host 192.168.1.20 --server terminal --csr-csv build/csr.csv' |
|
# You should see the LiteX BIOS and be able to interact with it |
|
# - To load a file to RAM (@0x40000000 len=0x400000) use: |
|
# wishbone-tool --ethernet-host 192.168.1.20 --server load-file --csr-csv build/csr.csv |
|
# --load-address 0x40000000 |
|
# --load-name build/colorlight_5a_75b/software/<filename> |
|
# To disassemble raw file: |
|
# ../fpga/litex/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-objdump |
|
# -D -b binary ./build/colorlight_5a_75b/software/bios/bios.bin -m riscv |
|
# |
|
import os |
|
import argparse |
|
import sys |
|
|
|
from migen import * |
|
from migen.genlib.misc import WaitTimer |
|
from migen.genlib.resetsync import AsyncResetSynchronizer |
|
|
|
from litex.build.io import DDROutput |
|
|
|
from litex_boards.platforms import colorlight_5a_75b |
|
|
|
from litex.build.lattice.trellis import trellis_args, trellis_argdict |
|
|
|
from litex.soc.cores.clock import * |
|
from litex.soc.cores.spi_flash import ECP5SPIFlash |
|
from litex.soc.cores.gpio import GPIOOut |
|
from litex.soc.integration.soc_core import * |
|
from litex.soc.integration.builder import * |
|
|
|
from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage, CSRField |
|
from litex.soc.interconnect.stream import SyncFIFO |
|
|
|
from litedram.modules import M12L16161A, M12L64322A |
|
from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY |
|
from litedram.frontend.dma import LiteDRAMDMAReader, LiteDRAMDMAWriter |
|
|
|
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII |
|
|
|
from litex.build.generic_platform import * |
|
|
|
import litex.soc.doc as lxsocdoc |
|
|
|
# KQ's helper modules ... |
|
from libmodules.systime import SysTime |
|
from libmodules.dramtransfer import DRAMTransfer |
|
|
|
from neopixelengine import NeoPixelEngine |
|
|
|
from helpers.prepare_firmware import copyjob |
|
|
|
# Explicit IO naming, taken from board colorlight 5a 75b board defs. (rev. 7.0) |
|
# from https://github.com/q3k/chubby75/blob/master/5a-75b/hardware_V7.0.md |
|
#_connectors_v7_0 = [ |
|
# ("j1", "F3 F1 G3 - G2 H3 H5 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
# ("j2", "J4 K3 G1 - K4 C2 E3 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
# ("j3", "H4 K5 P1 - R1 L5 F2 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
# ("j4", "P4 R2 M8 - M9 T6 R6 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
# ("j5", "M11 N11 P12 - K15 N12 L16 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
# ("j6", "K16 J15 J16 - J12 H15 G16 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
# ("j7", "H13 J13 H12 - G14 H14 G15 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
# ("j8", "A15 F16 A14 - E13 B14 A13 F15 L2 K1 J5 K2 B16 J14 F12 -"), |
|
#] |
|
|
|
_gpios = [ |
|
# Attn. Jx/pin descriptions are 1-based, but zero based defs. used! |
|
|
|
# J1 |
|
("gpio", 0, Pins("j1:0"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 1, Pins("j1:1"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 2, Pins("j1:2"), IOStandard("LVCMOS33")), # Input now |
|
# GND |
|
("gpio", 3, Pins("j1:4"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 4, Pins("j1:5"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 5, Pins("j1:6"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 6, Pins("j1:7"), IOStandard("LVCMOS33")), |
|
("gpio", 7, Pins("j1:8"), IOStandard("LVCMOS33")), |
|
("gpio", 8, Pins("j1:9"), IOStandard("LVCMOS33")), |
|
("gpio", 9, Pins("j1:10"), IOStandard("LVCMOS33")), |
|
("gpio", 10, Pins("j1:11"), IOStandard("LVCMOS33")), |
|
("gpio", 11, Pins("j1:12"), IOStandard("LVCMOS33")), |
|
("gpio", 12, Pins("j1:13"), IOStandard("LVCMOS33")), |
|
("gpio", 13, Pins("j1:14"), IOStandard("LVCMOS33")), |
|
# GND |
|
|
|
# J2 |
|
("gpio", 14, Pins("j2:0"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 15, Pins("j2:1"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 16, Pins("j2:2"), IOStandard("LVCMOS33")), |
|
# GND |
|
("gpio", 17, Pins("j2:4"), IOStandard("LVCMOS33")), |
|
("gpio", 18, Pins("j2:5"), IOStandard("LVCMOS33")), |
|
("gpio", 19, Pins("j2:6"), IOStandard("LVCMOS33")), |
|
("gpio", 20, Pins("j2:7"), IOStandard("LVCMOS33")), |
|
("gpio", 21, Pins("j2:8"), IOStandard("LVCMOS33")), |
|
("gpio", 22, Pins("j2:9"), IOStandard("LVCMOS33")), |
|
("gpio", 23, Pins("j2:10"), IOStandard("LVCMOS33")), |
|
("gpio", 24, Pins("j2:11"), IOStandard("LVCMOS33")), |
|
("gpio", 25, Pins("j2:12"), IOStandard("LVCMOS33")), |
|
("gpio", 26, Pins("j2:13"), IOStandard("LVCMOS33")), |
|
("gpio", 27, Pins("j2:14"), IOStandard("LVCMOS33")), |
|
# GND |
|
|
|
# J3 |
|
("gpio", 28, Pins("j3:0"), IOStandard("LVCMOS33")), |
|
("gpio", 29, Pins("j3:1"), IOStandard("LVCMOS33")), |
|
("gpio", 30, Pins("j3:2"), IOStandard("LVCMOS33")), |
|
# GND |
|
("gpio", 31, Pins("j3:4"), IOStandard("LVCMOS33")), |
|
("gpio", 32, Pins("j3:5"), IOStandard("LVCMOS33")), |
|
("gpio", 33, Pins("j3:6"), IOStandard("LVCMOS33")), |
|
("gpio", 34, Pins("j3:7"), IOStandard("LVCMOS33")), |
|
("gpio", 35, Pins("j3:8"), IOStandard("LVCMOS33")), |
|
("gpio", 36, Pins("j3:9"), IOStandard("LVCMOS33")), |
|
("gpio", 37, Pins("j3:10"), IOStandard("LVCMOS33")), |
|
("gpio", 38, Pins("j3:11"), IOStandard("LVCMOS33")), |
|
("gpio", 39, Pins("j3:12"), IOStandard("LVCMOS33")), |
|
("gpio", 40, Pins("j3:13"), IOStandard("LVCMOS33")), |
|
("gpio", 41, Pins("j3:14"), IOStandard("LVCMOS33")), |
|
# GND |
|
|
|
# J4 |
|
("gpio", 42, Pins("j4:0"), IOStandard("LVCMOS33")), # j4 pin 1 |
|
("gpio", 43, Pins("j4:1"), IOStandard("LVCMOS33")), # j4 pin 2 |
|
("gpio", 44, Pins("j4:2"), IOStandard("LVCMOS33")), # j4 pin 3 |
|
# j4 pin 4, GND |
|
("gpio", 45, Pins("j4:4"), IOStandard("LVCMOS33")), # j4 pin 5 |
|
("gpio", 46, Pins("j4:5"), IOStandard("LVCMOS33")), # j4 pin 6 |
|
("gpio", 47, Pins("j4:6"), IOStandard("LVCMOS33")), # j4 pin 7 |
|
("gpio", 48, Pins("j4:7"), IOStandard("LVCMOS33")), # j4 pin 8 |
|
("gpio", 49, Pins("j4:8"), IOStandard("LVCMOS33")), # j4 pin 9 |
|
("gpio", 50, Pins("j4:9"), IOStandard("LVCMOS33")), # j4 pin 10 |
|
("gpio", 51, Pins("j4:10"), IOStandard("LVCMOS33")), # j4 pin 11 |
|
("gpio", 52, Pins("j4:11"), IOStandard("LVCMOS33")), # j4 pin 12 |
|
("gpio", 53, Pins("j4:12"), IOStandard("LVCMOS33")), # j4 pin 13 |
|
("gpio", 54, Pins("j4:13"), IOStandard("LVCMOS33")), # j4 pin 14 |
|
("gpio", 55, Pins("j4:14"), IOStandard("LVCMOS33")), # j4 pin 15 |
|
# j4 pin 16, GND |
|
# J5 |
|
("gpio", 56, Pins("j5:0"), IOStandard("LVCMOS33")), |
|
("gpio", 57, Pins("j5:1"), IOStandard("LVCMOS33")), |
|
("gpio", 58, Pins("j5:2"), IOStandard("LVCMOS33")), |
|
# GND |
|
("gpio", 59, Pins("j5:4"), IOStandard("LVCMOS33")), |
|
("gpio", 60, Pins("j5:5"), IOStandard("LVCMOS33")), |
|
("gpio", 61, Pins("j5:6"), IOStandard("LVCMOS33")), |
|
("gpio", 62, Pins("j5:7"), IOStandard("LVCMOS33")), |
|
("gpio", 63, Pins("j5:8"), IOStandard("LVCMOS33")), |
|
("gpio", 64, Pins("j5:9"), IOStandard("LVCMOS33")), |
|
("gpio", 65, Pins("j5:10"), IOStandard("LVCMOS33")), |
|
("gpio", 66, Pins("j5:11"), IOStandard("LVCMOS33")), |
|
("gpio", 67, Pins("j5:12"), IOStandard("LVCMOS33")), |
|
("gpio", 68, Pins("j5:13"), IOStandard("LVCMOS33")), |
|
("gpio", 69, Pins("j5:14"), IOStandard("LVCMOS33")), |
|
# GND |
|
|
|
# J6 |
|
("gpio", 70, Pins("j6:0"), IOStandard("LVCMOS33")), |
|
("gpio", 71, Pins("j6:1"), IOStandard("LVCMOS33")), |
|
("gpio", 72, Pins("j6:2"), IOStandard("LVCMOS33")), |
|
# GND |
|
("gpio", 73, Pins("j6:4"), IOStandard("LVCMOS33")), |
|
("gpio", 74, Pins("j6:5"), IOStandard("LVCMOS33")), |
|
("gpio", 75, Pins("j6:6"), IOStandard("LVCMOS33")), |
|
("gpio", 76, Pins("j6:7"), IOStandard("LVCMOS33")), |
|
("gpio", 77, Pins("j6:8"), IOStandard("LVCMOS33")), |
|
("gpio", 78, Pins("j6:9"), IOStandard("LVCMOS33")), |
|
("gpio", 79, Pins("j6:10"), IOStandard("LVCMOS33")), |
|
("gpio", 80, Pins("j6:11"), IOStandard("LVCMOS33")), |
|
("gpio", 81, Pins("j6:12"), IOStandard("LVCMOS33")), |
|
("gpio", 82, Pins("j6:13"), IOStandard("LVCMOS33")), |
|
("gpio", 83, Pins("j6:14"), IOStandard("LVCMOS33")), |
|
# GND |
|
|
|
# J7 |
|
("gpio", 84, Pins("j7:0"), IOStandard("LVCMOS33")), |
|
("gpio", 85, Pins("j7:1"), IOStandard("LVCMOS33")), |
|
("gpio", 86, Pins("j7:2"), IOStandard("LVCMOS33")), |
|
# GND |
|
("gpio", 87, Pins("j7:4"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 88, Pins("j7:5"), IOStandard("LVCMOS33")), |
|
("gpio", 89, Pins("j7:6"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 90, Pins("j7:7"), IOStandard("LVCMOS33")), |
|
("gpio", 91, Pins("j7:8"), IOStandard("LVCMOS33")), |
|
("gpio", 92, Pins("j7:9"), IOStandard("LVCMOS33")), |
|
("gpio", 93, Pins("j7:10"), IOStandard("LVCMOS33")), |
|
("gpio", 94, Pins("j7:11"), IOStandard("LVCMOS33")), |
|
("gpio", 95, Pins("j7:12"), IOStandard("LVCMOS33")), |
|
("gpio", 96, Pins("j7:13"), IOStandard("LVCMOS33")), |
|
("gpio", 97, Pins("j7:14"), IOStandard("LVCMOS33")), |
|
# GND |
|
|
|
# J8 |
|
("gpio", 98, Pins("j8:0"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 99, Pins("j8:1"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 100, Pins("j8:2"), IOStandard("LVCMOS33")), # Input now |
|
# GND |
|
("gpio", 101, Pins("j8:4"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 102, Pins("j8:5"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 103, Pins("j8:6"), IOStandard("LVCMOS33")), # Input now |
|
("gpio", 104, Pins("j8:7"), IOStandard("LVCMOS33")), |
|
("gpio", 105, Pins("j8:8"), IOStandard("LVCMOS33")), |
|
("gpio", 106, Pins("j8:9"), IOStandard("LVCMOS33")), |
|
("gpio", 107, Pins("j8:10"), IOStandard("LVCMOS33")), |
|
("gpio", 108, Pins("j8:11"), IOStandard("LVCMOS33")), |
|
("gpio", 109, Pins("j8:12"), IOStandard("LVCMOS33")), |
|
("gpio", 110, Pins("j8:13"), IOStandard("LVCMOS33")), |
|
("gpio", 111, Pins("j8:14"), IOStandard("LVCMOS33")), |
|
# GND |
|
] |
|
|
|
# CRG ---------------------------------------------------------------------------------------------- |
|
|
|
class _CRG(Module): |
|
def __init__(self, platform, sys_clk_freq, use_internal_osc=False, with_usb_pll=False, with_rst=True, sdram_rate="1:1"): |
|
self.clock_domains.cd_sys = ClockDomain() |
|
if sdram_rate == "1:2": |
|
self.clock_domains.cd_sys2x = ClockDomain() |
|
self.clock_domains.cd_sys2x_ps = ClockDomain(reset_less=True) |
|
else: |
|
self.clock_domains.cd_sys_ps = ClockDomain(reset_less=True) |
|
|
|
# # # |
|
|
|
# Clk / Rst |
|
if not use_internal_osc: |
|
clk = platform.request("clk25") |
|
clk_freq = 25e6 |
|
else: |
|
clk = Signal() |
|
div = 5 |
|
self.specials += Instance("OSCG", |
|
p_DIV = div, |
|
o_OSC = clk) |
|
clk_freq = 310e6/div |
|
|
|
rst_n = 1 if not with_rst else platform.request("user_btn_n", 0) |
|
|
|
# PLL |
|
self.submodules.pll = pll = ECP5PLL() |
|
self.comb += pll.reset.eq(~rst_n) |
|
pll.register_clkin(clk, clk_freq) |
|
pll.create_clkout(self.cd_sys, sys_clk_freq) |
|
if sdram_rate == "1:2": |
|
pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq) |
|
pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180) # Idealy 90° but needs to be increased. |
|
else: |
|
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=180) # Idealy 90° but needs to be increased. |
|
|
|
# USB PLL |
|
if with_usb_pll: |
|
self.submodules.usb_pll = usb_pll = ECP5PLL() |
|
self.comb += usb_pll.reset.eq(~rst_n) |
|
usb_pll.register_clkin(clk, clk_freq) |
|
self.clock_domains.cd_usb_12 = ClockDomain() |
|
self.clock_domains.cd_usb_48 = ClockDomain() |
|
usb_pll.create_clkout(self.cd_usb_12, 12e6, margin=0) |
|
usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0) |
|
|
|
# SDRAM clock |
|
sdram_clk = ClockSignal("sys2x_ps" if sdram_rate == "1:2" else "sys_ps") |
|
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk) |
|
|
|
# BaseSoC ------------------------------------------------------------------------------------------ |
|
|
|
class BaseSoC(SoCCore): |
|
def __init__(self, board, revision, with_ethernet=False, with_etherbone=False, eth_phy=0, ip_address=None, mac_address=None, sys_clk_freq=60e6, use_internal_osc=False, sdram_rate="1:1", **kwargs): |
|
platform = colorlight_5a_75b.Platform(revision="7.0") |
|
|
|
# SoCCore ---------------------------------------------------------------------------------- |
|
SoCCore.__init__(self, platform, int(sys_clk_freq), |
|
ident = "LiteX SoC on Colorlight " + board.upper(), |
|
ident_version = True, |
|
**kwargs) |
|
|
|
# CRG -------------------------------------------------------------------------------------- |
|
with_rst = kwargs["uart_name"] not in ["serial", "bridge"] # serial_rx shared with user_btn_n. |
|
with_usb_pll = kwargs.get("uart_name", None) == "usb_acm" |
|
self.submodules.crg = _CRG(platform, sys_clk_freq, use_internal_osc=use_internal_osc, with_usb_pll=with_usb_pll,with_rst=with_rst, sdram_rate=sdram_rate) |
|
|
|
# SDR SDRAM -------------------------------------------------------------------------------- |
|
if not self.integrated_main_ram_size: |
|
sdrphy_cls = HalfRateGENSDRPHY if sdram_rate == "1:2" else GENSDRPHY |
|
self.submodules.sdrphy = sdrphy_cls(platform.request("sdram")) |
|
if board == "5a-75e" and revision == "6.0": |
|
sdram_cls = M12L64322A |
|
sdram_size = 0x80000000 |
|
else: |
|
sdram_cls = M12L16161A |
|
sdram_size = 0x40000000 |
|
self.add_sdram("sdram", |
|
phy = self.sdrphy, |
|
module = sdram_cls(sys_clk_freq, sdram_rate), |
|
origin = self.mem_map["main_ram"], |
|
size = kwargs.get("max_sdram_size", sdram_size), |
|
l2_cache_size = kwargs.get("l2_size", 8192), |
|
l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128), |
|
l2_cache_reverse = True |
|
) |
|
|
|
# Ethernet / Etherbone --------------------------------------------------------------------- |
|
if with_ethernet or with_etherbone: |
|
self.submodules.ethphy = LiteEthPHYRGMII( |
|
clock_pads = self.platform.request("eth_clocks", eth_phy), |
|
pads = self.platform.request("eth", eth_phy)) |
|
self.add_csr("ethphy") |
|
if with_ethernet: |
|
self.add_ethernet(phy=self.ethphy) |
|
if with_etherbone: |
|
self.add_etherbone( |
|
phy=self.ethphy, |
|
ip_address = ip_address, |
|
mac_address = mac_address, |
|
) |
|
# Add platform specific I/O |
|
platform.add_extension(_gpios) # General LED outputs |
|
|
|
# For U28 3.3V(!) inputs: (also see separate picture) |
|
self.J1_1 = J1_1 = platform.request("gpio", 0) # Pins for logical evaluation |
|
self.J1_2 = J1_2 = platform.request("gpio", 1) |
|
self.J1_3 = J1_3 = platform.request("gpio", 2) |
|
self.J1_5 = J1_5 = platform.request("gpio", 3) |
|
self.J1_6 = J1_6 = platform.request("gpio", 4) |
|
self.J1_7 = J1_7 = platform.request("gpio", 5) |
|
self.J2_1 = J2_1 = platform.request("gpio", 14) |
|
self.J2_2 = J2_2 = platform.request("gpio", 15) |
|
''' |
|
# For U15 (not used currently) |
|
J7_5 = Signal(1) |
|
self.comb += J7_5.eq(platform.request("gpio", 87)) |
|
J7_7 = Signal(1) |
|
self.comb += J7_7.eq(platform.request("gpio", 89)) |
|
J8_1 = Signal(1) |
|
self.comb += J8_1.eq(platform.request("gpio", 98)) |
|
J8_2 = Signal(1) |
|
self.comb += J8_2.eq(platform.request("gpio", 99)) |
|
J8_3 = Signal(1) |
|
self.comb += J8_3.eq(platform.request("gpio", 100)) |
|
J8_5 = Signal(1) |
|
self.comb += J8_5.eq(platform.request("gpio", 101)) |
|
J8_6 = Signal(1) |
|
self.comb += J8_6.eq(platform.request("gpio", 102)) |
|
J8_7 = Signal(1) |
|
self.comb += J8_7.eq(platform.request("gpio", 103)) |
|
''' |
|
# OR it all together: Every input lights LED ... |
|
self.led_logic1 = led_logic1 = Signal(1) |
|
self.comb += led_logic1.eq(J1_1 | J1_2 | J1_3 | J1_5 | J1_6 | J1_7 | J2_1 | J2_2) |
|
#led_logic2 = Signal(1) # Not used currently |
|
#self.comb += led_logic2.eq(J8_1 | J8_2 | J8_3 | J8_5 | J8_6 | J8_7 | J7_5 | J7_7) |
|
|
|
# Base counter (used for clocking) |
|
counter = Signal(32) # 32-Bit counter |
|
self.sync += counter.eq(counter + 1) |
|
|
|
# USERLED blink (on-board LED) |
|
# only w/ uart-name=crossover option: |
|
if kwargs["uart_name"] not in ["serial", "bridge"]: |
|
self.comb += platform.request("user_led_n").eq(~(counter[23] | led_logic1)) #| led_logic2) # ~2Hz | inputs |
|
|
|
# System time (count) |
|
self.submodules.systime = systime = SysTime(comparecount=0x0000EA90) |
|
self.add_csr("systime") |
|
|
|
# DRAM test |
|
MAXWORDS = 512 #32 # Transfer length x 32-bit, FIFO depth |
|
self.submodules.mm2s = mm2s = LiteDRAMDMAReader(self.sdram.crossbar.get_port(), fifo_depth=MAXWORDS, fifo_buffered=True) |
|
mm2s.add_csr() |
|
self.add_csr("mm2s") |
|
self.submodules.sync_fifo = sync_fifo = SyncFIFO([("data", 32)], MAXWORDS, True) |
|
self.comb += mm2s.source.connect(sync_fifo.sink) # Connect DMA-Reader.source -> FIFO.sink |
|
self.submodules.dramtransfer = dramtransfer = DRAMTransfer(maxwords=MAXWORDS, dma_reader=mm2s, sync_fifo=sync_fifo) |
|
self.add_csr("dramtransfer") |
|
|
|
# Adjust no. for your actual project ... |
|
max_TABLES = 64 #2 # 1..64 |
|
max_LEDS_per_chain = MAXWORDS # 1..512 |
|
self.submodules.npe = NeoPixelEngine(n_TABLES=max_TABLES, n_LEDs=max_LEDS_per_chain, dramtransfer=dramtransfer) |
|
self.add_csr("npe") |
|
for i in range(42,56+2): # Example: Do output on J4 (14) & J5 (2) |
|
self.comb += platform.request("gpio", i).eq(self.npe.bDataPin[i-42]) # Output data pin |
|
|
|
# Build -------------------------------------------------------------------------------------------- |
|
|
|
def main(): |
|
parser = argparse.ArgumentParser(description="LiteX SoC on Colorlight 5A-75X") |
|
builder_args(parser) |
|
soc_core_args(parser) |
|
trellis_args(parser) |
|
parser.add_argument("--build", action="store_true", help="Build bitstream") |
|
parser.add_argument("--load", action="store_true", help="Load bitstream") |
|
parser.add_argument("--board", default="5a-75b", help="Board type: 5a-75b (default) & don't change!") |
|
parser.add_argument("--revision", default="7.0", type=str, help="Board revision 7.0 (default) & don't change!") |
|
parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") |
|
parser.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support") |
|
parser.add_argument("--eth-phy", default=0, type=int, help="Ethernet PHY 0 or 1 (default=0)") |
|
parser.add_argument("--ip-address", default="192.168.1.50", help="Ethernet IP address of the board.") |
|
parser.add_argument("--mac-address", default="0x726b895bc2e2", help="Ethernet MAC address of the board.") |
|
parser.add_argument("--sys-clk-freq", default=60e6, type=float, help="System clock frequency (default=60MHz)") |
|
parser.add_argument("--use-internal-osc", action="store_true", help="Use internal oscillator") |
|
parser.add_argument("--sdram-rate", default="1:1", help="SDRAM Rate 1:1 Full Rate (default), 1:2 Half Rate") |
|
parser.add_argument("--csr_csv", default="build/csr.csv", help="CSR list location") |
|
parser.add_argument("--doc", action="store_true", help="Create doc files for sphinx generator") |
|
parser.add_argument("--flash", action="store_true", help="Load bitstream to flash") |
|
args = parser.parse_args() |
|
|
|
#assert not (args.with_ethernet and args.with_etherbone) |
|
soc = BaseSoC(board=args.board, revision=args.revision, |
|
with_ethernet = args.with_ethernet, |
|
with_etherbone = args.with_etherbone, |
|
eth_phy = args.eth_phy, |
|
ip_address = args.ip_address, |
|
mac_address = int(args.mac_address, 0), |
|
sys_clk_freq = args.sys_clk_freq, |
|
use_internal_osc = args.use_internal_osc, |
|
sdram_rate = args.sdram_rate, |
|
**soc_core_argdict(args)) |
|
|
|
# 32MBit SPIFlash ------------------------------------------------------------------------ |
|
flashbase = 0xc0000000 |
|
flashoffset = 0x100000 # Used to be zero (default) |
|
soc.mem_map["spiflash"] = flashbase # Length: 0x01000000 ('til 0xc1000000 - 1) |
|
# Boot at +1MB |
|
soc.add_constant("FLASH_BOOT_ADDRESS", soc.mem_map["spiflash"] + 1024*1024) # 0xc0100000 |
|
soc.add_spi_flash(name="spiflash", mode="1x", dummy_cycles=8, clk_freq=5e6) |
|
|
|
builder = Builder(soc, **builder_argdict(args)) |
|
# Now override boot address (used to be zero/default) |
|
args.ecppack_bootaddr = flashbase + flashoffset # 0xC0100000 |
|
builder.build(**trellis_argdict(args), run=args.build) # Written here to (local) build tree |
|
|
|
if args.doc: |
|
print("Generating documentation for sphinx ...") |
|
lxsocdoc.generate_docs(soc, "build/documentation/", project_name="neopixelar", author="KQ") |
|
print("Generate via: 'sphinx-build -b html build/documentation build/documentation/html'") |
|
|
|
if args.load: |
|
prog = soc.platform.create_programmer() |
|
prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".svf")) |
|
return |
|
|
|
if args.flash: # Convert Bit File to Jtag Write Flash command |
|
name = os.path.join(builder.gateware_dir, soc.build_name) |
|
print(f"Executing ./bit_to_flash.py {name}.bit {name}.svf.flash") |
|
from helpers.bit_to_flash import convertBitToFlashFile |
|
convertBitToFlashFile(name + ".bit", name + ".svf.flash", address=0) |
|
from helpers.load_to_flash import load2flash |
|
load2flash(name + ".svf.flash") |
|
return |
|
|
|
if __name__ == "__main__": |
|
copyjob() # Create backup if nec. & move our firmware to the correct location |
|
main() |
|
# Maybe revoke backup action here ...
|
|
|