Beispiel #1
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)
Beispiel #2
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)
Beispiel #3
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)
Beispiel #4
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)