Code Monkey home page Code Monkey logo

litex-nexus-mipi's Introduction

LiteX MIPI CSI testing on CrossLink NX VIP

Build and load the design:

python crosslink_nx_vip.py --build --toolchain oxide --nexus-es-device
ecpprog -S build/crosslink_nx_vip/gateware/crosslink_nx_vip.bit

Build and load the software:

cd software
make load

Type serialboot to start the boot. If the camera I2C is working correctly, you should see:

IMX258_REG_CHIP_ID 0258

Initialisation currently takes a while due to the slow PicoRV32+HyperRAM combo, this can be improved. Once at the prompt, type packet to print the first 128 words of the last received MIPI CSI-2 packet.

Examples:

2b09601d
31233136
bd393a35
382e243b
32ba3930
3c3037d3
403e3735
7b282d30
42384a39
38c83a35
2b3531dd
3b363434
02393b3d
4e3be144
3496392c

the 2b09601d header corresponds to a RAW10 packet with 2400 bytes (1920 pixels) of data.

litex-nexus-mipi's People

Contributors

gatecat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

litex-nexus-mipi's Issues

Porting to crosslinknx evaluation board

Hi!

I'm trying to get MIPI CSI working on the Crosslinknx evaluation board. Unfortunately, I don't see anything on the byte clock - 'freq' returns 0 Hz and the data / packets are all empty. I had a similar setup (I2C + CSI, no soft core) written in Verilog and built on Radiant with the same issue. Here are the changes I've made to your original project:

  • fix import
  • replace register_mem with add_slave
  • replace the HyperRAM main_ram with LRAM
  • changed serial output to pmod0

Other than this I also made some changes to the Makefile and C source to make it compatible with the new litex setup. I can push it to a new branch if that's useful. Unfortunately, I don't have a VIP board to test it, so I didn't make a PR.

As shown below I tried different combinations of constraints, but no success. Also for some reason, the project doesn't work when built with radiant (led chaser stuck with all LEDs on, no BIOS on UART), but that's probably a separate issue. I would appreciate any ideas or inputs about how I can go forward with this. Was it working at the time of publishing this? If yes, could you send me the versions so I can try to replicate it?

Thanks!

#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2020 David Corrigan <[email protected]>
# Copyright (c) 2020 Alan Green <[email protected]>
# Copyright (c) 2020-21 gatecat <[email protected]>
#
# SPDX-License-Identifier: BSD-2-Clause

from migen import *

from litex_boards.platforms import lattice_crosslink_nx_evn

from litex_boards.targets.lattice_crosslink_nx_evn import _CRG
from litex.build.io import CRG

from litex.soc.cores.ram import NXLRAM
from litex.build.generic_platform import *

from litex.soc.interconnect import wishbone

from litex.soc.cores.clock import *
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.integration.soc import SoCRegion
from litex.soc.cores.led import LedChaser
from litex.soc.cores.bitbang import I2CMaster
from litex.soc.cores.freqmeter import FreqMeter
from litex.soc.cores.gpio import GPIOIn

from litex.build.lattice.oxide import oxide_args, oxide_argdict

from dphy_wrapper import DPHY_CSIRX_CIL
from mipi_csi import *

kB = 1024
mB = 1024*kB

camera = [   
    ("camera", 0,
        # Subsignal("clkp", Pins("X")),
        # Subsignal("clkn", Pins("X")),
        # Subsignal("dp", Pins("X X X X")),
        # Subsignal("dn", Pins("X X X X"))
        Subsignal("clkp", Pins("DPHY0")),
        Subsignal("clkn", Pins("DPHY0")),
        # Subsignal("dp", Pins("B2 A3 C2 A4"), IOStandard("MIPI_DPHY")),
        # Subsignal("dn", Pins("C1 B3 D1 B4"), IOStandard("LVCMOS12H"))
        Subsignal("dp", Pins("DPHY0 DPHY0 DPHY0 DPHY0")),
        Subsignal("dn", Pins("DPHY0 DPHY0 DPHY0 DPHY0"))
    ),

    ("camera_i2c", 0,
        Subsignal("scl", Pins("Y5")),
        Subsignal("sda", Pins("W5")),
        IOStandard("LVCMOS18H")
    ),

    ("camera_reset", 0, Pins("W18"), IOStandard("LVCMOS18H")),
]

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

class BaseSoC(SoCCore):
    SoCCore.mem_map = {
        "rom":              0x00000000,
        "sram":             0x40000000,
        "main_ram":         0x50000000,
        "csr":              0xf0000000,
    }
    def __init__(self, sys_clk_freq=int(75e6), hyperram="none", toolchain="radiant", **kwargs):
        platform = lattice_crosslink_nx_evn.Platform(device="LIFCL-40-9BG400C", toolchain=toolchain)

        # CRG --------------------------------------------------------------------------------------
        self.crg = _CRG(platform, sys_clk_freq)

        # SoCCore -----------------------------------------_----------------------------------------
        # Disable Integrated SRAM since we want to instantiate LRAM specifically for it
        kwargs["integrated_sram_size"] = 0
        # Make serial_pmods available
        platform.add_extension(lattice_crosslink_nx_evn.serial_pmods)
        
        # Set uart output to pmod0
        kwargs["uart_name"] = "serial_pmod0"
        platform.add_extension(camera)
        SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on Crosslink-NX Evaluation Board", **kwargs)

        # 128KB LRAM (used as SRAM and main RAM) ---------------------------------------------
        self.spram = NXLRAM(32, 64*kB)
        self.bus.add_slave("sram", self.spram.bus, SoCRegion(origin=self.mem_map["sram"], size=64*kB))

        self.main_ram = NXLRAM(32, 64*kB)
        self.bus.add_slave("main_ram", self.main_ram.bus, SoCRegion(origin=self.mem_map["main_ram"], size=64*kB))

        # Leds -------------------------------------------------------------------------------------
        self.leds = LedChaser(
            pads         = Cat(*[platform.request("user_led", i) for i in range(14)]),
            sys_clk_freq = sys_clk_freq)

        self.submodules.i2c = I2CMaster(platform.request("camera_i2c", 0))
        self.add_csr("i2c")

        self.submodules.dphy = DPHY_CSIRX_CIL(
            pads        = platform.request("camera", 0),
            num_lanes   = 4,
            clk_mode    = "ENABLED",
            deskew      = "DISABLED",
            gearing     = 8,
            loc         = "TDPHY_CORE2",
        )

        cam_rst = platform.request("camera_reset", 0)
        self.comb += cam_rst.eq(ResetSignal())

        self.comb += [
            self.dphy.sync_clk.eq(ClockSignal()),
            self.dphy.sync_rst.eq(ResetSignal()),
            self.dphy.pd_dphy.eq(0),
            self.dphy.hs_rx_en.eq(1),
        ]

        self.submodules.clk_byte_freq = FreqMeter(period=int(sys_clk_freq), clk=self.dphy.clk_byte)
        self.add_csr("clk_byte_freq")
        self.submodules.hs_rx_data = GPIOIn(pads=self.dphy.hs_rx_data)
        self.add_csr("hs_rx_data")
        self.submodules.hs_rx_sync = GPIOIn(pads=self.dphy.hs_rx_sync)
        self.add_csr("hs_rx_sync")

        self.clock_domains.cd_mipi = ClockDomain()
        self.comb += self.cd_mipi.clk.eq(self.dphy.clk_byte)
        dphy_header = Signal(32)
        for i in range(0, 4):
            prev_sync = Signal()
            self.sync.mipi += prev_sync.eq(self.dphy.hs_rx_sync[i])
            self.sync.mipi += If(prev_sync, dphy_header[(8*i):(8*(i+1))].eq(self.dphy.hs_rx_data[(8*i):(8*(i+1))]))
        self.submodules.dphy_header = GPIOIn(pads=dphy_header)
        self.add_csr("dphy_header")

        wa = WordAligner(lane_width=8, num_lanes=4, depth=3)
        swapped_data = Cat(self.dphy.hs_rx_data[24:32], self.dphy.hs_rx_data[8:16], self.dphy.hs_rx_data[16:24], self.dphy.hs_rx_data[0:8])
        self.sync.mipi += [
            wa.data_in.eq(swapped_data),
            wa.sync_in.eq(self.dphy.hs_rx_sync)
        ]
        self.submodules.wa = wa

        packet_cap = PacketCapture(data=wa.data_out, data_sync=wa.sync_out, depth=128)
        self.submodules.packet_cap = packet_cap
        packet_io = wishbone.SRAM(self.packet_cap.mem, read_only=True)
        self.submodules.packet_io = packet_io
        self.bus.add_slave("packet_io", packet_io.bus, SoCRegion(origin=0xb0000000, size=0x4000, cached=False, mode="r"))

        # ----------------------------------------------------------------
        image_cap = ImageCapture(data=wa.data_out, data_sync=wa.sync_out, subsample_x=10, subsample_y=32, out_width=60, out_height=33)
        self.submodules.image_cap = image_cap
        image_io = wishbone.SRAM(self.image_cap.mem, read_only=True)
        self.submodules.image_io = image_io
        self.bus.add_slave("image_io", image_io.bus, SoCRegion(origin=0xb0010000, size=0x4000, cached=False, mode="r"))

        # self.add_uartbone(uart_name="serial")

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

def main():
    from litex.build.parser import LiteXArgumentParser
    parser = LiteXArgumentParser(platform=lattice_crosslink_nx_evn.Platform, description="LiteX SoC on Crosslink-NX Eval Board.")
    parser.add_target_argument("--device",        default="LIFCL-40-9BG400C", help="FPGA device (LIFCL-40-9BG400C, LIFCL-40-8BG400CES, or LIFCL-40-8BG400CES2).")
    parser.add_target_argument("--sys-clk-freq",  default=75e6, type=float,   help="System clock frequency.")
    parser.add_target_argument("--serial",        default="serial",           help="UART Pins (serial (requires R15 and R17 to be soldered) or serial_pmod[0-2]).")
    parser.add_target_argument("--programmer",    default="radiant",          help="Programmer (radiant or ecpprog or openocd).")
    parser.add_target_argument("--address",       default=0x0,                help="Flash address to program bitstream at.")
    parser.add_target_argument("--prog-target",   default="direct",           help="Programming Target (direct or flash).")
    parser.add_target_argument("--with-spi-flash", action="store_true",       help="Enable SPI Flash (MMAPed).")
    parser.add_target_argument("--with-uartbone", action="store_true",        help="Add UartBone on 1st serial.")
    args = parser.parse_args()

    soc = BaseSoC(
        sys_clk_freq = `args.sys_clk_freq,`
        device       = args.device,
        toolchain    = args.toolchain,
        with_spi_flash = args.with_spi_flash,
        with_uartbone = args.with_uartbone,
        **parser.soc_argdict
    )
    builder = Builder(soc, **parser.builder_argdict)
    if args.build:
        builder.build(**parser.toolchain_argdict)

if __name__ == "__main__":
    main()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.