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)
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, use_dsp=False, placer="heap", output_dir="build", pnr_seed=0, sim=False, **kwargs): self.output_dir = output_dir clk_freq = int(sysclkfreq) # Core ------------------------------------------------------------------------------------------- SoCCore.__init__(self, platform, clk_freq, integrated_sram_size=0, uart_name="crossover", cpu_reset_address=self.mem_map["spiflash"]+GATEWARE_SIZE, csr_data_width=32, **kwargs) # with_uart=False self.submodules.crg = platform.CRG(platform) self.add_csr("crg") # Version ---------------------------------------------------------------------------------------- self.submodules.git = GitInfo() self.add_csr("git") # Power management ------------------------------------------------------------------------------- # Betrusted Power management interface self.submodules.power = BtPower(platform.request("power")) self.add_csr("power") # Keyboard power-on + debug mux ------------------------------------------------------------------ # Use to debug bootstrapping issues, avoid internal state on SoC messing with access to UART pads. # Prevents sleep/wake from working due to loss of modal pinmux. debugonly = False if debugonly: self.submodules.uart_bridge = UARTWishboneBridge(platform.request("serial"), clk_freq, baudrate=115200) self.add_wb_master(self.uart_bridge.wishbone) if hasattr(self, "cpu"): os.path.join(output_dir, "gateware") self.register_mem("vexriscv_debug", 0xf00f0000, self.cpu.debug_bus, 0x100) else: serialpads = platform.request("serial") dbguart_tx = Signal() dbguart_rx = Signal() dbgpads = Record([('rx', 1), ('tx', 1)], name="serial") dbgpads.rx = dbguart_rx dbgpads.tx = dbguart_tx # serialpad RX needs to drive a scan signal so we can detect it on the other side of the matrix keycol0_ts = TSTriple(1) self.specials += keycol0_ts.get_tristate(serialpads.rx) #self.comb += serialpads.rx.eq(1) self.comb += dbgpads.rx.eq(keycol0_ts.i) self.comb += self.power.mon1.eq(platform.request("up5k_keyrow1")) self.comb += self.power.mon0.eq(platform.request("up5k_keyrow0")) # serialpad TX is what we use to test for keyboard hit to power on the SOC # only allow test keyboard hit patterns when the SOC is powered off self.comb += serialpads.tx.eq( (~self.power.soc_on & self.power.power.fields.kbddrive) | (self.power.soc_on & dbgpads.tx) ) self.comb += keycol0_ts.oe.eq( ~self.power.soc_on & self.power.power.fields.kbddrive ) # force signal on the rx pin when in power off & scan self.comb += keycol0_ts.o.eq(1) # drive a '1' for scan # Debug block ------------------------------------------------------------------------------------ self.submodules.uart_bridge = UARTWishboneBridge(dbgpads, clk_freq, baudrate=115200) self.add_wb_master(self.uart_bridge.wishbone) if hasattr(self, "cpu"): os.path.join(output_dir, "gateware") self.register_mem("vexriscv_debug", 0xf00f0000, self.cpu.debug_bus, 0x100) # RAM/ROM/reset cluster -------------------------------------------------------------------------- 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 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=SPI_FLASH_SIZE) self.add_csr("picorvspi") # I2C -------------------------------------------------------------------------------------------- self.submodules.i2c = HardI2C(platform, platform.request("i2c", 0)) self.add_wb_slave(self.mem_map["i2c"], self.i2c.bus, 16*4) self.add_memory_region("i2c", self.mem_map["i2c"], 16*4, type='io') self.add_csr("i2c") self.add_interrupt("i2c") # High-resolution tick timer --------------------------------------------------------------------- self.submodules.ticktimer = TickTimer(1000, clk_freq, bits=40) self.add_csr("ticktimer") self.add_interrupt("ticktimer") # COM port (spi peripheral to Artix) ------------------------------------------------------------------ # FIXME: we should have these RTL blocks come from a deps/gateware submodule, not rtl. This way sims are consistent with implementation self.submodules.com = SpiFifoPeripheral(platform.request("com")) self.add_wb_slave(self.mem_map["com"], self.com.bus, 4) self.add_memory_region("com", self.mem_map["com"], 4, type='io') self.add_csr("com") self.add_interrupt("com") self.comb += self.com.oe.eq(self.power.stats.fields.state) # only drive to FPGA when it's powered up # SPI port to wifi (controller) ------------------------------------------------------------------ self.submodules.wifi = ClockDomainsRenamer({'spi':'sys'})(SpiController(platform.request("wifi"), gpio_cs=True)) # control CS with GPIO per wf200 API spec self.add_csr("wifi") self.add_interrupt("wifi") #### Platform config & build below --------------------------------------------------------------- # 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) # Allow loops for RNG placement platform.toolchain.build_template[1] += " --ignore-loops" if 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, pnr_placer="heap", pnr_seed=0, debug=True, boot_vector=0x20020000, **kwargs): """Create a basic SoC for iCEBreaker. Create a basic SoC for iCEBreaker. The `sys` frequency will run at 12 MHz. Args: pnr_placer (str): Which placer to use in nextpnr pnr_seed (int): Which seed to use in nextpnr Returns: Newly-constructed SoC """ platform = Platform() if "cpu_type" not in kwargs: kwargs["cpu_type"] = None kwargs["cpu_variant"] = None else: kwargs["cpu_reset_address"] = boot_vector clk_freq = int(12e6) # Force the SRAM size to 0, because we add our own SRAM with SPRAM kwargs["integrated_sram_size"] = 0 kwargs["integrated_rom_size"] = 0 if debug: kwargs["uart_name"] = "crossover" if kwargs["cpu_type"] == "vexriscv": kwargs["cpu_variant"] = kwargs["cpu_variant"] + "+debug" SoCCore.__init__(self, platform, clk_freq, with_uart=True, with_ctrl=True, **kwargs) # If there is a VexRiscv CPU, add a fake ROM that simply tells the CPU # to jump to the given address. if hasattr(self, "cpu") and self.cpu.name == "vexriscv": self.add_memory_region("rom", 0, 16) self.submodules.rom = JumpToAddressROM(16, boot_vector) 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) # 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.SpiFlash(spi_pads, dummy=6, endianness="little") self.register_mem("spiflash", self.mem_map["spiflash"], self.lxspi.bus, size=16 * 1024 * 1024) self.add_csr("lxspi") # In debug mode, add a UART bridge. This takes over from the normal UART bridge, # however you can use the "crossover" UART to communicate with this over the bridge. if debug: self.submodules.uart_bridge = UARTWishboneBridge( platform.request("serial"), clk_freq, baudrate=115200) self.add_wb_master(self.uart_bridge.wishbone) if hasattr(self, "cpu") and self.cpu.name == "vexriscv": self.register_mem("vexriscv_debug", 0xf00f0000, self.cpu.debug_bus, 0x100) ledsignals = Signal(2) self.submodules.leds = GPIOOut(ledsignals) self.comb += platform.request("user_ledr_n").eq(ledsignals[0]) self.comb += platform.request("user_ledg_n").eq(ledsignals[1]) self.add_csr("leds") # 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)
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)
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)
def __init__(self, board, pnr_placer="heap", pnr_seed=0, usb_core="dummyusb", usb_bridge=False, use_dsp=True, **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, eptri 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.platforms.fomu_pvt import Platform elif board == "hacker": from litex_boards.platforms.fomu_hacker import Platform elif board == "evt": from litex_boards.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) 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) # 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) 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)
def __init__(self, debug=True, boot_vector=0x20040000, **kwargs): """Create a basic SoC for iCEBreaker. Create a basic SoC for iCEBreaker. The `sys` frequency will run at 12 MHz. Returns: Newly-constructed SoC """ platform = Platform() kwargs["cpu_variant"] = "lite" kwargs["cpu_reset_address"] = boot_vector if debug: kwargs["uart_name"] = "crossover" kwargs["cpu_variant"] = "lite+debug" clk_freq = int(12e6) # Force the SRAM size to 0, because we add our own SRAM with SPRAM kwargs["integrated_sram_size"] = 0 kwargs["integrated_rom_size"] = 0 SoCCore.__init__(self, platform, clk_freq, **kwargs) # If there is a VexRiscv CPU, add a fake ROM that simply tells the CPU # to jump to the given address. if hasattr(self, "cpu") and self.cpu.name == "vexriscv": self.add_memory_region("rom", 0, 16) self.submodules.rom = JumpToAddressROM(16, boot_vector) 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) # 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.SpiFlash(spi_pads, dummy=6, endianness="little") self.register_mem("spiflash", self.mem_map["spiflash"], self.lxspi.bus, size=16 * 1024 * 1024) self.add_csr("lxspi") # In debug mode, add a UART bridge. This takes over from the normal UART bridge, # however you can use the "crossover" UART to communicate with this over the bridge. if debug: self.submodules.uart_bridge = UARTWishboneBridge( platform.request("serial"), clk_freq, baudrate=115200) self.add_wb_master(self.uart_bridge.wishbone) if hasattr(self, "cpu") and self.cpu.name == "vexriscv": self.register_mem("vexriscv_debug", 0xf00f0000, self.cpu.debug_bus, 0x100) self.submodules.leds = Leds( Cat(platform.request("user_ledr_n"), platform.request("user_ledg_n")), led_polarity=0x03, led_name=[["ledr", "The Red LED on the main iCEBreaker board."], ["ledg", "The Green LED on the main iCEBreaker board."]]) self.add_csr("leds")