Esempio n. 1
0
    def __init__(self,
                 sys_clk_freq=int(48e6),
                 x5_clk_freq=None,
                 toolchain="trellis",
                 **kwargs):
        platform = evb_platform.Platform(toolchain=toolchain)

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self,
                         platform,
                         sys_clk_freq,
                         ident="LiteX SOC on @loxodes ECP5 Evaluation Board",
                         ident_version=True,
                         **kwargs)

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

        # HyperRam ---------------------------------------------------------------------------------
        self.mem_map["hyperram"] = 0x20000000
        self.submodules.hyperram = HyperRAM(platform.request("hyperram"))
        self.add_wb_slave(self.mem_map["hyperram"], self.hyperram.bus)
        self.add_memory_region("hyperram", self.mem_map["hyperram"],
                               8 * 1024 * 1024)

        # SPIFlash ---------------------------------------------------------------------------------
        self.submodules.spiflash = ECP5SPIFlash(
            pads=platform.request("spiflash"),
            sys_clk_freq=sys_clk_freq,
            spi_clk_freq=5e6,
        )
        self.add_csr("spiflash")

        # Wishbone  usb debug port
        # see https://gist.github.com/enjoy-digital/82ed88b77ef0b1e3e91b0592e44eaa14
        os.system(
            "git clone https://github.com/litex-hub/valentyusb -b hw_cdc_eptri"
        )
        sys.path.append("valentyusb")
        from valentyusb.usbcore.cpu import dummyusb, epfifo
        from valentyusb.usbcore import io as usbio
        usb_debug = True
        usb_pads = platform.request("usb_aux")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb = dummyusb.DummyUsb(
            usb_iobuf, debug=usb_debug
        )  #epfifo.PerEndpointFifoInterface(usb_iobuf, debug=usb_debug)
        self.add_wb_master(self.usb.debug_bridge.wishbone)
        #self.register_mem("vexriscv_debug", 0xf00f0000, self.cpu.debug_bus, 0x100)
        # https://github.com/enjoy-digital/litex/issues/345
        # Leds -------------------------------------------------------------------------------------
        self.submodules.leds = LedChaser(pads=platform.request_all("user_led"),
                                         sys_clk_freq=sys_clk_freq)
        self.add_csr("leds")
Esempio n. 2
0
    def __init__(self, platform, is_sim=False, **kwargs):
        clk_freq = int(48e6)
        SoCCore.__init__(self, platform, clk_freq,
                         cpu_type=None,
                         cpu_variant="linux+debug",
                         integrated_sram_size=4096,
                         **kwargs)
        if is_sim:
            self.submodules.crg = CocotbPlatform._CRG(self.platform)
        else:
            self.submodules.crg = _CRG(self.platform)

        # Add a "Version" module so we can see what version of the board this is.
        self.submodules.version = Version("proto2", [
            (0x02, "proto2", "Prototype Version 2 (red)")
        ], 0)

        # Add a "USB" module to let us debug the device.
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb = ClockDomainsRenamer({
            "usb_48": "clk48",
            "usb_12": "clk12",
        })(DummyUsb(usb_iobuf, debug=True, product="Hackaday Supercon Badge"))
        self.add_wb_master(self.usb.debug_bridge.wishbone)

        # Add the 16 MB SPI flash as XIP memory at address 0x03000000
        if not is_sim:
            flash = SpiFlashDualQuad(platform.request("spiflash4x"), dummy=5)
            flash.add_clk_primitive(self.platform.device)
            self.submodules.lxspi = flash
            self.register_mem("spiflash", 0x03000000, self.lxspi.bus, size=16 * 1024 * 1024)

        # Add the 16 MB SPI RAM at address 0x04000000
        ram1 = SpiRamQuad(platform.request("spiram4x", 0), dummy=5)
        self.submodules.ram1 = ram1
        self.register_mem("ram1", 0x04000000, self.ram1.bus, size=8 * 1024 * 1024)

        # Let us reboot the device
        self.submodules.reboot = Reboot(platform.request("programn"))

        # Add a Messible for sending messages to the host
        self.submodules.messible = Messible()

        # Ensure timing is correctly set up
        if not is_sim:
            self.platform.toolchain.build_template[1] += " --speed 8" # Add "speed grade 8" to nextpnr-ecp5
            self.platform.toolchain.freq_constraints["sys"] = 48

        if is_sim:
            class _WishboneBridge(Module):
                def __init__(self, interface):
                    self.wishbone = interface
            self.add_cpu(_WishboneBridge(self.platform.request("wishbone")))
            self.add_wb_master(self.cpu.wishbone)
Esempio n. 3
0
    def __init__(self,
                 platform,
                 output_dir="build",
                 placer=None,
                 pnr_seed=0,
                 use_pll=True,
                 **kwargs):
        clk_freq = int(12e6)
        self.submodules.crg = _CRG(platform, use_pll=use_pll)
        SoCCore.__init__(self,
                         platform,
                         clk_freq,
                         cpu_type=None,
                         cpu_variant=None,
                         integrated_sram_size=0,
                         with_uart=False,
                         with_ctrl=False,
                         **kwargs)

        # Add the LED driver block
        led_pads = platform.request("rgb_led")
        self.submodules.rgb = FomuRGB(led_pads)

        # UP5K has single port RAM, which is a dedicated 128 kilobyte block.
        # Use this as CPU RAM.
        spram_size = 128 * 1024
        self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
        self.register_mem("sram", 0x10000000, self.spram.bus, spram_size)

        # Add USB pads.  We use DummyUsb, which simply enumerates as a USB
        # device.  Then all interaction is done via the wishbone bridge.
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=True)
        self.add_wb_master(self.usb.debug_bridge.wishbone)

        # Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command.
        # "-reult" adds an additional LUT pass to pack more stuff in, and
        # "-dffe_min_ce_use 4" flag prevents Yosys from generating a
        # Clock Enable signal for a LUT that has fewer than 4 flip-flops.
        # This increases density, and lets us use the FPGA more efficiently.
        platform.toolchain.nextpnr_yosys_template[
            2] += " -relut -dffe_min_ce_use 4"

        # Allow us to set the nextpnr seed, because some values don't meet timing.
        platform.toolchain.nextpnr_build_template[1] += " --seed " + str(
            pnr_seed)

        # Different placers can improve packing efficiency, however not all placers
        # are enabled on all builds of nextpnr-ice40.  Let the user override which
        # placer they want to use.
        if placer is not None:
            platform.toolchain.nextpnr_build_template[
                1] += " --placer {}".format(placer)
Esempio n. 4
0
    def __init__(self,
                 sys_clk_freq=int(100e6),
                 with_pwm=False,
                 with_gpio=False,
                 gpio_width=32,
                 with_spi_master=False,
                 spi_master_data_width=8,
                 spi_master_clk_freq=8e6,
                 **kwargs):

        platform = Platform(_io)

        # CRG --------------------------------------------------------------------------------------
        self.submodules.crg = _CRG(platform)

        # SoCMini ----------------------------------------------------------------------------------
        print(kwargs)
        SoCMini.__init__(self, platform, clk_freq=sys_clk_freq, **kwargs)

        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb = eptri.TriEndpointInterface(usb_iobuf,
                                                         debug=False)
        self.add_csr("usb")

        # Wishbone Master
        if kwargs["bus"] == "wishbone":
            wb_bus = wishbone.Interface()
            self.bus.add_master(master=wb_bus)
            platform.add_extension(wb_bus.get_ios("wb"))
            wb_pads = platform.request("wb")
            self.comb += wb_bus.connect_to_pads(wb_pads, mode="slave")

        # IRQs
        for name, loc in sorted(self.irq.locs.items()):
            module = getattr(self, name)
            platform.add_extension([("irq_" + name, 0, Pins(1))])
            irq_pin = platform.request("irq_" + name)
            self.comb += irq_pin.eq(module.ev.irq)
Esempio n. 5
0
    def __init__(self, platform, boot_source="rand",
                 debug=None, bios_file=None,
                 use_dsp=False, placer="heap", output_dir="build",
                 pnr_seed=0,
                 warmboot_offsets=None,
                 **kwargs):
        # Disable integrated RAM as we'll add it later
        self.integrated_sram_size = 0

        self.output_dir = output_dir

        clk_freq = int(12e6)
        self.submodules.crg = _CRG(platform)

        SoCCore.__init__(self, platform, clk_freq, integrated_sram_size=0, with_uart=False, **kwargs)

        usb_debug = False
        if debug is not None:
            if debug == "uart":
                from litex.soc.cores.uart import UARTWishboneBridge
                self.submodules.uart_bridge = UARTWishboneBridge(platform.request("serial"), clk_freq, baudrate=115200)
                self.add_wb_master(self.uart_bridge.wishbone)
            elif debug == "usb":
                usb_debug = True
            elif debug == "spi":
                import spibone
                # Add SPI Wishbone bridge
                debug_device = [
                    ("spidebug", 0,
                        Subsignal("mosi", Pins("dbg:0")),
                        Subsignal("miso", Pins("dbg:1")),
                        Subsignal("clk",  Pins("dbg:2")),
                        Subsignal("cs_n", Pins("dbg:3")),
                    )
                ]
                platform.add_extension(debug_device)
                spi_pads = platform.request("spidebug")
                self.submodules.spibone = ClockDomainsRenamer("usb_12")(spibone.SpiWishboneBridge(spi_pads, wires=4))
                self.add_wb_master(self.spibone.wishbone)
            if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone):
                self.cpu.use_external_variant("rtl/VexRiscv_Fomu_Debug.v")
                os.path.join(output_dir, "gateware")
                self.register_mem("vexriscv_debug", 0xf00f0000, self.cpu.debug_bus, 0x100)
        else:
            if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone):
                self.cpu.use_external_variant("rtl/VexRiscv_Fomu.v")

        # SPRAM- UP5K has single port RAM, might as well use it as SRAM to
        # free up scarce block RAM.
        spram_size = 128*1024
        self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
        self.register_mem("sram", self.mem_map["sram"], self.spram.bus, spram_size)

        # Add a Messible for device->host communications
        self.submodules.messible = Messible()

        if boot_source == "rand":
            kwargs['cpu_reset_address'] = 0
            bios_size = 0x2000
            self.submodules.random_rom = RandomFirmwareROM(bios_size)
            self.add_constant("ROM_DISABLE", 1)
            self.register_rom(self.random_rom.bus, bios_size)
        elif boot_source == "bios":
            kwargs['cpu_reset_address'] = 0
            if bios_file is None:
                self.integrated_rom_size = bios_size = 0x2000
                self.submodules.rom = wishbone.SRAM(bios_size, read_only=True, init=[])
                self.register_rom(self.rom.bus, bios_size)
            else:
                bios_size = 0x2000
                self.submodules.firmware_rom = FirmwareROM(bios_size, bios_file)
                self.add_constant("ROM_DISABLE", 1)
                self.register_rom(self.firmware_rom.bus, bios_size)

        elif boot_source == "spi":
            kwargs['cpu_reset_address'] = 0
            self.integrated_rom_size = bios_size = 0x2000
            gateware_size = 0x1a000
            self.flash_boot_address = self.mem_map["spiflash"] + gateware_size
            self.submodules.rom = wishbone.SRAM(bios_size, read_only=True, init=[])
            self.register_rom(self.rom.bus, bios_size)
        else:
            raise ValueError("unrecognized boot_source: {}".format(boot_source))

        # The litex SPI module supports memory-mapped reads, as well as a bit-banged mode
        # for doing writes.
        spi_pads = platform.request("spiflash4x")
        self.submodules.lxspi = spi_flash.SpiFlashDualQuad(spi_pads, dummy=platform.spi_dummy, endianness="little")
        self.register_mem("spiflash", self.mem_map["spiflash"], self.lxspi.bus, size=platform.spi_size)

        # Add USB pads, as well as the appropriate USB controller.  If no CPU is
        # present, use the DummyUsb controller.
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone):
            self.submodules.usb = eptri.TriEndpointInterface(usb_iobuf, debug=usb_debug)
        else:
            self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=usb_debug)

        if usb_debug:
            self.add_wb_master(self.usb.debug_bridge.wishbone)
        # For the EVT board, ensure the pulldown pin is tristated as an input
        if hasattr(usb_pads, "pulldown"):
            pulldown = TSTriple()
            self.specials += pulldown.get_tristate(usb_pads.pulldown)
            self.comb += pulldown.oe.eq(0)

        # Add GPIO pads for the touch buttons
        platform.add_extension(TouchPads.touch_device)
        self.submodules.touch = TouchPads(platform.request("touch_pads"))

        # Allow the user to reboot the ICE40.  Additionally, connect the CPU
        # RESET line to a register that can be modified, to allow for
        # us to debug programs even during reset.
        self.submodules.reboot = SBWarmBoot(self, warmboot_offsets)
        if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone):
            self.cpu.cpu_params.update(
                i_externalResetVector=self.reboot.addr.storage,
            )

        self.submodules.rgb = SBLED(platform.revision, platform.request("rgb_led"))
        self.submodules.version = Version(platform.revision, self, pnr_seed, models=[
                ("0x45", "E", "Fomu EVT"),
                ("0x44", "D", "Fomu DVT"),
                ("0x50", "P", "Fomu PVT (production)"),
                ("0x48", "H", "Fomu Hacker"),
                ("0x3f", "?", "Unknown model"),
            ])

        # Override default LiteX's yosys/build templates
        assert hasattr(platform.toolchain, "yosys_template")
        assert hasattr(platform.toolchain, "build_template")
        platform.toolchain.yosys_template = [
            "{read_files}",
            "attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0",
            "synth_ice40 -json {build_name}.json -top {build_name}",
        ]
        platform.toolchain.build_template = [
            "yosys -q -l {build_name}.rpt {build_name}.ys",
            "nextpnr-ice40 --json {build_name}.json --pcf {build_name}.pcf --asc {build_name}.txt \
            --pre-pack {build_name}_pre_pack.py --{architecture} --package {package}",
            "icepack {build_name}.txt {build_name}.bin"
        ]

        # Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command.
        # The "-reult" adds an additional LUT pass to pack more stuff in,
        # and the "-dffe_min_ce_use 4" flag prevents Yosys from generating a
        # Clock Enable signal for a LUT that has fewer than 4 flip-flops.
        # This increases density, and lets us use the FPGA more efficiently.
        platform.toolchain.yosys_template[2] += " -relut -abc2 -dffe_min_ce_use 4 -relut"
        if use_dsp:
            platform.toolchain.yosys_template[2] += " -dsp"

        # Disable final deep-sleep power down so firmware words are loaded
        # onto softcore's address bus.
        platform.toolchain.build_template[2] = "icepack -s {build_name}.txt {build_name}.bin"

        # Allow us to set the nextpnr seed
        platform.toolchain.build_template[1] += " --seed " + str(pnr_seed)

        if placer is not None:
            platform.toolchain.build_template[1] += " --placer {}".format(placer)
Esempio n. 6
0
    def __init__(self,
                 board,
                 pnr_placer="heap",
                 pnr_seed=0,
                 usb_core="dummyusb",
                 usb_bridge=False,
                 **kwargs):
        """Create a basic SoC for Fomu.

        Create a basic SoC for Fomu, including a 48 MHz and 12 MHz clock
        domain called `usb_48` and `usb_12`.  The `sys` frequency will
        run at 12 MHz.

        The USB core will optionally have a bridge to the Wishbone bus.

        Args:
            board (str): Which Fomu board to build for: pvt, evt, or hacker
            pnr_placer (str): Which placer to use in nextpnr
            pnr_seed (int): Which seed to use in nextpnr
            usb_core (str): The name of the USB core to use, if any: dummyusb, epfifo
            usb_bridge (bool): Whether to include a USB-to-Wishbone bridge
        Raises:
            ValueError: If either the `usb_core` or `board` are unrecognized
        Returns:
            Newly-constructed SoC
        """
        if board == "pvt":
            from litex_boards.partner.platforms.fomu_pvt import Platform
        elif board == "hacker":
            from litex_boards.partner.platforms.fomu_hacker import Platform
        elif board == "evt":
            from litex_boards.partner.platforms.fomu_evt import Platform
        else:
            raise ValueError("unrecognized fomu board: {}".format(board))
        platform = Platform()

        if "cpu_type" not in kwargs:
            kwargs["cpu_type"] = None
            kwargs["cpu_variant"] = None

        clk_freq = int(12e6)

        SoCCore.__init__(self,
                         platform,
                         clk_freq,
                         integrated_sram_size=0,
                         with_uart=False,
                         with_ctrl=False,
                         **kwargs)

        self.submodules.crg = _CRG(platform)

        # UP5K has single port RAM, which is a dedicated 128 kilobyte block.
        # Use this as CPU RAM.
        spram_size = 128 * 1024
        self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
        self.register_mem("sram", self.mem_map["sram"], self.spram.bus,
                          spram_size)

        if usb_core is not None:
            # Add USB pads.  We use DummyUsb, which simply enumerates as a USB
            # device.  Then all interaction is done via the wishbone bridge.
            usb_pads = platform.request("usb")
            usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n,
                                    usb_pads.pullup)
            if usb_core == "dummyusb":
                self.submodules.usb = dummyusb.DummyUsb(usb_iobuf,
                                                        debug=usb_bridge)
            elif usb_core == "epfifo":
                self.submodules.usb = epfifo.PerEndpointFifo(usb_iobuf,
                                                             debug=usb_bridge)
            else:
                raise ValueError("unrecognized usb_core: {}".args(usb_core))
            if usb_bridge:
                self.add_wb_master(self.usb.debug_bridge.wishbone)

        # Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command.
        # "-reult" adds an additional LUT pass to pack more stuff in, and
        # "-dffe_min_ce_use 4" flag prevents Yosys from generating a
        # Clock Enable signal for a LUT that has fewer than 4 flip-flops.
        # This increases density, and lets us use the FPGA more efficiently.
        platform.toolchain.nextpnr_yosys_template[
            2] += " -relut -dffe_min_ce_use 4"

        # Allow us to set the nextpnr seed, because some values don't meet timing.
        platform.toolchain.nextpnr_build_template[1] += " --seed " + str(
            pnr_seed)

        # Different placers can improve packing efficiency, however not all placers
        # are enabled on all builds of nextpnr-ice40.  Let the user override which
        # placer they want to use.
        if pnr_placer is not None:
            platform.toolchain.nextpnr_build_template[
                1] += " --placer {}".format(pnr_placer)
Esempio n. 7
0
    def __init__(self, platform, debug=False, **kwargs):
        clk_freq = int(12e6)

        if "cpu_type" not in kwargs:
            kwargs["cpu_type"] = None
            kwargs["cpu_variant"] = None

        if "with_uart" not in kwargs:
            kwargs["with_uart"] = False

        if "with_ctrl" not in kwargs:
            kwargs["with_ctrl"] = False

        kwargs["integrated_sram_size"] = 0

        bios_size = kwargs["integrated_rom_size"]
        kwargs["integrated_rom_size"] = 0
        kwargs["cpu_reset_address"] = self.mem_map["spiflash"]+platform.bootloader_size+platform.gateware_size

        SoCCore.__init__(self, platform, clk_freq, **kwargs)

        self.submodules.crg = _CRG(platform)

        # SPRAM- UP5K has single port RAM, might as well use it as SRAM to
        # free up scarce block RAM.
        spram_size = 128*1024
        self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
        self.register_mem("sram", self.mem_map["sram"], self.spram.bus, spram_size)

        # Control and Status
        self.submodules.cas = cas.ControlAndStatus(platform, clk_freq)

        # SPI flash peripheral
        self.submodules.spiflash = spi_flash.SpiFlashSingle(
            platform.request("spiflash"),
            dummy=platform.spiflash_read_dummy_bits,
            div=platform.spiflash_clock_div)
        self.add_csr("spiflash")
        self.add_constant("SPIFLASH_PAGE_SIZE", platform.spiflash_page_size)
        self.add_constant("SPIFLASH_SECTOR_SIZE", platform.spiflash_sector_size)
        self.register_mem("spiflash", self.mem_map["spiflash"],
            self.spiflash.bus, size=platform.spiflash_total_size)

        self.add_constant("ROM_DISABLE", 1)
        self.add_memory_region(
            "rom", kwargs["cpu_reset_address"], bios_size,
            type="cached+linker")
        self.flash_boot_address = kwargs["cpu_reset_address"]+bios_size
        define_flash_constants(self)

        # We don't have a DRAM, so use the remaining SPI flash for user
        # program.
        self.add_memory_region("user_flash",
            self.flash_boot_address,
            # Leave a grace area- possible one-by-off bug in add_memory_region?
            # Possible fix: addr < origin + length - 1
            platform.spiflash_total_size - (self.flash_boot_address - self.mem_map["spiflash"]) - 0x100,
            type="cached+linker")

        # Add USB pads
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=debug)
        if debug:
            self.add_wb_master(self.usb.debug_bridge.wishbone)

        # For the EVT board, ensure the pulldown pin is tristated as an input
        if hasattr(usb_pads, "pulldown"):
            pulldown = TSTriple()
            self.specials += pulldown.get_tristate(usb_pads.pulldown)
            self.comb += pulldown.oe.eq(0)
Esempio n. 8
0
    def __init__(self, platform, is_sim=False, debug=True, **kwargs):
        clk_freq = int(12e6)
        SoCCore.__init__(self,
                         platform,
                         clk_freq,
                         integrated_rom_size=16384,
                         integrated_sram_size=131072,
                         with_uart=True,
                         uart_stub=True,
                         **kwargs)
        if is_sim:
            self.submodules.crg = CocotbPlatform._CRG(self.platform)
        else:
            self.submodules.crg = _CRG(self.platform, fast_sysclk=False)

        # Add a "Version" module so we can see what version of the board this is.
        self.submodules.version = Version(
            "proto2", [(0x02, "proto2", "Prototype Version 2 (red)")], 0)

        # Add a "USB" module to let us debug the device.
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb = ClockDomainsRenamer({
            "usb_48": "clk48",
            "usb_12": "clk12",
            # })(DummyUsb(usb_iobuf, debug=debug, product="Hackaday Supercon Badge", cdc=True))
        })(TriEndpointInterface(usb_iobuf, debug=debug))

        dir_path = os.path.dirname(os.path.realpath(__file__))
        if debug:
            from litex.soc.cores.uart import UARTWishboneBridge
            self.submodules.uart_bridge = UARTWishboneBridge(
                platform.request("serial"), clk_freq, baudrate=115200)
            self.add_wb_master(self.uart_bridge.wishbone)
            self.add_wb_master(self.usb.debug_bridge.wishbone)

            if self.cpu_type is not None:
                self.register_mem("vexriscv_debug", 0xf00f0000,
                                  self.cpu.debug_bus, 0x200)
                self.cpu.use_external_variant(dir_path +
                                              "/rtl/VexRiscv_HaD_Debug.v")
        elif self.cpu_type is not None:
            self.cpu.use_external_variant(dir_path + "/rtl/VexRiscv_HaD.v")

        # Add the 16 MB SPI flash as XIP memory at address 0x03000000
        if not is_sim:
            flash = SpiFlashDualQuad(platform.request("spiflash4x"),
                                     dummy=6,
                                     endianness="little")
            flash.add_clk_primitive(self.platform.device)
            self.submodules.lxspi = flash
            self.register_mem("spiflash",
                              self.mem_map["spiflash"],
                              self.lxspi.bus,
                              size=16 * 1024 * 1024)
            # self.submodules.picorvspi = flash = PicoRVSpi(self.platform, pads=platform.request("spiflash"), size=16 * 1024 * 1024)
            # self.register_mem("spiflash", self.mem_map["spiflash"], self.picorvspi.bus, size=self.picorvspi.size)
            self.add_constant("ROM_BOOT_ADDRESS",
                              self.mem_map["spiflash"] + 0x300000)

        # # Add the 16 MB SPI RAM at address 0x40000000 # Value at 40010000: afbfcfef
        reset_cycles = 2**14 - 1
        if is_sim:
            reset_cycles = 0
        ram = SpiRamDualQuad(platform.request("spiram4x", 0),
                             platform.request("spiram4x", 1),
                             dummy=5,
                             reset_cycles=reset_cycles,
                             qpi=True)
        self.submodules.ram = ram
        self.register_mem("main_ram",
                          self.mem_map["main_ram"],
                          self.ram.bus,
                          size=16 * 1024 * 1024)

        # Let us reboot the device
        self.submodules.reboot = Reboot(platform.request("programn"))

        # Add a Messible for sending messages to the host
        self.submodules.messible = Messible()

        # Add an LCD so we can see what's up
        self.submodules.lcdif = LCDIF(platform.request("lcd"))

        # Ensure timing is correctly set up
        if not is_sim:
            self.platform.toolchain.build_template[
                1] += " --speed 8"  # Add "speed grade 8" to nextpnr-ecp5
            self.platform.toolchain.freq_constraints["sys"] = 48

        if is_sim:
            self.add_wb_master(self.platform.request("wishbone"))

        # SAO
        if not kwargs["sao0_disable"]:
            self.submodules.sao0 = ShittyAddOn(
                self.platform,
                self.platform.request("sao", 0),
                disable_i2c=kwargs["sao0_disable_i2c"])
            self.add_csr("sao0")
        if not kwargs["sao1_disable"]:
            self.submodules.sao1 = ShittyAddOn(
                self.platform,
                self.platform.request("sao", 1),
                disable_i2c=kwargs["sao1_disable_i2c"])
            self.add_csr("sao1")
        # PMOD
        platform.add_extension(_pmod_gpio)
        self.submodules.pmod = GPIOBidirectional(
            self.platform.request("pmod_gpio"))
        self.add_csr("pmod")
        # GENIO
        if not kwargs["genio_disable"]:
            platform.add_extension(_genio_gpio)
            self.submodules.genio = GPIOBidirectional(
                self.platform.request("genio_gpio"))
            self.add_csr("genio")
        # LEDs
        self.submodules.led0 = gpio.GPIOOut(self.platform.request("led", 0))
        self.add_csr("led0")
        self.submodules.led1 = gpio.GPIOOut(self.platform.request("led", 1))
        self.add_csr("led1")
        # Keypad
        self.submodules.keypad = gpio.GPIOIn(
            Cat(self.platform.request("keypad", 0).flatten()))
        self.add_csr("keypad")
Esempio n. 9
0
    def __init__(self, platform):
        # Set up the basic address space layout and create basic
        # select signals for each entry in the memory map.
        self.address_bus = Signal(16)
        for name, address_range in self.memory_map.items():
            fast_sel = Signal(name=name + "_sel")
            slow_sel = Signal(name=name + "_sel_slow")
            setattr(self, name + "_sel", fast_sel)
            setattr(self, name + "_sel_slow", slow_sel)
            self.comb += [
                fast_sel.eq(
                    Mux(
                        wrap(self.address_bus >= address_range.start)
                        & wrap(self.address_bus < address_range.start +
                               address_range.size), 1, 0))
            ]
            # Latched versions, needed to drive the databus logic
            self.sync += [
                slow_sel.eq(
                    Mux(
                        wrap(self.address_bus >= address_range.start)
                        & wrap(self.address_bus < address_range.start +
                               address_range.size), 1, 0))
            ]

        # Fomu clock/reset generator, using the PLL to generate a 48MHz and 12MHz clock.
        # The 12MHz clock becomes cd_sys; the 48MHz clock is available as cd_usb_48.
        self.submodules.crg = CRG(platform, use_pll=True)

        #self.clock_domains.cd_sys = ClockDomain()
        #clk48_raw = platform.request("clk48")
        #platform.add_period_constraint(clk48_raw, 1e9/48e6)
        #self.startup_delay = Signal(12, reset=4095)
        #self.comb += [self.cd_sys.clk.eq(clk48_raw),
        #    self.cd_sys.rst.eq(self.startup_delay!=0)]
        #self.sync += [
        #    If(self.startup_delay==0,self.startup_delay.eq(0)).Else(self.startup_delay.eq(self.startup_delay-1))
        #    ]
        #self.clk_freq = 48000000
        # Output the reset to avoid some trimming.
        #self.comb += [
        #    platform.request("usb").d_p.eq(self.cd_sys.rst)
        #    ]

        # CPU
        self.submodules.cpu = A6502(platform)

        # Basic RAM.
        self.submodules.ram = FomuSPRAM(platform)

        # Boot ROM (for debug only)
        self.submodules.high_os_rom = FomuROM(platform)

        # LEDs for I/O
        self.submodules.rgb = SBLED(platform)

        # Wishbone bridge
        self.submodules.wishbone = FomuBridge(platform)

        # Build up a mux for the data bus (in), IRQ, NMI, RDY, and connect up the chip selects.
        mux = Constant(0)
        rdy_mux = Constant(1)
        irq_mux = Constant(0)
        nmi_mux = Constant(0)

        for name, address_range in self.memory_map.items():
            try:
                # Find the module and its select signals
                module = getattr(self, name)
            except AttributeError:
                print("Warning: Memory map defines \'" + name +
                      "\' but no submodule exists.")
                continue
            select_fast = getattr(self, name + "_sel")
            select_slow = getattr(self, name + "_sel_slow")

            # Extend the existing muxes for this module. Slow select used for mux
            # because this CPU core reads one cycle behind the address bus.
            mux = Mux(select_slow, module.data_out, mux)
            rdy_mux = Mux(select_slow, module.rdy, rdy_mux)
            irq_mux = irq_mux | module.irq
            nmi_mux = nmi_mux | module.nmi

            self.comb += [
                # Connect up the CS signals.
                module.cs.eq(select_fast),
                module.cs_slow.eq(select_slow),
                # Wire up the address bus in to each device too.
                module.address.eq(self.address_bus - address_range.start),
                # And the data bus out to it.
                module.data_in.eq(self.cpu.data_out),
                module.we.eq(self.cpu.we)
            ]

            print("Connected device", name, "at", address_range)

        print("Constructed data mux:", mux)
        print("Constructed RDY mux:", rdy_mux)
        self.comb += [
            self.cpu.data_in.eq(mux),
            self.cpu.rdy.eq(rdy_mux),
            self.cpu.irq.eq(irq_mux),
            self.cpu.nmi.eq(nmi_mux),
            self.address_bus.eq(self.cpu.address)
        ]

        # Set up a dummyusb device.
        from valentyusb.usbcore import io as usbio
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb = FomuUSBCDC(usb_iobuf)
Esempio n. 10
0
File: fomu.py Progetto: jaseg/litex
    def __init__(self,
                 board,
                 pnr_placer="heap",
                 pnr_seed=0,
                 usb_core="dummyusb",
                 usb_bridge=False,
                 **kwargs):
        """Create a basic SoC for Fomu.

        Create a basic SoC for Fomu, including a 48 MHz and 12 MHz clock
        domain called `usb_48` and `usb_12`.  The `sys` frequency will
        run at 12 MHz.

        The USB core will optionally have a bridge to the Wishbone bus.

        Args:
            board (str): Which Fomu board to build for: pvt, evt, or hacker
            pnr_placer (str): Which placer to use in nextpnr
            pnr_seed (int): Which seed to use in nextpnr
            usb_core (str): The name of the USB core to use, if any: dummyusb, epfifo
            usb_bridge (bool): Whether to include a USB-to-Wishbone bridge
        Raises:
            ValueError: If either the `usb_core` or `board` are unrecognized
        Returns:
            Newly-constructed SoC
        """
        if board == "pvt":
            from litex_boards.partner.platforms.fomu_pvt import Platform
        elif board == "hacker":
            from litex_boards.partner.platforms.fomu_hacker import Platform
        elif board == "evt":
            from litex_boards.partner.platforms.fomu_evt import Platform
        else:
            raise ValueError("unrecognized fomu board: {}".format(board))
        platform = Platform()

        if "cpu_type" not in kwargs:
            kwargs["cpu_type"] = None
            kwargs["cpu_variant"] = None

        clk_freq = int(12e6)

        SoCCore.__init__(self,
                         platform,
                         clk_freq,
                         integrated_sram_size=0,
                         with_uart=False,
                         with_ctrl=False,
                         **kwargs)

        self.submodules.crg = _CRG(platform)

        # UP5K has single port RAM, which is a dedicated 128 kilobyte block.
        # Use this as CPU RAM.
        spram_size = 128 * 1024
        self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
        self.register_mem("sram", self.mem_map["sram"], self.spram.bus,
                          spram_size)

        if usb_core is not None:
            # Add USB pads.  We use DummyUsb, which simply enumerates as a USB
            # device.  Then all interaction is done via the wishbone bridge.
            usb_pads = platform.request("usb")
            usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n,
                                    usb_pads.pullup)
            if usb_core == "dummyusb":
                self.submodules.usb = dummyusb.DummyUsb(usb_iobuf,
                                                        debug=usb_bridge)
            elif usb_core == "epfifo":
                self.submodules.usb = epfifo.PerEndpointFifo(usb_iobuf,
                                                             debug=usb_bridge)
            else:
                raise ValueError("unrecognized usb_core: {}".args(usb_core))
            if usb_bridge:
                self.add_wb_master(self.usb.debug_bridge.wishbone)
Esempio n. 11
0
    def __init__(self,
                 platform,
                 boot_source="rand",
                 debug=None,
                 bios_file=None,
                 use_pll=True,
                 use_dsp=False,
                 placer=None,
                 output_dir="build",
                 pnr_seed=0,
                 **kwargs):
        # Disable integrated RAM as we'll add it later
        self.integrated_sram_size = 0

        self.output_dir = output_dir

        clk_freq = int(12e6)
        self.submodules.crg = _CRG(platform, use_pll=use_pll)

        SoCCore.__init__(self,
                         platform,
                         clk_freq,
                         integrated_sram_size=0,
                         with_uart=False,
                         **kwargs)

        usb_debug = False
        if debug is not None:
            if debug == "uart":
                from litex.soc.cores.uart import UARTWishboneBridge
                self.submodules.uart_bridge = UARTWishboneBridge(
                    platform.request("serial"), clk_freq, baudrate=115200)
                self.add_wb_master(self.uart_bridge.wishbone)
            elif debug == "usb":
                usb_debug = True
            if hasattr(self, "cpu"):
                self.cpu.use_external_variant("rtl/2-stage-1024-cache-debug.v")
                self.copy_memory_file(
                    "2-stage-1024-cache-debug.v_toplevel_RegFilePlugin_regFile.bin"
                )
                os.path.join(output_dir, "gateware")
                self.register_mem("vexriscv_debug", 0xf00f0000,
                                  self.cpu.debug_bus, 0x100)
        else:
            if hasattr(self, "cpu"):
                self.cpu.use_external_variant("rtl/2-stage-1024-cache.v")
                self.copy_memory_file(
                    "2-stage-1024-cache.v_toplevel_RegFilePlugin_regFile.bin")

        # SPRAM- UP5K has single port RAM, might as well use it as SRAM to
        # free up scarce block RAM.
        spram_size = 128 * 1024
        self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size)
        self.register_mem("sram", self.mem_map["sram"], self.spram.bus,
                          spram_size)

        if boot_source == "rand":
            kwargs['cpu_reset_address'] = 0
            bios_size = 0x2000
            self.submodules.random_rom = RandomFirmwareROM(bios_size)
            self.add_constant("ROM_DISABLE", 1)
            self.register_rom(self.random_rom.bus, bios_size)
        elif boot_source == "bios":
            kwargs['cpu_reset_address'] = 0
            if bios_file is None:
                self.integrated_rom_size = bios_size = 0x2000
                self.submodules.rom = wishbone.SRAM(bios_size,
                                                    read_only=True,
                                                    init=[])
                self.register_rom(self.rom.bus, bios_size)
            else:
                bios_size = 0x2000
                self.submodules.firmware_rom = FirmwareROM(
                    bios_size, bios_file)
                self.add_constant("ROM_DISABLE", 1)
                self.register_rom(self.firmware_rom.bus, bios_size)

        elif boot_source == "spi":
            bios_size = 0x8000
            kwargs['cpu_reset_address'] = self.mem_map[
                "spiflash"] + platform.gateware_size
            self.add_memory_region("rom", kwargs['cpu_reset_address'],
                                   bios_size)
            self.add_constant("ROM_DISABLE", 1)
            self.flash_boot_address = self.mem_map[
                "spiflash"] + platform.gateware_size + bios_size
            self.add_memory_region(
                "user_flash",
                self.flash_boot_address,
                # Leave a grace area- possible one-by-off bug in add_memory_region?
                # Possible fix: addr < origin + length - 1
                platform.spiflash_total_size -
                (self.flash_boot_address - self.mem_map["spiflash"]) - 0x100)
        else:
            raise ValueError(
                "unrecognized boot_source: {}".format(boot_source))

        # Add a simple bit-banged SPI Flash module
        spi_pads = platform.request("spiflash")
        self.submodules.picorvspi = PicoRVSpi(platform, spi_pads)
        self.register_mem("spiflash",
                          self.mem_map["spiflash"],
                          self.picorvspi.bus,
                          size=self.picorvspi.size)

        self.submodules.reboot = SBWarmBoot(self)
        if hasattr(self, "cpu"):
            self.cpu.cpu_params.update(
                i_externalResetVector=self.reboot.addr.storage, )

        self.submodules.rgb = SBLED(platform.revision, platform.request("led"))
        self.submodules.version = Version(platform.revision, self)

        # Add USB pads
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        if hasattr(self, "cpu"):
            self.submodules.usb = epfifo.PerEndpointFifoInterface(
                usb_iobuf, debug=usb_debug)
        else:
            self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=usb_debug)

        if usb_debug:
            self.add_wb_master(self.usb.debug_bridge.wishbone)
        # For the EVT board, ensure the pulldown pin is tristated as an input
        if hasattr(usb_pads, "pulldown"):
            pulldown = TSTriple()
            self.specials += pulldown.get_tristate(usb_pads.pulldown)
            self.comb += pulldown.oe.eq(0)
        # self.submodules.usb = epmem.MemInterface(usb_iobuf)
        # self.submodules.usb = unififo.UsbUniFifo(usb_iobuf)

        # Add GPIO pads for the touch buttons
        self.submodules.touch = TouchPads(platform.request("touch"))

        # Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command.
        # The "-reult" adds an additional LUT pass to pack more stuff in,
        # and the "-dffe_min_ce_use 4" flag prevents Yosys from generating a
        # Clock Enable signal for a LUT that has fewer than 4 flip-flops.
        # This increases density, and lets us use the FPGA more efficiently.
        platform.toolchain.nextpnr_yosys_template[
            2] += " -relut -dffe_min_ce_use 4"
        if use_dsp:
            platform.toolchain.nextpnr_yosys_template[2] += " -dsp"

        # Disable final deep-sleep power down so firmware words are loaded
        # onto softcore's address bus.
        platform.toolchain.build_template[
            3] = "icepack -s {build_name}.txt {build_name}.bin"
        platform.toolchain.nextpnr_build_template[
            2] = "icepack -s {build_name}.txt {build_name}.bin"

        # Allow us to set the nextpnr seed
        platform.toolchain.nextpnr_build_template[1] += " --seed " + str(
            pnr_seed)

        if placer is not None:
            platform.toolchain.nextpnr_build_template[
                1] += " --placer {}".format(placer)
    def __init__(self,
        pnr_placer="heap", pnr_seed=0, usb_core="dummyusb", usb_bridge=False,
        use_dsp=True, **kwargs):
        """Create a basic SoC for the TinyFPGA_BX.

        Create a basic SoC for TinyFPGA_BX, including a 48 MHz and 12 MHz clock
        domain called `usb_48` and `usb_12`.  The `sys` frequency will
        run at 16 MHz.

        The USB core will optionally have a bridge to the Wishbone bus.

        Args:
            pnr_placer (str): Which placer to use in nextpnr
            pnr_seed (int): Which seed to use in nextpnr
            usb_core (str): The name of the USB core to use, if any: dummyusb, epfifo, eptri
            usb_bridge (bool): Whether to include a USB-to-Wishbone bridge
        Raises:
            ValueError: If the `usb_core` is unrecognized
        Returns:
            Newly-constructed SoC
        """
        from litex_boards.platforms.tinyfpga_bx import Platform
        platform = Platform()

        if "cpu_type" not in kwargs:
            kwargs["cpu_type"] = None
            kwargs["cpu_variant"] = None

        clk_freq = int(16e6)

        if "with_uart" not in kwargs:
            kwargs["with_uart"] = False

        if "with_ctrl" not in kwargs:
            kwargs["with_ctrl"] = False

        kwargs["integrated_sram_size"] = 0
        SoCCore.__init__(self, platform, clk_freq, **kwargs)

        self.submodules.crg = _CRG(platform)

        if usb_core is not None:
            # Add USB pads.  We use DummyUsb, which simply enumerates as a USB
            # device.  Then all interaction is done via the wishbone bridge.
            usb_pads = platform.request("usb")
            usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
            if usb_core == "dummyusb":
                self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=usb_bridge)
            elif usb_core == "epfifo":
                self.submodules.usb = epfifo.PerEndpointFifo(usb_iobuf, debug=usb_bridge)
            elif usb_core == "eptri":
                self.submodules.usb = eptri.TriEndpointInterface(usb_iobuf, debug=usb_bridge)
            else:
                raise ValueError("unrecognized usb_core: {}".format(usb_core))
            if usb_bridge:
                self.add_wb_master(self.usb.debug_bridge.wishbone)

        # Override default LiteX's yosys/build templates
        assert hasattr(platform.toolchain, "yosys_template")
        assert hasattr(platform.toolchain, "build_template")
        platform.toolchain.yosys_template = [
            "{read_files}",
            "attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0",
            "synth_ice40 -json {build_name}.json -top {build_name}",
        ]
        platform.toolchain.build_template = [
            "yosys -q -l {build_name}.rpt {build_name}.ys",
            "nextpnr-ice40 --json {build_name}.json --pcf {build_name}.pcf --asc {build_name}.txt \
            --pre-pack {build_name}_pre_pack.py --{architecture} --package {package}",
            "icepack {build_name}.txt {build_name}.bin"
        ]

        # Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command.
        # The "-reult" adds an additional LUT pass to pack more stuff in,
        # and the "-dffe_min_ce_use 4" flag prevents Yosys from generating a
        # Clock Enable signal for a LUT that has fewer than 4 flip-flops.
        # This increases density, and lets us use the FPGA more efficiently.
        platform.toolchain.yosys_template[2] += " -relut -abc2 -dffe_min_ce_use 4 -relut"
        if use_dsp:
            platform.toolchain.yosys_template[2] += " -dsp"

        # Disable final deep-sleep power down so firmware words are loaded
        # onto softcore's address bus.
        platform.toolchain.build_template[2] = "icepack -s {build_name}.txt {build_name}.bin"

        # Allow us to set the nextpnr seed
        platform.toolchain.build_template[1] += " --seed " + str(pnr_seed)

        if pnr_placer is not None:
            platform.toolchain.build_template[1] += " --placer {}".format(pnr_placer)
Esempio n. 13
0
    def __init__(self, sys_clk_freq=int(48e6), toolchain="trellis", **kwargs):
        # Board Revision ---------------------------------------------------------------------------
        revision = kwargs.get("revision", "0.2")
        device = kwargs.get("device", "25F")

        platform = orangecrab.Platform(revision=revision,
                                       device=device,
                                       toolchain=toolchain)

        platform.add_extension(extras)

        # Disconnect Serial Debug (Stub required so BIOS is kept happy)
        kwargs['uart_name'] = "stream"

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self,
                         platform,
                         clk_freq=sys_clk_freq,
                         csr_data_width=32,
                         **kwargs)

        # connect UART stream to NULL
        self.comb += self.uart.source.ready.eq(1)

        # CRG --------------------------------------------------------------------------------------
        self.submodules.crg = crg = CRG(platform,
                                        sys_clk_freq,
                                        with_usb_pll=True)

        # DDR3 SDRAM -------------------------------------------------------------------------------
        if not self.integrated_main_ram_size:
            available_sdram_modules = {
                "MT41K64M16": MT41K64M16,
                "MT41K128M16": MT41K128M16,
                "MT41K256M16": MT41K256M16,
                "MT41K512M16": MT41K512M16,
            }
            sdram_module = available_sdram_modules.get(
                kwargs.get("sdram_device", "MT41K64M16"))

            ddram_pads = platform.request("ddram")
            self.submodules.ddrphy = ECP5DDRPHY(pads=ddram_pads,
                                                sys_clk_freq=sys_clk_freq)
            self.ddrphy.settings.rtt_nom = "disabled"
            self.add_csr("ddrphy")
            if hasattr(ddram_pads, "vccio"):
                self.comb += ddram_pads.vccio.eq(0b111111)
            if hasattr(ddram_pads, "gnd"):
                self.comb += ddram_pads.gnd.eq(0)
            self.comb += self.crg.stop.eq(self.ddrphy.init.stop)
            self.comb += self.crg.reset.eq(self.ddrphy.init.reset)
            self.add_sdram("sdram",
                           phy=self.ddrphy,
                           module=sdram_module(sys_clk_freq, "1:2"),
                           origin=self.mem_map["main_ram"],
                           size=kwargs.get("max_sdram_size", 0x40000000),
                           l2_cache_size=kwargs.get("l2_size", 8192),
                           l2_cache_min_data_width=kwargs.get(
                               "min_l2_data_width", 128),
                           l2_cache_reverse=True)

        # RGB LED
        self.submodules.rgb = RGB(platform.request("rgb_led", 0))
        #self.submodules.gpio = GPIOTristateCustom(platform.request("gpio", 0))

        self.submodules.gpio = IOPort(platform.request("gpio", 0))

        try:
            self.submodules.button = GPIOIn(platform.request("usr_btn"))
        except:
            ...

        # Analog Mux
        #self.submodules.asense = AnalogSense(platform.request("analog"))

        # drive PROGRAMN HIGH
        self.comb += platform.request("rst_n").eq(1)

        # The litex SPI module supports memory-mapped reads, as well as a bit-banged mode
        # for doing writes.
        spi_pads = platform.request("spiflash4x")
        self.submodules.lxspi = spi_flash.SpiFlashDualQuad(spi_pads,
                                                           dummy=6,
                                                           endianness="little")
        self.lxspi.add_clk_primitive(platform.device)
        self.register_mem("spiflash",
                          self.mem_map["spiflash"],
                          self.lxspi.bus,
                          size=16 * 1024 * 1024)

        # Attach USB to a seperate CSR bus that's decoupled from our CPU clock
        usb_pads = platform.request("usb")
        usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
        self.submodules.usb0 = CSRClockDomainWrapper(usb_iobuf)
        self.comb += self.cpu.interrupt[self.interrupt_map['usb']].eq(
            self.usb0.irq)

        from litex.soc.integration.soc_core import SoCRegion
        self.bus.add_slave(
            'usb', self.usb0.bus,
            SoCRegion(origin=0x90000000, size=0x1000, cached=False))

        self.constants[
            "FLASH_BOOT_ADDRESS"] = self.mem_map['spiflash'] + 0x00100000