diff --git a/.bsp/sbt.json b/.bsp/sbt.json new file mode 100644 index 00000000..38bad7f1 --- /dev/null +++ b/.bsp/sbt.json @@ -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"]} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7baed033..d5182cc9 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,32 @@ debug.log .vscode +.idea obj_dir *.fst -imgui.ini \ No newline at end of file +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 diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/hardware.bin b/blocks/verilog/utils/spi/alhambra_ii/spi_controller/hardware.bin deleted file mode 100644 index 16b10321..00000000 Binary files a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/hardware.bin and /dev/null differ diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/hardware.bin b/blocks/verilog/utils/spi/alhambra_ii/spi_poc/hardware.bin deleted file mode 100644 index f97ef724..00000000 Binary files a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/hardware.bin and /dev/null differ diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/hardware.bin b/blocks/verilog/utils/spi/alhambra_ii/spi_rom/hardware.bin deleted file mode 100644 index 7a4dd5fa..00000000 Binary files a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/hardware.bin and /dev/null differ diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/hardware.bin b/blocks/verilog/utils/uart/uart_rx_leds/src/hardware.bin deleted file mode 100644 index 45b1b704..00000000 Binary files a/blocks/verilog/utils/uart/uart_rx_leds/src/hardware.bin and /dev/null differ diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/hardware.bin b/blocks/verilog/utils/uart/uart_rx_pwm/src/hardware.bin deleted file mode 100644 index d2a5e146..00000000 Binary files a/blocks/verilog/utils/uart/uart_rx_pwm/src/hardware.bin and /dev/null differ diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.bin b/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.bin deleted file mode 100644 index 9e0d3753..00000000 Binary files a/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.bin and /dev/null differ diff --git a/build.sbt b/build.sbt new file mode 100644 index 00000000..79d4a8f0 --- /dev/null +++ b/build.sbt @@ -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 diff --git a/designs/cam_to_hdmi/radiona_ulx3s.py b/designs/cam_to_hdmi/radiona_ulx3s.py new file mode 100755 index 00000000..e90f71ca --- /dev/null +++ b/designs/cam_to_hdmi/radiona_ulx3s.py @@ -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 +# Copyright (c) 2018 David Shah +# 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() diff --git a/designs/cam_to_hdmi/sim.py b/designs/cam_to_hdmi/sim.py new file mode 100755 index 00000000..9a67a41a --- /dev/null +++ b/designs/cam_to_hdmi/sim.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX. +# +# Copyright (c) 2015-2020 Florent Kermarrec +# Copyright (c) 2020 Antmicro +# Copyright (c) 2017 Pierre-Olivier Vauboin +# SPDX-License-Identifier: BSD-2-Clause + +import sys +import argparse + +from litex.soc.cores.bitbang import I2CMasterSim +from migen import * + +from litex.build.generic_platform import * +from litex.build.sim import SimPlatform +from litex.build.sim.config import SimConfig +from litex.build.sim.verilator import verilator_build_args, verilator_build_argdict + +from litex.tools.litex_sim import generate_gtkw_savefile + +from litex.soc.integration.common import * +from litex.soc.integration.soc_core import * +from litex.soc.integration.builder import * +from litex.soc.integration.soc import * +from litex.soc.cores.gpio import GPIOTristate +from litex.soc.cores.cpu import CPUS + +from litedram import modules as litedram_modules +from litedram.modules import parse_spd_hexdump +from litedram.phy.model import sdram_module_nphases, get_sdram_phy_settings +from litedram.phy.model import SDRAMPHYModel + +#from fpga_robotics.cores.video.ov7670 import OV7670, OV7670Emulator + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + # Clk / Rst. + ("sys_clk", 0, Pins(1)), + ("sys_rst", 0, Pins(1)), + + # Serial. + ("serial", 0, + Subsignal("source_valid", Pins(1)), + Subsignal("source_ready", Pins(1)), + Subsignal("source_data", Pins(8)), + + Subsignal("sink_valid", Pins(1)), + Subsignal("sink_ready", Pins(1)), + Subsignal("sink_data", Pins(8)), + ), + + # I2C. + ("i2c", 0, + Subsignal("scl", Pins(1)), + Subsignal("sda_out", Pins(1)), + Subsignal("sda_in", Pins(1)), + ), + + # Tristate GPIOs (for sim control/status). + ("gpio", 0, + Subsignal("oe", Pins(32)), + Subsignal("o", Pins(32)), + Subsignal("i", Pins(32)), + ), + + ("ov7670", 0, + Subsignal("xclk", Pins(1)), + Subsignal("pclk", Pins(1)), + Subsignal("href", Pins(1)), + Subsignal("vsync", Pins(1)), + Subsignal("data", Pins(8)), + ) +] + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(SimPlatform): + def __init__(self): + SimPlatform.__init__(self, "SIM", _io) + +# Simulation SoC ----------------------------------------------------------------------------------- + +class SimSoC(SoCCore): + def __init__(self, + with_sdram = False, + sdram_module = "MT48LC16M16", + sdram_init = [], + sdram_data_width = 32, + sdram_spd_data = None, + sdram_verbosity = 0, + with_i2c=False, + with_gpio = False, + sim_debug = False, + trace_reset_on = False, + **kwargs): + platform = Platform() + sys_clk_freq = int(1e6) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = CRG(platform.request("sys_clk")) + + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, clk_freq=sys_clk_freq, + ident = "LiteX Simulation", + **kwargs) + + # BIOS Config ------------------------------------------------------------------------------ + # FIXME: Expose? + #self.add_config("BIOS_NO_PROMPT") + #self.add_config("BIOS_NO_DELAYS") + #self.add_config("BIOS_NO_BUILD_TIME") + #self.add_config("BIOS_NO_CRC") + + # SDRAM ------------------------------------------------------------------------------------ + if not self.integrated_main_ram_size and with_sdram: + sdram_clk_freq = int(100e6) # FIXME: use 100MHz timings + if sdram_spd_data is None: + sdram_module_cls = getattr(litedram_modules, sdram_module) + sdram_rate = "1:{}".format(sdram_module_nphases[sdram_module_cls.memtype]) + sdram_module = sdram_module_cls(sdram_clk_freq, sdram_rate) + else: + sdram_module = litedram_modules.SDRAMModule.from_spd_data(sdram_spd_data, sdram_clk_freq) + self.submodules.sdrphy = SDRAMPHYModel( + module = sdram_module, + data_width = sdram_data_width, + clk_freq = sdram_clk_freq, + verbosity = sdram_verbosity, + init = sdram_init) + self.add_sdram("sdram", + phy = self.sdrphy, + module = sdram_module, + l2_cache_size = kwargs.get("l2_size", 8192), + l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128), + l2_cache_reverse = False + ) + if sdram_init != []: + # Skip SDRAM test to avoid corrupting pre-initialized contents. + self.add_constant("SDRAM_TEST_DISABLE") + else: + # Reduce memtest size for simulation speedup + self.add_constant("MEMTEST_DATA_SIZE", 8*1024) + self.add_constant("MEMTEST_ADDR_SIZE", 8*1024) + + # I2C -------------------------------------------------------------------------------------- + if with_i2c: + pads = platform.request("i2c", 0) + self.submodules.i2c = I2CMasterSim(pads) + + # GPIO -------------------------------------------------------------------------------------- + if with_gpio: + self.submodules.gpio = GPIOTristate(platform.request("gpio"), with_irq=True) + self.irq.add("gpio", use_loc_if_exists=True) + + #self.submodules.ov7670_emu = ov7670_emu = OV7670Emulator() + #self.submodules.ov7670 = OV7670(pads = ov7670_emu.pads) + + # Simulation debugging ---------------------------------------------------------------------- + if sim_debug: + platform.add_debug(self, reset=1 if trace_reset_on else 0) + else: + self.comb += platform.trace.eq(1) + +# Build -------------------------------------------------------------------------------------------- + +def sim_args(parser): + builder_args(parser) + soc_core_args(parser) + verilator_build_args(parser) + parser.add_argument("--rom-init", default=None, help="ROM init file (.bin or .json).") + parser.add_argument("--ram-init", default=None, help="RAM init file (.bin or .json).") + parser.add_argument("--with-sdram", action="store_true", help="Enable SDRAM support.") + parser.add_argument("--sdram-module", default="MT48LC16M16", help="Select SDRAM chip.") + parser.add_argument("--sdram-data-width", default=32, help="Set SDRAM chip data width.") + parser.add_argument("--sdram-init", default=None, help="SDRAM init file (.bin or .json).") + parser.add_argument("--sdram-from-spd-dump", default=None, help="Generate SDRAM module based on data from SPD EEPROM dump.") + parser.add_argument("--sdram-verbosity", default=0, help="Set SDRAM checker verbosity.") + parser.add_argument("--with-gpio", action="store_true", help="Enable Tristate GPIO (32 pins).") + parser.add_argument("--sim-debug", action="store_true", help="Add simulation debugging modules.") + parser.add_argument("--gtkwave-savefile", action="store_true", help="Generate GTKWave savefile.") + parser.add_argument("--non-interactive", action="store_true", help="Run simulation without user input.") + +def main(): + from litex.soc.integration.soc import LiteXSoCArgumentParser + parser = LiteXSoCArgumentParser(description="LiteX SoC Simulation utility") + sim_args(parser) + args = parser.parse_args() + + soc_kwargs = soc_core_argdict(args) + builder_kwargs = builder_argdict(args) + verilator_build_kwargs = verilator_build_argdict(args) + + sys_clk_freq = int(1e6) + sim_config = SimConfig() + sim_config.add_clocker("sys_clk", freq_hz=sys_clk_freq) + + # Configuration -------------------------------------------------------------------------------- + + cpu = CPUS.get(soc_kwargs.get("cpu_type", "vexriscv")) + bus_data_width = int(soc_kwargs["bus_data_width"]) + + # UART. + if soc_kwargs["uart_name"] == "serial": + soc_kwargs["uart_name"] = "sim" + sim_config.add_module("serial2console", "serial") + + # ROM. + if args.rom_init: + soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init, + data_width = bus_data_width, + endianness = cpu.endianness + ) + + # RAM / SDRAM. + ram_boot_offset = 0x40000000 # FIXME + ram_boot_address = None + soc_kwargs["integrated_main_ram_size"] = args.integrated_main_ram_size + if args.integrated_main_ram_size: + if args.ram_init is not None: + soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init, + data_width = bus_data_width, + endianness = cpu.endianness, + offset = ram_boot_offset + ) + ram_boot_address = get_boot_address(args.ram_init) + elif args.with_sdram: + assert args.ram_init is None + soc_kwargs["sdram_module"] = args.sdram_module + soc_kwargs["sdram_data_width"] = int(args.sdram_data_width) + soc_kwargs["sdram_verbosity"] = int(args.sdram_verbosity) + if args.sdram_from_spd_dump: + soc_kwargs["sdram_spd_data"] = parse_spd_hexdump(args.sdram_from_spd_dump) + if args.sdram_init is not None: + soc_kwargs["sdram_init"] = get_mem_data(args.sdram_init, + data_width = bus_data_width, + endianness = cpu.endianness, + offset = ram_boot_offset + ) + ram_boot_address = get_boot_address(args.sdram_init) + + # SoC ------------------------------------------------------------------------------------------ + soc = SimSoC( + with_sdram = args.with_sdram, + with_i2c = True, + with_gpio = args.with_gpio, + sim_debug = args.sim_debug, + trace_reset_on = int(float(args.trace_start)) > 0 or int(float(args.trace_end)) > 0, + **soc_kwargs) + if ram_boot_address is not None: + if ram_boot_address == 0: + ram_boot_address = ram_boot_offset + soc.add_constant("ROM_BOOT_ADDRESS", ram_boot_address) + + # Build/Run ------------------------------------------------------------------------------------ + def pre_run_callback(vns): + if args.trace: + generate_gtkw_savefile(builder, vns, args.trace_fst) + + builder = Builder(soc, **builder_kwargs) + builder.build( + sim_config = sim_config, + interactive = not args.non_interactive, + pre_run_callback = pre_run_callback, + **verilator_build_kwargs, + ) + +if __name__ == "__main__": + main() diff --git a/designs/cam_to_hdmi/software/bios/Makefile b/designs/cam_to_hdmi/software/bios/Makefile new file mode 100644 index 00000000..17d3a040 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/Makefile @@ -0,0 +1,52 @@ +BUILD_DIR?=../build/ + +include $(BUILD_DIR)/software/include/generated/variables.mak +include $(SOC_DIRECTORY)/software/common.mak + +OBJDUMP := $(TARGET_PREFIX)objdump + +OBJECTS = delay.o sccb.o ov7670.o main.o isr.o crt0.o + +CFLAGS += -DDEBUG=1 + +all: bios.bin + $(PYTHON) -m litex.soc.software.memusage bios.elf $(BUILD_DIR)/software/include/generated/regions.ld $(TRIPLE) + +# pull in dependency info for *existing* .o files +-include $(OBJECTS:.o=.d) + +%.bin: %.elf + $(OBJCOPY) -O binary $< $@ + chmod -x $@ + +bios.elf: $(OBJECTS) + $(CC) $(LDFLAGS) -T linker.ld -N -o $@ \ + $(OBJECTS) \ + $(PACKAGES:%=-L$(BUILD_DIR)/software/%) \ + -Wl,--gc-sections \ + -Wl,-Map,$@.map \ + $(LIBS:lib%=-l%) + chmod -x $@ + +%.asm: %.elf + $(OBJDUMP) -S -d $^ > $@ + +main.o: main.c + $(compile) + +crt0.o: $(CPU_DIRECTORY)/crt0.S + $(assemble) + +%.o: %.cpp + $(compilexx) + +%.o: %.c + $(compile) + +%.o: %.S + $(assemble) + +clean: + $(RM) $(OBJECTS) $(OBJECTS:.o=.d) bios.elf bios.bin .*~ *~ + +.PHONY: all main.o clean load diff --git a/designs/cam_to_hdmi/software/bios/delay.c b/designs/cam_to_hdmi/software/bios/delay.c new file mode 100644 index 00000000..2108c358 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/delay.c @@ -0,0 +1,18 @@ +#include "delay.h" +#include "generated/soc.h" + +#define MS_PERIOD_CYCLES (CONFIG_CLOCK_FREQUENCY / 1000) + + +static inline void cdelay(int i) +{ + while(i > 0) { + __asm__ volatile(CONFIG_CPU_NOP); + i--; + } +} + +void delay(unsigned int ms) +{ + cdelay(MS_PERIOD_CYCLES*ms); +} \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/delay.h b/designs/cam_to_hdmi/software/bios/delay.h new file mode 100644 index 00000000..d00d9c2a --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/delay.h @@ -0,0 +1,3 @@ +#pragma once + +void delay(unsigned int ms); \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/isr.c b/designs/cam_to_hdmi/software/bios/isr.c new file mode 100644 index 00000000..ade38b7c --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/isr.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +void isr(void); + +#ifdef CONFIG_CPU_HAS_INTERRUPT + +void isr(void) { + __attribute__((unused)) unsigned int irqs; + + irqs = irq_pending() & irq_getmask(); + +#ifndef UART_POLLING + if (irqs & (1 << UART_INTERRUPT)) uart_isr(); +#endif +} + +#else + +void isr(void){}; + +#endif diff --git a/designs/cam_to_hdmi/software/bios/linker-rom.ld b/designs/cam_to_hdmi/software/bios/linker-rom.ld new file mode 100644 index 00000000..66f8b9af --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/linker-rom.ld @@ -0,0 +1,94 @@ +INCLUDE generated/output_format.ld +ENTRY(_start) + +INCLUDE generated/regions.ld + +SECTIONS +{ + .text : + { + _ftext = .; + /* ARM (Quicklogic EOS-S3, Gowin EMCU) interrupt vector tables use section name "isr_vector" */ + /* - such a table has to be placed at start */ + KEEP(*(.isr_vector)) + /* Make sure crt0 files come first, and they, and the isr */ + /* don't get disposed of by greedy optimisation */ + *crt0*(.text) + KEEP(*crt0*(.text)) + KEEP(*(.text.isr)) + + *(.text .stub .text.* .gnu.linkonce.t.*) + _etext = .; + } > rom + + .rodata : + { + . = ALIGN(8); + _frodata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got .got.*) + *(.toc .toc.*) + + /* Make sure the file is aligned on disk as well + as in memory; CRC calculation requires that. */ + FILL(0); + . = ALIGN(8); + _erodata = .; + } > rom + + .commands : + { + PROVIDE_HIDDEN (__bios_cmd_start = .); + KEEP(*(.bios_cmd)) + PROVIDE_HIDDEN (__bios_cmd_end = .); + } > rom + + .init : + { + PROVIDE_HIDDEN (__bios_init_start = .); + KEEP(*(.bios_init)) + PROVIDE_HIDDEN (__bios_init_end = .); + } > rom + + .data : + { + . = ALIGN(8); + _fdata = .; + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + *(.sdata .sdata.* .gnu.linkonce.s.*) + + /* Make sure the file is aligned on disk as well + as in memory; CRC calculation requires that. */ + FILL(0); + . = ALIGN(8); + _edata = .; + } > sram AT > rom + + .bss : + { + . = ALIGN(8); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + _ebss = .; + _end = .; + } > sram + + /DISCARD/ : + { + *(.eh_frame) + *(.comment) + } +} + +PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram)); + +PROVIDE(_fdata_rom = LOADADDR(.data)); +PROVIDE(_edata_rom = LOADADDR(.data) + SIZEOF(.data)); diff --git a/designs/cam_to_hdmi/software/bios/linker.ld b/designs/cam_to_hdmi/software/bios/linker.ld new file mode 100644 index 00000000..9b5f1423 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/linker.ld @@ -0,0 +1,64 @@ +INCLUDE generated/output_format.ld +ENTRY(_start) + +__DYNAMIC = 0; + +INCLUDE generated/regions.ld + +SECTIONS +{ + .text : + { + _ftext = .; + /* Make sure crt0 files come first, and they, and the isr */ + /* don't get disposed of by greedy optimisation */ + *crt0*(.text) + KEEP(*crt0*(.text)) + KEEP(*(.text.isr)) + + *(.text .stub .text.* .gnu.linkonce.t.*) + _etext = .; + } > main_ram + + .rodata : + { + . = ALIGN(8); + _frodata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + . = ALIGN(8); + _erodata = .; + } > main_ram + + .data : + { + . = ALIGN(8); + _fdata = .; + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + _gp = ALIGN(16); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(8); + _edata = .; + } > sram AT > main_ram + + .bss : + { + . = ALIGN(8); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + _ebss = .; + _end = .; + } > sram +} + +PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram)); + +PROVIDE(_fdata_rom = LOADADDR(.data)); +PROVIDE(_edata_rom = LOADADDR(.data) + SIZEOF(.data)); \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/log.h b/designs/cam_to_hdmi/software/bios/log.h new file mode 100644 index 00000000..ada4a850 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/log.h @@ -0,0 +1,9 @@ +#pragma once +#include + +// https://stackoverflow.com/a/1644898 + +#define debug_print(fmt, ...) \ + do { \ + if (DEBUG) printf("%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + } while (0) diff --git a/designs/cam_to_hdmi/software/bios/main.c b/designs/cam_to_hdmi/software/bios/main.c new file mode 100644 index 00000000..c59e7e52 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/main.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "sensor.h" +#include "ov7670.h" +#include "sccb.h" +#include "log.h" + + +//------------------------------------------------- +// main - program entry point +//------------------------------------------------- + +int main(int argc, char *argv[]) { +#ifdef CONFIG_CPU_HAS_INTERRUPT + irq_setmask(0); + irq_setie(1); +#endif + uart_init(); + + debug_print("sccb init\n"); + SCCB_Init(0); + + debug_print("probing bus\n"); + uint8_t slv_addr = SCCB_Probe(OV7670_SCCB_ADDR); + debug_print("found device at %"PRIx8"\n", slv_addr); + + sensor_t ov7670_sensor; + ov7670_detect(slv_addr, &(ov7670_sensor.id)); + ov7670_sensor.slv_addr = slv_addr; + ov7670_init(&ov7670_sensor); + + debug_print("initializing ov7670 sensor\n"); + ov7670_sensor.reset(&ov7670_sensor); + ov7670_sensor.set_framesize(&ov7670_sensor, FRAMESIZE_QQVGA); + ov7670_sensor.set_pixformat(&ov7670_sensor, PIXFORMAT_RGB565); + + return 0; +} \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/ov7670.c b/designs/cam_to_hdmi/software/bios/ov7670.c new file mode 100644 index 00000000..960f1c20 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/ov7670.c @@ -0,0 +1,452 @@ +/* + * This file is part of the OpenMV project. + * author: Juan Schiavoni + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV7725 driver. + * + * + * + * 2022 David Lobato + * Modified to implement basic ov7670 handling on litex platform + */ +#include +#include +#include +#include "sccb.h" +#include "ov7670.h" +#include "ov7670_regs.h" +#include "delay.h" +#include "log.h" + +static int ov7670_clkrc = 0x01; + +/* + * The default register settings, as obtained from OmniVision. There + * is really no making sense of most of these - lots of "reserved" values + * and such. + * + * These settings give VGA YUYV. + */ +struct regval_list { + uint8_t reg_num; + uint8_t value; +}; + +static struct regval_list ov7670_default_regs[] = { + /* Sensor automatically sets output window when resolution changes. */ + {TSLB, 0x04}, + + /* Frame rate 30 fps at 12 Mhz clock */ + {CLKRC, 0x00}, + {DBLV, 0x4A}, + + {COM10, COM10_VSYNC_NEG | COM10_PCLK_FREE}, + + /* Improve white balance */ + {COM4, 0x40}, + + /* Improve color */ + {RSVD_B0, 0x84}, + + /* Enable 50/60 Hz auto detection */ + {COM11, COM11_EXP|COM11_HZAUTO}, + + /* Disable some delays */ + {HSYST, 0}, + {HSYEN, 0}, + + {MVFP, MVFP_SUN}, + + /* More reserved magic, some of which tweaks white balance */ + {AWBC1, 0x0a}, + {AWBC2, 0xf0}, + {AWBC3, 0x34}, + {AWBC4, 0x58}, + {AWBC5, 0x28}, + {AWBC6, 0x3a}, + + {AWBCTR3, 0x0a}, + {AWBCTR2, 0x55}, + {AWBCTR1, 0x11}, + {AWBCTR0, 0x9e}, + + {COM8, COM8_FAST_AUTO|COM8_STEP_UNLIMIT|COM8_AGC_EN|COM8_AEC_EN|COM8_AWB_EN}, + + /* End marker is FF because in ov7670 the address of GAIN 0 and default value too. */ + {0xFF, 0xFF}, +}; + +static struct regval_list ov7670_fmt_yuv422[] = { + { COM7, 0x0 }, /* Selects YUV mode */ + { RGB444, 0 }, /* No RGB444 please */ + { COM1, 0 }, /* CCIR601 */ + { COM15, COM15_R00FF }, + { MVFP, MVFP_SUN }, + { COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */ + { MTX1, 0x80 }, /* "matrix coefficient 1" */ + { MTX2, 0x80 }, /* "matrix coefficient 2" */ + { MTX3, 0 }, /* vb */ + { MTX4, 0x22 }, /* "matrix coefficient 4" */ + { MTX5, 0x5e }, /* "matrix coefficient 5" */ + { MTX6, 0x80 }, /* "matrix coefficient 6" */ + { COM13, COM13_UVSAT }, + { 0xff, 0xff }, /* END MARKER */ +}; + +static struct regval_list ov7670_fmt_rgb565[] = { + { COM7, COM7_FMT_RGB565 }, /* Selects RGB mode */ + { RGB444, 0 }, /* No RGB444 please */ + { COM1, 0x0 }, /* CCIR601 */ + { COM15, COM15_RGB565 |COM15_R00FF }, + { MVFP, MVFP_SUN }, + { COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */ + { MTX1, 0xb3 }, /* "matrix coefficient 1" */ + { MTX2, 0xb3 }, /* "matrix coefficient 2" */ + { MTX3, 0 }, /* vb */ + { MTX4, 0x3d }, /* "matrix coefficient 4" */ + { MTX5, 0xa7 }, /* "matrix coefficient 5" */ + { MTX6, 0xe4 }, /* "matrix coefficient 6" */ + { COM13, COM13_UVSAT }, + { 0xff, 0xff }, /* END MARKER */ +}; + + +static struct regval_list ov7670_vga[] = { + { COM3, 0x00 }, + { COM14, 0x00 }, + { SCALING_XSC, 0x3A }, + { SCALING_YSC, 0x35 }, + { SCALING_DCWCTR, 0x11 }, + { SCALING_PCLK_DIV, 0xF0 }, + { SCALING_PCLK_DELAY, 0x02 }, + { 0xff, 0xff }, +}; + +static struct regval_list ov7670_qvga[] = { + { COM3, 0x04 }, + { COM14, 0x19 }, + { SCALING_XSC, 0x3A }, + { SCALING_YSC, 0x35 }, + { SCALING_DCWCTR, 0x11 }, + { SCALING_PCLK_DIV, 0xF1 }, + { SCALING_PCLK_DELAY, 0x02 }, + { 0xff, 0xff }, +}; + +static struct regval_list ov7670_qqvga[] = { + { COM3, 0x04 }, //DCW enable + { COM14, 0x1a }, //pixel clock divided by 4, manual scaling enable, DCW and PCLK controlled by register + { SCALING_XSC, 0x3a }, + { SCALING_YSC, 0x35 }, + { SCALING_DCWCTR, 0x22 }, //downsample by 4 + { SCALING_PCLK_DIV, 0xf2 }, //pixel clock divided by 4 + { SCALING_PCLK_DELAY, 0x02 }, + { 0xff, 0xff }, +}; + +/* + * Write a list of register settings; ff/ff stops the process. + */ +static int ov7670_write_array(sensor_t *sensor, struct regval_list *vals) +{ +int ret = 0; + + while ( (vals->reg_num != 0xff || vals->value != 0xff) && (ret == 0) ) { + ret = SCCB_Write(sensor->slv_addr, vals->reg_num, vals->value); + + debug_print("reset reg %02X, W(%02X) R(%02X)\n", vals->reg_num, vals->value, SCCB_Read(sensor->slv_addr, vals->reg_num) ); + + vals++; + } + + return ret; +} + +/* + * Calculate the frame control registers. + */ +static int ov7670_frame_control(sensor_t *sensor, int hstart, int hstop, int vstart, int vstop) +{ +struct regval_list frame[7]; + + frame[0].reg_num = HSTART; + frame[0].value = (hstart >> 3); + + frame[1].reg_num = HSTOP; + frame[1].value = (hstop >> 3); + + frame[2].reg_num = HREF; + frame[2].value = (((hstop & 0x07) << 3) | (hstart & 0x07)); + + frame[3].reg_num = VSTART; + frame[3].value = (vstart >> 2); + + frame[4].reg_num = VSTOP; + frame[4].value = (vstop >> 2); + + frame[5].reg_num = VREF; + frame[5].value = (((vstop & 0x02) << 2) | (vstart & 0x02)); + + /* End mark */ + frame[5].reg_num = 0xFF; + frame[5].value = 0xFF; + + return ov7670_write_array(sensor, frame); +} + +static int reset(sensor_t *sensor) +{ + int ret; + + // Reset all registers + SCCB_Write(sensor->slv_addr, COM7, COM7_RESET); + + // Delay 10 ms + delay(10); + + ret = ov7670_write_array(sensor, ov7670_default_regs); + + // Delay + delay(30); + + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ +int ret; + + switch (pixformat) { + case PIXFORMAT_RGB565: + case PIXFORMAT_RGB888: + ret = ov7670_write_array(sensor, ov7670_fmt_rgb565); + break; + + case PIXFORMAT_YUV422: + case PIXFORMAT_GRAYSCALE: + default: + ret = ov7670_write_array(sensor, ov7670_fmt_yuv422); + break; + } + + delay(30); + + /* + * If we're running RGB565, we must rewrite clkrc after setting + * the other parameters or the image looks poor. If we're *not* + * doing RGB565, we must not rewrite clkrc or the image looks + * *really* poor. + * + * (Update) Now that we retain clkrc state, we should be able + * to write it unconditionally, and that will make the frame + * rate persistent too. + */ + if (pixformat == PIXFORMAT_RGB565) { + ret = SCCB_Write(sensor->slv_addr, CLKRC, ov7670_clkrc); + } + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret; + + // store clkrc before changing window settings... + ov7670_clkrc = SCCB_Read(sensor->slv_addr, CLKRC); + + switch (framesize){ + case FRAMESIZE_VGA: + if( (ret = ov7670_write_array(sensor, ov7670_vga)) == 0 ) { + /* These values from Omnivision */ + ret = ov7670_frame_control(sensor, 158, 14, 10, 490); + } + break; + case FRAMESIZE_QVGA: + if( (ret = ov7670_write_array(sensor, ov7670_qvga)) == 0 ) { + /* These values from Omnivision */ + ret = ov7670_frame_control(sensor, 158, 14, 10, 490); + } + break; + case FRAMESIZE_QQVGA: + if( (ret = ov7670_write_array(sensor, ov7670_qqvga)) == 0 ) { + /* These values from Omnivision */ + ret = ov7670_frame_control(sensor, 158, 14, 10, 490); + } + break; + + default: + ret = -1; + } + + delay(30); + + if (ret == 0) { + sensor->status.framesize = framesize; + } + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + uint8_t ret = 0; + // Read register scaling_xsc + uint8_t reg = SCCB_Read(sensor->slv_addr, SCALING_XSC); + + // Pattern to set color bar bit[0]=0 in every case + reg = SCALING_XSC_CBAR(reg); + + // Write pattern to SCALING_XSC + ret = SCCB_Write(sensor->slv_addr, SCALING_XSC, reg); + + // Read register scaling_ysc + reg = SCCB_Read(sensor->slv_addr, SCALING_YSC); + + // Pattern to set color bar bit[0]=0 in every case + reg = SCALING_YSC_CBAR(reg, enable); + + // Write pattern to SCALING_YSC + ret = ret | SCCB_Write(sensor->slv_addr, SCALING_YSC, reg); + + // return 0 or 0xFF + return ret; +} + +static int set_whitebal(sensor_t *sensor, int enable) +{ + // Read register COM8 + uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); + + // Set white bal on/off + reg = COM8_SET_AWB(reg, enable); + + // Write back register COM8 + return SCCB_Write(sensor->slv_addr, COM8, reg); +} + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + // Read register COM8 + uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); + + // Set white bal on/off + reg = COM8_SET_AGC(reg, enable); + + // Write back register COM8 + return SCCB_Write(sensor->slv_addr, COM8, reg); +} + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + // Read register COM8 + uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); + + // Set white bal on/off + reg = COM8_SET_AEC(reg, enable); + + // Write back register COM8 + return SCCB_Write(sensor->slv_addr, COM8, reg); +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + // Read register MVFP + uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP); + + // Set mirror on/off + reg = MVFP_SET_MIRROR(reg, enable); + + // Write back register MVFP + return SCCB_Write(sensor->slv_addr, MVFP, reg); +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + // Read register MVFP + uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP); + + // Set mirror on/off + reg = MVFP_SET_FLIP(reg, enable); + + // Write back register MVFP + return SCCB_Write(sensor->slv_addr, MVFP, reg); +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.awb = 0; + sensor->status.aec = 0; + sensor->status.agc = 0; + sensor->status.hmirror = 0; + sensor->status.vflip = 0; + sensor->status.colorbar = 0; + return 0; +} + +static int set_dummy(sensor_t *sensor, int val){ return -1; } +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; } + +int ov7670_detect(int slv_addr, sensor_id_t *id) +{ + if (OV7670_SCCB_ADDR == slv_addr) { + SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor + uint16_t PID = SCCB_Read(slv_addr, 0x0A); + if (OV7670_PID == PID) { + id->PID = PID; + id->VER = SCCB_Read(slv_addr, REG_VER); + id->MIDL = SCCB_Read(slv_addr, REG_MIDL); + id->MIDH = SCCB_Read(slv_addr, REG_MIDH); + return PID; + } else { + debug_print("Mismatch PID=0x%x\n", PID); + } + } + return 0; +} + +int ov7670_init(sensor_t *sensor) +{ + // Set function pointers + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_colorbar = set_colorbar; + sensor->set_whitebal = set_whitebal; + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + //not supported + sensor->set_brightness= set_dummy; + sensor->set_saturation= set_dummy; + sensor->set_quality = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + sensor->set_aec2 = set_dummy; + sensor->set_aec_value = set_dummy; + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + sensor->set_dcw = set_dummy; + sensor->set_bpc = set_dummy; + sensor->set_wpc = set_dummy; + sensor->set_awb_gain = set_dummy; + sensor->set_agc_gain = set_dummy; + sensor->set_raw_gma = set_dummy; + sensor->set_lenc = set_dummy; + sensor->set_sharpness = set_dummy; + sensor->set_denoise = set_dummy; + + // Retrieve sensor's signature + sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH); + sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL); + sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID); + sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER); + + debug_print("OV7670 Attached\n"); + + return 0; +} \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/ov7670.h b/designs/cam_to_hdmi/software/bios/ov7670.h new file mode 100644 index 00000000..795f7f9d --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/ov7670.h @@ -0,0 +1,36 @@ +/* + * This file is part of the OpenMV project. + * author: Juan Schiavoni + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV7670 driver. + * + * + * 2022 David Lobato + * Modified to implement basic ov7670 handling on litex platform + */ +#ifndef __OV7670_H__ +#define __OV7670_H__ +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int ov7670_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int ov7670_init(sensor_t *sensor); + +#endif // __OV7670_H__ diff --git a/designs/cam_to_hdmi/software/bios/ov7670_regs.h b/designs/cam_to_hdmi/software/bios/ov7670_regs.h new file mode 100644 index 00000000..1678203c --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/ov7670_regs.h @@ -0,0 +1,357 @@ +/* + * This file is for the OpenMV project so the OV7670 can be used + * author: Juan Schiavoni + * + * OV7670 register definitions. + * + * 2022 David Lobato + * Modified to implement basic ov7670 handling on litex platform + */ +#ifndef __OV7670_REG_REGS_H__ +#define __OV7670_REG_REGS_H__ +#define GAIN 0x00 /* AGC – Gain control gain setting */ +#define BLUE 0x01 /* AWB – Blue channel gain setting */ +#define RED 0x02 /* AWB – Red channel gain setting */ +#define VREF 0x03 /* AWB – Green channel gain setting */ +#define COM1 0x04 /* Common Control 1 */ +#define BAVG 0x05 /* U/B Average Level */ +#define GAVG 0x06 /* Y/Gb Average Level */ +#define AECH 0x07 /* Exposure VAlue - AEC MSB 5 bits */ +#define RAVG 0x08 /* V/R Average Level */ + +#define COM2 0x09 /* Common Control 2 */ +#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */ +#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */ +#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */ +#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */ +#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */ + +#define REG_PID 0x0A /* Product ID Number MSB */ +#define REG_VER 0x0B /* Product ID Number LSB */ + +#define COM3 0x0C /* Common Control 3 */ +#define COM3_SWAP_OUT 0x40 /* Output data MSB/LSB swap */ +#define COM3_TRI_CLK 0x20 /* Tri-state output clock */ +#define COM3_TRI_DATA 0x10 /* Tri-state option output */ +#define COM3_SCALE_EN 0x08 /* Scale enable */ +#define COM3_DCW 0x04 /* DCW enable */ + +#define COM4 0x0D /* Common Control 4 */ +#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */ +#define COM4_PLL_4x 0x40 /* PLL frequency 4x */ +#define COM4_PLL_6x 0x80 /* PLL frequency 6x */ +#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */ +#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */ +#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */ +#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */ +#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */ + +#define COM5 0x0E /* Common Control 5 */ +#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */ +#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */ +#define COM5_AFR_0 0x00 /* No reduction of frame rate */ +#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */ +#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */ +#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */ +#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */ +#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */ +#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */ +#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */ + +#define COM6 0x0F /* Common Control 6 */ +#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */ + +#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */ +#define CLKRC 0x11 /* Internal Clock */ + +#define COM7 0x12 /* Common Control 7 */ +#define COM7_RESET 0x80 /* SCCB Register Reset */ +#define COM7_RES_VGA 0x00 /* Resolution VGA */ +#define COM7_RES_QVGA 0x40 /* Resolution QVGA */ +#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */ +#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */ +#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */ +#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */ +#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */ +#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */ +#define COM7_FMT_YUV 0x00 /* Output format YUV */ +#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */ +#define COM7_FMT_RGB 0x04 /* Output format RGB */ +#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */ +#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x5)<<0)) + +#define COM8 0x13 /* Common Control 8 */ +#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */ +#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */ +#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */ +#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */ +#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */ +#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */ +#define COM8_AGC_EN 0x04 /* AGC Enable */ +#define COM8_AWB_EN 0x02 /* AWB Enable */ +#define COM8_AEC_EN 0x01 /* AEC Enable */ +#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2)) +#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1)) +#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0)) + +#define COM9 0x14 /* Common Control 9 */ +#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */ +#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */ +#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */ +#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */ +#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */ +#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */ +#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ +#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ +#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4)) + +#define COM10 0x15 /* Common Control 10 */ +#define COM10_NEGATIVE 0x80 /* Output negative data */ +#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ +#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */ +#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */ +#define COM10_PCLK_REV 0x10 /* PCLK reverse */ +#define COM10_HREF_REV 0x08 /* HREF reverse */ +#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */ +#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */ +#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ +#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */ +#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */ + +#define RSVD_16 0x16 /* Reserved register */ + +#define HSTART 0x17 /* Horizontal Frame (HREF column) Start high 8-bit(low 3 bits are at HREF[2:0]) */ +#define HSTOP 0x18 /* Horizontal Frame (HREF column) end high 8-bit (low 3 bits are at HREF[5:3]) */ +#define VSTART 0x19 /* Vertical Frame (row) Start high 8-bit (low 2 bits are at VREF[1:0]) */ +#define VSTOP 0x1A /* Vertical Frame (row) End high 8-bit (low 2 bits are at VREF[3:2]) */ +#define PSHFT 0x1B /* Data Format - Pixel Delay Select */ +#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */ +#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */ + +#define MVFP 0x1E /* Mirror/Vflip Enable */ +#define MVFP_MIRROR 0x20 /* Mirror image */ +#define MVFP_FLIP 0x10 /* Vertical flip */ +#define MVFP_SUN 0x02 /* Black sun enable */ +#define MVFP_SET_MIRROR(r,x) ((r&0xDF)|((x&1)<<5)) /* change only bit5 according to x */ +#define MVFP_SET_FLIP(r,x) ((r&0xEF)|((x&1)<<4)) /* change only bit4 according to x */ + +#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period (Reserved?) */ +#define ADCCTR0 0x20 /* ADC control */ +#define ADCCTR1 0x21 /* reserved */ +#define ADCCTR2 0x22 /* reserved */ +#define ADCCTR3 0x23 /* reserved */ +#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */ +#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */ +#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */ +#define BBIAS 0x27 /* B channel signal output bias (effective only when COM6[3]=1) */ +#define GbBIAS 0x28 /* Gb channel signal output bias (effective only when COM6[3]=1) */ +#define RSVD_29 0x29 /* reserved */ +#define EXHCH 0x2A /* Dummy Pixel Insert MSB */ +#define EXHCL 0x2B /* Dummy Pixel Insert LSB */ +#define RBIAS 0x2C /* R channel signal output bias (effective only when COM6[3]=1) */ +#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */ +#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */ +#define YAVE 0x2F /* Y/G Channel Average Value */ +#define HSYST 0x30 /* HSync rising edge delay */ +#define HSYEN 0x31 /* HSync falling edge delay */ +#define HREF 0x32 /* Image Start and Size Control DIFFERENT CONTROL SEQUENCE */ +#define CHLF 0x33 /* Array Current control */ +#define ARBLM 0x34 /* Array reference control */ +#define RSVD_35 0x35 /* Reserved */ +#define RSVD_36 0x36 /* Reserved */ +#define ADC 0x37 /* ADC control */ +#define ACOM 0x38 /* ADC and analog common mode control */ +#define OFON 0x39 /* ADC offset control */ +#define TSLB 0x3A /* Line buffer test option */ + +#define COM11 0x3B /* Common control 11 */ +#define COM11_EXP 0x02 +#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ + +#define COM12 0x3C /* Common control 12 */ + +#define COM13 0x3D /* Common control 13 */ +#define COM13_GAMMA 0x80 /* Gamma enable */ +#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ + +#define COM14 0x3E /* Common Control 14 */ + +#define EDGE 0x3F /* edge enhancement adjustment */ +#define COM15 0x40 /* Common Control 15 DIFFERENT CONTROLS */ +#define COM15_SET_RGB565(r,x) ((r&0xEF)|((x&1)<<4)) /* set rgb565 mode */ +#define COM15_RGB565 0x10 /* RGB565 output */ +#define COM15_R00FF 0xC0 /* Output range: [00] to [FF] */ + +#define COM16 0x41 /* Common Control 16 DIFFERENT CONTROLS */ +#define COM16_AWBGAIN 0x08 /* AWB gain enable */ +#define COM17 0x42 /* Common Control 17 */ + +#define AWBC1 0x43 /* Reserved */ +#define AWBC2 0x44 /* Reserved */ +#define AWBC3 0x45 /* Reserved */ +#define AWBC4 0x46 /* Reserved */ +#define AWBC5 0x47 /* Reserved */ +#define AWBC6 0x48 /* Reserved */ + +#define RSVD_49 0x49 /* Reserved */ +#define RSVD_4A 0x4A /* Reserved */ + +#define REG4B 0x4B /* Register 4B */ +#define DNSTH 0x4C /* Denoise strength */ + +#define RSVD_4D 0x4D /* Reserved */ +#define RSVD_4E 0x4E /* Reserved */ + +#define MTX1 0x4F /* Matrix coefficient 1 */ +#define MTX2 0x50 /* Matrix coefficient 2 */ +#define MTX3 0x51 /* Matrix coefficient 3 */ +#define MTX4 0x52 /* Matrix coefficient 4 */ +#define MTX5 0x53 /* Matrix coefficient 5 */ +#define MTX6 0x54 /* Matrix coefficient 6 */ +#define BRIGHTNESS 0x55 /* Brightness control */ +#define CONTRAST 0x56 /* Contrast control */ +#define CONTRASCENTER 0x57 /* Contrast center */ +#define MTXS 0x58 /* Matrix coefficient sign for coefficient 5 to 0*/ + +#define RSVD_59 0x59 /* Reserved */ +#define RSVD_5A 0x5A /* Reserved */ +#define RSVD_5B 0x5B /* Reserved */ +#define RSVD_5C 0x5C /* Reserved */ +#define RSVD_5D 0x5D /* Reserved */ +#define RSVD_5E 0x5E /* Reserved */ +#define RSVD_5F 0x5F /* Reserved */ +#define RSVD_60 0x60 /* Reserved */ +#define RSVD_61 0x61 /* Reserved */ + +#define LCC1 0x62 /* Lens correction option 1 */ + +#define LCC2 0x63 /* Lens correction option 2 */ +#define LCC3 0x64 /* Lens correction option 3 */ +#define LCC4 0x65 /* Lens correction option 4 */ +#define LCC5 0x66 /* Lens correction option 5 */ + +#define MANU 0x67 /* Manual U Value */ +#define MANV 0x68 /* Manual V Value */ +#define GFIX 0x69 /* Fix gain control */ +#define GGAIN 0x6A /* G channel AWB gain */ + +#define DBLV 0x6B /* PLL and clock ? */ + +#define AWBCTR3 0x6C /* AWB Control 3 */ +#define AWBCTR2 0x6D /* AWB Control 2 */ +#define AWBCTR1 0x6E /* AWB Control 1 */ +#define AWBCTR0 0x6F /* AWB Control 0 */ +#define SCALING_XSC 0x70 /* test pattern and horizontal scaling factor */ +#define SCALING_XSC_CBAR(r) (r&0x7F) /* make sure bit7 is 0 for color bar */ +#define SCALING_YSC 0x71 /* test pattern and vertical scaling factor */ +#define SCALING_YSC_CBAR(r,x) ((r&0x7F)|((x&1)<<7)) /* change bit7 for color bar on/off */ +#define SCALING_DCWCTR 0x72 /* DCW control */ +#define SCALING_PCLK_DIV 0x73 /* */ +#define REG74 0x74 /* */ +#define REG75 0x75 /* */ +#define REG76 0x76 /* */ +#define REG77 0x77 /* */ + +#define RSVD_78 0x78 /* Reserved */ +#define RSVD_79 0x79 /* Reserved */ + +#define SLOP 0x7A /* Gamma curve highest segment slope */ +#define GAM1 0x7B /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */ +#define GAM2 0x7C /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */ +#define GAM3 0x7D /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */ +#define GAM4 0x7E /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */ +#define GAM5 0x7F /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */ +#define GAM6 0x80 /* Gamma Curve 6rd Segment Input End Point 0x30 Output Value */ +#define GAM7 0x81 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */ +#define GAM8 0x82 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */ +#define GAM9 0x83 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */ +#define GAM10 0x84 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */ +#define GAM11 0x85 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */ +#define GAM12 0x86 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */ +#define GAM13 0x87 /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */ +#define GAM14 0x88 /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */ +#define GAM15 0x89 /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */ + +#define RSVD_8A 0x8A /* Reserved */ +#define RSVD_8B 0x8B /* Reserved */ + +#define RGB444 0x8C /* */ + +#define RSVD_8D 0x8D /* Reserved */ +#define RSVD_8E 0x8E /* Reserved */ +#define RSVD_8F 0x8F /* Reserved */ +#define RSVD_90 0x90 /* Reserved */ +#define RSVD_91 0x91 /* Reserved */ + +#define DM_LNL 0x92 /* Dummy line low 8 bit */ +#define DM_LNH 0x93 /* Dummy line high 8 bit */ +#define LCC6 0x94 /* Lens correction option 6 */ +#define LCC7 0x95 /* Lens correction option 7 */ + +#define RSVD_96 0x96 /* Reserved */ +#define RSVD_97 0x97 /* Reserved */ +#define RSVD_98 0x98 /* Reserved */ +#define RSVD_99 0x99 /* Reserved */ +#define RSVD_9A 0x9A /* Reserved */ +#define RSVD_9B 0x9B /* Reserved */ +#define RSVD_9C 0x9C /* Reserved */ + +#define BD50ST 0x9D /* 50 Hz banding filter value */ +#define BD60ST 0x9E /* 60 Hz banding filter value */ +#define HAECC1 0x9F /* Histogram-based AEC/AGC control 1 */ +#define HAECC2 0xA0 /* Histogram-based AEC/AGC control 2 */ + +#define RSVD_A1 0xA1 /* Reserved */ + +#define SCALING_PCLK_DELAY 0xA2 /* Pixel clock delay */ + +#define RSVD_A3 0xA3 /* Reserved */ + +#define NT_CNTRL 0xA4 /* */ +#define BD50MAX 0xA5 /* 50 Hz banding step limit */ +#define HAECC3 0xA6 /* Histogram-based AEC/AGC control 3 */ +#define HAECC4 0xA7 /* Histogram-based AEC/AGC control 4 */ +#define HAECC5 0xA8 /* Histogram-based AEC/AGC control 5 */ +#define HAECC6 0xA9 /* Histogram-based AEC/AGC control 6 */ + +#define HAECC7 0xAA /* Histogram-based AEC/AGC control 7 */ +#define HAECC_EN 0x80 /* Histogram-based AEC algorithm enable */ + +#define BD60MAX 0xAB /* 60 Hz banding step limit */ + +#define STR_OPT 0xAC /* Register AC */ +#define STR_R 0xAD /* R gain for led output frame */ +#define STR_G 0xAE /* G gain for led output frame */ +#define STR_B 0xAF /* B gain for led output frame */ +#define RSVD_B0 0xB0 /* Reserved */ +#define ABLC1 0xB1 /* */ +#define RSVD_B2 0xB2 /* Reserved */ +#define THL_ST 0xB3 /* ABLC target */ +#define THL_DLT 0xB5 /* ABLC stable range */ + +#define RSVD_B6 0xB6 /* Reserved */ +#define RSVD_B7 0xB7 /* Reserved */ +#define RSVD_B8 0xB8 /* Reserved */ +#define RSVD_B9 0xB9 /* Reserved */ +#define RSVD_BA 0xBA /* Reserved */ +#define RSVD_BB 0xBB /* Reserved */ +#define RSVD_BC 0xBC /* Reserved */ +#define RSVD_BD 0xBD /* Reserved */ + +#define AD_CHB 0xBE /* blue channel black level compensation */ +#define AD_CHR 0xBF /* Red channel black level compensation */ +#define AD_CHGb 0xC0 /* Gb channel black level compensation */ +#define AD_CHGr 0xC1 /* Gr channel black level compensation */ + +#define RSVD_C2 0xC2 /* Reserved */ +#define RSVD_C3 0xC3 /* Reserved */ +#define RSVD_C4 0xC4 /* Reserved */ +#define RSVD_C5 0xC5 /* Reserved */ +#define RSVD_C6 0xC6 /* Reserved */ +#define RSVD_C7 0xC7 /* Reserved */ +#define RSVD_C8 0xC8 /* Reserved */ + +#define SATCTR 0xC9 /* Saturation control */ +#define SET_REG(reg, x) (##reg_DEFAULT|x) + +#endif //__OV7670_REG_REGS_H__ \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/sccb.c b/designs/cam_to_hdmi/software/bios/sccb.c new file mode 100644 index 00000000..cc2f4011 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/sccb.c @@ -0,0 +1,65 @@ +#include "sccb.h" +#include "sensor.h" +#include "log.h" +#include +#include + +static int sccb_i2c_port; + +int SCCB_Init(int i2c_num) +{ + if (i2c_num < 0 || i2c_num > get_i2c_devs_count()) { + return -1; + } + set_i2c_active_dev(i2c_num); + sccb_i2c_port = i2c_num; + i2c_reset(); + + return 0; +} + +int SCCB_Deinit(void) +{ + return 0; +} + +uint8_t SCCB_Probe(uint8_t slv_addr) +{ + if(i2c_poll(slv_addr)) { + return slv_addr; + } + + return 0; +} + +uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) +{ + uint8_t data=0; + + if (!i2c_read(slv_addr, reg, &data, 1, true)) { + debug_print("SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x\n", slv_addr, reg, data); + return -1; + } + + return data; +} + +uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) +{ + if (!i2c_write(slv_addr, reg, &data, 1)) { + debug_print("SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x\n", slv_addr, reg, data); + return -1; + } + + return 0; +} + +uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) +{ + return 0;//not implemented +} + +uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) +{ + return 0;//not implemented +} \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/sccb.h b/designs/cam_to_hdmi/software/bios/sccb.h new file mode 100644 index 00000000..4664811b --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/sccb.h @@ -0,0 +1,24 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * SCCB (I2C like) driver. + * + * + * 2022 David Lobato + * Modified to implement basic ov7670 handling on litex platform + */ +#ifndef __SCCB_H__ +#define __SCCB_H__ +#include + +int SCCB_Init(int sccb_i2c_port); +int SCCB_Deinit(void); +uint8_t SCCB_Probe(uint8_t slv_addr); +uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); +uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); +uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); +uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); + +#endif // __SCCB_H__ \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/sensor.c b/designs/cam_to_hdmi/software/bios/sensor.c new file mode 100644 index 00000000..128934ac --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/sensor.c @@ -0,0 +1,2 @@ +#include +#include "sensor.h" \ No newline at end of file diff --git a/designs/cam_to_hdmi/software/bios/sensor.h b/designs/cam_to_hdmi/software/bios/sensor.h new file mode 100644 index 00000000..bbd23155 --- /dev/null +++ b/designs/cam_to_hdmi/software/bios/sensor.h @@ -0,0 +1,257 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * Sensor abstraction layer. + * + * + * 2022 David Lobato + * Modified to implement basic ov7670 handling on litex platform + */ +#ifndef __SENSOR_H__ +#define __SENSOR_H__ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + OV9650_PID = 0x96, + OV7725_PID = 0x77, + OV2640_PID = 0x26, + OV3660_PID = 0x3660, + OV5640_PID = 0x5640, + OV7670_PID = 0x76, + NT99141_PID = 0x1410, + GC2145_PID = 0x2145, + GC032A_PID = 0x232a, + GC0308_PID = 0x9b, + BF3005_PID = 0x30, + BF20A6_PID = 0x20a6, + SC101IOT_PID = 0xda4a, + SC030IOT_PID = 0x9a46, + SC031GS_PID = 0x0031, +} camera_pid_t; + +typedef enum { + CAMERA_OV7725, + CAMERA_OV2640, + CAMERA_OV3660, + CAMERA_OV5640, + CAMERA_OV7670, + CAMERA_NT99141, + CAMERA_GC2145, + CAMERA_GC032A, + CAMERA_GC0308, + CAMERA_BF3005, + CAMERA_BF20A6, + CAMERA_SC101IOT, + CAMERA_SC030IOT, + CAMERA_SC031GS, + CAMERA_MODEL_MAX, + CAMERA_NONE, +} camera_model_t; + +typedef enum { + OV2640_SCCB_ADDR = 0x30,// 0x60 >> 1 + OV5640_SCCB_ADDR = 0x3C,// 0x78 >> 1 + OV3660_SCCB_ADDR = 0x3C,// 0x78 >> 1 + OV7725_SCCB_ADDR = 0x21,// 0x42 >> 1 + OV7670_SCCB_ADDR = 0x21,// 0x42 >> 1 + NT99141_SCCB_ADDR = 0x2A,// 0x54 >> 1 + GC2145_SCCB_ADDR = 0x3C,// 0x78 >> 1 + GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1 + GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1 + BF3005_SCCB_ADDR = 0x6E, + BF20A6_SCCB_ADDR = 0x6E, + SC101IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 + SC030IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 + SC031GS_SCCB_ADDR = 0x30, +} camera_sccb_addr_t; + +typedef enum { + PIXFORMAT_RGB565, // 2BPP/RGB565 + PIXFORMAT_YUV422, // 2BPP/YUV422 + PIXFORMAT_YUV420, // 1.5BPP/YUV420 + PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE + PIXFORMAT_JPEG, // JPEG/COMPRESSED + PIXFORMAT_RGB888, // 3BPP/RGB888 + PIXFORMAT_RAW, // RAW + PIXFORMAT_RGB444, // 3BP2P/RGB444 + PIXFORMAT_RGB555, // 3BP2P/RGB555 +} pixformat_t; + +typedef enum { + FRAMESIZE_96X96, // 96x96 + FRAMESIZE_QQVGA, // 160x120 + FRAMESIZE_QCIF, // 176x144 + FRAMESIZE_HQVGA, // 240x176 + FRAMESIZE_240X240, // 240x240 + FRAMESIZE_QVGA, // 320x240 + FRAMESIZE_CIF, // 400x296 + FRAMESIZE_HVGA, // 480x320 + FRAMESIZE_VGA, // 640x480 + FRAMESIZE_SVGA, // 800x600 + FRAMESIZE_XGA, // 1024x768 + FRAMESIZE_HD, // 1280x720 + FRAMESIZE_SXGA, // 1280x1024 + FRAMESIZE_UXGA, // 1600x1200 + // 3MP Sensors + FRAMESIZE_FHD, // 1920x1080 + FRAMESIZE_P_HD, // 720x1280 + FRAMESIZE_P_3MP, // 864x1536 + FRAMESIZE_QXGA, // 2048x1536 + // 5MP Sensors + FRAMESIZE_QHD, // 2560x1440 + FRAMESIZE_WQXGA, // 2560x1600 + FRAMESIZE_P_FHD, // 1080x1920 + FRAMESIZE_QSXGA, // 2560x1920 + FRAMESIZE_INVALID +} framesize_t; + +typedef struct { + const camera_model_t model; + const char *name; + const camera_sccb_addr_t sccb_addr; + const camera_pid_t pid; + const framesize_t max_size; + const bool support_jpeg; +} camera_sensor_info_t; + +typedef enum { + ASPECT_RATIO_4X3, + ASPECT_RATIO_3X2, + ASPECT_RATIO_16X10, + ASPECT_RATIO_5X3, + ASPECT_RATIO_16X9, + ASPECT_RATIO_21X9, + ASPECT_RATIO_5X4, + ASPECT_RATIO_1X1, + ASPECT_RATIO_9X16 +} aspect_ratio_t; + +typedef enum { + GAINCEILING_2X, + GAINCEILING_4X, + GAINCEILING_8X, + GAINCEILING_16X, + GAINCEILING_32X, + GAINCEILING_64X, + GAINCEILING_128X, +} gainceiling_t; + +typedef struct { + uint16_t max_width; + uint16_t max_height; + uint16_t start_x; + uint16_t start_y; + uint16_t end_x; + uint16_t end_y; + uint16_t offset_x; + uint16_t offset_y; + uint16_t total_x; + uint16_t total_y; +} ratio_settings_t; + +typedef struct { + const uint16_t width; + const uint16_t height; + const aspect_ratio_t aspect_ratio; +} resolution_info_t; + +typedef struct { + uint8_t MIDH; + uint8_t MIDL; + uint16_t PID; + uint8_t VER; +} sensor_id_t; + +typedef struct { + framesize_t framesize;//0 - 10 + bool scale; + bool binning; + uint8_t quality;//0 - 63 + int8_t brightness;//-2 - 2 + int8_t contrast;//-2 - 2 + int8_t saturation;//-2 - 2 + int8_t sharpness;//-2 - 2 + uint8_t denoise; + uint8_t special_effect;//0 - 6 + uint8_t wb_mode;//0 - 4 + uint8_t awb; + uint8_t awb_gain; + uint8_t aec; + uint8_t aec2; + int8_t ae_level;//-2 - 2 + uint16_t aec_value;//0 - 1200 + uint8_t agc; + uint8_t agc_gain;//0 - 30 + uint8_t gainceiling;//0 - 6 + uint8_t bpc; + uint8_t wpc; + uint8_t raw_gma; + uint8_t lenc; + uint8_t hmirror; + uint8_t vflip; + uint8_t dcw; + uint8_t colorbar; +} camera_status_t; + +typedef struct _sensor sensor_t; +typedef struct _sensor { + sensor_id_t id; // Sensor ID. + uint8_t slv_addr; // Sensor I2C slave address. + pixformat_t pixformat; + camera_status_t status; + int xclk_freq_hz; + + // Sensor function pointers + int (*init_status) (sensor_t *sensor); + int (*reset) (sensor_t *sensor); // Reset the configuration of the sensor, and return ESP_OK if reset is successful + int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat); + int (*set_framesize) (sensor_t *sensor, framesize_t framesize); + int (*set_contrast) (sensor_t *sensor, int level); + int (*set_brightness) (sensor_t *sensor, int level); + int (*set_saturation) (sensor_t *sensor, int level); + int (*set_sharpness) (sensor_t *sensor, int level); + int (*set_denoise) (sensor_t *sensor, int level); + int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling); + int (*set_quality) (sensor_t *sensor, int quality); + int (*set_colorbar) (sensor_t *sensor, int enable); + int (*set_whitebal) (sensor_t *sensor, int enable); + int (*set_gain_ctrl) (sensor_t *sensor, int enable); + int (*set_exposure_ctrl) (sensor_t *sensor, int enable); + int (*set_hmirror) (sensor_t *sensor, int enable); + int (*set_vflip) (sensor_t *sensor, int enable); + + int (*set_aec2) (sensor_t *sensor, int enable); + int (*set_awb_gain) (sensor_t *sensor, int enable); + int (*set_agc_gain) (sensor_t *sensor, int gain); + int (*set_aec_value) (sensor_t *sensor, int gain); + + int (*set_special_effect) (sensor_t *sensor, int effect); + int (*set_wb_mode) (sensor_t *sensor, int mode); + int (*set_ae_level) (sensor_t *sensor, int level); + + int (*set_dcw) (sensor_t *sensor, int enable); + int (*set_bpc) (sensor_t *sensor, int enable); + int (*set_wpc) (sensor_t *sensor, int enable); + + int (*set_raw_gma) (sensor_t *sensor, int enable); + int (*set_lenc) (sensor_t *sensor, int enable); + + int (*get_reg) (sensor_t *sensor, int reg, int mask); + int (*set_reg) (sensor_t *sensor, int reg, int mask, int value); + int (*set_res_raw) (sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning); + int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk); + int (*set_xclk) (sensor_t *sensor, int timer, int xclk); +} sensor_t; + +#ifdef __cplusplus +} +#endif + +#endif /* __SENSOR_H__ */ diff --git a/doc/OV7670_2006.pdf b/doc/OV7670_2006.pdf new file mode 100644 index 00000000..dd401271 Binary files /dev/null and b/doc/OV7670_2006.pdf differ diff --git a/doc/schematics_v308.pdf b/doc/schematics_v308.pdf new file mode 100644 index 00000000..8332f1ca Binary files /dev/null and b/doc/schematics_v308.pdf differ diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/abc.history b/gateware/main/python/fpga_robotics/__init__.py similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/abc.history rename to gateware/main/python/fpga_robotics/__init__.py diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/abc.history b/gateware/main/python/fpga_robotics/cores/__init__.py similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/abc.history rename to gateware/main/python/fpga_robotics/cores/__init__.py diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/abc.history b/gateware/main/python/fpga_robotics/cores/video/__init__.py similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/abc.history rename to gateware/main/python/fpga_robotics/cores/video/__init__.py diff --git a/gateware/main/python/fpga_robotics/cores/video/ov7670.py b/gateware/main/python/fpga_robotics/cores/video/ov7670.py new file mode 100644 index 00000000..a2122824 --- /dev/null +++ b/gateware/main/python/fpga_robotics/cores/video/ov7670.py @@ -0,0 +1,177 @@ +import math +import os + +from litex.build.generic_platform import GenericPlatform, Pins, Subsignal +from litex.soc.interconnect import stream +from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus +from litex.soc.interconnect.stream import Endpoint +from migen import * +from migen.genlib.cdc import MultiReg +from migen.genlib.resetsync import AsyncResetSynchronizer + +# max resolution is 640*480 +hbits = 10 +vbits = 10 + +class OV7670Capture(Module): + def __init__(self, pads, clock_domain="sys"): + self.vsync = Signal() + self.href = Signal() + self.data = Signal(8) + + self.specials += [ + MultiReg(pads.vsync, self.vsync, clock_domain, 3), + MultiReg(pads.href, self.href, clock_domain, 3), + MultiReg(pads.data, self.data, clock_domain, 3), + ] + + # self.source = source = Endpoint([("vsync", 1), ("href", 1), ("data", 8)]) + # + # row_count = Signal(vbits) + # + # # frame edge detection + # vsync_d = Signal() + # vsync_rise = Signal() + # self.sync += vsync_d.eq(pads.vsync) + # self.comb += vsync_rise.eq(pads.vsync & ~vsync_d) + # + # # row edge detection + # href_d = Signal() + # href_rise = Signal() + # self.sync += href_d.eq(pads.href) + # self.comb += href_rise.eq(pads.href & ~href_d) + # + # self.submodules.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE")) + # fsm.act("IDLE", + # source.valid.eq(0), + # NextValue(row_count, 0), + # If(pads.vsync, NextState("CAPTURE")) + # ) + # fsm.act("CAPTURE", + # source.valid.eq(pads.href), + # source.data.eq(pads.data), + # If(vsync_rise, NextState("IDLE")), + # If(href_rise, NextValue(row_count, row_count + 1)) + # ) + # self.comb += source.first.eq(row_count == 1) + +# class OV7670CRG(Module): +# def __init__(self, pads, clock_domain="sys"): + #self.clock_domains.cd_pixel = ClockDomain() + # self.comb += self.cd_pixel.clk.eq(pads.pclk) + # self.specials += AsyncResetSynchronizer(self.cd_pixel, ResetSignal(clock_domain)) + +class OV7670FrameCounter(Module): + def __init__(self): + self.vsync = Signal() + self.counter = Signal(32) + + self.sync += If(self.vsync, self.counter.eq(self.counter + 1)) + + + +class OV7670(Module, AutoCSR): + def __init__(self, pads, clock_domain="sys"): + self.vsync = Signal() + self.href = Signal() + self.data = Signal(8) + + self.specials += [ + MultiReg(pads.vsync, self.vsync, clock_domain, 3), + MultiReg(pads.href, self.href, clock_domain, 3), + MultiReg(pads.data, self.data, clock_domain, 3), + ] + + self.submodules.frame_counter = frame_counter = ClockDomainsRenamer(clock_domain)(OV7670FrameCounter()) + self.comb += frame_counter.vsync.eq(self.vsync) + + self._frame_counter = CSRStatus(32) + self.specials += MultiReg(frame_counter.counter, self._frame_counter.status) + + #self.submodules.capture = capture = OV7670Capture(pads, clock_domain) + + + + + #self.submodules.crg = OV7670CRG(pads, clock_domain) + + # Capture + # self.submodules.capture = capture = ClockDomainsRenamer("pixel")(OV7670Capture(pads)) + # self.submodules.cdc = cdc = stream.ClockDomainCrossing( + # layout=[("data", 8)], + # cd_from="pixel", + # cd_to=clock_domain + # ) + # + # self.comb += capture.source.connect(cdc.sink) + # + # self.source = cdc.source + + +# Video Timings ------------------------------------------------------------------------------------ + +class OV7670Emulator(Module): + def __init__(self): + self.pads = pads = Record([ + ("pclk", 1), + ("vsync", 1), + ("href", 1), + ("data", 4), + ]) + + # self.enable = enable = Signal() + # self.hres = hres = Signal(hbits) + # self.hsync_start = hsync_start = Signal(hbits) + # self.hsync_end = hsync_end = Signal(hbits) + # self.hscan = hscan = Signal(hbits) + # + # self.vres = vres = Signal(vbits) + # self.vsync_start = vsync_start = Signal(vbits) + # self.vsync_end = vsync_end = Signal(vbits) + # self.vscan = vscan = Signal(vbits) + # + # # Generate timings. + # hactive = Signal() + # vactive = Signal() + # fsm = FSM(reset_state="IDLE") + # fsm = ResetInserter()(fsm) + # self.submodules.fsm = fsm + # self.comb += fsm.reset.eq(~enable) + # fsm.act("IDLE", + # NextValue(hactive, 0), + # NextValue(vactive, 0), + # NextValue(source.hres, hres), + # NextValue(source.vres, vres), + # NextValue(source.hcount, 0), + # NextValue(source.vcount, 0), + # NextState("RUN") + # ) + # self.comb += source.de.eq(hactive & vactive) # DE when both HActive and VActive. + # self.sync += source.first.eq((source.hcount == 0) & (source.vcount == 0)), + # self.sync += source.last.eq((source.hcount == hscan) & (source.vcount == vscan)), + # fsm.act("RUN", + # source.valid.eq(1), + # If(source.ready, + # # Increment HCount. + # NextValue(source.hcount, source.hcount + 1), + # # Generate HActive / HSync. + # If(source.hcount == 0, NextValue(hactive, 1)), # Start of HActive. + # If(source.hcount == hres, NextValue(hactive, 0)), # End of HActive. + # If(source.hcount == hsync_start, NextValue(source.hsync, 1)), + # If(source.hcount == hsync_end, NextValue(source.hsync, 0)), # End of HSync. + # If(source.hcount == hscan, NextValue(source.hcount, 0)), # End of HScan. + # + # If(source.hcount == hsync_start, + # # Increment VCount. + # NextValue(source.vcount, source.vcount + 1), + # # Generate VActive / VSync. + # If(source.vcount == 0, NextValue(vactive, 1)), # Start of VActive. + # If(source.vcount == vres, NextValue(vactive, 0)), # End of VActive. + # If(source.vcount == vsync_start, NextValue(source.vsync, 1)), + # If(source.vcount == vsync_end, NextValue(source.vsync, 0)), # End of VSync. + # If(source.vcount == vscan, NextValue(source.vcount, 0)) # End of VScan. + # ) + # ) + # ) + + self.comb += pads.pclk.eq(ClockSignal()) diff --git a/sim_fpga/examples/example1/rtl/README.md b/gateware/main/python/fpga_robotics/cores/video/proc/__init__.py similarity index 100% rename from sim_fpga/examples/example1/rtl/README.md rename to gateware/main/python/fpga_robotics/cores/video/proc/__init__.py diff --git a/gateware/main/python/fpga_robotics/cores/video/proc/ov7670.py b/gateware/main/python/fpga_robotics/cores/video/proc/ov7670.py new file mode 100644 index 00000000..bf8191b3 --- /dev/null +++ b/gateware/main/python/fpga_robotics/cores/video/proc/ov7670.py @@ -0,0 +1,45 @@ +import os + +from litex.soc.interconnect.csr import AutoCSR, CSRStatus +from migen import * +from migen.genlib.cdc import MultiReg + + +class OV7670Stats(Module, AutoCSR): + def __init__(self, platform, pads, clock_domain="sys", capture_clock_domain="pclk"): + self.pclk = Signal() + self.vsync = Signal() + self.href = Signal() + self.data = Signal(8) + + self._frame_counter = CSRStatus(32, description="Frame counter") + self._frame_size = CSRStatus(32, description="Frame size") + frame_counter = Signal(32) + frame_size = Signal(32) + self.specials += [ + MultiReg(frame_counter, self._frame_counter.status), + MultiReg(frame_size, self._frame_size.status), + ] + + self.ov7670_stats_params = dict( + i_rst=ResetSignal(clock_domain), + i_clk=ClockSignal(clock_domain), + i_pclk_clk=ClockSignal(capture_clock_domain), + i_pclk_reset=ResetSignal(capture_clock_domain), + i_io_camif_vsync=self.vsync, + i_io_camif_href=self.href, + i_io_camif_data=self.data, + o_io_frame_counter=frame_counter, + o_io_frame_size=frame_size + ) + + self.add_sources(platform) + + @staticmethod + def add_sources(platform): + vdir = "gateware/rtl/jt51" + platform.add_source_dir(os.path.join(vdir, "hdl"), recursive=False) + platform.add_verilog_include_path(os.path.join(vdir, "hdl")) + + def do_finalize(self): + self.specials += Instance("OV7670Stats", **self.ov7670_stats_params) diff --git a/gateware/main/scala/fpga_robotics/video/input/CamCapture.scala b/gateware/main/scala/fpga_robotics/video/input/CamCapture.scala new file mode 100644 index 00000000..885a0519 --- /dev/null +++ b/gateware/main/scala/fpga_robotics/video/input/CamCapture.scala @@ -0,0 +1,51 @@ +package fpga_robotics.video.input + +import spinal.core._ +import spinal.lib._ +import spinal.lib.fsm._ + +case class CamCapture(dataWidth: Int = 8 ) extends Component { + val io = new Bundle { + val camif: CamIF = slave(CamIF(dataWidth)) + val read = master(Flow(camif.data)) + val startOfFrame = out Bool() + val endOfFrame = out Bool() + } + + val fsm = new StateMachine { + io.read.setIdle() + io.startOfFrame := False + io.endOfFrame := False + + val idleState = new State with EntryPoint + val captureState = new State + + idleState + .whenIsActive { + when(io.camif.vsync.fall()) { + goto(captureState) + } + } + .onExit(io.startOfFrame := True) + + captureState + .whenIsActive { + when(io.camif.href) { + io.read.push(io.camif.data) + } + when(io.camif.vsync) { + goto(idleState) + } + } + .onExit(io.endOfFrame := True) + } +} + +object CamCapture { + def main(args: Array[String]): Unit = { + val outRtlDir = if (!args.isEmpty) args(0) else "gateware/main/verilog/video/input" + SpinalConfig( + targetDirectory = outRtlDir, + ).generateVerilog(CamCapture()) + } +} \ No newline at end of file diff --git a/gateware/main/scala/fpga_robotics/video/input/CamIF.scala b/gateware/main/scala/fpga_robotics/video/input/CamIF.scala new file mode 100644 index 00000000..086e0d2b --- /dev/null +++ b/gateware/main/scala/fpga_robotics/video/input/CamIF.scala @@ -0,0 +1,18 @@ +package fpga_robotics.video.input + +import spinal.core._ +import spinal.lib._ + +case class CamIF(dataWidth: Int = 8) extends Bundle with IMasterSlave { + //val pclk = Bool() + val vsync = Bool() + val href = Bool() + val data = Bits(dataWidth bits) + + override def asMaster(): Unit = { + //out(pclk) + out(vsync) + out(href) + out(data) + } +} \ No newline at end of file diff --git a/gateware/main/scala/fpga_robotics/video/input/OV7670.scala b/gateware/main/scala/fpga_robotics/video/input/OV7670.scala new file mode 100644 index 00000000..1a22d5e6 --- /dev/null +++ b/gateware/main/scala/fpga_robotics/video/input/OV7670.scala @@ -0,0 +1,42 @@ +package fpga_robotics.video.input + +import spinal.core._ +import spinal.lib._ + +case class OV7670(captureClk: ClockDomain) extends Component { + val io = new Bundle { + val camif: CamIF = slave(CamIF()) + val read = master(Flow(camif.data)) + val startOfFrame = out Bool() + val endOfFrame = out Bool() + } + + var captureClockingArea = new ClockingArea(captureClk) { + val capture = CamCapture() + val startOfFrame = RegNext(capture.io.startOfFrame) init(False) + val endOfFrameReg = RegNext(capture.io.endOfFrame) init(False) + } + + io.camif <> captureClockingArea.capture.io.camif + io.startOfFrame := BufferCC(captureClockingArea.startOfFrame, init = False) + io.endOfFrame := BufferCC(captureClockingArea.endOfFrameReg, init = False) + + val fifo = StreamFifoCC( + dataType = io.read.payload, + depth = 4, + pushClock = captureClk, + popClock = ClockDomain.current + ) + + fifo.io.push << captureClockingArea.capture.io.read.toStream(False) + fifo.io.pop.toFlow >> io.read +} + +object OV7670 { + def main(args: Array[String]): Unit = { + val outRtlDir = if (!args.isEmpty) args(0) else "gateware/main/verilog/video/input" + SpinalConfig( + targetDirectory = outRtlDir, + ).generateVerilog(OV7670(ClockDomain.external("pclk"))).printPruned() + } +} \ No newline at end of file diff --git a/gateware/main/scala/fpga_robotics/video/proc/LineBuffer3x3.scala b/gateware/main/scala/fpga_robotics/video/proc/LineBuffer3x3.scala new file mode 100644 index 00000000..351e4bd7 --- /dev/null +++ b/gateware/main/scala/fpga_robotics/video/proc/LineBuffer3x3.scala @@ -0,0 +1,102 @@ +package fpga_robotics.video.proc + +import spinal.core._ +import spinal.lib._ + +case class LineBuffer3x3Generics(elementWidth: Int = 8, maxRowWidth: Int = 256) { + def maxDelayValue(): Int = maxRowWidth*2 + 2 +} + +case class LineBuffer3x3(generics: LineBuffer3x3Generics) extends Component { + require(generics.maxRowWidth >= 1) + require(isPow2(generics.maxRowWidth)) + + val io = new Bundle { + val init = in Bool() + val rowWidth = in UInt (log2Up(generics.maxRowWidth + 1) bit) + val initialDelay = in UInt (log2Up((generics.maxDelayValue()) + 1) bit) + + val input = slave Stream(Bits(generics.elementWidth bits)) + val output = master Stream(Vec(Bits(generics.elementWidth bits), 9)) + } + + val delayValueNext = UInt(log2Up((generics.maxDelayValue()) + 1) bit) + val delay = RegNext(delayValueNext) init(0) + val delayWillDecrement = False + val pendingRsp = RegInit(False) + + val rowShifter = new Area { + val row0 = new Mem(Bits(generics.elementWidth bits), generics.maxRowWidth) + val row1 = new Mem(Bits(generics.elementWidth bits), generics.maxRowWidth) + val readPtr = Counter(generics.maxRowWidth) + val writePtr = UInt(log2Up(generics.maxRowWidth) bit) + val writeOffset = Reg(io.rowWidth) init(0) + + val row0Front = row0(readPtr.value) + val row1Front = row1(readPtr.value) + + writePtr := (readPtr.value + writeOffset).resized + + when(io.input.fire) { + row0(writePtr) := io.input.payload + row1(writePtr) := row0Front + readPtr.increment() + } + + when(io.init) { + readPtr.clear() + writeOffset := io.rowWidth + } + } + + val window3x3 = new Area { + val input0 = io.input.payload + val input1 = rowShifter.row0Front + val input2 = rowShifter.row1Front + + val shift = io.input.fire + + val row0_0 = RegNextWhen(input0, shift) init(0) + val row0_1 = RegNextWhen(row0_0, shift) init(0) + val row0_2 = RegNextWhen(row0_1, shift) init(0) + + val row1_0 = RegNextWhen(input1, shift) init(0) + val row1_1 = RegNextWhen(row1_0, shift) init(0) + val row1_2 = RegNextWhen(row1_1, shift) init(0) + + val row2_0 = RegNextWhen(input2, shift) init(0) + val row2_1 = RegNextWhen(row2_0, shift) init(0) + val row2_2 = RegNextWhen(row2_1, shift) init(0) + + val output = Vec(row0_0, row0_1, row0_2, row1_0, row1_1, row1_2, row2_0, row2_1, row2_2) + } + + delayValueNext := (delay - U(delayWillDecrement)).resized + + when(io.input.fire) { + delayWillDecrement := (delay =/= 0) + } + + when(io.init) { + delayValueNext := io.initialDelay + } + + when(io.input.fire && (delay === 0)) { + pendingRsp := True + } elsewhen(io.output.fire) { + pendingRsp := False + } + + io.input.ready := ((delay =/= 0) || io.output.ready) + io.output.valid := pendingRsp + io.output.payload := Vec(window3x3.output.reverse) +} + +object LineBuffer3x3 { + def main(args: Array[String]) { + val outRtlDir = if (!args.isEmpty) args(0) else "gateware/main/verilog/video/proc" + SpinalConfig( + targetDirectory = outRtlDir + ).generateVerilog(LineBuffer3x3(LineBuffer3x3Generics())) + } +} \ No newline at end of file diff --git a/gateware/main/scala/fpga_robotics/video/proc/OV7670Stats.scala b/gateware/main/scala/fpga_robotics/video/proc/OV7670Stats.scala new file mode 100644 index 00000000..a6032041 --- /dev/null +++ b/gateware/main/scala/fpga_robotics/video/proc/OV7670Stats.scala @@ -0,0 +1,46 @@ +package fpga_robotics.video.proc + +import fpga_robotics.video.input.{CamIF, OV7670} +import spinal.core._ +import spinal.lib._ + +case class OV7670Stats(captureClk: ClockDomain) extends Component { + val io = new Bundle { + val camif: CamIF = slave(CamIF()) + val frame_counter: UInt = out UInt(32 bits) + val frame_size: UInt = out UInt(32 bits) + } + + val ov7670 = OV7670(captureClk) + + val frame_counter = Counter(32 bit) + val frame_size_counter = Counter(32 bit) + val frame_size = Reg(io.frame_size) init(0) + + when(ov7670.io.startOfFrame.rise()) { + frame_counter.increment() + frame_size_counter.clear() + } + + when(ov7670.io.endOfFrame.rise()) { + frame_size := frame_size_counter.value + } + + when(ov7670.io.read.fire) { + frame_size_counter.increment() + } + + io.camif <> ov7670.io.camif + io.frame_counter := frame_counter.value + io.frame_size := frame_size +} + +object OV7670Stats { + def main(args: Array[String]): Unit = { + val outRtlDir = if (!args.isEmpty) args(0) else "gateware/main/verilog/video/proc" + SpinalConfig( + targetDirectory = outRtlDir, + defaultClockDomainFrequency = FixedFrequency(100 MHz) + ).generateVerilog(OV7670Stats(ClockDomain.external("pclk"))).printPruned() + } +} \ No newline at end of file diff --git a/blocks/verilog/color_centroid/readme.md b/gateware/main/verilog/color_centroid/readme.md similarity index 100% rename from blocks/verilog/color_centroid/readme.md rename to gateware/main/verilog/color_centroid/readme.md diff --git a/blocks/verilog/color_centroid/sim_img80x60_colorcentroid/color_proc.v b/gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/color_proc.v similarity index 100% rename from blocks/verilog/color_centroid/sim_img80x60_colorcentroid/color_proc.v rename to gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/color_proc.v diff --git a/blocks/verilog/color_centroid/sim_img80x60_colorcentroid/dibujo.png b/gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/dibujo.png similarity index 100% rename from blocks/verilog/color_centroid/sim_img80x60_colorcentroid/dibujo.png rename to gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/dibujo.png diff --git a/blocks/verilog/color_centroid/sim_img80x60_colorcentroid/marco.png b/gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/marco.png similarity index 100% rename from blocks/verilog/color_centroid/sim_img80x60_colorcentroid/marco.png rename to gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/marco.png diff --git a/blocks/verilog/color_centroid/sim_img80x60_colorcentroid/rom.vhd b/gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/rom.vhd similarity index 100% rename from blocks/verilog/color_centroid/sim_img80x60_colorcentroid/rom.vhd rename to gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/rom.vhd diff --git a/blocks/verilog/color_centroid/sim_img80x60_colorcentroid/rom_dibujo.vhd b/gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/rom_dibujo.vhd similarity index 100% rename from blocks/verilog/color_centroid/sim_img80x60_colorcentroid/rom_dibujo.vhd rename to gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/rom_dibujo.vhd diff --git a/blocks/verilog/color_centroid/sim_img80x60_colorcentroid/tb_uno.vhd b/gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/tb_uno.vhd similarity index 100% rename from blocks/verilog/color_centroid/sim_img80x60_colorcentroid/tb_uno.vhd rename to gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/tb_uno.vhd diff --git a/blocks/verilog/color_centroid/sim_img80x60_colorcentroid/top_colorcentroid.v b/gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/top_colorcentroid.v similarity index 100% rename from blocks/verilog/color_centroid/sim_img80x60_colorcentroid/top_colorcentroid.v rename to gateware/main/verilog/color_centroid/sim_img80x60_colorcentroid/top_colorcentroid.v diff --git a/blocks/verilog/utils/division/readme.md b/gateware/main/verilog/utils/division/readme.md similarity index 100% rename from blocks/verilog/utils/division/readme.md rename to gateware/main/verilog/utils/division/readme.md diff --git a/blocks/verilog/utils/division/seq_int_div/readme.md b/gateware/main/verilog/utils/division/seq_int_div/readme.md similarity index 100% rename from blocks/verilog/utils/division/seq_int_div/readme.md rename to gateware/main/verilog/utils/division/seq_int_div/readme.md diff --git a/blocks/verilog/utils/division/seq_int_div/vhd/div_seq.vhd b/gateware/main/verilog/utils/division/seq_int_div/vhd/div_seq.vhd similarity index 100% rename from blocks/verilog/utils/division/seq_int_div/vhd/div_seq.vhd rename to gateware/main/verilog/utils/division/seq_int_div/vhd/div_seq.vhd diff --git a/blocks/verilog/utils/division/seq_int_div/vhd/tb_div_seq.vhd b/gateware/main/verilog/utils/division/seq_int_div/vhd/tb_div_seq.vhd similarity index 100% rename from blocks/verilog/utils/division/seq_int_div/vhd/tb_div_seq.vhd rename to gateware/main/verilog/utils/division/seq_int_div/vhd/tb_div_seq.vhd diff --git a/blocks/verilog/utils/division/seq_int_div/vrl/div_ver.v b/gateware/main/verilog/utils/division/seq_int_div/vrl/div_ver.v similarity index 100% rename from blocks/verilog/utils/division/seq_int_div/vrl/div_ver.v rename to gateware/main/verilog/utils/division/seq_int_div/vrl/div_ver.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/alhambra2_gopigo3.png b/gateware/main/verilog/utils/spi/alhambra_ii/alhambra2_gopigo3.png similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/alhambra2_gopigo3.png rename to gateware/main/verilog/utils/spi/alhambra_ii/alhambra2_gopigo3.png diff --git a/blocks/verilog/utils/spi/alhambra_ii/readme.md b/gateware/main/verilog/utils/spi/alhambra_ii/readme.md similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/readme.md rename to gateware/main/verilog/utils/spi/alhambra_ii/readme.md diff --git a/sim_fpga/examples/poc/example2/rtl/README.md b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/abc.history similarity index 100% rename from sim_fpga/examples/poc/example2/rtl/README.md rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/abc.history diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/apio.ini b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/apio.ini similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/apio.ini rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/apio.ini diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.pcf b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.pcf similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.pcf rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.pcf diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/btntest_spi_controller.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/hardware.asc b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/hardware.asc similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/hardware.asc rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/hardware.asc diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/hardware.json b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/hardware.json similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/hardware.json rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/hardware.json diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/spi_ctrl.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/spi_ctrl.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/spi_ctrl.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/spi_ctrl.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/spi_master.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/spi_master.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/spi_master.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/spi_master.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/tb_testbtn.vhd b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/tb_testbtn.vhd similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/tb_testbtn.vhd rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/tb_testbtn.vhd diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/tb_top_spi_controller.vhd b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/tb_top_spi_controller.vhd similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/tb_top_spi_controller.vhd rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/tb_top_spi_controller.vhd diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller_wrp.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller_wrp.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller_wrp.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_controller/top_spi_controller_wrp.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/apio.ini b/gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/apio.ini similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_poc/apio.ini rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/apio.ini diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/hardware.asc b/gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/hardware.asc similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_poc/hardware.asc rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/hardware.asc diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/spi_ledctrl.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/spi_ledctrl.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_poc/spi_ledctrl.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/spi_ledctrl.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/spi_master.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/spi_master.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_poc/spi_master.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/spi_master.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/tb_top_spi_leds.vhd b/gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/tb_top_spi_leds.vhd similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_poc/tb_top_spi_leds.vhd rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/tb_top_spi_leds.vhd diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.pcf b/gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.pcf similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.pcf rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.pcf diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_poc/top_spi_leds.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/apio.ini b/gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/apio.ini similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_rom/apio.ini rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/apio.ini diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/hardware.asc b/gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/hardware.asc similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_rom/hardware.asc rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/hardware.asc diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/spi_master.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/spi_master.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_rom/spi_master.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/spi_master.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/spi_romctrl.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/spi_romctrl.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_rom/spi_romctrl.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/spi_romctrl.v diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/tb_top_spi_rom.vhd b/gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/tb_top_spi_rom.vhd similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_rom/tb_top_spi_rom.vhd rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/tb_top_spi_rom.vhd diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.pcf b/gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.pcf similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.pcf rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.pcf diff --git a/blocks/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.v b/gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.v similarity index 100% rename from blocks/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.v rename to gateware/main/verilog/utils/spi/alhambra_ii/spi_rom/top_spi_rom.v diff --git a/blocks/verilog/utils/uart/uart_rx_leds/readme.md b/gateware/main/verilog/utils/uart/uart_rx_leds/readme.md similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/readme.md rename to gateware/main/verilog/utils/uart/uart_rx_leds/readme.md diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/Nexys4DDR_Master.ucf b/gateware/main/verilog/utils/uart/uart_rx_leds/src/Nexys4DDR_Master.ucf similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/Nexys4DDR_Master.ucf rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/Nexys4DDR_Master.ucf diff --git a/sim_fpga/examples/poc/example3/rtl/README.md b/gateware/main/verilog/utils/uart/uart_rx_leds/src/abc.history similarity index 100% rename from sim_fpga/examples/poc/example3/rtl/README.md rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/abc.history diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/apio.ini b/gateware/main/verilog/utils/uart/uart_rx_leds/src/apio.ini similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/apio.ini rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/apio.ini diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/hardware.asc b/gateware/main/verilog/utils/uart/uart_rx_leds/src/hardware.asc similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/hardware.asc rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/hardware.asc diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/hardware.json b/gateware/main/verilog/utils/uart/uart_rx_leds/src/hardware.json similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/hardware.json rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/hardware.json diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/leds.v b/gateware/main/verilog/utils/uart/uart_rx_leds/src/leds.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/leds.v rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/leds.v diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.pcf b/gateware/main/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.pcf similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.pcf rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.pcf diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.v b/gateware/main/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.v rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/top_uart_rx.v diff --git a/blocks/verilog/utils/uart/uart_rx_leds/src/uart_rx.v b/gateware/main/verilog/utils/uart/uart_rx_leds/src/uart_rx.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_leds/src/uart_rx.v rename to gateware/main/verilog/utils/uart/uart_rx_leds/src/uart_rx.v diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_samepower.png b/gateware/main/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_samepower.png similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_samepower.png rename to gateware/main/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_samepower.png diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_separated.png b/gateware/main/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_separated.png similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_separated.png rename to gateware/main/verilog/utils/uart/uart_rx_pwm/alhambra2_l293opto_motor_separated.png diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/readme.md b/gateware/main/verilog/utils/uart/uart_rx_pwm/readme.md similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/readme.md rename to gateware/main/verilog/utils/uart/uart_rx_pwm/readme.md diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/Nexys4DDR_Master.ucf b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/Nexys4DDR_Master.ucf similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/Nexys4DDR_Master.ucf rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/Nexys4DDR_Master.ucf diff --git a/sim_fpga/examples/poc/example4/rtl/README.md b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/abc.history similarity index 100% rename from sim_fpga/examples/poc/example4/rtl/README.md rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/abc.history diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/apio.ini b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/apio.ini similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/apio.ini rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/apio.ini diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/hardware.asc b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/hardware.asc similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/hardware.asc rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/hardware.asc diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/hardware.json b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/hardware.json similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/hardware.json rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/hardware.json diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/leds.v b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/leds.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/leds.v rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/leds.v diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/apio.ini b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/apio.ini similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/apio.ini rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/apio.ini diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.asc b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.asc similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.asc rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.asc diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.json b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.json similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.json rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/hardware.json diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.pcf b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.pcf similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.pcf rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.pcf diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.v b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.v rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/motor_test/motor_test.v diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/pwm_motor.v b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/pwm_motor.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/pwm_motor.v rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/pwm_motor.v diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/tb_pwm.vhd b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/tb_pwm.vhd similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/tb_pwm.vhd rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/tb_pwm.vhd diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/tb_top_uart_pwm.vhd b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/tb_top_uart_pwm.vhd similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/tb_top_uart_pwm.vhd rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/tb_top_uart_pwm.vhd diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/tb_uart_rx.vhd b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/tb_uart_rx.vhd similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/tb_uart_rx.vhd rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/tb_uart_rx.vhd diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.pcf b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.pcf similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.pcf rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.pcf diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.v b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.v rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/top_uart_pwm.v diff --git a/blocks/verilog/utils/uart/uart_rx_pwm/src/uart_rx.v b/gateware/main/verilog/utils/uart/uart_rx_pwm/src/uart_rx.v similarity index 100% rename from blocks/verilog/utils/uart/uart_rx_pwm/src/uart_rx.v rename to gateware/main/verilog/utils/uart/uart_rx_pwm/src/uart_rx.v diff --git a/gateware/main/verilog/video/input/OV7670.v b/gateware/main/verilog/video/input/OV7670.v new file mode 100644 index 00000000..ca232619 --- /dev/null +++ b/gateware/main/verilog/video/input/OV7670.v @@ -0,0 +1,483 @@ +// Generator : SpinalHDL v1.7.3 git head : aeaeece704fe43c766e0d36a93f2ecbb8a9f2003 +// Component : OV7670 +// Git hash : 749447bfc80bbacb0111c7be39e2686735433d6d + +`timescale 1ns/1ps + +module OV7670 ( + input io_camif_vsync, + input io_camif_href, + input [7:0] io_camif_data, + output io_read_valid, + output [7:0] io_read_payload, + output io_startOfFrame, + output io_endOfFrame, + input pclk_clk, + input pclk_reset, + input clk, + input reset +); + + wire captureClockingArea_capture_io_read_valid; + wire [7:0] captureClockingArea_capture_io_read_payload; + wire captureClockingArea_capture_io_startOfFrame; + wire captureClockingArea_capture_io_endOfFrame; + wire captureClockingArea_startOfFrame_buffercc_io_dataOut; + wire captureClockingArea_endOfFrameReg_buffercc_io_dataOut; + wire fifo_io_push_ready; + wire fifo_io_pop_valid; + wire [7:0] fifo_io_pop_payload; + wire [2:0] fifo_io_pushOccupancy; + wire [2:0] fifo_io_popOccupancy; + reg captureClockingArea_startOfFrame; + reg captureClockingArea_endOfFrameReg; + wire captureClockingArea_capture_io_read_toStream_valid; + wire captureClockingArea_capture_io_read_toStream_ready; + wire [7:0] captureClockingArea_capture_io_read_toStream_payload; + + CamCapture captureClockingArea_capture ( + .io_camif_vsync (io_camif_vsync ), //i + .io_camif_href (io_camif_href ), //i + .io_camif_data (io_camif_data[7:0] ), //i + .io_read_valid (captureClockingArea_capture_io_read_valid ), //o + .io_read_payload (captureClockingArea_capture_io_read_payload[7:0]), //o + .io_startOfFrame (captureClockingArea_capture_io_startOfFrame ), //o + .io_endOfFrame (captureClockingArea_capture_io_endOfFrame ), //o + .pclk_clk (pclk_clk ), //i + .pclk_reset (pclk_reset ) //i + ); + BufferCC_3 captureClockingArea_startOfFrame_buffercc ( + .io_dataIn (captureClockingArea_startOfFrame ), //i + .io_dataOut (captureClockingArea_startOfFrame_buffercc_io_dataOut), //o + .clk (clk ), //i + .reset (reset ) //i + ); + BufferCC_3 captureClockingArea_endOfFrameReg_buffercc ( + .io_dataIn (captureClockingArea_endOfFrameReg ), //i + .io_dataOut (captureClockingArea_endOfFrameReg_buffercc_io_dataOut), //o + .clk (clk ), //i + .reset (reset ) //i + ); + StreamFifoCC fifo ( + .io_push_valid (captureClockingArea_capture_io_read_toStream_valid ), //i + .io_push_ready (fifo_io_push_ready ), //o + .io_push_payload (captureClockingArea_capture_io_read_toStream_payload[7:0]), //i + .io_pop_valid (fifo_io_pop_valid ), //o + .io_pop_ready (1'b1 ), //i + .io_pop_payload (fifo_io_pop_payload[7:0] ), //o + .io_pushOccupancy (fifo_io_pushOccupancy[2:0] ), //o + .io_popOccupancy (fifo_io_popOccupancy[2:0] ), //o + .pclk_clk (pclk_clk ), //i + .pclk_reset (pclk_reset ), //i + .clk (clk ) //i + ); + assign io_startOfFrame = captureClockingArea_startOfFrame_buffercc_io_dataOut; + assign io_endOfFrame = captureClockingArea_endOfFrameReg_buffercc_io_dataOut; + assign captureClockingArea_capture_io_read_toStream_valid = captureClockingArea_capture_io_read_valid; + assign captureClockingArea_capture_io_read_toStream_payload = captureClockingArea_capture_io_read_payload; + assign captureClockingArea_capture_io_read_toStream_ready = fifo_io_push_ready; + assign io_read_valid = fifo_io_pop_valid; + assign io_read_payload = fifo_io_pop_payload; + always @(posedge pclk_clk or posedge pclk_reset) begin + if(pclk_reset) begin + captureClockingArea_startOfFrame <= 1'b0; + captureClockingArea_endOfFrameReg <= 1'b0; + end else begin + captureClockingArea_startOfFrame <= captureClockingArea_capture_io_startOfFrame; + captureClockingArea_endOfFrameReg <= captureClockingArea_capture_io_endOfFrame; + end + end + + +endmodule + +module StreamFifoCC ( + input io_push_valid, + output io_push_ready, + input [7:0] io_push_payload, + output io_pop_valid, + input io_pop_ready, + output [7:0] io_pop_payload, + output [2:0] io_pushOccupancy, + output [2:0] io_popOccupancy, + input pclk_clk, + input pclk_reset, + input clk +); + + reg [7:0] _zz_ram_port1; + wire [2:0] popToPushGray_buffercc_io_dataOut; + wire bufferCC_5_io_dataOut; + wire [2:0] pushToPopGray_buffercc_io_dataOut; + wire [2:0] _zz_pushCC_pushPtrGray; + wire [1:0] _zz_ram_port; + wire [2:0] _zz_popCC_popPtrGray; + wire [1:0] _zz_ram_port_1; + wire _zz_ram_port_2; + wire [1:0] _zz_io_pop_payload_1; + wire _zz_io_pop_payload_2; + reg _zz_1; + wire [2:0] popToPushGray; + wire [2:0] pushToPopGray; + reg [2:0] pushCC_pushPtr; + wire [2:0] pushCC_pushPtrPlus; + wire io_push_fire; + reg [2:0] pushCC_pushPtrGray; + wire [2:0] pushCC_popPtrGray; + wire pushCC_full; + wire io_push_fire_1; + wire _zz_io_pushOccupancy; + wire _zz_io_pushOccupancy_1; + wire pclk_reset_syncronized; + reg [2:0] popCC_popPtr; + wire [2:0] popCC_popPtrPlus; + wire io_pop_fire; + reg [2:0] popCC_popPtrGray; + wire [2:0] popCC_pushPtrGray; + wire popCC_empty; + wire io_pop_fire_1; + wire [2:0] _zz_io_pop_payload; + wire io_pop_fire_2; + wire _zz_io_popOccupancy; + wire _zz_io_popOccupancy_1; + reg [7:0] ram [0:3]; + + assign _zz_pushCC_pushPtrGray = (pushCC_pushPtrPlus >>> 1'b1); + assign _zz_ram_port = pushCC_pushPtr[1:0]; + assign _zz_popCC_popPtrGray = (popCC_popPtrPlus >>> 1'b1); + assign _zz_io_pop_payload_1 = _zz_io_pop_payload[1:0]; + assign _zz_io_pop_payload_2 = 1'b1; + always @(posedge pclk_clk) begin + if(_zz_1) begin + ram[_zz_ram_port] <= io_push_payload; + end + end + + always @(posedge clk) begin + if(_zz_io_pop_payload_2) begin + _zz_ram_port1 <= ram[_zz_io_pop_payload_1]; + end + end + + BufferCC popToPushGray_buffercc ( + .io_dataIn (popToPushGray[2:0] ), //i + .io_dataOut (popToPushGray_buffercc_io_dataOut[2:0]), //o + .pclk_clk (pclk_clk ), //i + .pclk_reset (pclk_reset ) //i + ); + BufferCC_1 bufferCC_5 ( + .io_dataIn (1'b0 ), //i + .io_dataOut (bufferCC_5_io_dataOut), //o + .clk (clk ), //i + .pclk_reset (pclk_reset ) //i + ); + BufferCC_2 pushToPopGray_buffercc ( + .io_dataIn (pushToPopGray[2:0] ), //i + .io_dataOut (pushToPopGray_buffercc_io_dataOut[2:0]), //o + .clk (clk ), //i + .pclk_reset_syncronized (pclk_reset_syncronized ) //i + ); + always @(*) begin + _zz_1 = 1'b0; + if(io_push_fire_1) begin + _zz_1 = 1'b1; + end + end + + assign pushCC_pushPtrPlus = (pushCC_pushPtr + 3'b001); + assign io_push_fire = (io_push_valid && io_push_ready); + assign pushCC_popPtrGray = popToPushGray_buffercc_io_dataOut; + assign pushCC_full = ((pushCC_pushPtrGray[2 : 1] == (~ pushCC_popPtrGray[2 : 1])) && (pushCC_pushPtrGray[0 : 0] == pushCC_popPtrGray[0 : 0])); + assign io_push_ready = (! pushCC_full); + assign io_push_fire_1 = (io_push_valid && io_push_ready); + assign _zz_io_pushOccupancy = (pushCC_popPtrGray[1] ^ _zz_io_pushOccupancy_1); + assign _zz_io_pushOccupancy_1 = pushCC_popPtrGray[2]; + assign io_pushOccupancy = (pushCC_pushPtr - {_zz_io_pushOccupancy_1,{_zz_io_pushOccupancy,(pushCC_popPtrGray[0] ^ _zz_io_pushOccupancy)}}); + assign pclk_reset_syncronized = bufferCC_5_io_dataOut; + assign popCC_popPtrPlus = (popCC_popPtr + 3'b001); + assign io_pop_fire = (io_pop_valid && io_pop_ready); + assign popCC_pushPtrGray = pushToPopGray_buffercc_io_dataOut; + assign popCC_empty = (popCC_popPtrGray == popCC_pushPtrGray); + assign io_pop_valid = (! popCC_empty); + assign io_pop_fire_1 = (io_pop_valid && io_pop_ready); + assign _zz_io_pop_payload = (io_pop_fire_1 ? popCC_popPtrPlus : popCC_popPtr); + assign io_pop_payload = _zz_ram_port1; + assign io_pop_fire_2 = (io_pop_valid && io_pop_ready); + assign _zz_io_popOccupancy = (popCC_pushPtrGray[1] ^ _zz_io_popOccupancy_1); + assign _zz_io_popOccupancy_1 = popCC_pushPtrGray[2]; + assign io_popOccupancy = ({_zz_io_popOccupancy_1,{_zz_io_popOccupancy,(popCC_pushPtrGray[0] ^ _zz_io_popOccupancy)}} - popCC_popPtr); + assign pushToPopGray = pushCC_pushPtrGray; + assign popToPushGray = popCC_popPtrGray; + always @(posedge pclk_clk or posedge pclk_reset) begin + if(pclk_reset) begin + pushCC_pushPtr <= 3'b000; + pushCC_pushPtrGray <= 3'b000; + end else begin + if(io_push_fire) begin + pushCC_pushPtrGray <= (_zz_pushCC_pushPtrGray ^ pushCC_pushPtrPlus); + end + if(io_push_fire_1) begin + pushCC_pushPtr <= pushCC_pushPtrPlus; + end + end + end + + always @(posedge clk or posedge pclk_reset_syncronized) begin + if(pclk_reset_syncronized) begin + popCC_popPtr <= 3'b000; + popCC_popPtrGray <= 3'b000; + end else begin + if(io_pop_fire) begin + popCC_popPtrGray <= (_zz_popCC_popPtrGray ^ popCC_popPtrPlus); + end + if(io_pop_fire_2) begin + popCC_popPtr <= popCC_popPtrPlus; + end + end + end + + +endmodule + +//BufferCC_3 replaced by BufferCC_3 + +module BufferCC_3 ( + input io_dataIn, + output io_dataOut, + input clk, + input reset +); + + (* async_reg = "true" *) reg buffers_0; + (* async_reg = "true" *) reg buffers_1; + + assign io_dataOut = buffers_1; + always @(posedge clk) begin + buffers_0 <= io_dataIn; + buffers_1 <= buffers_0; + end + + +endmodule + +module CamCapture ( + input io_camif_vsync, + input io_camif_href, + input [7:0] io_camif_data, + output reg io_read_valid, + output reg [7:0] io_read_payload, + output reg io_startOfFrame, + output reg io_endOfFrame, + input pclk_clk, + input pclk_reset +); + localparam fsm_enumDef_BOOT = 2'd0; + localparam fsm_enumDef_idleState = 2'd1; + localparam fsm_enumDef_captureState = 2'd2; + + wire fsm_wantExit; + reg fsm_wantStart; + wire fsm_wantKill; + reg [1:0] fsm_stateReg; + reg [1:0] fsm_stateNext; + reg io_camif_vsync_regNext; + wire when_CamCapture_l25; + wire when_StateMachine_l234; + wire when_StateMachine_l234_1; + `ifndef SYNTHESIS + reg [95:0] fsm_stateReg_string; + reg [95:0] fsm_stateNext_string; + `endif + + + `ifndef SYNTHESIS + always @(*) begin + case(fsm_stateReg) + fsm_enumDef_BOOT : fsm_stateReg_string = "BOOT "; + fsm_enumDef_idleState : fsm_stateReg_string = "idleState "; + fsm_enumDef_captureState : fsm_stateReg_string = "captureState"; + default : fsm_stateReg_string = "????????????"; + endcase + end + always @(*) begin + case(fsm_stateNext) + fsm_enumDef_BOOT : fsm_stateNext_string = "BOOT "; + fsm_enumDef_idleState : fsm_stateNext_string = "idleState "; + fsm_enumDef_captureState : fsm_stateNext_string = "captureState"; + default : fsm_stateNext_string = "????????????"; + endcase + end + `endif + + assign fsm_wantExit = 1'b0; + always @(*) begin + fsm_wantStart = 1'b0; + case(fsm_stateReg) + fsm_enumDef_idleState : begin + end + fsm_enumDef_captureState : begin + end + default : begin + fsm_wantStart = 1'b1; + end + endcase + end + + assign fsm_wantKill = 1'b0; + always @(*) begin + io_read_valid = 1'b0; + case(fsm_stateReg) + fsm_enumDef_idleState : begin + end + fsm_enumDef_captureState : begin + if(io_camif_href) begin + io_read_valid = 1'b1; + end + end + default : begin + end + endcase + end + + always @(*) begin + io_read_payload = 8'bxxxxxxxx; + case(fsm_stateReg) + fsm_enumDef_idleState : begin + end + fsm_enumDef_captureState : begin + if(io_camif_href) begin + io_read_payload = io_camif_data; + end + end + default : begin + end + endcase + end + + always @(*) begin + io_startOfFrame = 1'b0; + if(when_StateMachine_l234) begin + io_startOfFrame = 1'b1; + end + end + + always @(*) begin + io_endOfFrame = 1'b0; + if(when_StateMachine_l234_1) begin + io_endOfFrame = 1'b1; + end + end + + always @(*) begin + fsm_stateNext = fsm_stateReg; + case(fsm_stateReg) + fsm_enumDef_idleState : begin + if(when_CamCapture_l25) begin + fsm_stateNext = fsm_enumDef_captureState; + end + end + fsm_enumDef_captureState : begin + if(io_camif_vsync) begin + fsm_stateNext = fsm_enumDef_idleState; + end + end + default : begin + end + endcase + if(fsm_wantStart) begin + fsm_stateNext = fsm_enumDef_idleState; + end + if(fsm_wantKill) begin + fsm_stateNext = fsm_enumDef_BOOT; + end + end + + assign when_CamCapture_l25 = ((! io_camif_vsync) && io_camif_vsync_regNext); + assign when_StateMachine_l234 = ((fsm_stateReg == fsm_enumDef_idleState) && (! (fsm_stateNext == fsm_enumDef_idleState))); + assign when_StateMachine_l234_1 = ((fsm_stateReg == fsm_enumDef_captureState) && (! (fsm_stateNext == fsm_enumDef_captureState))); + always @(posedge pclk_clk or posedge pclk_reset) begin + if(pclk_reset) begin + fsm_stateReg <= fsm_enumDef_BOOT; + end else begin + fsm_stateReg <= fsm_stateNext; + end + end + + always @(posedge pclk_clk) begin + io_camif_vsync_regNext <= io_camif_vsync; + end + + +endmodule + +module BufferCC_2 ( + input [2:0] io_dataIn, + output [2:0] io_dataOut, + input clk, + input pclk_reset_syncronized +); + + (* async_reg = "true" *) reg [2:0] buffers_0; + (* async_reg = "true" *) reg [2:0] buffers_1; + + assign io_dataOut = buffers_1; + always @(posedge clk or posedge pclk_reset_syncronized) begin + if(pclk_reset_syncronized) begin + buffers_0 <= 3'b000; + buffers_1 <= 3'b000; + end else begin + buffers_0 <= io_dataIn; + buffers_1 <= buffers_0; + end + end + + +endmodule + +module BufferCC_1 ( + input io_dataIn, + output io_dataOut, + input clk, + input pclk_reset +); + + (* async_reg = "true" *) reg buffers_0; + (* async_reg = "true" *) reg buffers_1; + + assign io_dataOut = buffers_1; + always @(posedge clk or posedge pclk_reset) begin + if(pclk_reset) begin + buffers_0 <= 1'b1; + buffers_1 <= 1'b1; + end else begin + buffers_0 <= io_dataIn; + buffers_1 <= buffers_0; + end + end + + +endmodule + +module BufferCC ( + input [2:0] io_dataIn, + output [2:0] io_dataOut, + input pclk_clk, + input pclk_reset +); + + (* async_reg = "true" *) reg [2:0] buffers_0; + (* async_reg = "true" *) reg [2:0] buffers_1; + + assign io_dataOut = buffers_1; + always @(posedge pclk_clk or posedge pclk_reset) begin + if(pclk_reset) begin + buffers_0 <= 3'b000; + buffers_1 <= 3'b000; + end else begin + buffers_0 <= io_dataIn; + buffers_1 <= buffers_0; + end + end + + +endmodule diff --git a/sim_fpga/examples/poc/example5/rtl/README.md b/gateware/test/python/__init__.py similarity index 100% rename from sim_fpga/examples/poc/example5/rtl/README.md rename to gateware/test/python/__init__.py diff --git a/gateware/test/python/test_ov7670.py b/gateware/test/python/test_ov7670.py new file mode 100644 index 00000000..c0e0d8c8 --- /dev/null +++ b/gateware/test/python/test_ov7670.py @@ -0,0 +1,58 @@ +import unittest + +from litex.gen.sim import run_simulation,passive + +from fpga_robotics.cores.video.ov7670 import OV7670Capture + + +class TestOV7670Capture(unittest.TestCase): + def test_ov7670_capture(self): + data = [] + + @passive + def consumer_generator(dut): + while True: + if (yield dut.source.valid): + data.append((yield dut.source.data)) + yield + def generator(dut, nframes, nrows, row_data): + yield dut.vsync.eq(0) + yield dut.href.eq(0) + yield dut.data.eq(0) + yield + + for f in range(nframes): + yield dut.vsync.eq(1) + yield + yield dut.vsync.eq(1) + yield + yield dut.vsync.eq(1) + yield + yield dut.vsync.eq(0) + yield + for r in range(nrows): + for d in row_data: + yield dut.data.eq(d) + yield dut.href.eq(1) + yield + yield dut.href.eq(0) + yield + yield dut.vsync.eq(1) + yield + + # check data + self.assertEqual(len(data), nframes * nrows * len(row_data)) + self.assertEqual(data, nframes * nrows * row_data) + + + row_data = [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff] + dut = OV7670Capture() + + generators = { + "sys": [ + generator(dut, 2, 8, row_data), + consumer_generator(dut) + ] + } + + run_simulation(dut, generators, vcd_name="sim.vcd") diff --git a/gateware/test/scala/fpga_robotics/video/input/CamCaptureTest.scala b/gateware/test/scala/fpga_robotics/video/input/CamCaptureTest.scala new file mode 100644 index 00000000..0aad05f4 --- /dev/null +++ b/gateware/test/scala/fpga_robotics/video/input/CamCaptureTest.scala @@ -0,0 +1,52 @@ +package fpga_robotics.video.input + +import org.scalatest.funsuite.AnyFunSuite +import spinal.core.sim._ + +class CamCaptureTest extends AnyFunSuite { + val compiled: SimCompiled[CamCapture] = SimConfig.withWave.compile(CamCapture()) + + test("test read data") { + compiled.doSim{ dut => + dut.clockDomain.forkStimulus(10) + + dut.io.camif.vsync #= false + dut.io.camif.href #= false + + dut.clockDomain.waitSampling() + + dut.io.camif.vsync #= true + dut.clockDomain.waitSampling() + + for(i <- 0 until 4) { //frames + dut.io.camif.vsync #= false + dut.clockDomain.waitSampling() + assert(dut.io.startOfFrame.toBoolean) + + for(j <- 0 until 2) { //rows + dut.io.camif.href #= true + val readThread = fork { + for (k <- 0 until 16) { //data + dut.clockDomain.waitSamplingWhere(dut.io.read.valid.toBoolean) + assert(dut.io.read.payload.toInt == k) + } + } + for(k <- 0 until 16) { //data + dut.io.camif.data #= k + dut.clockDomain.waitSampling() + } + dut.io.camif.href #= false + dut.clockDomain.waitSampling() + readThread.join() + } + + dut.io.camif.vsync #= true + dut.clockDomain.waitSampling() + assert(dut.io.endOfFrame.toBoolean) + } + + dut.io.camif.vsync #= false + dut.clockDomain.waitSampling() + } + } +} diff --git a/gateware/test/scala/fpga_robotics/video/input/OV7670Test.scala b/gateware/test/scala/fpga_robotics/video/input/OV7670Test.scala new file mode 100644 index 00000000..581bbe77 --- /dev/null +++ b/gateware/test/scala/fpga_robotics/video/input/OV7670Test.scala @@ -0,0 +1,59 @@ +package fpga_robotics.video.input + +import org.scalatest.funsuite.AnyFunSuite +import spinal.core.ClockDomain +import spinal.core.sim._ + +class OV7670Test extends AnyFunSuite { + val compiled: SimCompiled[OV7670] = SimConfig.withWave.compile(OV7670(ClockDomain.external("pclk"))) + + test("test read data") { + compiled.doSim { dut => + dut.clockDomain.forkStimulus(10) + dut.captureClk.forkStimulus(40) + dut.io.camif.vsync #= false + dut.io.camif.href #= false + + dut.captureClk.waitSampling(8) + + val readThread = fork { + for (i <- 0 until 4) { //frames + dut.clockDomain.waitSamplingWhere(dut.io.startOfFrame.toBoolean) + for (j <- 0 until 2) { //rows + for (k <- 0 until 16) { //data + dut.clockDomain.waitSamplingWhere(dut.io.read.valid.toBoolean) + assert(dut.io.read.payload.toInt == k) + } + } + dut.clockDomain.waitSamplingWhere(dut.io.endOfFrame.toBoolean) + } + } + + dut.io.camif.vsync #= true + dut.captureClk.waitSampling() + + for (i <- 0 until 4) { //frames + dut.io.camif.vsync #= false + dut.captureClk.waitSampling() + + for (j <- 0 until 2) { //rows + dut.io.camif.href #= true + for (k <- 0 until 16) { //data + dut.io.camif.data #= k + dut.captureClk.waitSampling() + } + dut.io.camif.href #= false + dut.captureClk.waitSampling() + } + + dut.io.camif.vsync #= true + dut.captureClk.waitSampling() + } + + dut.io.camif.vsync #= false + dut.captureClk.waitSampling() + + readThread.join() + } + } +} diff --git a/gateware/test/scala/fpga_robotics/video/proc/OV7670StatsTest.scala b/gateware/test/scala/fpga_robotics/video/proc/OV7670StatsTest.scala new file mode 100644 index 00000000..27ae711a --- /dev/null +++ b/gateware/test/scala/fpga_robotics/video/proc/OV7670StatsTest.scala @@ -0,0 +1,44 @@ +package fpga_robotics.video.proc + +import org.scalatest.funsuite.AnyFunSuite +import spinal.core.ClockDomain +import spinal.core.sim._ + +class OV7670StatsTest extends AnyFunSuite { + val compiled: SimCompiled[OV7670Stats] = SimConfig.withWave.compile(OV7670Stats(ClockDomain.external("pclk"))) + + test("test stats") { + compiled.doSim { dut => + dut.clockDomain.forkStimulus(10) + dut.captureClk.forkStimulus(40) + dut.io.camif.vsync #= false + dut.io.camif.href #= false + + dut.captureClk.waitSampling(8) + + dut.io.camif.vsync #= true + dut.captureClk.waitSampling() + + for (i <- 0 until 4) { //frames + dut.io.camif.vsync #= false + dut.captureClk.waitSampling() + + for (j <- 0 until 2) { //rows + dut.io.camif.href #= true + for (k <- 0 until 16) { //data + dut.io.camif.data #= k + dut.captureClk.waitSampling() + } + dut.io.camif.href #= false + dut.captureClk.waitSampling() + } + + dut.io.camif.vsync #= true + dut.captureClk.waitSampling() + } + + dut.io.camif.vsync #= false + dut.captureClk.waitSampling() + } + } +} diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 00000000..1e70b0c1 --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.6.0 diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 00000000..e69de29b diff --git a/sim_fpga/README.md b/sim_tools/README.md similarity index 100% rename from sim_fpga/README.md rename to sim_tools/README.md diff --git a/sim_fpga/docs/sim_running.png b/sim_tools/docs/sim_running.png similarity index 100% rename from sim_fpga/docs/sim_running.png rename to sim_tools/docs/sim_running.png diff --git a/sim_fpga/examples/example1/Makefile b/sim_tools/examples/example1/Makefile similarity index 100% rename from sim_fpga/examples/example1/Makefile rename to sim_tools/examples/example1/Makefile diff --git a/sim_fpga/examples/example1/include/input_driver.h b/sim_tools/examples/example1/include/input_driver.h similarity index 100% rename from sim_fpga/examples/example1/include/input_driver.h rename to sim_tools/examples/example1/include/input_driver.h diff --git a/sim_fpga/examples/example1/include/output_monitor.h b/sim_tools/examples/example1/include/output_monitor.h similarity index 100% rename from sim_fpga/examples/example1/include/output_monitor.h rename to sim_tools/examples/example1/include/output_monitor.h diff --git a/sim_tools/examples/example1/rtl/README.md b/sim_tools/examples/example1/rtl/README.md new file mode 100644 index 00000000..e69de29b diff --git a/sim_fpga/examples/example1/rtl/calc_filter.v b/sim_tools/examples/example1/rtl/calc_filter.v similarity index 100% rename from sim_fpga/examples/example1/rtl/calc_filter.v rename to sim_tools/examples/example1/rtl/calc_filter.v diff --git a/sim_fpga/examples/example1/rtl/design_top.v b/sim_tools/examples/example1/rtl/design_top.v similarity index 100% rename from sim_fpga/examples/example1/rtl/design_top.v rename to sim_tools/examples/example1/rtl/design_top.v diff --git a/sim_fpga/examples/example1/rtl/frame_buff.v b/sim_tools/examples/example1/rtl/frame_buff.v similarity index 100% rename from sim_fpga/examples/example1/rtl/frame_buff.v rename to sim_tools/examples/example1/rtl/frame_buff.v diff --git a/sim_fpga/examples/example1/rtl/image_proc.v b/sim_tools/examples/example1/rtl/image_proc.v similarity index 100% rename from sim_fpga/examples/example1/rtl/image_proc.v rename to sim_tools/examples/example1/rtl/image_proc.v diff --git a/sim_fpga/examples/example1/rtl/simulacionTest.png b/sim_tools/examples/example1/rtl/simulacionTest.png similarity index 100% rename from sim_fpga/examples/example1/rtl/simulacionTest.png rename to sim_tools/examples/example1/rtl/simulacionTest.png diff --git a/sim_fpga/examples/example1/src/ebu_colorbars_96x72.png b/sim_tools/examples/example1/src/ebu_colorbars_96x72.png similarity index 100% rename from sim_fpga/examples/example1/src/ebu_colorbars_96x72.png rename to sim_tools/examples/example1/src/ebu_colorbars_96x72.png diff --git a/sim_fpga/examples/example1/src/fa-solid-900.ttf b/sim_tools/examples/example1/src/fa-solid-900.ttf similarity index 100% rename from sim_fpga/examples/example1/src/fa-solid-900.ttf rename to sim_tools/examples/example1/src/fa-solid-900.ttf diff --git a/sim_fpga/examples/example1/src/input_driver.cpp b/sim_tools/examples/example1/src/input_driver.cpp similarity index 100% rename from sim_fpga/examples/example1/src/input_driver.cpp rename to sim_tools/examples/example1/src/input_driver.cpp diff --git a/sim_fpga/examples/example1/src/main.cpp b/sim_tools/examples/example1/src/main.cpp similarity index 100% rename from sim_fpga/examples/example1/src/main.cpp rename to sim_tools/examples/example1/src/main.cpp diff --git a/sim_fpga/examples/example1/src/output_monitor.cpp b/sim_tools/examples/example1/src/output_monitor.cpp similarity index 100% rename from sim_fpga/examples/example1/src/output_monitor.cpp rename to sim_tools/examples/example1/src/output_monitor.cpp diff --git a/sim_fpga/examples/example1/src/red_ball.svg b/sim_tools/examples/example1/src/red_ball.svg similarity index 100% rename from sim_fpga/examples/example1/src/red_ball.svg rename to sim_tools/examples/example1/src/red_ball.svg diff --git a/sim_fpga/examples/example1/src/red_ball_center_80x60.png b/sim_tools/examples/example1/src/red_ball_center_80x60.png similarity index 100% rename from sim_fpga/examples/example1/src/red_ball_center_80x60.png rename to sim_tools/examples/example1/src/red_ball_center_80x60.png diff --git a/sim_fpga/examples/example1/src/red_ball_left_80x60.png b/sim_tools/examples/example1/src/red_ball_left_80x60.png similarity index 100% rename from sim_fpga/examples/example1/src/red_ball_left_80x60.png rename to sim_tools/examples/example1/src/red_ball_left_80x60.png diff --git a/sim_fpga/examples/example1/src/red_ball_right_80x60.png b/sim_tools/examples/example1/src/red_ball_right_80x60.png similarity index 100% rename from sim_fpga/examples/example1/src/red_ball_right_80x60.png rename to sim_tools/examples/example1/src/red_ball_right_80x60.png diff --git a/sim_fpga/examples/poc/example1/.gitignore b/sim_tools/examples/poc/example1/.gitignore similarity index 100% rename from sim_fpga/examples/poc/example1/.gitignore rename to sim_tools/examples/poc/example1/.gitignore diff --git a/sim_fpga/examples/poc/example1/Makefile b/sim_tools/examples/poc/example1/Makefile similarity index 100% rename from sim_fpga/examples/poc/example1/Makefile rename to sim_tools/examples/poc/example1/Makefile diff --git a/sim_fpga/examples/poc/example1/build.sbt b/sim_tools/examples/poc/example1/build.sbt similarity index 100% rename from sim_fpga/examples/poc/example1/build.sbt rename to sim_tools/examples/poc/example1/build.sbt diff --git a/sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/ColorFilterPixelProcessor.scala b/sim_tools/examples/poc/example1/gateware/main/scala/jderobot/ColorFilterPixelProcessor.scala similarity index 100% rename from sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/ColorFilterPixelProcessor.scala rename to sim_tools/examples/poc/example1/gateware/main/scala/jderobot/ColorFilterPixelProcessor.scala diff --git a/sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/PixelReader.scala b/sim_tools/examples/poc/example1/gateware/main/scala/jderobot/PixelReader.scala similarity index 100% rename from sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/PixelReader.scala rename to sim_tools/examples/poc/example1/gateware/main/scala/jderobot/PixelReader.scala diff --git a/sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/PixelWriter.scala b/sim_tools/examples/poc/example1/gateware/main/scala/jderobot/PixelWriter.scala similarity index 100% rename from sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/PixelWriter.scala rename to sim_tools/examples/poc/example1/gateware/main/scala/jderobot/PixelWriter.scala diff --git a/sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/TopPixelProcessor.scala b/sim_tools/examples/poc/example1/gateware/main/scala/jderobot/TopPixelProcessor.scala similarity index 100% rename from sim_fpga/examples/poc/example1/gateware/main/scala/jderobot/TopPixelProcessor.scala rename to sim_tools/examples/poc/example1/gateware/main/scala/jderobot/TopPixelProcessor.scala diff --git a/sim_fpga/examples/poc/example1/gateware/test/scala/jderobot/PixelReaderTest.scala b/sim_tools/examples/poc/example1/gateware/test/scala/jderobot/PixelReaderTest.scala similarity index 100% rename from sim_fpga/examples/poc/example1/gateware/test/scala/jderobot/PixelReaderTest.scala rename to sim_tools/examples/poc/example1/gateware/test/scala/jderobot/PixelReaderTest.scala diff --git a/sim_fpga/examples/poc/example1/include/stb_image.h b/sim_tools/examples/poc/example1/include/stb_image.h similarity index 100% rename from sim_fpga/examples/poc/example1/include/stb_image.h rename to sim_tools/examples/poc/example1/include/stb_image.h diff --git a/sim_fpga/examples/poc/example1/rtl/TopPixelProcessor.v b/sim_tools/examples/poc/example1/rtl/TopPixelProcessor.v similarity index 100% rename from sim_fpga/examples/poc/example1/rtl/TopPixelProcessor.v rename to sim_tools/examples/poc/example1/rtl/TopPixelProcessor.v diff --git a/sim_fpga/examples/poc/example1/src/ebu_colorbars_96x72.png b/sim_tools/examples/poc/example1/src/ebu_colorbars_96x72.png similarity index 100% rename from sim_fpga/examples/poc/example1/src/ebu_colorbars_96x72.png rename to sim_tools/examples/poc/example1/src/ebu_colorbars_96x72.png diff --git a/sim_fpga/examples/poc/example1/src/main.cpp b/sim_tools/examples/poc/example1/src/main.cpp similarity index 100% rename from sim_fpga/examples/poc/example1/src/main.cpp rename to sim_tools/examples/poc/example1/src/main.cpp diff --git a/sim_fpga/examples/poc/example2/Makefile b/sim_tools/examples/poc/example2/Makefile similarity index 100% rename from sim_fpga/examples/poc/example2/Makefile rename to sim_tools/examples/poc/example2/Makefile diff --git a/sim_tools/examples/poc/example2/rtl/README.md b/sim_tools/examples/poc/example2/rtl/README.md new file mode 100644 index 00000000..e69de29b diff --git a/sim_fpga/examples/poc/example2/rtl/calc_filter.v b/sim_tools/examples/poc/example2/rtl/calc_filter.v similarity index 100% rename from sim_fpga/examples/poc/example2/rtl/calc_filter.v rename to sim_tools/examples/poc/example2/rtl/calc_filter.v diff --git a/sim_fpga/examples/poc/example2/rtl/design_top.v b/sim_tools/examples/poc/example2/rtl/design_top.v similarity index 100% rename from sim_fpga/examples/poc/example2/rtl/design_top.v rename to sim_tools/examples/poc/example2/rtl/design_top.v diff --git a/sim_fpga/examples/poc/example2/rtl/frame_buff.v b/sim_tools/examples/poc/example2/rtl/frame_buff.v similarity index 100% rename from sim_fpga/examples/poc/example2/rtl/frame_buff.v rename to sim_tools/examples/poc/example2/rtl/frame_buff.v diff --git a/sim_fpga/examples/poc/example2/rtl/image_proc.v b/sim_tools/examples/poc/example2/rtl/image_proc.v similarity index 100% rename from sim_fpga/examples/poc/example2/rtl/image_proc.v rename to sim_tools/examples/poc/example2/rtl/image_proc.v diff --git a/sim_fpga/examples/poc/example2/rtl/simulacionTest.png b/sim_tools/examples/poc/example2/rtl/simulacionTest.png similarity index 100% rename from sim_fpga/examples/poc/example2/rtl/simulacionTest.png rename to sim_tools/examples/poc/example2/rtl/simulacionTest.png diff --git a/sim_fpga/examples/poc/example2/src/ebu_colorbars_96x72.png b/sim_tools/examples/poc/example2/src/ebu_colorbars_96x72.png similarity index 100% rename from sim_fpga/examples/poc/example2/src/ebu_colorbars_96x72.png rename to sim_tools/examples/poc/example2/src/ebu_colorbars_96x72.png diff --git a/sim_fpga/examples/poc/example2/src/fa-solid-900.ttf b/sim_tools/examples/poc/example2/src/fa-solid-900.ttf similarity index 100% rename from sim_fpga/examples/poc/example2/src/fa-solid-900.ttf rename to sim_tools/examples/poc/example2/src/fa-solid-900.ttf diff --git a/sim_fpga/examples/poc/example2/src/main.cpp b/sim_tools/examples/poc/example2/src/main.cpp similarity index 100% rename from sim_fpga/examples/poc/example2/src/main.cpp rename to sim_tools/examples/poc/example2/src/main.cpp diff --git a/sim_fpga/examples/poc/example2/src/red_ball.svg b/sim_tools/examples/poc/example2/src/red_ball.svg similarity index 100% rename from sim_fpga/examples/poc/example2/src/red_ball.svg rename to sim_tools/examples/poc/example2/src/red_ball.svg diff --git a/sim_fpga/examples/poc/example2/src/red_ball_center_80x60.png b/sim_tools/examples/poc/example2/src/red_ball_center_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example2/src/red_ball_center_80x60.png rename to sim_tools/examples/poc/example2/src/red_ball_center_80x60.png diff --git a/sim_fpga/examples/poc/example2/src/red_ball_left_80x60.png b/sim_tools/examples/poc/example2/src/red_ball_left_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example2/src/red_ball_left_80x60.png rename to sim_tools/examples/poc/example2/src/red_ball_left_80x60.png diff --git a/sim_fpga/examples/poc/example2/src/red_ball_right_80x60.png b/sim_tools/examples/poc/example2/src/red_ball_right_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example2/src/red_ball_right_80x60.png rename to sim_tools/examples/poc/example2/src/red_ball_right_80x60.png diff --git a/sim_fpga/examples/poc/example3/Makefile b/sim_tools/examples/poc/example3/Makefile similarity index 100% rename from sim_fpga/examples/poc/example3/Makefile rename to sim_tools/examples/poc/example3/Makefile diff --git a/sim_fpga/examples/poc/example3/include/dut_handler.h b/sim_tools/examples/poc/example3/include/dut_handler.h similarity index 100% rename from sim_fpga/examples/poc/example3/include/dut_handler.h rename to sim_tools/examples/poc/example3/include/dut_handler.h diff --git a/sim_fpga/examples/poc/example3/include/gl_texture_utils.h b/sim_tools/examples/poc/example3/include/gl_texture_utils.h similarity index 100% rename from sim_fpga/examples/poc/example3/include/gl_texture_utils.h rename to sim_tools/examples/poc/example3/include/gl_texture_utils.h diff --git a/sim_fpga/examples/poc/example3/include/input_driver.h b/sim_tools/examples/poc/example3/include/input_driver.h similarity index 100% rename from sim_fpga/examples/poc/example3/include/input_driver.h rename to sim_tools/examples/poc/example3/include/input_driver.h diff --git a/sim_fpga/examples/poc/example3/include/output_monitor.h b/sim_tools/examples/poc/example3/include/output_monitor.h similarity index 100% rename from sim_fpga/examples/poc/example3/include/output_monitor.h rename to sim_tools/examples/poc/example3/include/output_monitor.h diff --git a/sim_fpga/examples/poc/example3/include/sim_element.h b/sim_tools/examples/poc/example3/include/sim_element.h similarity index 100% rename from sim_fpga/examples/poc/example3/include/sim_element.h rename to sim_tools/examples/poc/example3/include/sim_element.h diff --git a/sim_tools/examples/poc/example3/rtl/README.md b/sim_tools/examples/poc/example3/rtl/README.md new file mode 100644 index 00000000..e69de29b diff --git a/sim_fpga/examples/poc/example3/rtl/calc_filter.v b/sim_tools/examples/poc/example3/rtl/calc_filter.v similarity index 100% rename from sim_fpga/examples/poc/example3/rtl/calc_filter.v rename to sim_tools/examples/poc/example3/rtl/calc_filter.v diff --git a/sim_fpga/examples/poc/example3/rtl/design_top.v b/sim_tools/examples/poc/example3/rtl/design_top.v similarity index 100% rename from sim_fpga/examples/poc/example3/rtl/design_top.v rename to sim_tools/examples/poc/example3/rtl/design_top.v diff --git a/sim_fpga/examples/poc/example3/rtl/frame_buff.v b/sim_tools/examples/poc/example3/rtl/frame_buff.v similarity index 100% rename from sim_fpga/examples/poc/example3/rtl/frame_buff.v rename to sim_tools/examples/poc/example3/rtl/frame_buff.v diff --git a/sim_fpga/examples/poc/example3/rtl/image_proc.v b/sim_tools/examples/poc/example3/rtl/image_proc.v similarity index 100% rename from sim_fpga/examples/poc/example3/rtl/image_proc.v rename to sim_tools/examples/poc/example3/rtl/image_proc.v diff --git a/sim_fpga/examples/poc/example3/rtl/simulacionTest.png b/sim_tools/examples/poc/example3/rtl/simulacionTest.png similarity index 100% rename from sim_fpga/examples/poc/example3/rtl/simulacionTest.png rename to sim_tools/examples/poc/example3/rtl/simulacionTest.png diff --git a/sim_fpga/examples/poc/example3/src/ebu_colorbars_96x72.png b/sim_tools/examples/poc/example3/src/ebu_colorbars_96x72.png similarity index 100% rename from sim_fpga/examples/poc/example3/src/ebu_colorbars_96x72.png rename to sim_tools/examples/poc/example3/src/ebu_colorbars_96x72.png diff --git a/sim_fpga/examples/poc/example3/src/fa-solid-900.ttf b/sim_tools/examples/poc/example3/src/fa-solid-900.ttf similarity index 100% rename from sim_fpga/examples/poc/example3/src/fa-solid-900.ttf rename to sim_tools/examples/poc/example3/src/fa-solid-900.ttf diff --git a/sim_fpga/examples/poc/example3/src/gl_texture_utils.cpp b/sim_tools/examples/poc/example3/src/gl_texture_utils.cpp similarity index 100% rename from sim_fpga/examples/poc/example3/src/gl_texture_utils.cpp rename to sim_tools/examples/poc/example3/src/gl_texture_utils.cpp diff --git a/sim_fpga/examples/poc/example3/src/input_driver.cpp b/sim_tools/examples/poc/example3/src/input_driver.cpp similarity index 100% rename from sim_fpga/examples/poc/example3/src/input_driver.cpp rename to sim_tools/examples/poc/example3/src/input_driver.cpp diff --git a/sim_fpga/examples/poc/example3/src/main.cpp b/sim_tools/examples/poc/example3/src/main.cpp similarity index 100% rename from sim_fpga/examples/poc/example3/src/main.cpp rename to sim_tools/examples/poc/example3/src/main.cpp diff --git a/sim_fpga/examples/poc/example3/src/output_monitor.cpp b/sim_tools/examples/poc/example3/src/output_monitor.cpp similarity index 100% rename from sim_fpga/examples/poc/example3/src/output_monitor.cpp rename to sim_tools/examples/poc/example3/src/output_monitor.cpp diff --git a/sim_fpga/examples/poc/example3/src/red_ball.svg b/sim_tools/examples/poc/example3/src/red_ball.svg similarity index 100% rename from sim_fpga/examples/poc/example3/src/red_ball.svg rename to sim_tools/examples/poc/example3/src/red_ball.svg diff --git a/sim_fpga/examples/poc/example3/src/red_ball_center_80x60.png b/sim_tools/examples/poc/example3/src/red_ball_center_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example3/src/red_ball_center_80x60.png rename to sim_tools/examples/poc/example3/src/red_ball_center_80x60.png diff --git a/sim_fpga/examples/poc/example3/src/red_ball_left_80x60.png b/sim_tools/examples/poc/example3/src/red_ball_left_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example3/src/red_ball_left_80x60.png rename to sim_tools/examples/poc/example3/src/red_ball_left_80x60.png diff --git a/sim_fpga/examples/poc/example3/src/red_ball_right_80x60.png b/sim_tools/examples/poc/example3/src/red_ball_right_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example3/src/red_ball_right_80x60.png rename to sim_tools/examples/poc/example3/src/red_ball_right_80x60.png diff --git a/sim_fpga/examples/poc/example4/Makefile b/sim_tools/examples/poc/example4/Makefile similarity index 100% rename from sim_fpga/examples/poc/example4/Makefile rename to sim_tools/examples/poc/example4/Makefile diff --git a/sim_tools/examples/poc/example4/rtl/README.md b/sim_tools/examples/poc/example4/rtl/README.md new file mode 100644 index 00000000..e69de29b diff --git a/sim_fpga/examples/poc/example4/rtl/calc_filter.v b/sim_tools/examples/poc/example4/rtl/calc_filter.v similarity index 100% rename from sim_fpga/examples/poc/example4/rtl/calc_filter.v rename to sim_tools/examples/poc/example4/rtl/calc_filter.v diff --git a/sim_fpga/examples/poc/example4/rtl/design_top.v b/sim_tools/examples/poc/example4/rtl/design_top.v similarity index 100% rename from sim_fpga/examples/poc/example4/rtl/design_top.v rename to sim_tools/examples/poc/example4/rtl/design_top.v diff --git a/sim_fpga/examples/poc/example4/rtl/frame_buff.v b/sim_tools/examples/poc/example4/rtl/frame_buff.v similarity index 100% rename from sim_fpga/examples/poc/example4/rtl/frame_buff.v rename to sim_tools/examples/poc/example4/rtl/frame_buff.v diff --git a/sim_fpga/examples/poc/example4/rtl/image_proc.v b/sim_tools/examples/poc/example4/rtl/image_proc.v similarity index 100% rename from sim_fpga/examples/poc/example4/rtl/image_proc.v rename to sim_tools/examples/poc/example4/rtl/image_proc.v diff --git a/sim_fpga/examples/poc/example4/rtl/simulacionTest.png b/sim_tools/examples/poc/example4/rtl/simulacionTest.png similarity index 100% rename from sim_fpga/examples/poc/example4/rtl/simulacionTest.png rename to sim_tools/examples/poc/example4/rtl/simulacionTest.png diff --git a/sim_fpga/examples/poc/example4/src/ebu_colorbars_96x72.png b/sim_tools/examples/poc/example4/src/ebu_colorbars_96x72.png similarity index 100% rename from sim_fpga/examples/poc/example4/src/ebu_colorbars_96x72.png rename to sim_tools/examples/poc/example4/src/ebu_colorbars_96x72.png diff --git a/sim_fpga/examples/poc/example4/src/fa-solid-900.ttf b/sim_tools/examples/poc/example4/src/fa-solid-900.ttf similarity index 100% rename from sim_fpga/examples/poc/example4/src/fa-solid-900.ttf rename to sim_tools/examples/poc/example4/src/fa-solid-900.ttf diff --git a/sim_fpga/examples/poc/example4/src/main.cpp b/sim_tools/examples/poc/example4/src/main.cpp similarity index 100% rename from sim_fpga/examples/poc/example4/src/main.cpp rename to sim_tools/examples/poc/example4/src/main.cpp diff --git a/sim_fpga/examples/poc/example4/src/red_ball.svg b/sim_tools/examples/poc/example4/src/red_ball.svg similarity index 100% rename from sim_fpga/examples/poc/example4/src/red_ball.svg rename to sim_tools/examples/poc/example4/src/red_ball.svg diff --git a/sim_fpga/examples/poc/example4/src/red_ball_center_80x60.png b/sim_tools/examples/poc/example4/src/red_ball_center_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example4/src/red_ball_center_80x60.png rename to sim_tools/examples/poc/example4/src/red_ball_center_80x60.png diff --git a/sim_fpga/examples/poc/example5/Makefile b/sim_tools/examples/poc/example5/Makefile similarity index 100% rename from sim_fpga/examples/poc/example5/Makefile rename to sim_tools/examples/poc/example5/Makefile diff --git a/sim_fpga/examples/poc/example5/README.md b/sim_tools/examples/poc/example5/README.md similarity index 100% rename from sim_fpga/examples/poc/example5/README.md rename to sim_tools/examples/poc/example5/README.md diff --git a/sim_tools/examples/poc/example5/rtl/README.md b/sim_tools/examples/poc/example5/rtl/README.md new file mode 100644 index 00000000..e69de29b diff --git a/sim_fpga/examples/poc/example5/rtl/calc_filter.v b/sim_tools/examples/poc/example5/rtl/calc_filter.v similarity index 100% rename from sim_fpga/examples/poc/example5/rtl/calc_filter.v rename to sim_tools/examples/poc/example5/rtl/calc_filter.v diff --git a/sim_fpga/examples/poc/example5/rtl/design_top.v b/sim_tools/examples/poc/example5/rtl/design_top.v similarity index 100% rename from sim_fpga/examples/poc/example5/rtl/design_top.v rename to sim_tools/examples/poc/example5/rtl/design_top.v diff --git a/sim_fpga/examples/poc/example5/rtl/frame_buff.v b/sim_tools/examples/poc/example5/rtl/frame_buff.v similarity index 100% rename from sim_fpga/examples/poc/example5/rtl/frame_buff.v rename to sim_tools/examples/poc/example5/rtl/frame_buff.v diff --git a/sim_fpga/examples/poc/example5/rtl/image_proc.v b/sim_tools/examples/poc/example5/rtl/image_proc.v similarity index 100% rename from sim_fpga/examples/poc/example5/rtl/image_proc.v rename to sim_tools/examples/poc/example5/rtl/image_proc.v diff --git a/sim_fpga/examples/poc/example5/rtl/simulacionTest.png b/sim_tools/examples/poc/example5/rtl/simulacionTest.png similarity index 100% rename from sim_fpga/examples/poc/example5/rtl/simulacionTest.png rename to sim_tools/examples/poc/example5/rtl/simulacionTest.png diff --git a/sim_fpga/examples/poc/example5/src/ebu_colorbars_96x72.png b/sim_tools/examples/poc/example5/src/ebu_colorbars_96x72.png similarity index 100% rename from sim_fpga/examples/poc/example5/src/ebu_colorbars_96x72.png rename to sim_tools/examples/poc/example5/src/ebu_colorbars_96x72.png diff --git a/sim_fpga/examples/poc/example5/src/fa-solid-900.ttf b/sim_tools/examples/poc/example5/src/fa-solid-900.ttf similarity index 100% rename from sim_fpga/examples/poc/example5/src/fa-solid-900.ttf rename to sim_tools/examples/poc/example5/src/fa-solid-900.ttf diff --git a/sim_fpga/examples/poc/example5/src/main.cpp b/sim_tools/examples/poc/example5/src/main.cpp similarity index 100% rename from sim_fpga/examples/poc/example5/src/main.cpp rename to sim_tools/examples/poc/example5/src/main.cpp diff --git a/sim_fpga/examples/poc/example5/src/red_ball.svg b/sim_tools/examples/poc/example5/src/red_ball.svg similarity index 100% rename from sim_fpga/examples/poc/example5/src/red_ball.svg rename to sim_tools/examples/poc/example5/src/red_ball.svg diff --git a/sim_fpga/examples/poc/example5/src/red_ball_center_80x60.png b/sim_tools/examples/poc/example5/src/red_ball_center_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example5/src/red_ball_center_80x60.png rename to sim_tools/examples/poc/example5/src/red_ball_center_80x60.png diff --git a/sim_fpga/examples/poc/example5/worlds/camera.world b/sim_tools/examples/poc/example5/worlds/camera.world similarity index 100% rename from sim_fpga/examples/poc/example5/worlds/camera.world rename to sim_tools/examples/poc/example5/worlds/camera.world diff --git a/sim_fpga/examples/poc/example6/Makefile b/sim_tools/examples/poc/example6/Makefile similarity index 100% rename from sim_fpga/examples/poc/example6/Makefile rename to sim_tools/examples/poc/example6/Makefile diff --git a/sim_fpga/examples/poc/example6/README.md b/sim_tools/examples/poc/example6/README.md similarity index 100% rename from sim_fpga/examples/poc/example6/README.md rename to sim_tools/examples/poc/example6/README.md diff --git a/sim_fpga/examples/poc/example6/example6.png b/sim_tools/examples/poc/example6/example6.png similarity index 100% rename from sim_fpga/examples/poc/example6/example6.png rename to sim_tools/examples/poc/example6/example6.png diff --git a/sim_fpga/examples/poc/example6/rtl/centroid.v b/sim_tools/examples/poc/example6/rtl/centroid.v similarity index 100% rename from sim_fpga/examples/poc/example6/rtl/centroid.v rename to sim_tools/examples/poc/example6/rtl/centroid.v diff --git a/sim_fpga/examples/poc/example6/rtl/color_proc.v b/sim_tools/examples/poc/example6/rtl/color_proc.v similarity index 100% rename from sim_fpga/examples/poc/example6/rtl/color_proc.v rename to sim_tools/examples/poc/example6/rtl/color_proc.v diff --git a/sim_fpga/examples/poc/example6/rtl/design_top.v b/sim_tools/examples/poc/example6/rtl/design_top.v similarity index 100% rename from sim_fpga/examples/poc/example6/rtl/design_top.v rename to sim_tools/examples/poc/example6/rtl/design_top.v diff --git a/sim_fpga/examples/poc/example6/rtl/frame_buffer.v b/sim_tools/examples/poc/example6/rtl/frame_buffer.v similarity index 100% rename from sim_fpga/examples/poc/example6/rtl/frame_buffer.v rename to sim_tools/examples/poc/example6/rtl/frame_buffer.v diff --git a/sim_fpga/examples/poc/example6/rtl/tb_design_top.vhd b/sim_tools/examples/poc/example6/rtl/tb_design_top.vhd similarity index 100% rename from sim_fpga/examples/poc/example6/rtl/tb_design_top.vhd rename to sim_tools/examples/poc/example6/rtl/tb_design_top.vhd diff --git a/sim_fpga/examples/poc/example6/src/fa-solid-900.ttf b/sim_tools/examples/poc/example6/src/fa-solid-900.ttf similarity index 100% rename from sim_fpga/examples/poc/example6/src/fa-solid-900.ttf rename to sim_tools/examples/poc/example6/src/fa-solid-900.ttf diff --git a/sim_fpga/examples/poc/example6/src/main.cpp b/sim_tools/examples/poc/example6/src/main.cpp similarity index 100% rename from sim_fpga/examples/poc/example6/src/main.cpp rename to sim_tools/examples/poc/example6/src/main.cpp diff --git a/sim_fpga/examples/poc/example6/src/red_ball.svg b/sim_tools/examples/poc/example6/src/red_ball.svg similarity index 100% rename from sim_fpga/examples/poc/example6/src/red_ball.svg rename to sim_tools/examples/poc/example6/src/red_ball.svg diff --git a/sim_fpga/examples/poc/example6/src/red_ball_center_80x60.png b/sim_tools/examples/poc/example6/src/red_ball_center_80x60.png similarity index 100% rename from sim_fpga/examples/poc/example6/src/red_ball_center_80x60.png rename to sim_tools/examples/poc/example6/src/red_ball_center_80x60.png diff --git a/sim_fpga/include/dut_handler.h b/sim_tools/include/dut_handler.h similarity index 100% rename from sim_fpga/include/dut_handler.h rename to sim_tools/include/dut_handler.h diff --git a/sim_fpga/include/gl_texture_utils.h b/sim_tools/include/gl_texture_utils.h similarity index 100% rename from sim_fpga/include/gl_texture_utils.h rename to sim_tools/include/gl_texture_utils.h diff --git a/sim_fpga/include/sim_element.h b/sim_tools/include/sim_element.h similarity index 100% rename from sim_fpga/include/sim_element.h rename to sim_tools/include/sim_element.h diff --git a/sim_fpga/src/gl_texture_utils.cpp b/sim_tools/src/gl_texture_utils.cpp similarity index 100% rename from sim_fpga/src/gl_texture_utils.cpp rename to sim_tools/src/gl_texture_utils.cpp