def __init__(self): self.sda = TSTriple(1) self.sda.w = self.sda.o self.sda.r = self.sda.i self.scl = TSTriple(1) self.scl.w = self.scl.o self.scl.r = self.scl.i
def __init__(self, platform): self.submodules.mux = i2c.I2CMux(platform.request("opsis_i2c")) self.submodules.master = i2c.I2C(self.mux.get_i2c_pads()) # Use a proper Tristate for the FX2 reset so the "pull up" works. fx2_reset = TSTriple(1) self.comb += [ fx2_reset.o.eq(0), ] self.specials += [ fx2_reset.get_tristate(platform.request("fx2_reset")), ] self.submodules.fx2_reset = GPIOOut(fx2_reset.oe) self.submodules.fx2_hack = I2CShiftReg(self.mux.get_i2c_pads())
class I2CPads: def __init__(self): self.sda = TSTriple(1) self.sda.w = self.sda.o self.sda.r = self.sda.i self.scl = TSTriple(1) self.scl.w = self.scl.o self.scl.r = self.scl.i def get_tristate(self, pads): return [ self.scl.get_tristate(pads.scl), self.sda.get_tristate(pads.sda), ] def connect(self, other_pads): return [ self.scl.oe.eq(other_pads.scl.oe), self.scl.w.eq(other_pads.scl.w), other_pads.scl.r.eq(self.scl.r), self.sda.oe.eq(other_pads.sda.oe), self.sda.w.eq(other_pads.sda.w), other_pads.sda.r.eq(self.sda.r), ]
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, 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, platform, pads, size=2*1024*1024): self.intro = ModuleDoc("See https://github.com/cliffordwolf/picorv32/tree/master/picosoc#spi-flash-controller-config-register; used with modifications") self.size = size self.bus = bus = wishbone.Interface() self.reset = Signal() cfg = Signal(32) cfg_we = Signal(4) cfg_out = Signal(32) # Add pulse the cfg_we line after reset reset_counter = Signal(2, reset=3) ic_reset = Signal(reset=1) self.sync += \ If(reset_counter != 0, reset_counter.eq(reset_counter - 1) ).Else( ic_reset.eq(0) ) self.rdata = CSRStatus(fields=[ CSRField("data", size=4, description="Data bits from SPI [3:hold, 2:wp, 1:cipo, 0:copi]"), ]) self.mode = CSRStorage(fields=[ CSRField("bitbang", size=1, description="Turn on bitbang mode", reset = 0), CSRField("csn", size=1, description="Chip select (set to `0` to select the chip)"), ]) self.wdata = CSRStorage(description="Writes to this field automatically pulse CLK", fields=[ CSRField("data", size=4, description="Data bits to SPI [3:hold, 2:wp, 1:cipo, 0:copi]"), CSRField("oe", size=4, description="Output enable for data pins"), ]) bb_clk = Signal() self.sync += [ bb_clk.eq(self.wdata.re), # auto-clock the SPI chip whenever wdata is written. Delay a cycle for setup/hold. ] copi_pad = TSTriple() cipo_pad = TSTriple() cs_n_pad = TSTriple() clk_pad = TSTriple() wp_pad = TSTriple() hold_pad = TSTriple() self.specials += copi_pad.get_tristate(pads.copi) self.specials += cipo_pad.get_tristate(pads.cipo) self.specials += cs_n_pad.get_tristate(pads.cs_n) self.specials += clk_pad.get_tristate(pads.clk) self.specials += wp_pad.get_tristate(pads.wp) self.specials += hold_pad.get_tristate(pads.hold) reset = Signal() self.comb += [ reset.eq(ResetSignal() | self.reset), cs_n_pad.oe.eq(~reset), clk_pad.oe.eq(~reset), ] flash_addr = Signal(24) # size/4 because data bus is 32 bits wide, -1 for base 0 mem_bits = bits_for(int(size/4)-1) pad = Signal(2) self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits-1])) read_active = Signal() spi_ready = Signal() self.sync += [ If(bus.stb & bus.cyc & ~read_active, read_active.eq(1), bus.ack.eq(0), ) .Elif(read_active & spi_ready, read_active.eq(0), bus.ack.eq(1), ) .Else( bus.ack.eq(0), read_active.eq(0), ) ] o_rdata = Signal(32) self.comb += bus.dat_r.eq(o_rdata) self.specials += Instance("spimemio", o_flash_io0_oe = copi_pad.oe, o_flash_io1_oe = cipo_pad.oe, o_flash_io2_oe = wp_pad.oe, o_flash_io3_oe = hold_pad.oe, o_flash_io0_do = copi_pad.o, o_flash_io1_do = cipo_pad.o, o_flash_io2_do = wp_pad.o, o_flash_io3_do = hold_pad.o, o_flash_csb = cs_n_pad.o, o_flash_clk = clk_pad.o, i_flash_io0_di = copi_pad.i, i_flash_io1_di = cipo_pad.i, i_flash_io2_di = wp_pad.i, i_flash_io3_di = hold_pad.i, i_resetn = ~reset, i_clk = ClockSignal(), i_valid = bus.stb & bus.cyc, o_ready = spi_ready, i_addr = flash_addr, o_rdata = o_rdata, i_bb_oe = self.wdata.fields.oe, i_bb_wd = self.wdata.fields.data, i_bb_clk = bb_clk, i_bb_csb = self.mode.fields.csn, o_bb_rd = self.rdata.fields.data, i_config_update = self.mode.re | ic_reset, i_memio_enable = ~self.mode.fields.bitbang, ) platform.add_source("rtl/spimemio.v")
def __init__(self, platform, pads, size=16 * 1024 * 1024): self.size = size self.bus = bus = wishbone.Interface() self.reset = Signal() self.cfg1 = CSRStorage(fields=[ CSRField( "bb_out", size=4, description="Output bits in bit-bang mode"), CSRField("bb_clk", description="Serial clock line in bit-bang mode"), CSRField("bb_cs", description="Chip select line in bit-bang mode"), ]) self.cfg2 = CSRStorage(fields=[ CSRField("bb_oe", size=4, description="Output Enable bits in bit-bang mode"), ]) self.cfg3 = CSRStorage(fields=[ CSRField( "rlat", size=4, description="Read latency/dummy cycle count"), CSRField("crm", description="Continuous Read Mode enable bit"), CSRField("qspi", description="Quad-SPI enable bit"), CSRField("ddr", description="Double Data Rate enable bit"), ]) self.cfg4 = CSRStorage(fields=[ CSRField( "memio", offset=7, reset=1, description= "Enable memory-mapped mode (set to 0 to enable bit-bang mode)") ]) self.stat1 = CSRStatus(fields=[ CSRField( "bb_in", size=4, description="Input bits in bit-bang mode"), ]) self.stat2 = CSRStatus(8, description="Reserved") self.stat3 = CSRStatus(8, description="Reserved") self.stat4 = CSRStatus(8, description="Reserved") cfg = Signal(32) cfg_we = Signal(4) cfg_out = Signal(32) self.comb += [ cfg.eq( Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage, self.cfg4.storage)), cfg_we.eq( Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re, self.cfg4.re)), self.stat1.status.eq(cfg_out[0:4]), self.stat2.status.eq(0), self.stat3.status.eq(0), self.stat4.status.eq(0), ] reset = Signal() mosi_pad = TSTriple() miso_pad = TSTriple() cs_n_pad = TSTriple() clk_pad = TSTriple() wp_pad = TSTriple() hold_pad = TSTriple() clk = Signal() if hasattr(pads, "clk"): clk = pads.clk self.specials += clk_pad.get_tristate(clk) self.comb += clk_pad.oe.eq(~reset) else: self.specials += Instance("USRMCLK", i_USRMCLKI=clk, i_USRMCLKTS=0) self.specials += mosi_pad.get_tristate(pads.mosi) self.specials += miso_pad.get_tristate(pads.miso) self.specials += cs_n_pad.get_tristate(pads.cs_n) self.specials += wp_pad.get_tristate(pads.wp) self.specials += hold_pad.get_tristate(pads.hold) self.comb += [ reset.eq(ResetSignal() | self.reset), cs_n_pad.oe.eq(~reset), ] flash_addr = Signal(24) # size/4 because data bus is 32 bits wide, -1 for base 0 mem_bits = bits_for(int(size / 4) - 1) pad = Signal(2) self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits - 1])) read_active = Signal() spi_ready = Signal() self.sync += [ If( bus.stb & bus.cyc & ~read_active, read_active.eq(1), bus.ack.eq(0), ).Elif( read_active & spi_ready, read_active.eq(0), bus.ack.eq(1), ).Else( bus.ack.eq(0), read_active.eq(0), ) ] o_rdata = Signal(32) self.comb += bus.dat_r.eq(o_rdata) self.specials += Instance( "spimemio", o_flash_io0_oe=mosi_pad.oe, o_flash_io1_oe=miso_pad.oe, o_flash_io2_oe=wp_pad.oe, o_flash_io3_oe=hold_pad.oe, o_flash_io0_do=mosi_pad.o, o_flash_io1_do=miso_pad.o, o_flash_io2_do=wp_pad.o, o_flash_io3_do=hold_pad.o, o_flash_csb=cs_n_pad.o, o_flash_clk=clk, i_flash_io0_di=mosi_pad.i, i_flash_io1_di=miso_pad.i, i_flash_io2_di=wp_pad.i, i_flash_io3_di=hold_pad.i, i_resetn=~reset, i_clk=ClockSignal(), i_valid=bus.stb & bus.cyc, o_ready=spi_ready, i_addr=flash_addr, o_rdata=o_rdata, i_cfgreg_we=cfg_we, i_cfgreg_di=cfg, o_cfgreg_do=cfg_out, ) platform.add_source("rtl/spimemio.v")
def __init__(self, platform, output_dir="build", **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, cpu_type=None, integrated_rom_size=0x0, integrated_sram_size=0x0, integrated_main_ram_size=0x0, csr_address_width=14, csr_data_width=8, with_uart=False, with_timer=False) # USB signals usb_p_tx = Signal() usb_n_tx = Signal() usb_p_rx = Signal() usb_n_rx = Signal() usb_tx_en = Signal() usb_p_t = TSTriple() usb_n_t = TSTriple() usb_pads = platform.request("usb") # Assign signals to triple self.comb += [ If(usb_tx_en, usb_p_rx.eq(0b1), usb_n_rx.eq(0b0), ).Else( usb_p_rx.eq(usb_p_t.i), usb_n_rx.eq(usb_n_t.i), ), usb_p_t.oe.eq(usb_tx_en), usb_n_t.oe.eq(usb_tx_en), usb_p_t.o.eq(usb_p_tx), usb_n_t.o.eq(usb_n_tx), ] # Assign pads to triple self.specials += usb_p_t.get_tristate(usb_pads.d_p) self.specials += usb_n_t.get_tristate(usb_pads.d_n) self.comb += usb_pads.tx_en.eq(usb_tx_en) self.comb += usb_pads.pullup.eq(0b1) platform.add_source("../tinyfpga/common/tinyfpga_bootloader.v") self.specials += Instance("tinyfpga_bootloader", i_clk_48mhz=self.crg.cd_usb_48.clk, i_clk=self.crg.cd_usb_48.clk, i_reset=self.crg.cd_sys.rst, # USB lines o_usb_p_tx=usb_p_tx, o_usb_n_tx=usb_n_tx, i_usb_p_rx=usb_p_rx, i_usb_n_rx=usb_n_rx, o_usb_tx_en=usb_tx_en )
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, platform, pads, size=2 * 1024 * 1024): self.size = size self.bus = bus = wishbone.Interface() self.reset = Signal() self.cfg1 = CSRStorage(size=8) self.cfg2 = CSRStorage(size=8) self.cfg3 = CSRStorage(size=8) self.cfg4 = CSRStorage(size=8) self.stat1 = CSRStatus(size=8) self.stat2 = CSRStatus(size=8) self.stat3 = CSRStatus(size=8) self.stat4 = CSRStatus(size=8) cfg = Signal(32) cfg_we = Signal(4) cfg_out = Signal(32) self.comb += [ cfg.eq( Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage, self.cfg4.storage)), cfg_we.eq( Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re, self.cfg4.re)), self.stat1.status.eq(cfg_out[0:8]), self.stat2.status.eq(cfg_out[8:16]), self.stat3.status.eq(cfg_out[16:24]), self.stat4.status.eq(cfg_out[24:32]), ] mosi_pad = TSTriple() miso_pad = TSTriple() cs_n_pad = TSTriple() clk_pad = TSTriple() wp_pad = TSTriple() hold_pad = TSTriple() self.specials += mosi_pad.get_tristate(pads.mosi) self.specials += miso_pad.get_tristate(pads.miso) self.specials += cs_n_pad.get_tristate(pads.cs_n) self.specials += clk_pad.get_tristate(pads.clk) self.specials += wp_pad.get_tristate(pads.wp) self.specials += hold_pad.get_tristate(pads.hold) reset = Signal() self.comb += [ reset.eq(ResetSignal() | self.reset), cs_n_pad.oe.eq(~reset), clk_pad.oe.eq(~reset), ] flash_addr = Signal(24) # size/4 because data bus is 32 bits wide, -1 for base 0 mem_bits = bits_for(int(size / 4) - 1) pad = Signal(2) self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits - 1])) read_active = Signal() spi_ready = Signal() self.sync += [ If( bus.stb & bus.cyc & ~read_active, read_active.eq(1), bus.ack.eq(0), ).Elif( read_active & spi_ready, read_active.eq(0), bus.ack.eq(1), ).Else( bus.ack.eq(0), read_active.eq(0), ) ] o_rdata = Signal(32) self.comb += bus.dat_r.eq(o_rdata) self.specials += Instance( "spimemio", o_flash_io0_oe=mosi_pad.oe, o_flash_io1_oe=miso_pad.oe, o_flash_io2_oe=wp_pad.oe, o_flash_io3_oe=hold_pad.oe, o_flash_io0_do=mosi_pad.o, o_flash_io1_do=miso_pad.o, o_flash_io2_do=wp_pad.o, o_flash_io3_do=hold_pad.o, o_flash_csb=cs_n_pad.o, o_flash_clk=clk_pad.o, i_flash_io0_di=mosi_pad.i, i_flash_io1_di=miso_pad.i, i_flash_io2_di=wp_pad.i, i_flash_io3_di=hold_pad.i, i_resetn=~reset, i_clk=ClockSignal(), i_valid=bus.stb & bus.cyc, o_ready=spi_ready, i_addr=flash_addr, o_rdata=o_rdata, i_cfgreg_we=cfg_we, i_cfgreg_di=cfg, o_cfgreg_do=cfg_out, ) platform.add_source("rtl/spimemio.v")
def __init__(self, pads): touch1 = TSTriple() touch2 = TSTriple() touch3 = TSTriple() touch4 = TSTriple() self.specials += touch1.get_tristate(pads.t1) self.specials += touch2.get_tristate(pads.t2) self.specials += touch3.get_tristate(pads.t3) self.specials += touch4.get_tristate(pads.t4) self.o = CSRStorage(size=4) self.oe = CSRStorage(size=4) self.i = CSRStatus(size=4) self.comb += [ touch1.o.eq(self.o.storage[0]), touch2.o.eq(self.o.storage[1]), touch3.o.eq(self.o.storage[2]), touch4.o.eq(self.o.storage[3]), touch1.oe.eq(self.oe.storage[0]), touch2.oe.eq(self.oe.storage[1]), touch3.oe.eq(self.oe.storage[2]), touch4.oe.eq(self.oe.storage[3]), self.i.status.eq(Cat(touch1.i, touch2.i, touch3.i, touch4.i)) ]
def __init__(self, platform, output_dir="build", usb_variant='dummy', **kwargs): # Disable integrated RAM as we'll add it later self.integrated_sram_size = 0 self.output_dir = output_dir clk_freq = int(48e6) self.submodules.crg = _CRG(platform) SoCCore.__init__(self, platform, clk_freq, cpu_type=None, integrated_rom_size=0x0, integrated_sram_size=0x0, integrated_main_ram_size=0x0, csr_address_width=14, csr_data_width=8, with_uart=False, with_timer=False) # USB signals usb_p_tx = Signal() usb_n_tx = Signal() usb_p_rx = Signal() usb_n_rx = Signal() usb_tx_en = Signal() usb_tx_en_dut = Signal() usb_reset = Signal() usb_p_t = TSTriple() usb_n_t = TSTriple() usb_pads = platform.request("usb") # Assign signals to triple self.comb += [ If( ~usb_tx_en_dut, usb_p_rx.eq(0b1), usb_n_rx.eq(0b0), ).Else( usb_p_rx.eq(usb_p_t.i), usb_n_rx.eq(usb_n_t.i), ), usb_p_t.oe.eq(~usb_tx_en_dut), usb_n_t.oe.eq(~usb_tx_en_dut), usb_p_t.o.eq(usb_p_tx), usb_n_t.o.eq(usb_n_tx), ] self.comb += usb_tx_en.eq(~usb_tx_en_dut) # Delay USB_TX_EN line for i in range(4): tx_en_tmp = Signal() self.sync.sys += tx_en_tmp.eq(usb_tx_en) usb_tx_en = tx_en_tmp self.comb += usb_reset.eq(~self.crg.cd_sys.rst) # Assign pads to triple self.specials += usb_p_t.get_tristate(usb_pads.d_p) self.specials += usb_n_t.get_tristate(usb_pads.d_n) # Deasserting tx_en should not be delayed self.comb += usb_pads.tx_en.eq(usb_tx_en & ~usb_tx_en_dut) platform.add_source("../usb1_device/rtl/verilog/usb1_core.v") self.specials += Instance( "usb1_core", i_clk_i=self.crg.cd_sys.clk, i_rst_i=usb_reset, # USB lines o_tx_dp=usb_p_tx, o_tx_dn=usb_n_tx, i_rx_dp=usb_p_rx, i_rx_dn=usb_n_rx, o_tx_oe=usb_tx_en_dut, i_rx_d=usb_p_rx, i_phy_tx_mode=0b1)
def __init__(self, pads, wires=4, with_tristate=True): self.wishbone = wishbone.Interface() # # # self.__doc__ = self.__doc__.format(wires) if wires == 4: self.mod_doc = Spi4WireDocumentation() elif wires == 3: self.mod_doc = Spi3WireDocumentation() elif wires == 2: self.mod_doc = Spi2WireDocumentation() clk = Signal() cs_n = Signal() mosi = Signal() miso = Signal() miso_en = Signal() counter = Signal(8) write_offset = Signal(5) command = Signal(8) address = Signal(32) value = Signal(32) wr = Signal() sync_byte = Signal(8) self.specials += [ MultiReg(pads.clk, clk), ] if wires == 2: io = TSTriple() self.specials += io.get_tristate(pads.mosi) self.specials += MultiReg(io.i, mosi) self.comb += io.o.eq(miso) self.comb += io.oe.eq(miso_en) elif wires == 3: self.specials += MultiReg(pads.cs_n, cs_n), io = TSTriple() self.specials += io.get_tristate(pads.mosi) self.specials += MultiReg(io.i, mosi) self.comb += io.o.eq(miso) self.comb += io.oe.eq(miso_en) elif wires == 4: self.specials += MultiReg(pads.cs_n, cs_n), self.specials += MultiReg(pads.mosi, mosi) if with_tristate: self.specials += Tristate(pads.miso, miso, ~cs_n) else: self.comb += pads.miso.eq(miso) else: raise ValueError("`wires` must be 2, 3, or 4") clk_last = Signal() clk_rising = Signal() clk_falling = Signal() self.sync += clk_last.eq(clk) self.comb += clk_rising.eq(clk & ~clk_last) self.comb += clk_falling.eq(~clk & clk_last) fsm = FSM(reset_state="IDLE") fsm = ResetInserter()(fsm) self.submodules += fsm self.comb += fsm.reset.eq(cs_n) # Connect the Wishbone bus up to our values self.comb += [ self.wishbone.adr.eq(address[2:]), self.wishbone.dat_w.eq(value), self.wishbone.sel.eq(2**len(self.wishbone.sel) - 1) ] # Constantly have the counter increase, except when it's reset # in the IDLE state self.sync += If(cs_n, counter.eq(0)).Elif(clk_rising, counter.eq(counter + 1)) if wires == 2: fsm.act( "IDLE", miso_en.eq(0), NextValue(miso, 1), If(clk_rising, NextValue(sync_byte, Cat(mosi, sync_byte))), If( sync_byte[0:7] == 0b101011, NextState("GET_TYPE_BYTE"), NextValue(counter, 0), NextValue(command, mosi), )) elif wires == 3 or wires == 4: fsm.act( "IDLE", miso_en.eq(0), NextValue(miso, 1), If( clk_rising, NextState("GET_TYPE_BYTE"), NextValue(command, mosi), ), ) else: raise ValueError("invalid `wires` count: {}".format(wires)) # Determine if it's a read or a write fsm.act( "GET_TYPE_BYTE", miso_en.eq(0), NextValue(miso, 1), If( counter == 8, # Write value If( command == 0, NextValue(wr, 1), NextState("READ_ADDRESS"), # Read value ).Elif( command == 1, NextValue(wr, 0), NextState("READ_ADDRESS"), ).Else(NextState("END"), ), ), If( clk_rising, NextValue(command, Cat(mosi, command)), ), ) fsm.act( "READ_ADDRESS", miso_en.eq(0), If( counter == 32 + 8, If( wr, NextState("READ_VALUE"), ).Else(NextState("READ_WISHBONE"), )), If( clk_rising, NextValue(address, Cat(mosi, address)), ), ) fsm.act( "READ_VALUE", miso_en.eq(0), If( counter == 32 + 32 + 8, NextState("WRITE_WISHBONE"), ), If( clk_rising, NextValue(value, Cat(mosi, value)), ), ) fsm.act( "WRITE_WISHBONE", self.wishbone.stb.eq(1), self.wishbone.we.eq(1), self.wishbone.cyc.eq(1), miso_en.eq(1), If( self.wishbone.ack | self.wishbone.err, NextState("WAIT_BYTE_BOUNDARY"), ), ) fsm.act( "READ_WISHBONE", self.wishbone.stb.eq(1), self.wishbone.we.eq(0), self.wishbone.cyc.eq(1), miso_en.eq(1), If( self.wishbone.ack | self.wishbone.err, NextState("WAIT_BYTE_BOUNDARY"), NextValue(value, self.wishbone.dat_r), ), ) fsm.act( "WAIT_BYTE_BOUNDARY", miso_en.eq(1), If( clk_falling, If( counter[0:3] == 0, NextValue(miso, 0), # For writes, fill in the 0 byte response If( wr, NextState("WRITE_WR_RESPONSE"), ).Else(NextState("WRITE_RESPONSE"), ), ), ), ) # Write the "01" byte that indicates a response fsm.act( "WRITE_RESPONSE", miso_en.eq(1), If( clk_falling, If( counter[0:3] == 0b111, NextValue(miso, 1), ).Elif(counter[0:3] == 0, NextValue(write_offset, 31), NextState("WRITE_VALUE")), ), ) # Write the actual value fsm.act( "WRITE_VALUE", miso_en.eq(1), NextValue(miso, value >> write_offset), If( clk_falling, NextValue(write_offset, write_offset - 1), If( write_offset == 0, NextValue(miso, 0), NextState("END"), ), ), ) fsm.act( "WRITE_WR_RESPONSE", miso_en.eq(1), If( clk_falling, If( counter[0:3] == 0, NextState("END"), ), ), ) if wires == 3 or wires == 4: fsm.act( "END", miso_en.eq(1), ) elif wires == 2: fsm.act("END", miso_en.eq(0), NextValue(sync_byte, 0), NextState("IDLE")) else: raise ValueError("invalid `wires` count: {}".format(wires))
def __init__(self, platform, pads): self.reset = Signal() mosi_pad = TSTriple() miso_pad = TSTriple() cs_n_pad = TSTriple() clk_pad = TSTriple() wp_pad = TSTriple() hold_pad = TSTriple() self.do = CSRStorage(size=6) self.oe = CSRStorage(size=6) self.di = CSRStatus(size=6) self.specials += mosi_pad.get_tristate(pads.mosi) self.specials += miso_pad.get_tristate(pads.miso) self.specials += cs_n_pad.get_tristate(pads.cs_n) self.specials += clk_pad.get_tristate(pads.clk) self.specials += wp_pad.get_tristate(pads.wp) self.specials += hold_pad.get_tristate(pads.hold) self.comb += [ mosi_pad.oe.eq(self.oe.storage[0]), miso_pad.oe.eq(self.oe.storage[1]), wp_pad.oe.eq(self.oe.storage[2]), hold_pad.oe.eq(self.oe.storage[3]), clk_pad.oe.eq(self.oe.storage[4]), cs_n_pad.oe.eq(self.oe.storage[5]), mosi_pad.o.eq(self.do.storage[0]), miso_pad.o.eq(self.do.storage[1]), wp_pad.o.eq(self.do.storage[2]), hold_pad.o.eq(self.do.storage[3]), clk_pad.o.eq(self.do.storage[4]), cs_n_pad.o.eq(self.do.storage[5]), self.di.status.eq( Cat(mosi_pad.i, miso_pad.i, wp_pad.i, hold_pad.i, clk_pad.i, cs_n_pad.i)), ]
def __init__(self, platform, pads, size=2 * 1024 * 1024): self.intro = ModuleDoc( "See https://github.com/cliffordwolf/picorv32/tree/master/picosoc#spi-flash-controller-config-register" ) self.size = size self.bus = bus = wishbone.Interface() self.reset = Signal() self.cfg1 = CSRStorage(size=8) self.cfg2 = CSRStorage(size=8) self.cfg3 = CSRStorage( size=8, reset=0x24 ) # set 1 for qspi (bit 21); lower 4 bits is "dummy" cycles self.cfg4 = CSRStorage(size=8) self.stat = CSRStatus(size=32) cfg = Signal(32) cfg_we = Signal(4) cfg_out = Signal(32) # Add pulse the cfg_we line after reset reset_counter = Signal(2, reset=3) ic_reset = Signal(reset=1) self.sync += \ If(reset_counter != 0, reset_counter.eq(reset_counter - 1) ).Else( ic_reset.eq(0) ) self.comb += [ cfg.eq( Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage, self.cfg4.storage)), cfg_we.eq( Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re | ic_reset, self.cfg4.re)), self.stat.status.eq(cfg_out), ] copi_pad = TSTriple() cipo_pad = TSTriple() cs_n_pad = TSTriple() clk_pad = TSTriple() wp_pad = TSTriple() hold_pad = TSTriple() self.specials += copi_pad.get_tristate(pads.copi) self.specials += cipo_pad.get_tristate(pads.cipo) self.specials += cs_n_pad.get_tristate(pads.cs_n) self.specials += clk_pad.get_tristate(pads.clk) self.specials += wp_pad.get_tristate(pads.wp) self.specials += hold_pad.get_tristate(pads.hold) reset = Signal() self.comb += [ reset.eq(ResetSignal() | self.reset), cs_n_pad.oe.eq(~reset), clk_pad.oe.eq(~reset), ] flash_addr = Signal(24) # size/4 because data bus is 32 bits wide, -1 for base 0 mem_bits = bits_for(int(size / 4) - 1) pad = Signal(2) self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits - 1])) read_active = Signal() spi_ready = Signal() self.sync += [ If( bus.stb & bus.cyc & ~read_active, read_active.eq(1), bus.ack.eq(0), ).Elif( read_active & spi_ready, read_active.eq(0), bus.ack.eq(1), ).Else( bus.ack.eq(0), read_active.eq(0), ) ] o_rdata = Signal(32) self.comb += bus.dat_r.eq(o_rdata) self.specials += Instance( "spimemio", o_flash_io0_oe=copi_pad.oe, o_flash_io1_oe=cipo_pad.oe, o_flash_io2_oe=wp_pad.oe, o_flash_io3_oe=hold_pad.oe, o_flash_io0_do=copi_pad.o, o_flash_io1_do=cipo_pad.o, o_flash_io2_do=wp_pad.o, o_flash_io3_do=hold_pad.o, o_flash_csb=cs_n_pad.o, o_flash_clk=clk_pad.o, i_flash_io0_di=copi_pad.i, i_flash_io1_di=cipo_pad.i, i_flash_io2_di=wp_pad.i, i_flash_io3_di=hold_pad.i, i_resetn=~reset, i_clk=ClockSignal(), i_valid=bus.stb & bus.cyc, o_ready=spi_ready, i_addr=flash_addr, o_rdata=o_rdata, i_cfgreg_we=cfg_we, i_cfgreg_di=cfg, o_cfgreg_do=cfg_out, ) platform.add_source("rtl/spimemio.v")