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)
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)
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)
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)