# Strongly inspired by the migen build of humpback # Using STM32 Nucleo-H743ZI2 board # Note to self: Pin assignment differs from Nucleo-H743ZI import os import subprocess from nmigen.build import * from nmigen.vendor.lattice_ice40 import * from nmigen_boards.resources import * from resources import * __all__ = ["HumpbackPlatform"] class HumpbackPlatform(LatticeICE40Platform): device = "iCE40HX8K" # Using ICE40HX8K-CT256 package = "CT256" default_clk = "clk25" resources = [ # Define clock Resource("clk25", 0, Pins("K9", dir="i"), Clock(25e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS") ), # Define user LED Resource("user_led", 0, Pins("H3", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS") ), # TODO: Define UART interfaces somewhere else, make it optional UARTResource(0, rx="T11", tx="M13", rts="M15", cts="T10", attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1) ), # UART1 interface: Read note for UART interface above # UART1 interface is broken due to pin rearrangement introduced for Nucleo-H743ZI2 # Uncomment if fixed, or found an alternative (e.g. bit banging UART) # *UARTResource(1, # tx="M11", rx="T13", rts="A6", cts="B16", # attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1) # ), # Define SPI interfaces # TODO; Make it optional, define it in a block # Note: Use "role=device" to make humpback a SPI slave # The ~CS pin is a global pin, but not being configured global. SPIResource(0, cs="R2", clk="C8", mosi="N5", miso="T2", attrs=Attrs(IO_STANDARD="SB_LVCMOS") ), # Define I2C interface # TODO: Make it optional, declare it in a block itself # Use "role=device" to make humpback a I2C slave I2CResource(0, sda="T16", scl="M12", attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1) ), ] # Using the dict approach in (o)migen # Note: Numbering is required in nMigen, so some probably not very meaningful strings/integers are inserted connectors = [ # EEM0 Connector Connector("eem", 0, { "d0_cc_n": "H1", "d0_cc_p": "J3", "d1_n" : "B1", "d1_p" : "F5", "d2_n" : "C2", "d2_p" : "C1", "d3_n" : "D2", "d3_p" : "F4", "d4_n" : "D1", "d4_p" : "G5", "d5_n" : "E3", "d5_p" : "G4", "d6_n" : "E2", "d6_p" : "H5", "d7_n" : "F3", "d7_p" : "G3", }), # EEM1 Connector Connector("eem", 1, { "d0_cc_n": "L3", "d0_cc_p": "L6", "d1_n": "F1", "d1_p": "H6", "d2_n": "G2", "d2_p": "H4", "d3_n": "H2", "d3_p": "J4", "d4_n": "J1", "d4_p": "J2", "d5_n": "K3", "d5_p": "K1", "d6_n": "L1", "d6_p": "L4", "d7_n": "M1", "d7_p": "K4", }), # EEM2 Connector Connector("eem", 2, { "d0_cc_n": "G1", "d0_cc_p": "J5", "d1_n": "M2", "d1_p": "K5", "d2_n": "N2", "d2_p": "L7", "d3_n": "M3", "d3_p": "M6", "d4_n": "N3", "d4_p": "L5", "d5_n": "M4", "d5_p": "P1", "d6_n": "M5", "d6_p": "P2", "d7_n": "N4", "d7_p": "R1", }), # STM32 Nucleo/ Arduino Connector # TODO: Suspect SPI mismatch Connector("stm32", "pins", { "PA0": "A2", # "PA1": "P14", # PA1 -> PB2, but PB2 has a mapping on FPGA already # "PA2": "B8", # PA2 -> PF6 "PA3": "L13", "PA5": "C8", "PA6": "T2", # "PA7": "N12", # PA7 -> PE9, but PE9 has a mapping on FPGA already # "PA8": "M9", # PA8 -> PF2 # "PA9": "P10", # PA9 -> PF1 # "PA10": "R10", # PA10 -> PF0 "PA15": "B14", "PB0": "A1", # "PB1": "G12", # PB1 -> PF4 "PB1": "M14", # PC1 -> PB1 "PB2": "B6", "PB5": "N5", # "PB6": "A7", # PB6 -> PG6 "PB6": "T13", # PG9 -> PB6 "PB7": "M11", # PG10 -> PB7 "PB8": "M12", "PB9": "T16", "PB10": "C3", "PB11": "F7", "PB12": "B13", "PB13": "B12", "PB15": "A11", "PC0": "L14", # "PC1": "M14", # PC1 -> PB1 # "PC2": "A9", # PC2 -> PF5 "PC2": "N16", # PC4 -> PC2 "PC3": "M16", # "PC4": "N16", # PC4 -> PC2 # "PC5": "P16", # PC5 -> PF10 "PC6": "B10", "PC7": "B15", "PC8": "H16", "PC9": "J10", "PC10": "J16", "PC11": "J15", "PC12": "K12", "PD0": "T9", "PD1": "N9", "PD2": "K13", "PD3": "T10", "PD4": "A6", "PD5": "T11", "PD6": "M13", "PD7": "L12", "PD11": "E5", "PD12": "D5", "PD13": "C5", "PD14": "R2", "PE0": "D3", "PE2": "P15", "PE3": "N10", "PE4": "R15", "PE5": "T15", "PE6": "M8", "PE7": "E6", "PE8": "D6", "PE9": "F12", "PE10": "A5", "PE11": "G11", "PE12": "B4", # "PE13": "F11", # PE13 -> PG12 # "PE14": "C4", # PE14 -> PE6, but PE6 has a mapping on FPGA already "PE14": "B9", # PF14 -> PE14 "PE15": "B3", "PF0": "R10", # PA10 -> PF0 "PF1": "P10", # PA9 -> PF1 "PF2": "M9", # PA8 -> PF2 "PF4": "G12", # PB1 -> PF4 "PF5": "A9", # PC2 -> PF5 "PF6": "B8", # PA2 -> PF6 "PF7": "L9", "PF8": "L10", "PF9": "P9", "PF10": "P16", # PC5 -> PF10 # "PF14": "B9", # PF14 -> PE14 # "PF15": "B16", # PF15 -> PG14 "PG0": "M7", "PG1": "P8", "PG2": "K14", "PG3": "K15", "PG6": "A7", # PB6 -> PG6 # "PG9": "T13", # PG9 -> PB6 # "PG10": "M11", # PG10 -> PB7 "PG12": "F11", # PE13 -> PG12 "PG14": "B16", # PF15 -> PG14 }), # Beaglebone Black Connector Connector("bb", "pins", { "CLKOUT": "R9", "GPIO0_7": "R14", "GPIO1_16": "A16", "GPIO1_17": "R3", "GPIO1_29": "D11", "GPIO1_31": "D14", "GPIO2_6": "D16", "GPIO2_7": "C16", "GPIO2_8": "E16", "GPIO2_9": "D15", "GPIO2_11": "F15", "GPIO2_13": "F16", "GPIO2_22": "C11", "GPIO2_23": "C10", "GPIO2_24": "E10", "GPIO2_25": "D4", "GPIO3_19": "P4", "GPIO3_21": "R4", "GPMC_A2": "T7", "GPMC_A3": "T1", "GPMC_A14": "F9", "GPMC_A15": "B7", "GPMC_AD0": "C12", "GPMC_AD1": "E11", "GPMC_AD2": "J12", "GPMC_AD3": "J11", "GPMC_AD4": "C13", "GPMC_AD5": "C14", "GPMC_AD6": "J14", "GPMC_AD7": "J13", "GPMC_AD8": "E13", "GPMC_AD9": "G13", "GPMC_AD10": "G14", "GPMC_AD11": "G10", "GPMC_AD12": "E14", "GPMC_AD13": "H14", "GPMC_AD14": "F14", "GPMC_AD15": "F13", "GPMC_ADVN": "H12", "GPMC_BE0N": "G16", "GPMC_CLK": "H11", "GPMC_CSN1": "D13", "GPMC_OEN": "H13", "GPMC_WE1N": "G15", }), # ESP32 Connector Connector("esp32", "pins", { "IO2": "D9", "IO4": "D7", "IO22": "C7", "IO34": "E9", "IO35": "C9", }), # OrangePI Zero Connector Connector("orange_pi", "pins", { "PG06": "A15", }), ] # tool chain setup, using default ICE40 HX8K evaluation code def toolchain_program(self, products, name): iceprog = os.environ.get("ICEPROG", "iceprog") with products.extract("{}.bin".format(name)) as bitstream_filename: subprocess.check_call([iceprog, "-S", bitstream_filename]) if __name__ == "__main__": from nmigen_boards.test.blinky import * HumpbackPlatform().build(Blinky(), do_program=False)