Skip to content

Commit

Permalink
Initial structure with gateware directory to store cores sources.
Browse files Browse the repository at this point in the history
Example SpinalHDL core handling ov7670 registered inputs
Example litex firmware to access ov7670 control bus
  • Loading branch information
dlobato committed Nov 13, 2022
1 parent ec22d55 commit 4078d76
Show file tree
Hide file tree
Showing 229 changed files with 3,229 additions and 1 deletion.
1 change: 1 addition & 0 deletions .bsp/sbt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"sbt","version":"1.6.0","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/usr/lib/jvm/java-11-openjdk-amd64/bin/java","-Xms100m","-Xmx100m","-classpath","/home/dlobato/.local/share/JetBrains/IdeaIC2022.2/Scala/launcher/sbt-launch.jar","-Dsbt.script=/usr/bin/sbt","xsbt.boot.Boot","-bsp"]}
28 changes: 27 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,32 @@
debug.log

.vscode
.idea
obj_dir
*.fst
imgui.ini
imgui.ini

build

*.d
*.o
*.bin
*.elf
*.map

*.egg-info/

# sbt specific
.cache/
.history/
.lib/
dist/*
target
lib_managed/
src_managed/
project/boot/
project/plugins/project/

simWorkspace/
tmp/
null
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
19 changes: 19 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ThisBuild / version := "1.0"
ThisBuild / scalaVersion := "2.12.16"
ThisBuild / organization := "org.jderobot"

val spinalVersion = "1.7.3"
val spinalCore = "com.github.spinalhdl" %% "spinalhdl-core" % spinalVersion
val spinalLib = "com.github.spinalhdl" %% "spinalhdl-lib" % spinalVersion
val spinalIdslPlugin = compilerPlugin("com.github.spinalhdl" %% "spinalhdl-idsl-plugin" % spinalVersion)
val scalatest = "org.scalatest" %% "scalatest-funsuite" % "3.2.14" % "test"

lazy val mylib = (project in file("."))
.settings(
name := "fpga-robotics",
Compile / scalaSource := baseDirectory.value / "gateware" / "main" / "scala",
Test / scalaSource := baseDirectory.value / "gateware" / "test" / "scala",
libraryDependencies ++= Seq(spinalCore, spinalLib, spinalIdslPlugin)
)

fork := true
229 changes: 229 additions & 0 deletions designs/cam_to_hdmi/radiona_ulx3s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
from litex.build.generic_platform import Subsignal, Pins, IOStandard, Misc
from litex.soc.cores.bitbang import I2CMaster
#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2018-2019 Florent Kermarrec <[email protected]>
# Copyright (c) 2018 David Shah <[email protected]>
# SPDX-License-Identifier: BSD-2-Clause

from migen import *
from migen.genlib.resetsync import AsyncResetSynchronizer

from litex.build.io import DDROutput, SDROutput

from litex_boards.platforms import radiona_ulx3s

from litex.build.lattice.trellis import trellis_args, trellis_argdict

from litex.soc.cores.clock import *
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.cores.video import VideoHDMIPHY
from litex.soc.cores.led import LedChaser
from litex.soc.cores.spi import SPIMaster
from litex.soc.cores.gpio import GPIOOut

from litedram import modules as litedram_modules
from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY

#from fpga_robotics.cores.video.ov7670 import OV7670


# CRG ----------------------------------------------------------------------------------------------

class _CRG(Module):
def __init__(self, platform, sys_clk_freq, with_usb_pll=False, with_video_pll=False, sdram_rate="1:1"):
self.rst = Signal()
self.clock_domains.cd_sys = ClockDomain()
if sdram_rate == "1:2":
self.clock_domains.cd_sys2x = ClockDomain()
self.clock_domains.cd_sys2x_ps = ClockDomain()
else:
self.clock_domains.cd_sys_ps = ClockDomain()

# # #

# Clk / Rst
clk25 = platform.request("clk25")
rst = platform.request("rst")

# PLL
self.submodules.pll = pll = ECP5PLL()
self.comb += pll.reset.eq(rst | self.rst)
pll.register_clkin(clk25, 25e6)
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=90)

# USB PLL
if with_usb_pll:
self.submodules.usb_pll = usb_pll = ECP5PLL()
self.comb += usb_pll.reset.eq(rst | self.rst)
usb_pll.register_clkin(clk25, 25e6)
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)

# Video PLL
if with_video_pll:
self.submodules.video_pll = video_pll = ECP5PLL()
self.comb += video_pll.reset.eq(rst | self.rst)
video_pll.register_clkin(clk25, 25e6)
self.clock_domains.cd_hdmi = ClockDomain()
self.clock_domains.cd_hdmi5x = ClockDomain()
video_pll.create_clkout(self.cd_hdmi, 25e6, margin=0)
video_pll.create_clkout(self.cd_hdmi5x, 125e6, margin=0)

# VideoProc PLL
self.submodules.videoproc_pll = videoproc_pll = ECP5PLL()
self.comb += videoproc_pll.reset.eq(rst | self.rst)
videoproc_pll.register_clkin(clk25, 25e6)
self.clock_domains.cd_videoproc = ClockDomain()
self.clock_domains.cd_xclk = ClockDomain()
videoproc_pll.create_clkout(self.cd_videoproc, 100e6, margin=0)
videoproc_pll.create_clkout(self.cd_xclk, 25e6, margin=0)
self.specials += DDROutput(1, 0, platform.request("ov7670_xclk"), ClockSignal("xclk"))

self.clock_domains.cd_pclk = cd_pclk = ClockDomain()
self.comb += cd_pclk.clk.eq(platform.request("ov7670_pclk"))
self.specials += AsyncResetSynchronizer(cd_pclk, rst | self.rst)

# 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)

# Prevent ESP32 from resetting FPGA
self.comb += platform.request("wifi_gpio0").eq(1)

# BaseSoC ------------------------------------------------------------------------------------------

class BaseSoC(SoCCore):
def __init__(self, device="LFE5U-45F", revision="2.0", toolchain="trellis",
sys_clk_freq=int(50e6), sdram_module_cls="MT48LC16M16", sdram_rate="1:1",
with_led_chaser=True, with_video_terminal=False, with_video_framebuffer=False,
with_spi_flash=False, **kwargs):
platform = radiona_ulx3s.Platform(device=device, revision=revision, toolchain=toolchain)
platform.add_extension([
("i2c", 0,
Subsignal("scl", Pins("C6"), IOStandard("LVCMOS33"), Misc("DRIVE=4"), Misc("PULLMODE=UP")), # GP6
Subsignal("sda", Pins("C7"), IOStandard("LVCMOS33"), Misc("DRIVE=4"), Misc("PULLMODE=UP")) # GN6
),
("ov7670_xclk", 0, Pins("B11"), IOStandard("LVCMOS33")), # GP0
("ov7670_pclk", 0, Pins("N16"), IOStandard("LVCMOS33")),
("ov7670", 0,
Subsignal("href", Pins("N17"), IOStandard("LVCMOS33")),
Subsignal("vsync", Pins("P16"), IOStandard("LVCMOS33")),
Subsignal("data", Pins("C16 D16 B17 C17 B15 C15 C18 D17"), IOStandard("LVCMOS33")),
)
])

# CRG --------------------------------------------------------------------------------------
with_usb_pll = kwargs.get("uart_name", None) == "usb_acm"
with_video_pll = with_video_terminal or with_video_framebuffer
self.submodules.crg = _CRG(platform, sys_clk_freq, with_usb_pll, with_video_pll, sdram_rate=sdram_rate)

# SoCCore ----------------------------------------------------------------------------------
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on ULX3S", **kwargs)

# 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"), sys_clk_freq)
self.add_sdram("sdram",
phy = self.sdrphy,
module = getattr(litedram_modules, sdram_module_cls)(sys_clk_freq, sdram_rate),
size = 0x40000000,
l2_cache_size = kwargs.get("l2_size", 8192)
)

# Video ------------------------------------------------------------------------------------
if with_video_terminal or with_video_framebuffer:
self.submodules.videophy = VideoHDMIPHY(platform.request("gpdi"), clock_domain="hdmi")
if with_video_terminal:
self.add_video_terminal(phy=self.videophy, timings="640x480@75Hz", clock_domain="hdmi")
if with_video_framebuffer:
self.add_video_framebuffer(phy=self.videophy, timings="640x480@75Hz", clock_domain="hdmi")

# SPI Flash --------------------------------------------------------------------------------
if with_spi_flash:
from litespi.modules import IS25LP128
from litespi.opcodes import SpiNorFlashOpCodes as Codes
self.add_spi_flash(mode="4x", module=IS25LP128(Codes.READ_1_1_4))

# Leds -------------------------------------------------------------------------------------
if with_led_chaser:
self.submodules.leds = LedChaser(
pads = platform.request_all("user_led"),
sys_clk_freq = sys_clk_freq)

# I2C --------------------------------------------------------------------------------------
pads = platform.request("i2c", 0)
self.submodules.i2c = I2CMaster(pads)

#ov7670_pads = platform.request("ov7670", 0)
#self.submodules.ov7670 = OV7670(pads = ov7670_pads, clock_domain="videoproc")



# Build --------------------------------------------------------------------------------------------

def main():
from litex.soc.integration.soc import LiteXSoCArgumentParser
parser = LiteXSoCArgumentParser(description="LiteX SoC on ULX3S")
target_group = parser.add_argument_group(title="Target options")
target_group.add_argument("--build", action="store_true", help="Build design.")
target_group.add_argument("--load", action="store_true", help="Load bitstream.")
target_group.add_argument("--toolchain", default="trellis", help="FPGA toolchain (trellis or diamond).")
target_group.add_argument("--device", default="LFE5U-45F", help="FPGA device (LFE5U-12F, LFE5U-25F, LFE5U-45F or LFE5U-85F).")
target_group.add_argument("--revision", default="2.0", help="Board revision (2.0 or 1.7).")
target_group.add_argument("--sys-clk-freq", default=50e6, help="System clock frequency.")
target_group.add_argument("--sdram-module", default="MT48LC16M16", help="SDRAM module (MT48LC16M16, AS4C32M16 or AS4C16M16).")
target_group.add_argument("--with-spi-flash", action="store_true", help="Enable SPI Flash (MMAPed).")
sdopts = target_group.add_mutually_exclusive_group()
sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.")
sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support.")
target_group.add_argument("--with-oled", action="store_true", help="Enable SDD1331 OLED support.")
target_group.add_argument("--sdram-rate", default="1:1", help="SDRAM Rate (1:1 Full Rate or 1:2 Half Rate).")
viopts = target_group.add_mutually_exclusive_group()
viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (HDMI).")
viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (HDMI).")
builder_args(parser)
soc_core_args(parser)
trellis_args(parser)
args = parser.parse_args()

soc = BaseSoC(
device = args.device,
revision = args.revision,
toolchain = args.toolchain,
sys_clk_freq = int(float(args.sys_clk_freq)),
sdram_module_cls = args.sdram_module,
sdram_rate = args.sdram_rate,
with_video_terminal = args.with_video_terminal,
with_video_framebuffer = args.with_video_framebuffer,
with_spi_flash = args.with_spi_flash,
**soc_core_argdict(args))
if args.with_spi_sdcard:
soc.add_spi_sdcard()
if args.with_sdcard:
soc.add_sdcard()
if args.with_oled:
soc.add_oled()

builder = Builder(soc, **builder_argdict(args))
builder_kargs = trellis_argdict(args) if args.toolchain == "trellis" else {}
if args.build:
builder.build(**builder_kargs)

if args.load:
prog = soc.platform.create_programmer()
prog.load_bitstream(builder.get_bitstream_filename(mode="sram", ext=".svf")) # FIXME

if __name__ == "__main__":
main()
Loading

0 comments on commit 4078d76

Please sign in to comment.