Merge pull request #211 from Acathla-fr/master
Lattice iCE40 UltraPlus Breakout board (iCE40UP5K-B-EVN) added
This commit is contained in:
commit
9e86c094c9
|
@ -0,0 +1,131 @@
|
|||
from litex.build.generic_platform import *
|
||||
from litex.build.lattice import LatticePlatform
|
||||
from litex.build.lattice.programmer import IceStormProgrammer
|
||||
|
||||
|
||||
_io = [
|
||||
# Clk
|
||||
("clk12", 0, Pins("35"), IOStandard("LVCMOS33")),
|
||||
|
||||
# LEDs
|
||||
("user_led_n", 0, Pins("39"), IOStandard("LVCMOS33")),
|
||||
("rgb_led", 0,
|
||||
Subsignal("r", Pins("41")),
|
||||
Subsignal("g", Pins("40")),
|
||||
Subsignal("b", Pins("39")),
|
||||
IOStandard("LVCMOS33")
|
||||
),
|
||||
|
||||
# Buttons
|
||||
("user_sw", 0, Pins("23"), IOStandard("LVCMOS33")),
|
||||
("user_sw", 1, Pins("25"), IOStandard("LVCMOS33")),
|
||||
("user_sw", 2, Pins("34"), IOStandard("LVCMOS33")),
|
||||
("user_sw", 3, Pins("43"), IOStandard("LVCMOS33"))
|
||||
]
|
||||
|
||||
spiflash = [
|
||||
# Only usable in PROG FLASH mode and J7 attached (see PCB silkscreen).
|
||||
("spiflash", 0,
|
||||
Subsignal("cs_n", Pins("16"), IOStandard("LVCMOS33")),
|
||||
Subsignal("clk", Pins("15"), IOStandard("LVCMOS33")),
|
||||
Subsignal("mosi", Pins("14"), IOStandard("LVCMOS33")),
|
||||
Subsignal("miso", Pins("17"), IOStandard("LVCMOS33")),
|
||||
),
|
||||
]
|
||||
|
||||
serial = [
|
||||
("serial", 0,
|
||||
Subsignal("tx", Pins("J3:0")),
|
||||
Subsignal("rx", Pins("J3:1")),
|
||||
IOStandard("LVCMOS33")
|
||||
),
|
||||
("serial", 1,
|
||||
Subsignal("tx", Pins("J3:2")),
|
||||
Subsignal("rx", Pins("J3:3")),
|
||||
IOStandard("LVCMOS33")
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
_connectors = [
|
||||
# Many pins on the AARDVARK, PMOD, J52/HEADER A, and J2/HEADER B connectors
|
||||
# are multiplexed with other I/O or connector pins. For completeness, all
|
||||
# pins are exposed here except Vdd, NC, and GND. Pin order is as specified
|
||||
# on the schematic (except for PMOD, which uses Digilent's numbering).
|
||||
|
||||
# AARDVARK connector omitted- although sysCONFIG pins are exposed on this
|
||||
# header (which can be used as GPIO), it is meant for flashing using an
|
||||
# external programmer rather than as an I/O port.
|
||||
|
||||
# PMOD connector shares pins with sysCONFIG- make sure to remove jumper
|
||||
# J7 if using the PMOD. TODO: Perhaps it would be better to split into two
|
||||
# single 6-pin PMODs.
|
||||
#
|
||||
# PMOD pinout (using ICE40 pin names):
|
||||
# 1, 2, 3, 4- SPI_SS, SPI_SI, SPI_SO, SPI_SCK
|
||||
# 5, 6, 7, 8- Free
|
||||
("PMOD", "16 17 14 15 27 26 32 31"),
|
||||
#Silk: SS MOSI MISO SCK 38B 39A 43A 42B
|
||||
|
||||
# J52 exposes LEDs and sysCONFIG pins (yet again). Make sure to remove
|
||||
# jumper J7 if using the PMOD. Pin order is as follows (right to left):
|
||||
# 12 10 8 6 4 2
|
||||
# 11 9 7 5 3 1
|
||||
#
|
||||
# J52's pinout (using ICE40 pin names for SPI flash):
|
||||
# 1, 2- Vdd
|
||||
# 3, 4- rgb_led.b, SPI_SI
|
||||
# 5, 6- rgb_led.g, SPI_SO
|
||||
# 7, 8- GND, SPI_SCK
|
||||
# 9, 10- rgb_led.r, SPI_SS
|
||||
# 11, 12- GND
|
||||
# 3 4 5 6 8 9 10
|
||||
("J52", "39 17 40 14 15 41 16"),
|
||||
|
||||
# Pin order of J2, and J3 are as follows (left to right/top to bottom):
|
||||
# 2 4 6 8 10 12 14 16 18 20
|
||||
# 1 3 5 7 9 11 13 15 17 19
|
||||
#
|
||||
# J2's pinout is shared by many things. Entire pinout listed follows:
|
||||
# 1, 2- Vdd
|
||||
# 3, 4- user_sw0, NC
|
||||
# 5, 6- user_sw1, NC
|
||||
# 7, 8- PMOD D5, Free
|
||||
# 9, 10- PMOD D4, Free
|
||||
# 11, 12- PMOD D6, Free
|
||||
# 13, 14- PMOD D7, Free
|
||||
# 15, 16- Free, 12.00 clock
|
||||
# 17, 18- user_sw2, GND
|
||||
# 19, 20- user_sw3, GND
|
||||
# 3 5 7 8 9 10 11 12 13 14 15 16 17 19
|
||||
("J2", "23 25 26 36 27 42 32 38 31 28 37 35 34 43"),
|
||||
# Silk:37A 36B 39A 48B 38B 51A 43A 50B 42B 41A 45A_G1 ICE_CLK 44B 49A
|
||||
# index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
|
||||
# Bank2: 4 3 48 45 47 44 46 2
|
||||
# Bank1: 12 21 13 20 19 18 11 10 9 6
|
||||
# J3's pinout is all Free, except 1 (Vdd) and 19 (GND).
|
||||
# 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20
|
||||
("J3", "12 4 21 3 13 48 20 45 19 47 18 44 11 46 10 2 9 6"),
|
||||
# Silk:22A 8A 23B 9B 24A 4A 25B_G3 5B 29B 2A 31B 3B_G6 20A 0A 18A 6A 16A 13B
|
||||
# index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
||||
]
|
||||
|
||||
|
||||
class Platform(LatticePlatform):
|
||||
default_clk_name = "clk12"
|
||||
default_clk_period = 1e9/12e6
|
||||
|
||||
def __init__(self):
|
||||
LatticePlatform.__init__(self, "ice40-up5k-sg48", _io, _connectors,
|
||||
toolchain="icestorm")
|
||||
self.add_extension(serial)
|
||||
self.add_extension(spiflash)
|
||||
|
||||
def create_programmer(self):
|
||||
return IceStormProgrammer()
|
||||
|
||||
def do_finalize(self, fragment):
|
||||
LatticePlatform.do_finalize(self, fragment)
|
||||
self.add_period_constraint(self.lookup_request("clk12", loose=True), 1e9/12e6)
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# This file is part of LiteX-Boards.
|
||||
#
|
||||
# Copyright (c) 2019 Sean Cross <sean@xobs.io>
|
||||
# Copyright (c) 2018 David Shah <dave@ds0.me>
|
||||
# Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
target="lattice_ice40up5k_evn"
|
||||
|
||||
from migen import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
|
||||
from litex_boards.platforms import lattice_ice40up5k_evn
|
||||
from litex.build.lattice.programmer import IceStormProgrammer
|
||||
|
||||
from litex.soc.cores.ram import Up5kSPRAM
|
||||
from litex.soc.cores.spi_flash import SpiFlash
|
||||
from litex.soc.cores.clock import iCE40PLL
|
||||
from litex.soc.integration.soc_core import *
|
||||
from litex.soc.integration.soc import SoCRegion
|
||||
from litex.soc.integration.builder import *
|
||||
from litex.soc.cores.led import LedChaser
|
||||
|
||||
kB = 1024
|
||||
mB = 1024*kB
|
||||
|
||||
|
||||
# CRG ----------------------------------------------------------------------------------------------
|
||||
|
||||
class _CRG(Module):
|
||||
def __init__(self, platform, sys_clk_freq):
|
||||
assert sys_clk_freq == 12e6
|
||||
self.rst = Signal()
|
||||
self.clock_domains.cd_sys = ClockDomain()
|
||||
self.clock_domains.cd_por = ClockDomain(reset_less=True)
|
||||
|
||||
# # #
|
||||
|
||||
# Clk/Rst
|
||||
sys = platform.request("clk12")
|
||||
platform.add_period_constraint(sys, 1e9/12e6)
|
||||
|
||||
# Power On Reset
|
||||
por_count = Signal(16, reset=2**16-1)
|
||||
por_done = Signal()
|
||||
self.comb += self.cd_por.clk.eq(ClockSignal("sys"))
|
||||
self.comb += por_done.eq(por_count == 0)
|
||||
self.sync.por += If(~por_done, por_count.eq(por_count - 1))
|
||||
|
||||
# Sys Clk
|
||||
self.comb += self.cd_sys.clk.eq(sys)
|
||||
self.specials += AsyncResetSynchronizer(self.cd_sys, ~por_done)
|
||||
|
||||
|
||||
# BaseSoC ------------------------------------------------------------------------------------------
|
||||
|
||||
class BaseSoC(SoCCore):
|
||||
mem_map = {**SoCCore.mem_map, **{"spiflash": 0x80000000}}
|
||||
def __init__(self, bios_flash_offset, sys_clk_freq=int(12e6), **kwargs):
|
||||
platform = lattice_ice40up5k_evn.Platform()
|
||||
|
||||
# Disable Integrated ROM/SRAM since too large for iCE40 and UP5K has specific SPRAM.
|
||||
kwargs["integrated_sram_size"] = 0
|
||||
kwargs["integrated_rom_size"] = 0
|
||||
|
||||
# Set CPU variant / reset address
|
||||
kwargs["cpu_reset_address"] = self.mem_map["spiflash"] + bios_flash_offset
|
||||
|
||||
# SoCCore ----------------------------------------------------------------------------------
|
||||
SoCCore.__init__(self, platform, sys_clk_freq,
|
||||
ident = "LiteX SoC on Lattice iCE40UP5k EVN breakout board",
|
||||
ident_version = True,
|
||||
**kwargs)
|
||||
|
||||
# CRG --------------------------------------------------------------------------------------
|
||||
self.submodules.crg = _CRG(platform, sys_clk_freq)
|
||||
|
||||
# 128KB SPRAM (used as SRAM) ---------------------------------------------------------------
|
||||
self.submodules.spram = Up5kSPRAM(size=128*kB)
|
||||
self.bus.add_slave("sram", self.spram.bus, SoCRegion(size=128*kB))
|
||||
|
||||
# SPI Flash --------------------------------------------------------------------------------
|
||||
self.add_spi_flash(mode="1x", dummy_cycles=8)
|
||||
# 4x mode is not possible on this board since WP and HOLD pins are not connected to the FPGA
|
||||
|
||||
# Add ROM linker region --------------------------------------------------------------------
|
||||
self.bus.add_region("rom", SoCRegion(
|
||||
origin = self.mem_map["spiflash"] + bios_flash_offset,
|
||||
size = 32*kB,
|
||||
linker = True)
|
||||
)
|
||||
|
||||
# Leds -------------------------------------------------------------------------------------
|
||||
self.submodules.leds = LedChaser(
|
||||
pads = platform.request_all("user_led_n"),
|
||||
sys_clk_freq = sys_clk_freq)
|
||||
|
||||
# Add a UART-Wishbone bridge -----------------------------------------
|
||||
debug_uart=False
|
||||
if debug_uart:
|
||||
# This will add a bridge on the second serial port defined in platform
|
||||
from litex.soc.cores.uart import UARTWishboneBridge
|
||||
self.submodules.uart_bridge = UARTWishboneBridge(
|
||||
platform.request("serial"),
|
||||
sys_clk_freq,
|
||||
baudrate=115200)
|
||||
self.add_wb_master(self.uart_bridge.wishbone)
|
||||
|
||||
# Flash --------------------------------------------------------------------------------------------
|
||||
|
||||
def flash(bios_flash_offset):
|
||||
from litex.build.dfu import DFUProg
|
||||
prog = IceStormProgrammer()
|
||||
bitstream = open("build/"+target+"/gateware/"+target+".bin", "rb")
|
||||
bios = open("build/"+target+"/software/bios/bios.bin", "rb")
|
||||
image = open("build/"+target+"/image.bin", "wb")
|
||||
# Copy bitstream at 0x00000000
|
||||
for i in range(0x00000000, 0x0020000):
|
||||
b = bitstream.read(1)
|
||||
if not b:
|
||||
image.write(0xff.to_bytes(1, "big"))
|
||||
else:
|
||||
image.write(b)
|
||||
# Copy bios at 0x00020000
|
||||
for i in range(0x00000000, 0x00010000):
|
||||
b = bios.read(1)
|
||||
if not b:
|
||||
image.write(0xff.to_bytes(1, "big"))
|
||||
else:
|
||||
image.write(b)
|
||||
bitstream.close()
|
||||
bios.close()
|
||||
image.close()
|
||||
print("Flashing bitstream (+bios)")
|
||||
prog.flash(0x0, "build/"+target+"/image.bin")
|
||||
|
||||
# Build --------------------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="LiteX SoC on Lattice iCE40UP5k EVN breakout board")
|
||||
parser.add_argument("--build", action="store_true", help="Build bitstream")
|
||||
parser.add_argument("--sys-clk-freq", default=12e6, help="System clock frequency (default: 12MHz)")
|
||||
parser.add_argument("--bios-flash-offset", default=0x20000, help="BIOS offset in SPI Flash (default: 0x20000)")
|
||||
parser.add_argument("--flash", action="store_true", help="Flash Bitstream")
|
||||
builder_args(parser)
|
||||
soc_core_args(parser)
|
||||
args = parser.parse_args()
|
||||
|
||||
soc = BaseSoC(
|
||||
bios_flash_offset = args.bios_flash_offset,
|
||||
sys_clk_freq = int(float(args.sys_clk_freq)),
|
||||
**soc_core_argdict(args)
|
||||
)
|
||||
builder = Builder(soc, **builder_argdict(args))
|
||||
builder.build(run=args.build)
|
||||
|
||||
if args.flash:
|
||||
flash(args.bios_flash_offset)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue