Skip to content

Commit 4078d76

Browse files
committed
Initial structure with gateware directory to store cores sources.
Example SpinalHDL core handling ov7670 registered inputs Example litex firmware to access ov7670 control bus
1 parent ec22d55 commit 4078d76

File tree

229 files changed

+3229
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

229 files changed

+3229
-1
lines changed

.bsp/sbt.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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"]}

.gitignore

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,32 @@
1414
debug.log
1515

1616
.vscode
17+
.idea
1718
obj_dir
1819
*.fst
19-
imgui.ini
20+
imgui.ini
21+
22+
build
23+
24+
*.d
25+
*.o
26+
*.bin
27+
*.elf
28+
*.map
29+
30+
*.egg-info/
31+
32+
# sbt specific
33+
.cache/
34+
.history/
35+
.lib/
36+
dist/*
37+
target
38+
lib_managed/
39+
src_managed/
40+
project/boot/
41+
project/plugins/project/
42+
43+
simWorkspace/
44+
tmp/
45+
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.

build.sbt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
ThisBuild / version := "1.0"
2+
ThisBuild / scalaVersion := "2.12.16"
3+
ThisBuild / organization := "org.jderobot"
4+
5+
val spinalVersion = "1.7.3"
6+
val spinalCore = "com.github.spinalhdl" %% "spinalhdl-core" % spinalVersion
7+
val spinalLib = "com.github.spinalhdl" %% "spinalhdl-lib" % spinalVersion
8+
val spinalIdslPlugin = compilerPlugin("com.github.spinalhdl" %% "spinalhdl-idsl-plugin" % spinalVersion)
9+
val scalatest = "org.scalatest" %% "scalatest-funsuite" % "3.2.14" % "test"
10+
11+
lazy val mylib = (project in file("."))
12+
.settings(
13+
name := "fpga-robotics",
14+
Compile / scalaSource := baseDirectory.value / "gateware" / "main" / "scala",
15+
Test / scalaSource := baseDirectory.value / "gateware" / "test" / "scala",
16+
libraryDependencies ++= Seq(spinalCore, spinalLib, spinalIdslPlugin)
17+
)
18+
19+
fork := true

designs/cam_to_hdmi/radiona_ulx3s.py

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#!/usr/bin/env python3
2+
from litex.build.generic_platform import Subsignal, Pins, IOStandard, Misc
3+
from litex.soc.cores.bitbang import I2CMaster
4+
#
5+
# This file is part of LiteX-Boards.
6+
#
7+
# Copyright (c) 2018-2019 Florent Kermarrec <[email protected]>
8+
# Copyright (c) 2018 David Shah <[email protected]>
9+
# SPDX-License-Identifier: BSD-2-Clause
10+
11+
from migen import *
12+
from migen.genlib.resetsync import AsyncResetSynchronizer
13+
14+
from litex.build.io import DDROutput, SDROutput
15+
16+
from litex_boards.platforms import radiona_ulx3s
17+
18+
from litex.build.lattice.trellis import trellis_args, trellis_argdict
19+
20+
from litex.soc.cores.clock import *
21+
from litex.soc.integration.soc_core import *
22+
from litex.soc.integration.builder import *
23+
from litex.soc.cores.video import VideoHDMIPHY
24+
from litex.soc.cores.led import LedChaser
25+
from litex.soc.cores.spi import SPIMaster
26+
from litex.soc.cores.gpio import GPIOOut
27+
28+
from litedram import modules as litedram_modules
29+
from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY
30+
31+
#from fpga_robotics.cores.video.ov7670 import OV7670
32+
33+
34+
# CRG ----------------------------------------------------------------------------------------------
35+
36+
class _CRG(Module):
37+
def __init__(self, platform, sys_clk_freq, with_usb_pll=False, with_video_pll=False, sdram_rate="1:1"):
38+
self.rst = Signal()
39+
self.clock_domains.cd_sys = ClockDomain()
40+
if sdram_rate == "1:2":
41+
self.clock_domains.cd_sys2x = ClockDomain()
42+
self.clock_domains.cd_sys2x_ps = ClockDomain()
43+
else:
44+
self.clock_domains.cd_sys_ps = ClockDomain()
45+
46+
# # #
47+
48+
# Clk / Rst
49+
clk25 = platform.request("clk25")
50+
rst = platform.request("rst")
51+
52+
# PLL
53+
self.submodules.pll = pll = ECP5PLL()
54+
self.comb += pll.reset.eq(rst | self.rst)
55+
pll.register_clkin(clk25, 25e6)
56+
pll.create_clkout(self.cd_sys, sys_clk_freq)
57+
if sdram_rate == "1:2":
58+
pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq)
59+
pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180) # Idealy 90° but needs to be increased.
60+
else:
61+
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90)
62+
63+
# USB PLL
64+
if with_usb_pll:
65+
self.submodules.usb_pll = usb_pll = ECP5PLL()
66+
self.comb += usb_pll.reset.eq(rst | self.rst)
67+
usb_pll.register_clkin(clk25, 25e6)
68+
self.clock_domains.cd_usb_12 = ClockDomain()
69+
self.clock_domains.cd_usb_48 = ClockDomain()
70+
usb_pll.create_clkout(self.cd_usb_12, 12e6, margin=0)
71+
usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0)
72+
73+
# Video PLL
74+
if with_video_pll:
75+
self.submodules.video_pll = video_pll = ECP5PLL()
76+
self.comb += video_pll.reset.eq(rst | self.rst)
77+
video_pll.register_clkin(clk25, 25e6)
78+
self.clock_domains.cd_hdmi = ClockDomain()
79+
self.clock_domains.cd_hdmi5x = ClockDomain()
80+
video_pll.create_clkout(self.cd_hdmi, 25e6, margin=0)
81+
video_pll.create_clkout(self.cd_hdmi5x, 125e6, margin=0)
82+
83+
# VideoProc PLL
84+
self.submodules.videoproc_pll = videoproc_pll = ECP5PLL()
85+
self.comb += videoproc_pll.reset.eq(rst | self.rst)
86+
videoproc_pll.register_clkin(clk25, 25e6)
87+
self.clock_domains.cd_videoproc = ClockDomain()
88+
self.clock_domains.cd_xclk = ClockDomain()
89+
videoproc_pll.create_clkout(self.cd_videoproc, 100e6, margin=0)
90+
videoproc_pll.create_clkout(self.cd_xclk, 25e6, margin=0)
91+
self.specials += DDROutput(1, 0, platform.request("ov7670_xclk"), ClockSignal("xclk"))
92+
93+
self.clock_domains.cd_pclk = cd_pclk = ClockDomain()
94+
self.comb += cd_pclk.clk.eq(platform.request("ov7670_pclk"))
95+
self.specials += AsyncResetSynchronizer(cd_pclk, rst | self.rst)
96+
97+
# SDRAM clock
98+
sdram_clk = ClockSignal("sys2x_ps" if sdram_rate == "1:2" else "sys_ps")
99+
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk)
100+
101+
# Prevent ESP32 from resetting FPGA
102+
self.comb += platform.request("wifi_gpio0").eq(1)
103+
104+
# BaseSoC ------------------------------------------------------------------------------------------
105+
106+
class BaseSoC(SoCCore):
107+
def __init__(self, device="LFE5U-45F", revision="2.0", toolchain="trellis",
108+
sys_clk_freq=int(50e6), sdram_module_cls="MT48LC16M16", sdram_rate="1:1",
109+
with_led_chaser=True, with_video_terminal=False, with_video_framebuffer=False,
110+
with_spi_flash=False, **kwargs):
111+
platform = radiona_ulx3s.Platform(device=device, revision=revision, toolchain=toolchain)
112+
platform.add_extension([
113+
("i2c", 0,
114+
Subsignal("scl", Pins("C6"), IOStandard("LVCMOS33"), Misc("DRIVE=4"), Misc("PULLMODE=UP")), # GP6
115+
Subsignal("sda", Pins("C7"), IOStandard("LVCMOS33"), Misc("DRIVE=4"), Misc("PULLMODE=UP")) # GN6
116+
),
117+
("ov7670_xclk", 0, Pins("B11"), IOStandard("LVCMOS33")), # GP0
118+
("ov7670_pclk", 0, Pins("N16"), IOStandard("LVCMOS33")),
119+
("ov7670", 0,
120+
Subsignal("href", Pins("N17"), IOStandard("LVCMOS33")),
121+
Subsignal("vsync", Pins("P16"), IOStandard("LVCMOS33")),
122+
Subsignal("data", Pins("C16 D16 B17 C17 B15 C15 C18 D17"), IOStandard("LVCMOS33")),
123+
)
124+
])
125+
126+
# CRG --------------------------------------------------------------------------------------
127+
with_usb_pll = kwargs.get("uart_name", None) == "usb_acm"
128+
with_video_pll = with_video_terminal or with_video_framebuffer
129+
self.submodules.crg = _CRG(platform, sys_clk_freq, with_usb_pll, with_video_pll, sdram_rate=sdram_rate)
130+
131+
# SoCCore ----------------------------------------------------------------------------------
132+
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on ULX3S", **kwargs)
133+
134+
# SDR SDRAM --------------------------------------------------------------------------------
135+
if not self.integrated_main_ram_size:
136+
sdrphy_cls = HalfRateGENSDRPHY if sdram_rate == "1:2" else GENSDRPHY
137+
self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"), sys_clk_freq)
138+
self.add_sdram("sdram",
139+
phy = self.sdrphy,
140+
module = getattr(litedram_modules, sdram_module_cls)(sys_clk_freq, sdram_rate),
141+
size = 0x40000000,
142+
l2_cache_size = kwargs.get("l2_size", 8192)
143+
)
144+
145+
# Video ------------------------------------------------------------------------------------
146+
if with_video_terminal or with_video_framebuffer:
147+
self.submodules.videophy = VideoHDMIPHY(platform.request("gpdi"), clock_domain="hdmi")
148+
if with_video_terminal:
149+
self.add_video_terminal(phy=self.videophy, timings="640x480@75Hz", clock_domain="hdmi")
150+
if with_video_framebuffer:
151+
self.add_video_framebuffer(phy=self.videophy, timings="640x480@75Hz", clock_domain="hdmi")
152+
153+
# SPI Flash --------------------------------------------------------------------------------
154+
if with_spi_flash:
155+
from litespi.modules import IS25LP128
156+
from litespi.opcodes import SpiNorFlashOpCodes as Codes
157+
self.add_spi_flash(mode="4x", module=IS25LP128(Codes.READ_1_1_4))
158+
159+
# Leds -------------------------------------------------------------------------------------
160+
if with_led_chaser:
161+
self.submodules.leds = LedChaser(
162+
pads = platform.request_all("user_led"),
163+
sys_clk_freq = sys_clk_freq)
164+
165+
# I2C --------------------------------------------------------------------------------------
166+
pads = platform.request("i2c", 0)
167+
self.submodules.i2c = I2CMaster(pads)
168+
169+
#ov7670_pads = platform.request("ov7670", 0)
170+
#self.submodules.ov7670 = OV7670(pads = ov7670_pads, clock_domain="videoproc")
171+
172+
173+
174+
# Build --------------------------------------------------------------------------------------------
175+
176+
def main():
177+
from litex.soc.integration.soc import LiteXSoCArgumentParser
178+
parser = LiteXSoCArgumentParser(description="LiteX SoC on ULX3S")
179+
target_group = parser.add_argument_group(title="Target options")
180+
target_group.add_argument("--build", action="store_true", help="Build design.")
181+
target_group.add_argument("--load", action="store_true", help="Load bitstream.")
182+
target_group.add_argument("--toolchain", default="trellis", help="FPGA toolchain (trellis or diamond).")
183+
target_group.add_argument("--device", default="LFE5U-45F", help="FPGA device (LFE5U-12F, LFE5U-25F, LFE5U-45F or LFE5U-85F).")
184+
target_group.add_argument("--revision", default="2.0", help="Board revision (2.0 or 1.7).")
185+
target_group.add_argument("--sys-clk-freq", default=50e6, help="System clock frequency.")
186+
target_group.add_argument("--sdram-module", default="MT48LC16M16", help="SDRAM module (MT48LC16M16, AS4C32M16 or AS4C16M16).")
187+
target_group.add_argument("--with-spi-flash", action="store_true", help="Enable SPI Flash (MMAPed).")
188+
sdopts = target_group.add_mutually_exclusive_group()
189+
sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.")
190+
sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support.")
191+
target_group.add_argument("--with-oled", action="store_true", help="Enable SDD1331 OLED support.")
192+
target_group.add_argument("--sdram-rate", default="1:1", help="SDRAM Rate (1:1 Full Rate or 1:2 Half Rate).")
193+
viopts = target_group.add_mutually_exclusive_group()
194+
viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (HDMI).")
195+
viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (HDMI).")
196+
builder_args(parser)
197+
soc_core_args(parser)
198+
trellis_args(parser)
199+
args = parser.parse_args()
200+
201+
soc = BaseSoC(
202+
device = args.device,
203+
revision = args.revision,
204+
toolchain = args.toolchain,
205+
sys_clk_freq = int(float(args.sys_clk_freq)),
206+
sdram_module_cls = args.sdram_module,
207+
sdram_rate = args.sdram_rate,
208+
with_video_terminal = args.with_video_terminal,
209+
with_video_framebuffer = args.with_video_framebuffer,
210+
with_spi_flash = args.with_spi_flash,
211+
**soc_core_argdict(args))
212+
if args.with_spi_sdcard:
213+
soc.add_spi_sdcard()
214+
if args.with_sdcard:
215+
soc.add_sdcard()
216+
if args.with_oled:
217+
soc.add_oled()
218+
219+
builder = Builder(soc, **builder_argdict(args))
220+
builder_kargs = trellis_argdict(args) if args.toolchain == "trellis" else {}
221+
if args.build:
222+
builder.build(**builder_kargs)
223+
224+
if args.load:
225+
prog = soc.platform.create_programmer()
226+
prog.load_bitstream(builder.get_bitstream_filename(mode="sram", ext=".svf")) # FIXME
227+
228+
if __name__ == "__main__":
229+
main()

0 commit comments

Comments
 (0)