aboutsummaryrefslogtreecommitdiff
path: root/amaranth_boards
diff options
context:
space:
mode:
authorwhitequark <whitequark@whitequark.org>2021-12-10 07:38:00 +0000
committerwhitequark <whitequark@whitequark.org>2021-12-10 08:30:37 +0000
commitb968cfade961a329c26035ef8bfdf3058e95a9f1 (patch)
tree94891b950cb0547868877027230ff09b9cb56d4a /amaranth_boards
parentbd7fdd379d8b28f8b542f251a11ca28297e8fd6f (diff)
Rename nMigen to Amaranth HDL.
Diffstat (limited to 'amaranth_boards')
-rw-r--r--amaranth_boards/__init__.py11
-rw-r--r--amaranth_boards/alchitry_au.py76
-rw-r--r--amaranth_boards/arrow_deca.py88
-rw-r--r--amaranth_boards/arty_a7.py230
-rw-r--r--amaranth_boards/arty_s7.py235
-rw-r--r--amaranth_boards/arty_z7.py175
-rw-r--r--amaranth_boards/atlys.py224
-rw-r--r--amaranth_boards/blackice.py61
-rw-r--r--amaranth_boards/blackice_ii.py63
-rw-r--r--amaranth_boards/chameleon96.py105
-rw-r--r--amaranth_boards/colorlight_5a75b_r7_0.py114
-rw-r--r--amaranth_boards/de0.py111
-rw-r--r--amaranth_boards/de0_cv.py99
-rw-r--r--amaranth_boards/de10_lite.py89
-rw-r--r--amaranth_boards/de10_nano.py95
-rw-r--r--amaranth_boards/de1_soc.py87
-rw-r--r--amaranth_boards/ebaz4205.py40
-rw-r--r--amaranth_boards/ecp5_5g_evn.py154
-rw-r--r--amaranth_boards/ecpix5.py232
-rw-r--r--amaranth_boards/extensions/__init__.py0
-rw-r--r--amaranth_boards/extensions/pmod.py94
-rw-r--r--amaranth_boards/fomu_hacker.py51
-rw-r--r--amaranth_boards/fomu_pvt.py51
-rw-r--r--amaranth_boards/genesys2.py363
-rw-r--r--amaranth_boards/ice40_hx1k_blink_evn.py48
-rw-r--r--amaranth_boards/ice40_hx8k_b_evn.py68
-rw-r--r--amaranth_boards/ice40_up5k_b_evn.py66
-rw-r--r--amaranth_boards/icebreaker.py75
-rw-r--r--amaranth_boards/icebreaker_bitsy.py51
-rw-r--r--amaranth_boards/icestick.py53
-rw-r--r--amaranth_boards/icesugar.py64
-rw-r--r--amaranth_boards/icesugar_nano.py48
-rw-r--r--amaranth_boards/kc705.py42
-rw-r--r--amaranth_boards/kcu105.py37
-rw-r--r--amaranth_boards/machxo3_sk.py74
-rw-r--r--amaranth_boards/mercury.py214
-rw-r--r--amaranth_boards/microzed_z010.py116
-rw-r--r--amaranth_boards/microzed_z020.py116
-rw-r--r--amaranth_boards/mister.py134
-rw-r--r--amaranth_boards/nandland_go.py50
-rw-r--r--amaranth_boards/nexys4ddr.py183
-rw-r--r--amaranth_boards/numato_mimas.py51
-rw-r--r--amaranth_boards/orangecrab_r0_1.py122
-rw-r--r--amaranth_boards/orangecrab_r0_2.py132
-rw-r--r--amaranth_boards/quickfeather.py82
-rw-r--r--amaranth_boards/resources/__init__.py4
-rw-r--r--amaranth_boards/resources/display.py36
-rw-r--r--amaranth_boards/resources/interface.py144
-rw-r--r--amaranth_boards/resources/memory.py190
-rw-r--r--amaranth_boards/resources/user.py43
-rw-r--r--amaranth_boards/rz_easyfpga_a2_2.py126
-rw-r--r--amaranth_boards/sk_xc6slx9.py55
-rw-r--r--amaranth_boards/supercon19badge.py167
-rw-r--r--amaranth_boards/te0714_03_50_2I.py132
-rw-r--r--amaranth_boards/test/__init__.py0
-rw-r--r--amaranth_boards/test/blinky.py48
-rw-r--r--amaranth_boards/tinyfpga_ax1.py24
-rw-r--r--amaranth_boards/tinyfpga_ax2.py24
-rw-r--r--amaranth_boards/tinyfpga_bx.py53
-rw-r--r--amaranth_boards/ulx3s.py197
-rw-r--r--amaranth_boards/upduino_v1.py36
-rw-r--r--amaranth_boards/upduino_v2.py30
-rw-r--r--amaranth_boards/versa_ecp5.py176
-rw-r--r--amaranth_boards/versa_ecp5_5g.py14
-rw-r--r--amaranth_boards/zturn_lite_z007s.py76
-rw-r--r--amaranth_boards/zturn_lite_z010.py8
66 files changed, 6257 insertions, 0 deletions
diff --git a/amaranth_boards/__init__.py b/amaranth_boards/__init__.py
new file mode 100644
index 0000000..6eb2e59
--- /dev/null
+++ b/amaranth_boards/__init__.py
@@ -0,0 +1,11 @@
+try:
+ try:
+ from importlib import metadata as importlib_metadata # py3.8+ stdlib
+ except ImportError:
+ import importlib_metadata # py3.7- shim
+ __version__ = importlib_metadata.version(__package__)
+except ImportError:
+ # No importlib_metadata. This shouldn't normally happen, but some people prefer not installing
+ # packages via pip at all, instead using PYTHONPATH directly or copying the package files into
+ # `lib/pythonX.Y/site-packages`. Although not a recommended way, we still try to support it.
+ __version__ = "unknown" # :nocov:
diff --git a/amaranth_boards/alchitry_au.py b/amaranth_boards/alchitry_au.py
new file mode 100644
index 0000000..49a7a51
--- /dev/null
+++ b/amaranth_boards/alchitry_au.py
@@ -0,0 +1,76 @@
+import os
+import subprocess
+import shutil
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["AlchitryAuPlatform"]
+
+
+def find_loader():
+ loader_prgm = os.environ.get("ALCHITRY_LOADER", shutil.which("loader"))
+ if loader_prgm is None:
+ raise EnvironmentError("Could not find Alchrity Loader. Place "
+ "it directly in PATH or specify path explicitly via the "
+ "ALCHITRY_LOADER environment variable")
+ bridge_bin = os.environ.get("ALCHITRY_BRIDGE_BIN", os.path.join(os.path.dirname(loader_prgm), "au_loader.bin"))
+ return (loader_prgm, bridge_bin)
+
+
+class AlchitryAuPlatform(Xilinx7SeriesPlatform):
+ device = "XC7A35T" # Artix 7 33K LEs
+ package = "FTG256"
+ speed = "1"
+ default_clk = "clk100"
+ resources = [
+ Resource("clk100", 0, Pins("N14", dir="i"),
+ Clock(10e7), Attrs(IOSTANDARD="LVCMOS33")),
+
+ # On-Board LED Array
+ *LEDResources(
+ pins="K13 K12 L14 L13 M16 M14 M12 N16",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("usb", 0,
+ Subsignal("usb_tx", Pins("P16", dir="o")),
+ Subsignal("usb_rx", Pins("P15", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ # TODO: This is untested
+ DDR3Resource(0,
+ rst_n="D13", clk_p="G14", clk_n="F14", clk_en="D15", cs_n="D16", we_n="E11", ras_n="D14", cas_n="D14",
+ a="F12 G16 G15 E16 H11 G12 H16 H12 H16 H13 E12 H14 F13 J15",
+ ba="E13 F15 E15",
+ dqs_p="B15 A15", dqs_n="B9 A10",
+ dq="A13 B16 B14 C11 C13 C16 C12 C14 D8 B11 C8 B10 A12 A8 B12 A9",
+ dm="A14 C9", odt="G11",
+ diff_attrs=Attrs(IOSTANDARD="LVDS"),
+ attrs=Attrs(IOSTANDARD="LVCMOS15")),
+ ]
+
+ connectors = [
+ Connector("bank", 0, "T8 T7 T5 R5 R8 P8 L2 L3 J1 K1 H1 H2 G1 G2 K5 E6 "
+ "T10 T9 R6 R7 P9 N9 K2 K3 J4 J5 H3 J3 H4 H5 N6 M6 "),
+ Connector("bank", 1, "D1 E2 A2 B2 E1 F2 F3 F4 A3 B4 A4 A5 B5 B6 A7 B7 "
+ "B1 C1 C2 C3 D3 E3 C4 D4 G4 G5 E5 F5 D5 D6 C6 C7 "),
+ Connector("bank", 2, "T13 R13 T12 R12 R11 R10 N2 N3 P3 P4 M4 L4 N4 M5 L5 P5 "
+ "P11 P10 N12 N11 P13 N13 M1 M2 P1 N1 R1 R2 T2 R3 T3 T4 "),
+ Connector("bank", 3, "L14 L13 M12 N16 R16 R15 P14 M15 P16 P15 - - - - - - "
+ "K13 K12 M16 M14 T16 T14 N14 - - - - - - - - - ")
+ ]
+
+ def toolchain_program(self, products, name):
+ (loader, bridge_bin) = find_loader()
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([loader, "-e", "-f", bitstream_filename,
+ "-p", bridge_bin
+ ])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ AlchitryAuPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/arrow_deca.py b/amaranth_boards/arrow_deca.py
new file mode 100644
index 0000000..5fd4245
--- /dev/null
+++ b/amaranth_boards/arrow_deca.py
@@ -0,0 +1,88 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["ArrowDECAPlatform"]
+
+
+class ArrowDECAPlatform(IntelPlatform):
+ device = "10M50DA" # MAX 10
+ package = "F484"
+ speed = "C6"
+ suffix = "GES"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("M8", dir="i"),
+ Clock(50e6), Attrs(io_standard="2.5 V")),
+ Resource("clk50", 1, Pins("P11", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3 V")),
+ Resource("clk50", 2, Pins("N15", dir="i"),
+ Clock(50e6), Attrs(io_standard="1.5 V")),
+ Resource("clk10", 0, Pins("M9", dir="i"),
+ Clock(10e6), Attrs(io_standard="2.5 V")),
+
+ *LEDResources(
+ pins="C7 C8 A6 B7 C4 A5 B4 C5",
+ invert=True,
+ attrs=Attrs(io_standard="1.2 V")),
+ *ButtonResources(
+ pins="H21 H22",
+ invert=True,
+ attrs=Attrs(io_standard="1.5 V")),
+ *SwitchResources(
+ pins="J21 J22",
+ attrs=Attrs(io_standard="1.5 V")),
+ ]
+ connectors = [
+ Connector("gpio", 0,
+ "W18 Y18 Y19 AA17 AA20 AA19 AB21 AB20 AB19 Y16 V16 "
+ "AB18 V15 W17 AB17 AA16 AB16 W16 AB15 W15 Y14 AA15 "
+ "AB14 AA14 AB13 AA13 AB12 AA12 AB11 AA11 AB10 Y13 Y11 "
+ "W13 W12 W11 V12 V11 V13 V14 Y17 W14 U15 R13"),
+ Connector("gpio", 1,
+ "Y5 Y6 W6 W7 W8 V8 AB8 V7 R11 AB7 AB6 "
+ "AA7 AA6 Y7 V10 U7 W9 W5 R9 W4 P9 V17 "
+ "W3"),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename])
+
+ @property
+ def file_templates(self):
+ # Configure the voltages of the I/O banks by appending the global
+ # assignments to the template. However, we create our own copy of the
+ # file templates before modifying them to avoid modifying the original.
+ return {
+ **super().file_templates,
+ "{{name}}.qsf":
+ super().file_templates.get("{{name}}.qsf") +
+ r"""
+ set_global_assignment -name IOBANK_VCCIO 2.5V -section_id 1A
+ set_global_assignment -name IOBANK_VCCIO 2.5V -section_id 1B
+ set_global_assignment -name IOBANK_VCCIO 2.5V -section_id 2
+ set_global_assignment -name IOBANK_VCCIO 3.3V -section_id 3
+ set_global_assignment -name IOBANK_VCCIO 3.3V -section_id 4
+ set_global_assignment -name IOBANK_VCCIO 1.5V -section_id 5
+ set_global_assignment -name IOBANK_VCCIO 1.5V -section_id 6
+ set_global_assignment -name IOBANK_VCCIO 1.8V -section_id 7
+ set_global_assignment -name IOBANK_VCCIO 1.2V -section_id 8
+
+ set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
+ set_global_assignment -name AUTO_RESTART_CONFIGURATION OFF
+ set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
+ set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
+ """
+ }
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ ArrowDECAPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/arty_a7.py b/amaranth_boards/arty_a7.py
new file mode 100644
index 0000000..3032349
--- /dev/null
+++ b/amaranth_boards/arty_a7.py
@@ -0,0 +1,230 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["ArtyA7_35Platform", "ArtyA7_100Platform"]
+
+
+class _ArtyA7Platform(Xilinx7SeriesPlatform):
+ package = "csg324"
+ speed = "1L"
+ default_clk = "clk100"
+ default_rst = "rst"
+ resources = [
+ Resource("clk100", 0, Pins("E3", dir="i"),
+ Clock(100e6), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("rst", 0, PinsN("C2", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+
+ *LEDResources(pins="H5 J5 T9 T10", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ RGBLEDResource(0, r="G6", g="F6", b="E1", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ RGBLEDResource(1, r="G3", g="J4", b="G4", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ RGBLEDResource(2, r="J3", g="J2", b="H4", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ RGBLEDResource(3, r="K1", g="H6", b="K2", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ *ButtonResources(pins="D9 C9 B9 B8 ", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ *SwitchResources(pins="A8 C11 C10 A10", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ UARTResource(0,
+ rx="A9", tx="D10",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ SPIResource(0,
+ cs_n="C1", clk="F1", copi="H1", cipo="G1",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ Resource("i2c", 0,
+ Subsignal("scl", Pins("L18", dir="io")),
+ Subsignal("sda", Pins("M18", dir="io")),
+ Subsignal("scl_pullup", Pins("A14", dir="o")),
+ Subsignal("sda_pullup", Pins("A13", dir="o")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="L13", clk="L16", copi="K17", cipo="K18", wp_n="L14", hold_n="M14",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ Resource("ddr3", 0,
+ Subsignal("rst", PinsN("K6", dir="o")),
+ Subsignal("clk", DiffPairs("U9", "V9", dir="o"), Attrs(IOSTANDARD="DIFF_SSTL135")),
+ Subsignal("clk_en", Pins("N5", dir="o")),
+ Subsignal("cs", PinsN("U8", dir="o")),
+ Subsignal("we", PinsN("P5", dir="o")),
+ Subsignal("ras", PinsN("P3", dir="o")),
+ Subsignal("cas", PinsN("M4", dir="o")),
+ Subsignal("a", Pins("R2 M6 N4 T1 N6 R7 V6 U7 R8 V7 R6 U6 T6 T8", dir="o")),
+ Subsignal("ba", Pins("R1 P4 P2", dir="o")),
+ Subsignal("dqs", DiffPairs("N2 U2", "N1 V2", dir="io"),
+ Attrs(IOSTANDARD="DIFF_SSTL135")),
+ Subsignal("dq", Pins("K5 L3 K3 L6 M3 M1 L4 M2 V4 T5 U4 V5 V1 T3 U3 R3", dir="io"),
+ Attrs(IN_TERM="UNTUNED_SPLIT_40")),
+ Subsignal("dm", Pins("L1 U1", dir="o")),
+ Subsignal("odt", Pins("R5", dir="o")),
+ Attrs(IOSTANDARD="SSTL135", SLEW="FAST"),
+ ),
+
+ Resource("eth_clk25", 0, Pins("G18", dir="o"),
+ Clock(25e6), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("eth_clk50", 0, Pins("G18", dir="o"),
+ Clock(50e6), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("eth_mii", 0,
+ Subsignal("rst", PinsN("C16", dir="o")),
+ Subsignal("mdio", Pins("K13", dir="io")),
+ Subsignal("mdc", Pins("F16", dir="o")),
+ Subsignal("tx_clk", Pins("H16", dir="i")),
+ Subsignal("tx_en", Pins("H15", dir="o")),
+ Subsignal("tx_data", Pins("H14 J14 J13 H17", dir="o")),
+ Subsignal("rx_clk", Pins("F15", dir="i")),
+ Subsignal("rx_dv", Pins("G16", dir="i"), Attrs(PULLDOWN="TRUE")), # strap to select MII
+ Subsignal("rx_er", Pins("C17", dir="i")),
+ Subsignal("rx_data", Pins("D18 E17 E18 G17", dir="i")),
+ Subsignal("col", Pins("D17", dir="i")),
+ Subsignal("crs", Pins("G14", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ Resource("eth_rmii", 0,
+ Subsignal("rst", PinsN("C16", dir="o")),
+ Subsignal("mdio", Pins("K13", dir="io")),
+ Subsignal("mdc", Pins("F16", dir="o")),
+ Subsignal("tx_en", Pins("H15", dir="o")),
+ Subsignal("tx_data", Pins("H14 J14", dir="o")),
+ Subsignal("rx_crs_dv", Pins("G14", dir="i")),
+ Subsignal("rx_dv", Pins("G16", dir="i"), Attrs(PULLUP="TRUE")), # strap to select RMII
+ Subsignal("rx_er", Pins("C17", dir="i")),
+ Subsignal("rx_data", Pins("D18 E17", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ )
+ ]
+ connectors = [
+ Connector("pmod", 0, "G13 B11 A11 D12 - - D13 B18 A18 K16 - -"), # JA
+ Connector("pmod", 1, "E15 E16 D15 C15 - - J17 J18 K15 J15 - -"), # JB
+ Connector("pmod", 2, "U12 V12 V10 V11 - - U14 V14 T13 U13 - -"), # JC
+ Connector("pmod", 3, " D4 D3 F4 F3 - - E2 D2 H2 G2 - -"), # JD
+
+ Connector("ck_io", 0, {
+ # Outer Digital Header
+ "io0": "V15",
+ "io1": "U16",
+ "io2": "P14",
+ "io3": "T11",
+ "io4": "R12",
+ "io5": "T14",
+ "io6": "T15",
+ "io7": "T16",
+ "io8": "N15",
+ "io9": "M16",
+ "io10": "V17",
+ "io11": "U18",
+ "io12": "R17",
+ "io13": "P17",
+
+ # Inner Digital Header
+ "io26": "U11",
+ "io27": "V16",
+ "io28": "M13",
+ "io29": "R10",
+ "io30": "R11",
+ "io31": "R13",
+ "io32": "R15",
+ "io33": "P15",
+ "io34": "R16",
+ "io35": "N16",
+ "io36": "N14",
+ "io37": "U17",
+ "io38": "T18",
+ "io39": "R18",
+ "io40": "P18",
+ "io41": "N17",
+
+ # Outer Analog Header as Digital IO
+ "a0": "F5",
+ "a1": "D8",
+ "a2": "C7",
+ "a3": "E7",
+ "a4": "D7",
+ "a5": "D5",
+
+ # Inner Analog Header as Digital IO
+ "io20": "B7",
+ "io21": "B6",
+ "io22": "E6",
+ "io23": "E5",
+ "io24": "A4",
+ "io25": "A3"
+ }),
+ Connector("xadc", 0, {
+ # Outer Analog Header
+ "vaux4_n": "C5",
+ "vaux4_p": "C6",
+ "vaux5_n": "A5",
+ "vaux5_p": "A6",
+ "vaux6_n": "B4",
+ "vaux6_p": "C4",
+ "vaux7_n": "A1",
+ "vaux7_p": "B1",
+ "vaux15_n": "B2",
+ "vaux15_p": "B3",
+ "vaux0_n": "C14",
+ "vaux0_p": "D14",
+
+ # Inner Analog Header
+ "vaux12_n": "B7",
+ "vaux12_p": "B6",
+ "vaux13_n": "E6",
+ "vaux13_p": "E5",
+ "vaux14_n": "A4",
+ "vaux14_p": "A3",
+
+ # Power Measurements
+ "vsnsuv_n": "B17",
+ "vsnsuv_p": "B16",
+ "vsns5v0_n": "B12",
+ "vsns5v0_p": "C12",
+ "isns5v0_n": "F14",
+ "isns5v0_n": "F13",
+ "isns0v95_n": "A16",
+ "isns0v95_n": "A15",
+ })
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = {
+ "script_before_bitstream":
+ "set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]",
+ "script_after_bitstream":
+ "write_cfgmem -force -format bin -interface spix4 -size 16 "
+ "-loadbit \"up 0x0 {name}.bit\" -file {name}.bin".format(name=name),
+ "add_constraints":
+ """
+ set_property INTERNAL_VREF 0.675 [get_iobanks 34]
+ set_property CFGBVS VCCO [current_design]
+ set_property CONFIG_VOLTAGE 3.3 [current_design]
+ """
+ }
+ return super().toolchain_prepare(fragment, name, **overrides, **kwargs)
+
+ def toolchain_program(self, products, name):
+ xc3sprog = os.environ.get("XC3SPROG", "xc3sprog")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.run([xc3sprog, "-c", "nexys4", bitstream_filename], check=True)
+
+
+class ArtyA7_35Platform(_ArtyA7Platform):
+ device = "xc7a35ti"
+
+
+class ArtyA7_100Platform(_ArtyA7Platform):
+ device = "xc7a100ti"
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ArtyA7_35Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/arty_s7.py b/amaranth_boards/arty_s7.py
new file mode 100644
index 0000000..5122617
--- /dev/null
+++ b/amaranth_boards/arty_s7.py
@@ -0,0 +1,235 @@
+import os
+import textwrap
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["ArtyS7_25Platform", "ArtyS7_50Platform"]
+
+
+class _ArtyS7Platform(Xilinx7SeriesPlatform):
+ package = "csga324"
+ speed = "1"
+ default_clk = "clk100"
+ default_rst = "rst"
+ resources = [
+ Resource("clk100", 0, Pins("R2", dir="i"),
+ Clock(100e6), Attrs(IOSTANDARD="SSTL135")),
+ Resource("rst", 0, PinsN("C18", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+
+ *LEDResources(pins="E18 F13 E13 H15", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ RGBLEDResource(0, r="J15", g="G17", b="F15", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ RGBLEDResource(1, r="E15", g="F18", b="E14", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ *ButtonResources(pins="G15 K16 J16 H13", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ *SwitchResources(pins="H14 H18 G18 M5", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ UARTResource(0,
+ rx="V12", tx="R12",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ SPIResource(0,
+ cs_n="H16", clk="G16", copi="H17", cipo="K14",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ I2CResource(0,
+ scl="J14", sda="J13",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="M13", clk="D11", copi="K17", cipo="K18", wp_n="L14", hold_n="M15",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ Resource("ddr3", 0,
+ Subsignal("rst", PinsN("J6", dir="o")),
+ Subsignal("clk", DiffPairs("R5", "T4", dir="o"), Attrs(IOSTANDARD="DIFF_SSTL135")),
+ Subsignal("clk_en", Pins("T2", dir="o")),
+ Subsignal("cs", PinsN("R3", dir="o")),
+ Subsignal("we", PinsN("P7", dir="o")),
+ Subsignal("ras", PinsN("U1", dir="o")),
+ Subsignal("cas", PinsN("V3", dir="o")),
+ Subsignal("a", Pins("U2 R4 V2 V4 T3 R7 V6 T6 U7 V7 P6 T5 R6 U6", dir="o")),
+ Subsignal("ba", Pins("V5 T1 U3", dir="o")),
+ Subsignal("dqs", DiffPairs("K1 N3", "L1 N2", dir="io"),
+ Attrs(IOSTANDARD="DIFF_SSTL135")),
+ Subsignal("dq", Pins("K2 K3 L4 M6 K6 M4 L5 L6 N4 R1 N1 N5 M2 P1 M1 P2", dir="io"),
+ Attrs(IN_TERM="UNTUNED_SPLIT_40")),
+ Subsignal("dm", Pins("K4 M3", dir="o")),
+ Subsignal("odt", Pins("P5", dir="o")),
+ Attrs(IOSTANDARD="SSTL135", SLEW="FAST"),
+ ),
+ ]
+ connectors = [
+ Connector("pmod", 0, "L17 L18 M14 N14 - - M16 M17 M18 N18 - -"), # JA
+ Connector("pmod", 1, "P17 P18 R18 T18 - - P14 P15 N15 P16 - -"), # JB
+ Connector("pmod", 2, "U15 V16 U17 U18 - - U16 P13 R13 V14 - -"), # JC
+ Connector("pmod", 3, "V15 U12 V13 T12 - - T13 R11 T11 U11 - -"), # JD
+
+ Connector("ck_io", 0, {
+ # Outer Digital Header
+ "io0": "L13",
+ "io1": "N13",
+ "io2": "L16",
+ "io3": "R14",
+ "io4": "T14",
+ "io5": "R16",
+ "io6": "R17",
+ "io7": "V17",
+ "io8": "R15",
+ "io9": "T15",
+ "io10": "H16",
+ "io11": "H17",
+ "io12": "K14",
+ "io13": "G16",
+
+ # Inner Digital Header
+ "io26": "U11",
+ "io27": "T11",
+ "io28": "R11",
+ "io29": "T13",
+ "io30": "T12",
+ "io31": "V13",
+ "io32": "U12",
+ "io33": "V15",
+ "io34": "V14",
+ "io35": "R13",
+ "io36": "P13",
+ "io37": "U16",
+ "io38": "U18",
+ "io39": "U17",
+ "io40": "V16",
+ "io41": "U15",
+
+ # Outer Analog Header as Digital IO
+ "a0": "G13",
+ "a1": "B16",
+ "a2": "A16",
+ "a3": "C13",
+ "a4": "C14",
+ "a5": "D18",
+
+ # Inner Analog Header as Digital IO
+ "io20": "B14",
+ "io21": "A14",
+ "io22": "D16",
+ "io23": "D17",
+ "io24": "D14",
+ "io25": "D15"
+ }),
+ Connector("xadc", 0, {
+ # Outer Analog Header
+ "vaux0_p": "B13",
+ "vaux0_n": "A13",
+ "vaux1_p": "B15",
+ "vaux1_n": "A15",
+ "vaux9_p": "E12",
+ "vaux9_n": "D12",
+ "vaux2_p": "B17",
+ "vaux2_n": "A17",
+ "vaux10_p": "C17",
+ "vaux10_n": "B18",
+ "vaux11_p": "E16",
+ "vaux11_n": "E17",
+
+ # Inner Analog Header
+ "vaux8_p": "B14",
+ "vaux8_n": "A14",
+ "vaux3_p": "D16",
+ "vaux3_n": "D17",
+ })
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = {
+ "script_before_bitstream":
+ "set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]",
+ "script_after_bitstream":
+ "write_cfgmem -force -format mcs -interface spix4 -size 16 "
+ "-loadbit \"up 0x0 {name}.bit\" -file {name}.mcs".format(name=name),
+ "add_constraints":
+ "set_property INTERNAL_VREF 0.675 [get_iobanks 34]"
+ }
+ return super().toolchain_prepare(fragment, name, **overrides, **kwargs)
+
+ def toolchain_program(self, product, name, *, programmer="vivado", flash=True):
+ assert programmer in ("vivado", "openocd")
+
+ if programmer == "vivado":
+ if flash:
+ # It does not appear possible to reset the FPGA via TCL after
+ # flash programming.
+ with product.extract("{}.bin".format(name)) as bitstream_filename:
+ cmd = textwrap.dedent("""
+ open_hw_manager
+ connect_hw_server
+ open_hw_target
+ current_hw_device [lindex [get_hw_devices] 0]
+ create_hw_cfgmem -hw_device [current_hw_device] s25fl128sxxxxxx0-spi-x1_x2_x4
+ set_property PROGRAM.FILES {{{}}} [current_hw_cfgmem]
+ set_property PROGRAM.ADDRESS_RANGE {{use_file}} [current_hw_cfgmem]
+ set_property PROGRAM.BLANK_CHECK 1 [current_hw_cfgmem]
+ set_property PROGRAM.ERASE 1 [current_hw_cfgmem]
+ set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]
+ set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]
+ create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]
+ program_hw_devices
+ program_hw_cfgmem
+ close_hw_manager
+ puts "Vivado TCL cannot reset boards. Reset or power-cycle your board now."
+ """).format(bitstream_filename).encode("utf-8")
+ subprocess.run(["vivado", "-nolog", "-nojournal", "-mode", "tcl"], input=cmd, check=True)
+ else:
+ with product.extract("{}.bit".format(name)) as bitstream_filename:
+ cmd = textwrap.dedent("""
+ open_hw_manager
+ connect_hw_server
+ open_hw_target
+ current_hw_device [lindex [get_hw_devices] 0]
+ set_property PROGRAM.FILE {{{}}} [current_hw_device]
+ program_hw_devices
+ close_hw_manager
+ """).format(bitstream_filename).encode("utf-8")
+ subprocess.run(["vivado", "-nolog", "-nojournal", "-mode", "tcl"], input=cmd, check=True)
+ else:
+ openocd = os.environ.get("OPENOCD", "openocd")
+ # In order, OpenOCD searches these directories for files:
+ # * $HOME/.openocd if $HOME exists (*nix)
+ # * Path pointed to by $OPENOCD_SCRIPTS if $OPENOCD_SCRIPTS exists
+ # * $APPDATA/OpenOCD on Windows
+ # Place the bscan_spi_xc7s50.bit proxy bitstream under a directory
+ # named "proxy" in one of the above directories so OpenOCD finds it.
+ if flash:
+ with product.extract("{}.bin".format(name)) as fn:
+ subprocess.check_call([openocd, "-f", "board/arty_s7.cfg",
+ "-c", """init;
+ jtagspi_init 0 [find proxy/bscan_spi_xc7s50.bit];
+ jtagspi_program {} 0;
+ xc7_program xc7.tap;
+ shutdown""".format(fn)])
+ else:
+ with product.extract("{}.bit".format(name)) as fn:
+ subprocess.check_call(["openocd", "-f", "board/arty_s7.cfg",
+ "-c", """init;
+ pld load 0 {};
+ shutdown""".format(fn)])
+
+
+class ArtyS7_50Platform(_ArtyS7Platform):
+ device = "xc7s50"
+
+
+class ArtyS7_25Platform(_ArtyS7Platform):
+ device = "xc7s25"
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ArtyS7_25Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/arty_z7.py b/amaranth_boards/arty_z7.py
new file mode 100644
index 0000000..48b75e0
--- /dev/null
+++ b/amaranth_boards/arty_z7.py
@@ -0,0 +1,175 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["ArtyZ720Platform"]
+
+
+class ArtyZ720Platform(Xilinx7SeriesPlatform):
+ device = "xc7z020"
+ package = "clg400"
+ speed = "1"
+ default_clk = "clk125"
+ resources = [
+ Resource("clk125", 0,
+ Pins("H16", dir="i"), Clock(125e6), Attrs(IOSTANDARD="LVCMOS33")),
+
+ *SwitchResources(
+ pins="M20 M19",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ RGBLEDResource(0,
+ r="N15", g="G17", b="L15", # LD4
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ RGBLEDResource(1, # LD5
+ r="M15", g="L14", b="G14",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ *LEDResources(
+ pins="R14 P14 N16 M14",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ *ButtonResources(
+ pins="D19 D20 L20 L19",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("audio", 0,
+ Subsignal("pwm", Pins("R18", dir="o")),
+ Subsignal("sd", PinsN("T17", dir="o")),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("crypto_sda", 0, # ATSHA204A
+ Pins("J15", dir="io"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("hdmi_rx", 0, # J10
+ Subsignal("cec", Pins("H17", dir="io")),
+ Subsignal("clk", DiffPairs("N18", "P19", dir="i"),
+ Attrs(IOSTANDARD="TMDS_33")),
+ Subsignal("d", DiffPairs("V20 T20 N20", "W20 U20 P20", dir="i"),
+ Attrs(IOSTANDARD="TMDS_33")),
+ Subsignal("hpd", Pins("T19", dir="o")),
+ Subsignal("scl", Pins("U14", dir="io")),
+ Subsignal("sda", Pins("U15", dir="io")),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("hdmi_tx", 0, # J11
+ Subsignal("cec", Pins("G15", dir="io")),
+ Subsignal("clk", DiffPairs("L16", "L17", dir="o"),
+ Attrs(IOSTANDARD="TMDS_33")),
+ Subsignal("d", DiffPairs("K17 K19 J18", "K18 J19 H18", dir="o"),
+ Attrs(IOSTANDARD="TMDS_33")),
+ Subsignal("hpd", PinsN("R19", dir="i")),
+ Subsignal("scl", Pins("M17", dir="io")),
+ Subsignal("sda", Pins("M18", dir="io")),
+ Attrs(IOSTANDARD="LVCMOS33"))
+ ]
+ connectors = [
+ Connector("pmod", 0, "Y18 Y19 Y16 Y17 - - U18 U19 W18 W19 - -"), # JA
+ Connector("pmod", 1, "W14 Y14 T11 T10 - - V16 W16 V12 W13 - -"), # JB
+
+ Connector("ck_io", 0, {
+ # Outer Digital Header
+ "io0": "T14",
+ "io1": "U12",
+ "io2": "U13",
+ "io3": "V13",
+ "io4": "V15",
+ "io5": "T15",
+ "io6": "R16",
+ "io7": "U17",
+ "io8": "V17",
+ "io9": "V18",
+ "io10": "T16",
+ "io11": "R17",
+ "io12": "P18",
+ "io13": "N17",
+
+ # Inner Digital Header
+ "io26": "U5",
+ "io27": "V5",
+ "io28": "V6",
+ "io29": "U7",
+ "io30": "V7",
+ "io31": "U8",
+ "io32": "V8",
+ "io33": "V10",
+ "io34": "W10",
+ "io35": "W6",
+ "io36": "Y6",
+ "io37": "Y7",
+ "io38": "W8",
+ "io39": "Y8",
+ "io40": "W9",
+ "io41": "Y9",
+
+ # Outer Analog Header as Digital IO
+ "a0": "Y11",
+ "a1": "Y12",
+ "a2": "W11",
+ "a3": "V11",
+ "a4": "T5",
+ "a5": "U10",
+
+ # Inner Analog Header as Digital IO
+ "a6": "F19",
+ "a7": "F20",
+ "a8": "C20",
+ "a9": "B20",
+ "a10": "B19",
+ "a11": "A20",
+
+ # Misc.
+ "a": "Y13"
+ }),
+
+ Connector("ck_spi", 0, {
+ "cipo": "W15",
+ "copi": "T12",
+ "sck": "H15",
+ "ss": "F16"
+ }),
+
+ Connector("ck_i2c", 0, {
+ "scl": "P16",
+ "sda": "P15"
+ }),
+
+ Connector("xadc", 0, {
+ # Outer Analog Header
+ "vaux1_n": "D18",
+ "vaux1_p": "E17",
+ "vaux9_n": "E19",
+ "vaux9_p": "E18",
+ "vaux6_n": "J14",
+ "vaux6_p": "K14",
+ "vaux15_n": "J16",
+ "vaux15_p": "K16",
+ "vaux5_n": "H20",
+ "vaux5_p": "J20",
+ "vaux13_n": "G20",
+ "vaux13_p": "G19",
+
+ # Inner Analog Header
+ "vaux12_n": "F20",
+ "vaux12_p": "F19",
+ "vaux0_n": "B20",
+ "vaux0_p": "C20",
+ "vaux8_n": "A20",
+ "vaux8_p": "B19"
+ })
+ ]
+
+ def toolchain_program(self, products, name, **kwargs):
+ xc3sprog = os.environ.get("XC3SPROG", "xc3sprog")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.run([xc3sprog, "-c", "jtaghs1_fast", "-p", "1", bitstream_filename], check=True)
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ArtyZ720Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/atlys.py b/amaranth_boards/atlys.py
new file mode 100644
index 0000000..96b5a26
--- /dev/null
+++ b/amaranth_boards/atlys.py
@@ -0,0 +1,224 @@
+import subprocess
+import textwrap
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_spartan_3_6 import *
+from .resources import *
+
+
+__all__ = ["AtlysPlatform"]
+
+
+class AtlysPlatform(XilinxSpartan6Platform):
+ """Platform file for Digilent Atlys Spartan 6 board.
+ https://reference.digilentinc.com/reference/programmable-logic/atlys/start"""
+
+ device = "xc6slx45"
+ package = "csg324"
+ speed = "3"
+
+ def __init__(self, *, JP12="2V5", **kwargs):
+ super().__init__(**kwargs)
+
+ assert JP12 in ["2V5", "3V3"]
+ self._JP12 = JP12
+
+ def bank2_iostandard(self):
+ return "LVCMOS25" if self._JP12 == "2V5" else "LVCMOS33"
+
+ default_clk = "clk100"
+ default_rst = "rst"
+ resources = [
+ Resource("rst", 0, PinsN("T15", dir="i"), Attrs(IOSTANDARD=bank2_iostandard)), # RESET
+ Resource("clk100", 0, Pins("L15", dir="i"),
+ Clock(100e6), Attrs(IOSTANDARD="LVCMOS33")), # GCLK
+
+ Resource("led", 0, Pins("U18", dir="o"), Attrs(IOSTANDARD="LVCMOS33")), # LD0
+ Resource("led", 1, Pins("M14", dir="o"), Attrs(IOSTANDARD="LVCMOS33")), # LD1
+ Resource("led", 2, Pins("N14", dir="o"), Attrs(IOSTANDARD="LVCMOS33")), # LD2
+ Resource("led", 3, Pins("L14", dir="o"), Attrs(IOSTANDARD="LVCMOS33")), # LD3
+ Resource("led", 4, Pins("M13", dir="o"), Attrs(IOSTANDARD="LVCMOS33")), # LD4
+ Resource("led", 5, Pins("D4", dir="o"), Attrs(IOSTANDARD="LVCMOS33")), # LD5
+ Resource("led", 6, Pins("P16", dir="o"), Attrs(IOSTANDARD="LVCMOS33")), # LD6
+ Resource("led", 7, Pins("N12", dir="o"), Attrs(IOSTANDARD=bank2_iostandard)), # LD7
+
+ Resource("button", 0, Pins("N4", dir="i"), Attrs(IOSTANDARD="LVCMOS18")), # BTNU
+ Resource("button", 1, Pins("P4", dir="i"), Attrs(IOSTANDARD="LVCMOS18")), # BTNL
+ Resource("button", 2, Pins("P3", dir="i"), Attrs(IOSTANDARD="LVCMOS18")), # BTND
+ Resource("button", 3, Pins("F6", dir="i"), Attrs(IOSTANDARD="LVCMOS18")), # BTNR
+ Resource("button", 4, Pins("F5", dir="i"), Attrs(IOSTANDARD="LVCMOS18")), # BTNC
+
+ Resource("switch", 0, Pins("A10", dir="i"), Attrs(IOSTANDARD="LVCMOS33")), # SW0
+ Resource("switch", 1, Pins("D14", dir="i"), Attrs(IOSTANDARD="LVCMOS33")), # SW1
+ Resource("switch", 2, Pins("C14", dir="i"), Attrs(IOSTANDARD="LVCMOS33")), # SW2
+ Resource("switch", 3, Pins("P15", dir="i"), Attrs(IOSTANDARD="LVCMOS33")), # SW3
+ Resource("switch", 4, Pins("P12", dir="i"), Attrs(IOSTANDARD=bank2_iostandard)), # SW4
+ Resource("switch", 5, Pins("R5", dir="i"), Attrs(IOSTANDARD=bank2_iostandard)), # SW5
+ Resource("switch", 6, Pins("T5", dir="i"), Attrs(IOSTANDARD=bank2_iostandard)), # SW6
+ Resource("switch", 7, Pins("E4", dir="i"), Attrs(IOSTANDARD="LVCMOS18")), # SW7
+
+ UARTResource(0, rx="A16", tx="B16", attrs=Attrs(IOSTANDARD="LVCMOS33")), # J17/UART
+
+ PS2Resource(0, # PS/2 keyboard interface converted from J13 "HOST" USB connector
+ clk="P17", dat="N15", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ PS2Resource(1, # PS/2 mouse interface converted from J13 "HOST" USB connector
+ clk="N18", dat="P18", attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ *SPIFlashResources(0,
+ cs_n="AE14", clk="AH18", copi="AF14", cipo="AF20", wp_n="AG21", hold_n="AG17",
+ attrs=Attrs(IOSTANDARD="LVCMOS25", SLEW="FAST"),
+ ),
+
+ Resource("ddr2", 0,
+ Subsignal("clk", DiffPairs("G3", "G1", dir="o"),
+ Attrs(IOSTANDARD="DIFF_SSTL18_II", IN_TERM="NONE")),
+ Subsignal("clk_en", Pins("H7", dir="o")),
+ Subsignal("we", PinsN("E3", dir="o")),
+ Subsignal("ras", PinsN("L5", dir="o")),
+ Subsignal("cas", PinsN("K5", dir="o")),
+ Subsignal("a", Pins("J7 J6 H5 L7 F3 H4 H3 H6 D2 D1 F4 D3 G6", dir="o")),
+ Subsignal("ba", Pins("F2 F1 E1", dir="o")),
+ Subsignal("dqs", DiffPairs("P2 L4", "P1 L3", dir="o"),
+ Attrs(IOSTANDARD="DIFF_SSTL18_II")),
+ Subsignal("dq", Pins("L2 L1 K2 K1 H2 H1 J3 J1 M3 M1 N2 N1 T2 T1 U2 U1", dir="io")),
+ Subsignal("dm", Pins("K4 K3", dir="o")),
+ Subsignal("odt", Pins("K6", dir="o")),
+ Attrs(IOSTANDARD="SSTL18_II", SLEW="FAST"),
+ ),
+
+ Resource("eth_gmii", 0,
+ Subsignal("rst", PinsN("G13", dir="o")),
+ Subsignal("int", PinsN("L16", dir="o")),
+ Subsignal("mdio", Pins("N17", dir="io")),
+ Subsignal("mdc", Pins("F16", dir="o")), # Max 8.3MHz
+ Subsignal("gtx_clk", Pins("L12", dir="o")),
+ Subsignal("tx_clk", Pins("K16", dir="i")),
+ Subsignal("tx_en", Pins("H15", dir="o")),
+ Subsignal("tx_er", Pins("G18", dir="o")),
+ Subsignal("tx_data", Pins("H16 H13 K14 K13 J13 G14 H12 K12", dir="o")),
+ Subsignal("rx_clk", Pins("K15", dir="i")),
+ Subsignal("rx_dv", Pins("F17", dir="i"), Attrs(PULLDOWN="TRUE")),
+ Subsignal("rx_er", Pins("F18", dir="i")),
+ Subsignal("rx_data", Pins("G16 H14 E16 F15 F14 E18 D16 D17", dir="i")),
+ Subsignal("col", Pins("C17", dir="i")),
+ Subsignal("crs", Pins("C18", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ Resource("eth_rgmii", 0,
+ Subsignal("rst", PinsN("G13", dir="o")),
+ Subsignal("int", PinsN("L16", dir="o")),
+ Subsignal("mdio", Pins("N17", dir="io")),
+ Subsignal("mdc", Pins("F16", dir="o")), # Max 8.3MHz
+ Subsignal("tx_clk", Pins("L12", dir="o")),
+ Subsignal("tx_ctl", Pins("H15", dir="o")),
+ Subsignal("tx_data", Pins("H16 H13 K14 K13", dir="o")),
+ Subsignal("rx_clk", Pins("K15", dir="i")),
+ Subsignal("rx_ctl", Pins("F17", dir="i"), Attrs(PULLDOWN="TRUE")),
+ Subsignal("rx_data", Pins("G16 H14 E16 F15", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ Resource("eth_mii", 0,
+ Subsignal("rst", PinsN("G13", dir="o")),
+ Subsignal("int", PinsN("L16", dir="o")),
+ Subsignal("mdio", Pins("N17", dir="io")),
+ Subsignal("mdc", Pins("F16", dir="o")), # Max 8.3MHz
+ Subsignal("tx_clk", Pins("K16", dir="i")),
+ Subsignal("tx_en", Pins("H15", dir="o")),
+ Subsignal("tx_er", Pins("G18", dir="o")),
+ Subsignal("tx_data", Pins("H16 H13 K14 K13", dir="o")),
+ Subsignal("rx_clk", Pins("K15", dir="i")),
+ Subsignal("rx_dv", Pins("F17", dir="i"), Attrs(PULLDOWN="TRUE")),
+ Subsignal("rx_er", Pins("F18", dir="i")),
+ Subsignal("rx_data", Pins("G16 H14 E16 F15", dir="i")),
+ Subsignal("col", Pins("C17", dir="i")),
+ Subsignal("crs", Pins("C18", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ # Device does not support RMII
+ Resource("eth_tbi", 0,
+ Subsignal("rst", PinsN("G13", dir="o")),
+ Subsignal("int", PinsN("L16", dir="o")),
+ Subsignal("mdio", Pins("N17", dir="io")),
+ Subsignal("mdc", Pins("F16", dir="o")), # Max 8.3MHz
+ Subsignal("tx_clk", Pins("L12", dir="o")),
+ Subsignal("tx_data", Pins("H16 H13 K14 K13 J13 G14 H12 K12 H15 G18", dir="o")),
+ Subsignal("rx_clk", Pins("K15 L12", dir="i")),
+ Subsignal("rx_data", Pins("G16 H14 E16 F15 F14 E18 D16 D17 F17 F18", dir="i")),
+ Subsignal("lpbk", Pins("C17", dir="o"), Attrs(PULLDOWN="TRUE")),
+ Subsignal("comma", Pins("C18", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ Resource("eth_rtbi", 0,
+ Subsignal("rst", PinsN("G13", dir="o")),
+ Subsignal("int", PinsN("L16", dir="o")),
+ Subsignal("mdio", Pins("N17", dir="io")),
+ Subsignal("mdc", Pins("F16", dir="o")), # Max 8.3MHz
+ Subsignal("tx_clk", Pins("L12", dir="o")),
+ Subsignal("tx_data", Pins("H16 H13 K14 K13 H15", dir="o")),
+ Subsignal("rx_clk", Pins("K15", dir="i")),
+ Subsignal("rx_data", Pins("G16 H14 E16 F15 F17", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ Resource("hdmi", 0, # J1, input only due to on board buffer, HDMI A connector
+ Subsignal("scl", Pins("C13"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("sda", Pins("A13"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("clk", DiffPairs("D11", "C11", dir="i")),
+ Subsignal("d", DiffPairs("G9 B11 B12", "F9 A11 A12", dir="i")),
+ Attrs(IOSTANDARD="TMDS_33"),
+ ),
+ Resource("hdmi", 1, # J2, output only due to on board buffer, HDMI A connector
+ Subsignal("scl", Pins("D9"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("sda", Pins("C9"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("clk", DiffPairs("B6", "A6", dir="o")),
+ Subsignal("d", DiffPairs("D8 C7 B8", "C8 A7 A8", dir="o")),
+ Attrs(IOSTANDARD="TMDS_33"),
+ ),
+ Resource("hdmi", 2, # J3, input only due to on board buffer, HDMI A connector
+ Subsignal("scl", Pins("M16"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("sda", Pins("M18"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("clk", DiffPairs("H17", "H18", dir="i")),
+ Subsignal("d", DiffPairs("K17 L17 J16", "K18 L18 J18", dir="i")),
+ Attrs(IOSTANDARD="TMDS_33"),
+ ),
+ Resource("hdmi", 3, # JA, input/output as it is unbuffered, HDMI D connector
+ Subsignal("scl", Pins("C13"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("sda", Pins("A13"), Attrs(IOSTANDARD="I2C")),
+ Subsignal("clk", DiffPairs("T9", "V9")),
+ Subsignal("d", DiffPairs("R3 T4 N5", "T3 V4 P6")),
+ Attrs(IOSTANDARD="TMDS_33"),
+ ),
+
+ Resource("ac97", 0,
+ Subsignal("clk", Pins("L13", dir="o")),
+ Subsignal("sync", Pins("U17", dir="o")),
+ Subsignal("reset", Pins("T17", dir="o")),
+ Subsignal("sdo", Pins("N18", dir="o")),
+ Subsignal("sdi", Pins("T18", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ ]
+ connectors = [
+ Connector("pmod", 0, "T3 R3 P6 N5 - - V9 T9 V4 T4 - -"), # JB
+
+ Connector("vhdci", 0, # JC
+ "U16 - U15 U13 - M11 R11 - T12 N10 - M10 U11 - R10 - - - - U10 - R8 M8 - U8 U7 - N7 T6 - R7 N6 - U5 "
+ "V16 - V15 V13 - N11 T11 - V12 P11 - N9 V11 - T10 - - - - V10 - T8 N8 - V8 V7 - P8 V6 - T7 P7 - V5 "
+ ),
+ ]
+
+ def toolchain_program(self, products, name):
+ with products.extract("{}.bit".format(name)) as bitfile:
+ cmd = textwrap.dedent("""
+ setMode -bscan
+ setCable -port auto
+ addDevice -p 1 -file "{}"
+ program -p 1
+ exit
+ """).format(bitfile).encode('utf-8')
+ subprocess.run(["impact", "-batch"], input=cmd, check=True)
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ AtlysPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/blackice.py b/amaranth_boards/blackice.py
new file mode 100644
index 0000000..1e2db73
--- /dev/null
+++ b/amaranth_boards/blackice.py
@@ -0,0 +1,61 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["BlackIcePlatform"]
+
+
+class BlackIcePlatform(LatticeICE40Platform):
+ device = "iCE40HX4K"
+ package = "TQ144"
+ default_clk = "clk100"
+ resources = [
+ Resource("clk100", 0, Pins("129", dir="i"),
+ Clock(100e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(pins="71 67 68 70", attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ # Semantic aliases
+ Resource("led_b", 0, Pins("71", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 0, Pins("67", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_o", 0, Pins("68", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_r", 0, Pins("70", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *ButtonResources(pins="63 64", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ *SwitchResources(pins="37 38 39 41", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ UARTResource(0,
+ rx="88", tx="85",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1),
+ role="dce"
+ ),
+
+ SRAMResource(0,
+ cs_n="136", oe_n="45", we_n="120",
+ a="137 138 139 141 142 42 43 44 73 74 75 76 115 116 117 118 119 78",
+ d="135 134 130 128 125 124 122 121 61 60 56 55 52 49 48 47",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS"),
+ ),
+ ]
+ connectors = [
+ Connector("pmod", 0, " 94 91 88 85 - - 95 93 90 87 - -"), # PMOD1/2
+ Connector("pmod", 1, "105 102 99 97 - - 104 101 98 96 - -"), # PMOD3/4
+ Connector("pmod", 2, "143 114 112 107 - - 144 113 110 106 - -"), # PMOD5/6
+ Connector("pmod", 3, " 10 9 2 1 - - 8 7 4 3 - -"), # PMOD7/8
+ Connector("pmod", 4, " 20 19 16 15 - - 18 17 12 11 - -"), # PMOD9/10
+ Connector("pmod", 5, " 34 33 22 21 - - 32 31 26 25 - -"), # PMOD11/12
+ Connector("pmod", 6, " 29 28 24 23 - -"), # PMOD13
+ Connector("pmod", 7, " 71 67 68 70 - -"), # PMOD14
+ ]
+
+ def toolchain_program(self, products, name):
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call(["cp", bitstream_filename, "/dev/ttyACM0"])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ BlackIcePlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/blackice_ii.py b/amaranth_boards/blackice_ii.py
new file mode 100644
index 0000000..99fd1e7
--- /dev/null
+++ b/amaranth_boards/blackice_ii.py
@@ -0,0 +1,63 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["BlackIceIIPlatform"]
+
+
+class BlackIceIIPlatform(LatticeICE40Platform):
+ device = "iCE40HX4K"
+ package = "TQ144"
+ default_clk = "clk100"
+ resources = [
+ Resource("clk100", 0, Pins("129", dir="i"),
+ Clock(100e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")
+ ),
+
+ *LEDResources(pins="71 67 68 70", attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ # Color aliases
+ Resource("led_b", 0, Pins("71", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 0, Pins("67", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_o", 0, Pins("68", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_r", 0, Pins("70", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *ButtonResources(pins="63 64", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ *SwitchResources(pins="37 38 39 41", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ UARTResource(0,
+ rx="88", tx="85", rts="91", cts="94",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1),
+ role="dce"
+ ),
+
+ SRAMResource(0,
+ cs_n="136", oe_n="29", we_n="120",
+ a="137 138 139 141 142 42 43 44 73 74 75 76 115 116 117 118 119 78",
+ d="136 135 134 130 125 124 122 121 62 61 60 56 55 48 47 45",
+ dm_n="24 28",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS"),
+ ),
+ ]
+ connectors = [
+ Connector("pmod", 0, " 94 91 88 85 - - 95 93 90 87 - -"), # PMOD1/2
+ Connector("pmod", 1, "105 102 99 97 - - 104 101 98 96 - -"), # PMOD3/4
+ Connector("pmod", 2, "143 114 112 107 - - 144 113 110 106 - -"), # PMOD5/6
+ Connector("pmod", 3, " 10 9 2 1 - - 8 7 4 3 - -"), # PMOD7/8
+ Connector("pmod", 4, " 20 19 16 15 - - 18 17 12 11 - -"), # PMOD9/10
+ Connector("pmod", 5, " 34 33 22 21 - - 32 31 26 25 - -"), # PMOD11/12
+ Connector("pmod", 6, " 37 38 39 41 - -"), # PMOD13
+ Connector("pmod", 7, " 71 67 68 70 - -"), # PMOD14
+ ]
+
+ def toolchain_program(self, products, name):
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call(["cp", bitstream_filename, "/dev/ttyACM0"])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ BlackIceIIPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/chameleon96.py b/amaranth_boards/chameleon96.py
new file mode 100644
index 0000000..412e7ed
--- /dev/null
+++ b/amaranth_boards/chameleon96.py
@@ -0,0 +1,105 @@
+import os
+import subprocess
+
+from amaranth import *
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["Chameleon96Platform"]
+
+
+class Chameleon96Platform(IntelPlatform):
+ device = "5CSEBA6" # Cyclone V SE 110K LEs
+ package = "U19" # UBGA-484
+ speed = "I7"
+ default_clk = "cyclonev_oscillator"
+ resources = [
+ # WIFI and BT LEDs
+ *LEDResources(
+ pins="Y19 Y20",
+ attrs=Attrs(io_standard="2.5 V")),
+
+ # TDA19988 HDMI transmitter
+ Resource("tda19988", 0,
+ Subsignal("vpa", Pins(" W8 W7 V6 V5 U6 ", dir="o")), # bits 3 to 7
+ Subsignal("vpb", Pins("AB5 AA5 AA8 AB8 AB9 Y11", dir="o")), # bits 2 to 7
+ Subsignal("vpc", Pins(" W6 Y5 AB7 AA7 AA6", dir="o")), # bits 3 to 7
+ Subsignal("pclk", Pins("AB10", dir="o")),
+ Subsignal("hsync", Pins("V10 ", dir="o")),
+ Subsignal("vsync", Pins("V7 ", dir="o")),
+ Subsignal("de", Pins("Y8 ", dir="o")),
+ Attrs(io_standard="1.8 V")
+ ),
+
+ I2CResource("tda19988_i2c", 0,
+ scl="U7", sda="U10",
+ attrs=Attrs(io_standard="1.8 V"),
+ ),
+
+ Resource("tda19988_i2s", 0,
+ Subsignal("mclk", Pins("V11 ", dir="o")), # OSC_IN/AP3
+ Subsignal("txd", Pins("AA11", dir="o")), # AP1
+ Subsignal("txc", Pins("W11 ", dir="o")), # ACLK
+ Subsignal("txfs", Pins("V9 ", dir="o")), # AP0
+ Attrs(io_standard="1.8 V")
+ ),
+
+ # Wifi and BT module
+ *SDCardResources("wifi", 0,
+ clk="AB20", cmd="AB18", dat0="Y14", dat1="AB19", dat2="AA18", dat3="AB15",
+ attrs=Attrs(io_standard="1.8 V"),
+ ),
+
+ Resource("bt", 0,
+ Subsignal("host_wake", Pins("AB12", dir="o")),
+ Attrs(io_standard="1.8 V"),
+ ),
+
+ Resource("bt_i2s", 0,
+ Subsignal("txd", Pins("Y15 ", dir="o")), # BT_PCM_IN
+ Subsignal("rxd", Pins("Y16 ", dir="i")), # BT_PCM_OUT
+ Subsignal("txc", Pins("AA13", dir="i")), # BT_PCM_CLK
+ Subsignal("txfs", Pins("AB13", dir="i")), # BT_PCM_SYNC
+ Attrs(io_standard="1.8 V"),
+ ),
+
+ UARTResource("bt_uart", 0,
+ rx="AB14", cts="AB17", tx="AA15", rts="AA16", role="dte",
+ attrs=Attrs(io_standard="1.8 V"),
+ ),
+ ]
+
+ connectors = [
+ # J3, 2x20 expansion port
+ Connector("J", 3,
+ "- - Y13 - W14 - C5 - C6 -"
+ "- - - - - E5 - F5 - A6"
+ "- A5 - - - - - - - -"
+ "- - - - - - - - - -"
+ ),
+
+ # J8, 2x30 high speed expansion port (MIPI CSI)
+ Connector("J", 8,
+ "- V16 - U17 - - - V17 - W18"
+ "- - - U18 W12 V19 - - - -"
+ "- - - - - - - - - -"
+ "- - - - - - - - - -"
+ "- - - - - - - - - -"
+ "- - - - - - - - - -"
+ ),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ # The @2 selects the second device in the JTAG chain, because this chip
+ # puts the ARM cores first.
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename + "@2"])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ Chameleon96Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/colorlight_5a75b_r7_0.py b/amaranth_boards/colorlight_5a75b_r7_0.py
new file mode 100644
index 0000000..5ade245
--- /dev/null
+++ b/amaranth_boards/colorlight_5a75b_r7_0.py
@@ -0,0 +1,114 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = ["Colorlight_5A75B_R70Platform"]
+
+
+class Colorlight_5A75B_R70Platform(LatticeECP5Platform):
+ device = "LFE5U-25F"
+ package = "BG256"
+ speed = "6"
+ default_clk = "clk25"
+
+ resources = [
+ Resource("clk25", 0, Pins("P6", dir="i"), Clock(25e6), Attrs(IO_TYPE="LVCMOS33")),
+
+ *LEDResources(pins="P11", invert = True,
+ attrs=Attrs(IO_TYPE="LVCMOS33", DRIVE="4")),
+
+ *ButtonResources(pins="M13", invert = True,
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")),
+
+ UARTResource(0,
+ tx="P11", # led (J19 DATA_LED-)
+ rx="M13", # btn (J19 KEY+)
+ attrs=Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ # SPIFlash (W25Q32JV) 1x/2x/4x speed
+ Resource("spi_flash", 0,
+ Subsignal("cs", PinsN("N8", dir="o")),
+ # Subsignal("clk", Pins("", dir="i")), # driven through USRMCLK
+ Subsignal("cipo", Pins("T8", dir="i")), # Chip: DI/IO0
+ Subsignal("copi", Pins("T7", dir="o")), # DO/IO1
+ # Subsignal("wp", PinsN("unknown", dir="o")), # IO2 Todo
+ # Subsignal("hold", PinsN("unknown", dir="o")), # IO3 Todo
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ # 2x ESMT M12L16161A-5T 1M x 16bit 200MHz SDRAMs (organized as 1M x 32bit)
+ # 2x WinBond W9816G6JH-6 1M x 16bit 166MHz SDRAMs (organized as 1M x 32bit) are lso reported
+ SDRAMResource(0,
+ clk="C6", we_n="C7", cas_n="E7", ras_n="D7",
+ ba="A7", a="A9 E10 B12 D13 C12 D11 D10 E9 D9 B7 C8",
+ dq="B13 C11 C10 A11 C9 E8 B6 B9 A6 B5 A5 B4 B3 C3 A2 B2 "
+ "E2 D3 A4 E4 D4 C4 E5 D5 E6 D6 D8 A8 B8 B10 B11 E11",
+ attrs=Attrs(PULLMODE="NONE", DRIVE="4", SLEWRATE="FAST", IO_TYPE="LVCMOS33")
+ ),
+
+ # Broadcom B50612D Gigabit Ethernet Transceiver
+ Resource("eth_rgmii", 0,
+ Subsignal("rst", PinsN("P5", dir="o")),
+ Subsignal("mdc", Pins("P3", dir="o")),
+ Subsignal("mdio", Pins("T2", dir="io")),
+ Subsignal("tx_clk", Pins("M2", dir="o")),
+ Subsignal("tx_ctl", Pins("M3", dir="o")),
+ Subsignal("tx_data", Pins("L1 L3 P2 L4", dir="o")),
+ Subsignal("rx_clk", Pins("M1", dir="i")),
+ Subsignal("rx_ctl", Pins("N6", dir="i")),
+ Subsignal("rx_data", Pins("N1 M5 N5 M6", dir="i")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ # Broadcom B50612D Gigabit Ethernet Transceiver
+ Resource("eth_rgmii", 1,
+ Subsignal("rst", PinsN("P5", dir="o")),
+ Subsignal("mdc", Pins("P3", dir="o")),
+ Subsignal("mdio", Pins("T2", dir="io")),
+ Subsignal("tx_clk", Pins("M12", dir="o")),
+ Subsignal("tx_ctl", Pins("R15", dir="o")),
+ Subsignal("tx_data", Pins("T14 R12 R13 R14", dir="o")),
+ Subsignal("rx_clk", Pins("M16", dir="i")),
+ Subsignal("rx_ctl", Pins("L15", dir="i")),
+ Subsignal("rx_data", Pins("P13 N13 P14 M15", dir="i")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ ]
+ connectors = [
+ Connector("j", 1, "F3 F1 G3 - G2 H3 H5 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 2, "J4 K3 G1 - K4 C2 E3 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 3, "H4 K5 P1 - R1 L5 F2 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 4, "P4 R2 M8 - M9 T6 R6 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 5, "M11 N11 P12 - K15 N12 L16 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 6, "K16 J15 J16 - J12 H15 G16 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 7, "H13 J13 H12 - G14 H14 G15 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 8, "A15 F16 A14 - E13 B14 A13 F15 L2 K1 J5 K2 B16 J14 F12 -"),
+ Connector("j", 19, " - M13 - - P11"),
+ ]
+
+ @property
+ def required_tools(self):
+ return super().required_tools + [
+ "openFPGALoader"
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = dict(ecppack_opts="--compress")
+ overrides.update(kwargs)
+ return super().toolchain_prepare(fragment, name, **overrides)
+
+ def toolchain_program(self, products, name):
+ tool = os.environ.get("OPENFPGALOADER", "openFPGALoader")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([tool, "-c", "ft232", "-m", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ Colorlight_5A75B_R70Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/de0.py b/amaranth_boards/de0.py
new file mode 100644
index 0000000..c10cce3
--- /dev/null
+++ b/amaranth_boards/de0.py
@@ -0,0 +1,111 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["DE0Platform"]
+
+
+class DE0Platform(IntelPlatform):
+ device = "EP3C16" # Cyclone III 15K LEs
+ package = "F484" # FBGA-484
+ speed = "C6"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("G21", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 1, Pins("B12", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+
+ *LEDResources(
+ pins="J1 J2 J3 H1 F2 E1 C1 C2 B2 B1",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *ButtonResources(
+ pins="H2 G3 F1", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *SwitchResources(
+ pins="J6 H5 H6 G4 G5 J7 H7 E3 E4 D2",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(0,
+ a="E11", b="F11", c="H12", d="H13", e="G12", f="F12", g="F13", dp="D13", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(1,
+ a="A13", b="B13", c="C13", d="A14", e="B14", f="E14", g="A15", dp="B15", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(2,
+ a="D15", b="A16", c="B16", d="E15", e="A17", f="B17", g="F14", dp="A18", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(3,
+ a="B18", b="F15", c="A19", d="B19", e="C19", f="D19", g="G15", dp="G16", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ UARTResource(0,
+ rx="U22", tx="U21", rts="V22", cts="V21",
+ attrs=Attrs(io_standard="3.3-V LVTTL"),
+ role="dce"),
+
+ Resource("display_hd44780", 0,
+ Subsignal("e", Pins("E21", dir="o")),
+ Subsignal("d", Pins("D22 D21 C22 C21 B22 B21 D20 C20", dir="io")),
+ Subsignal("rw", Pins("E22", dir="o")),
+ Subsignal("rs", Pins("F22", dir="o")),
+ # Backlight
+ Subsignal("bl", Pins("F21", dir="o")),
+ Attrs(io_standard="3.3-V LVTTL")
+ ),
+
+ VGAResource(0,
+ r="H19 H17 H20 H21",
+ g="H22 J17 K17 J21",
+ b="K22 K21 J22 K18",
+ hs="L21", vs="L22",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ PS2Resource(0, # Keyboard
+ clk="P22", dat="P21", attrs=Attrs(io_standard="3.3-V LVTTL")),
+ PS2Resource(1, # Mouse
+ clk="R21", dat="R22", attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ *SDCardResources(0,
+ clk="Y21", cmd="Y22", dat0="AA22", dat3="W21", wp_n="W20",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ SDRAMResource(0,
+ clk="E5", cke="E6", cs_n="G7", we_n="D6", ras_n="F7", cas_n="G8",
+ ba="B5 A4", a="C4 A3 B3 C3 A5 C6 B6 A6 C7 B7 B4 A7 C8",
+ dq="D10 G10 H10 E9 F9 G9 H9 F8 A8 B9 A9 C10 B10 A10 E10 F10", dqm="E7 B8",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ *NORFlashResources(0,
+ rst="R1", byte_n="AA1",
+ cs_n="N8", oe_n="R6", we_n="P4", wp_n="T3", by="M7",
+ a="P7 P5 P6 N7 N5 N6 M8 M4 P2 N2 N1 M3 M2 M1 L7 L6 AA2 M5 M6 P1 P3 R2",
+ dq="R7 P8 R8 U1 V2 V3 W1 Y1 T5 T7 T4 U2 V1 V4 W2 Y2",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ ]
+ connectors = [
+ Connector("j", 4,
+ "AB12 AB16 AA12 AA16 AA15 AB15 AA14 AB14 AB13 AA13 - - "
+ "AB10 AA10 AB8 AA8 AB5 AA5 AB3 AB4 AA3 AA4 V14 U14 "
+ "Y13 W13 U13 V12 - - R10 V11 Y10 W10 T8 V8 "
+ "W7 W6 V5 U7 "),
+ Connector("j", 5,
+ "AB11 AA20 AA11 AB20 AA19 AB19 AB18 AA18 AA17 AB17 - - "
+ "Y17 W17 U15 T15 W15 V15 R16 AB9 T16 AA9 AA7 AB7 "
+ "T14 R14 U12 T12 - - R11 R12 U10 T10 U9 T9 "
+ "Y7 U8 V6 V7 "),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ DE0Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/de0_cv.py b/amaranth_boards/de0_cv.py
new file mode 100644
index 0000000..adc607f
--- /dev/null
+++ b/amaranth_boards/de0_cv.py
@@ -0,0 +1,99 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["DE0CVPlatform"]
+
+
+class DE0CVPlatform(IntelPlatform):
+ device = "5CEBA4" # Cyclone V 49K LEs
+ package = "F23" # FBGA-484
+ speed = "C7"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("M9", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 1, Pins("H13", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 2, Pins("E10", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 3, Pins("V15", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+
+ *LEDResources(
+ pins="AA2 AA1 W2 Y3 N2 N1 U2 U1 L2 L1", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *ButtonResources(
+ pins="U7 W9 M7 M6", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *SwitchResources(
+ pins="U13 V13 T13 T12 AA15 AB15 AA14 AA13 AB13 AB12",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(0,
+ a="U21", b="V21", c="W22", d="W21", e="Y22", f="Y21", g="AA22", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(1,
+ a="AA20", b="AB20", c="AA19", d="AA18", e="AB18", f="AA17", g="U22", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(2,
+ a="Y19", b="AB17", c="AA10", d="Y14", e="V14", f="AB22", g="AB21", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(3,
+ a="Y16", b="W16", c="Y17", d="V16", e="U17", f="V18", g="V19", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(4,
+ a="U20", b="Y20", c="V20", d="U16", e="U15", f="Y15", g="P9", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(5,
+ a="N9", b="M8", c="T14", d="P14", e="C1", f="C2", g="W19", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ VGAResource(0,
+ r="A9 B10 C9 A5",
+ g="L7 K7 J7 J8",
+ b="B6 B7 A8 A7",
+ hs="H8", vs="G8",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ PS2Resource(0, # Keyboard
+ clk="D3", dat="G2", attrs=Attrs(io_standard="3.3-V LVTTL")),
+ PS2Resource(1, # Mouse
+ clk="E2", dat="G1", attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ *SDCardResources(0,
+ clk="H11", cmd="B11", dat0="K9", dat1="D12", dat2="E12", dat3="C11",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ SDRAMResource(0,
+ clk="AB11", cke="R6", cs_n="U6", we_n="AB5", ras_n="AB6", cas_n="V6",
+ ba="T7 AB7", a="W8 T8 U11 Y10 N6 AB10 P12 P7 P8 R5 U8 P6 R7",
+ dq="Y9 T10 R9 Y11 R10 R11 R12 AA12 AA9 AB8 AA8 AA7 V10 V9 U10 T9", dqm="U12 N8",
+ attrs=Attrs(io_standard="3.3-V LVCMOS")),
+ ]
+ connectors = [
+ Connector("j", 1,
+ "N16 B16 M16 C16 D17 K20 K21 K22 M20 M21 "
+ "- - N21 R22 R21 T22 N20 N19 M22 P19 "
+ "L22 P17 P16 M18 L18 L17 L19 K17 - - "
+ "K19 P18 R15 R17 R16 T20 T19 T18 T17 T15 "),
+ Connector("j", 2,
+ "H16 A12 H15 B12 A13 B13 C13 D13 G18 G17 "
+ "- - H18 J18 J19 G11 H10 J11 H14 A15 "
+ "J13 L8 A14 B15 C15 E14 E15 E16 - - "
+ "F14 F15 F13 F12 G16 G15 G13 G12 J17 K16 "),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ DE0CVPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/de10_lite.py b/amaranth_boards/de10_lite.py
new file mode 100644
index 0000000..de9ea84
--- /dev/null
+++ b/amaranth_boards/de10_lite.py
@@ -0,0 +1,89 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["DE10LitePlatform"]
+
+
+class DE10LitePlatform(IntelPlatform):
+ device = "10M50DA" # MAX10
+ package = "F484" # FBGA-484
+ speed = "C7"
+ suffix = "G"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk10", 0, Pins("N5", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 0, Pins("P11", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 1, Pins("N14", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+
+ *LEDResources(
+ pins="A8 A9 A10 B10 D13 C13 E14 D14 A11 B11",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *ButtonResources(
+ pins="B8 A7", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *SwitchResources(
+ pins="C10 C11 D12 C12 A12 B12 A13 A14 B14 F15",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(0,
+ a="C14", b="E15", c="C15", d="C16", e="E16", f="D17", g="C17", dp="D15", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(1,
+ a="C18", b="D18", c="E18", d="B16", e="A17", f="A18", g="B17", dp="A16", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(2,
+ a="B20", b="A20", c="B19", d="A21", e="B21", f="C22", g="B22", dp="A19", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(3,
+ a="F21", b="E22", c="E21", d="C19", e="C20", f="D19", g="E17", dp="D22", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(4,
+ a="F18", b="E20", c="E19", d="J18", e="H19", f="F19", g="F20", dp="F17", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(5,
+ a="J20", b="K20", c="L18", d="N18", e="M20", f="N19", g="N20", dp="L19", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # Arduino header
+ UARTResource(0,
+ rx="V10", tx="W10",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ SDRAMResource(0,
+ clk="L14", cs_n="U20", we_n="V20", ras_n="U22", cas_n="U21",
+ ba="T21 T22", a="U17 W19 V18 U18 U19 T18 T19 R18 P18 P19 T20 P20 R20",
+ dq="Y21 Y20 AA22 AA21 Y22 W22 W20 V21 P21 J22 H21 H22 G22 G20 G19 F22",
+ dqm="V22 J21", attrs=Attrs(io_standard="3.3-V LVCMOS")),
+
+ VGAResource(0,
+ r="AA1 V1 Y2 Y1",
+ g="W1 T2 R2 R1",
+ b="P1 T1 P4 N2",
+ hs="N3", vs="N1",
+ attrs=Attrs(io_standard="3.3-V LVTTL"))
+ ]
+ connectors = [
+ Connector("gpio", 0,
+ "V10 W10 V9 W9 V8 W8 V7 W7 W6 V5 W5 AA15 AA14 W13 W12 AB13 AB12 Y11 AB11 W11 AB10 "
+ "AA10 AA9 Y8 AA8 Y7 AA7 Y6 AA6 Y5 AA5 Y4 AB3 Y3 AB2 AA2"),
+ Connector("gpio", 5,
+ "AB5 AB6 AB7 AB8 AB9 Y10 AA11 AA12 AB17 AA17 AB19 AA19 Y19 AB20 AB21 AA20 F16"),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ DE10LitePlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/de10_nano.py b/amaranth_boards/de10_nano.py
new file mode 100644
index 0000000..1129813
--- /dev/null
+++ b/amaranth_boards/de10_nano.py
@@ -0,0 +1,95 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["DE10NanoPlatform"]
+
+
+# The MiSTer platform is built around the DE10-Nano; if you update one you should update the other.
+class DE10NanoPlatform(IntelPlatform):
+ device = "5CSEBA6" # Cyclone V 110K LEs
+ package = "U23" # UBGA-484
+ speed = "I7"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("V11", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 1, Pins("Y13", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 2, Pins("E11", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+
+ *LEDResources(
+ pins="W15 AA24 V16 V15 AF26 AE26 Y16 AA23",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *ButtonResources(
+ pins="AH17 AH16", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *SwitchResources(
+ pins="Y24 W24 W21 W20",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # Arduino header
+ UARTResource(0,
+ rx="AG13", tx="AF13",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # LTC2308 analogue-to-digital converter
+ SPIResource(0,
+ cs_n="U9", clk="V10", copi="AC4", cipo="AD4",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # ADV7513 HDMI transmitter
+ # Note this has a lot of input formats for tx_d, but this defaults to RGB24
+ Resource("adv7513", 0,
+ Subsignal("tx_d_r", Pins("AD12 AE12 W8 Y8 AD11 AD10 AE11 Y5", dir="o")),
+ Subsignal("tx_d_g", Pins("AF10 Y4 AE9 AB4 AE7 AF6 AF8 AF5", dir="o")),
+ Subsignal("tx_d_b", Pins("AE4 AH2 AH4 AH5 AH6 AG6 AF9 AE8", dir="o")),
+ Subsignal("tx_clk", Pins("AG5", dir="o")),
+ Subsignal("tx_de", Pins("AD19", dir="o")),
+ Subsignal("tx_hs", Pins("T8", dir="o")),
+ Subsignal("tx_vs", Pins("V13", dir="o")),
+ Subsignal("tx_int", Pins("AF11", dir="i")),
+ Subsignal("i2s0", Pins("T13", dir="o")),
+ Subsignal("mclk", Pins("U11", dir="o")),
+ Subsignal("lrclk", Pins("T11", dir="o")),
+ Subsignal("sclk", Pins("T12", dir="o")),
+ Subsignal("scl", Pins("U10", dir="o")),
+ Subsignal("sda", Pins("AA4", dir="io")),
+ Attrs(io_standard="3.3-V LVTTL")),
+ ]
+ connectors = [
+ # Located on the top of the board, above the chip.
+ Connector("gpio", 0,
+ "V12 E8 W12 D11 D8 AH13 AF7 AH14 AF4 AH3 "
+ "- - AD5 AG14 AE23 AE6 AD23 AE24 D12 AD20 "
+ "C12 AD17 AC23 AC22 Y19 AB23 AA19 W11 - - "
+ "AA18 W14 Y18 Y17 AB25 AB26 Y11 AA26 AA13 AA11 "),
+ # Located on the bottom of the board.
+ Connector("gpio", 1,
+ "Y15 AC24 AA15 AD26 AG28 AF28 AE25 AF27 AG26 AH27 "
+ "- - AG25 AH26 AH24 AF25 AG23 AF23 AG24 AH22 "
+ "AH21 AG21 AH23 AA20 AF22 AE22 AG20 AF21 - - "
+ "AG19 AH19 AG18 AH18 AF18 AF20 AG15 AE20 AE19 AE17 "),
+ Connector("arduino", 0,
+ "AG13 AF13 AG10 AG9 U14 U13 AG8 AH8 "
+ "AF17 AE15 AF15 AG16 AH11 AH12 AH9 AG11 "
+ "AH7"),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ # The @2 selects the second device in the JTAG chain, because this chip
+ # puts the ARM cores first.
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename + "@2"])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ DE10NanoPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/de1_soc.py b/amaranth_boards/de1_soc.py
new file mode 100644
index 0000000..8df8c46
--- /dev/null
+++ b/amaranth_boards/de1_soc.py
@@ -0,0 +1,87 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["DE1SoCPlatform"]
+
+
+class DE1SoCPlatform(IntelPlatform):
+ device = "5CSEMA5" # Cyclone V 85K LEs
+ package = "F31" # FBGA-896
+ speed = "C6"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("AF14", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 1, Pins("AA16", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 2, Pins("Y26", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 3, Pins("K14", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+
+ *LEDResources(
+ pins="V16 W16 V17 V18 W17 W19 Y19 W20 W21 Y21",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *ButtonResources(
+ pins="AA14 AA15 W15 Y16", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *SwitchResources(
+ pins="AB12 AC12 AF9 AF10 AD11 AD12 AE11 AC9 AD10 AE12",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(0,
+ a="AE26", b="AE27", c="AE28", d="AG27", e="AF28",
+ f="AG28", g="AH28", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(1,
+ a="AJ29", b="AH29", c="AH30", d="AG30", e="AF29",
+ f="AF30", g="AD27", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(2,
+ a="AB23", b="AE29", c="AD29", d="AC28", e="AD30",
+ f="AC29", g="AC30", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(3,
+ a="AD26", b="AC27", c="AD25", d="AC25", e="AB28",
+ f="AB25", g="AB22", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(4,
+ a="AA24", b="Y23", c="Y24", d="W22", e="W24",
+ f="V23", g="W25", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ Display7SegResource(5,
+ a="V25", b="AA28", c="Y27", d="AB27", e="AB26",
+ f="AA26", g="AA25", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ ]
+ connectors = [
+ # Located on the right hand side of the board
+ Connector("gpio", 0,
+ "AC18 Y17 AD17 Y18 AK16 AK18 AK19 AJ19 AJ17 AJ16 "
+ " - - AH18 AH17 AG16 AE16 AF16 AG17 AA18 AA19 "
+ "AE17 AC20 AH19 AJ20 AH20 AK21 AD19 AD20 - - "
+ "AE18 AE19 AF20 AF21 AF19 AG21 AF18 AG20 AG18 AJ21 "),
+
+ Connector("gpio", 1,
+ "AB17 AA21 AB21 AC23 AD24 AE23 AE24 AF25 AF26 AG25 "
+ "- - AG26 AH24 AH27 AJ27 AK29 AK28 AK27 AJ26 "
+ "AK26 AH25 AJ25 AJ24 AK24 AG23 AK23 AH23 - - "
+ "AK22 AJ22 AH22 AG22 AF24 AF23 AE22 AD21 AA20 AC22 "),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ # The @2 selects the second device in the JTAG chain, because this chip
+ # puts the ARM cores first.
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename + "@2"])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ DE1SoCPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/ebaz4205.py b/amaranth_boards/ebaz4205.py
new file mode 100644
index 0000000..eb4a692
--- /dev/null
+++ b/amaranth_boards/ebaz4205.py
@@ -0,0 +1,40 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["EBAZ4205Platform"]
+
+
+class EBAZ4205Platform(Xilinx7SeriesPlatform):
+ device = "xc7z010"
+ package = "clg400"
+ speed = "1"
+ default_clk = "clk33_333"
+ resources = [
+ Resource("clk33_333", 0,
+ Pins("N18", dir="i"), Clock(33.333e6), Attrs(IOSTANDARD="LVCMOS33")),
+
+ *LEDResources(
+ pins="W14 W13",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ UARTResource(0,
+ rx="B19", tx="B20",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ ]
+ connectors = [
+ ]
+
+ def toolchain_program(self, products, name, **kwargs):
+ xc3sprog = os.environ.get("XC3SPROG", "xc3sprog")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.run([xc3sprog, "-c", "jtaghs1_fast", "-p", "1", bitstream_filename], check=True)
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ EBAZ4205Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/ecp5_5g_evn.py b/amaranth_boards/ecp5_5g_evn.py
new file mode 100644
index 0000000..3eb6189
--- /dev/null
+++ b/amaranth_boards/ecp5_5g_evn.py
@@ -0,0 +1,154 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = ["ECP55GEVNPlatform"]
+
+
+class ECP55GEVNPlatform(LatticeECP5Platform):
+ device = "LFE5UM5G-85F"
+ package = "BG381"
+ speed = "8"
+ default_clk = "clk12"
+ default_rst = "rst"
+
+ def __init__(self, *, VCCIO1="2V5", VCCIO6="3V3", **kwargs):
+ """
+ VCCIO1 is connected by default to 2.5 V via R100 (can be set to 3.3 V by disconnecting
+ R100 and connecting R105)
+ VCCIO6 is connected to 3.3 V by default via R99 (can be switched to 2.5 V with R104,
+ see page 51 in the ECP5-5G-EVN datasheet)
+ """
+ super().__init__(**kwargs)
+ assert VCCIO1 in ("3V3", "2V5")
+ assert VCCIO6 in ("3V3", "2V5")
+ self._VCCIO1 = VCCIO1
+ self._VCCIO6 = VCCIO6
+
+ def _vccio_to_iostandard(self, vccio):
+ if vccio == "2V5":
+ return "LVCMOS25"
+ if vccio == "3V3":
+ return "LVCMOS33"
+ assert False
+
+ def bank1_iostandard(self):
+ return self._vccio_to_iostandard(self._VCCIO1)
+
+ def bank6_iostandard(self):
+ return self._vccio_to_iostandard(self._VCCIO6)
+
+ resources = [
+ Resource("rst", 0, PinsN("G2", dir="i"), Attrs(IO_TYPE="LVCMOS33")),
+ Resource("clk12", 0, Pins("A10", dir="i"),
+ Clock(12e6), Attrs(IO_TYPE="LVCMOS33")),
+
+ # By default this CLK is not populated, see User Manual Section 4.
+ Resource("extclk", 0, Pins("B11", dir="i"),
+ Attrs(IO_TYPE="LVCMOS33")),
+
+ *LEDResources(pins="A13 A12 B19 A18 B18 C17 A17 B17", invert=True,
+ attrs=Attrs(IO_TYPE=bank1_iostandard)),
+ *ButtonResources(pins="P4", invert=True,
+ attrs=Attrs(IO_TYPE=bank6_iostandard)),
+ *SwitchResources(pins={1: "J1", 2: "H1", 3: "K1"}, invert=True,
+ attrs=Attrs(IO_TYPE=bank6_iostandard)),
+ *SwitchResources(pins={4: "E15", 5: "D16", 6: "B16", 7: "C16", 8: "A16"}, invert=True,
+ attrs=Attrs(IO_TYPE=bank1_iostandard)),
+
+ # In order to use the UART as a UART you need to swap two resistor jumpers,
+ # and potentially reconfigure the onboard FTDI chip, see section 6.2 in the
+ # User Manual for hardware instructions, and
+ # https://github.com/trabucayre/fixFT2232_ecp5evn to reconfigure the FTDI.
+ UARTResource(0,
+ rx="P2", tx="P3",
+ attrs=Attrs(IO_TYPE=bank6_iostandard, PULLMODE="UP")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="R2", clk="U3", cipo="V2", copi="W2", wp_n="Y2", hold_n="W1",
+ attrs=Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ Resource("serdes", 0,
+ Subsignal("tx", DiffPairs("W4", "W5", dir="o")),
+ Subsignal("rx", DiffPairs("Y5", "Y6", dir="i")),
+ ),
+ Resource("serdes", 1,
+ Subsignal("tx", DiffPairs("W8", "W9", dir="o")),
+ Subsignal("rx", DiffPairs("Y7", "Y8", dir="i")),
+ ),
+ Resource("serdes", 2,
+ Subsignal("tx", DiffPairs("W13", "W14", dir="o")),
+ Subsignal("rx", DiffPairs("Y14", "Y15", dir="i")),
+ ),
+ Resource("serdes", 3,
+ Subsignal("tx", DiffPairs("W17", "W18", dir="o")),
+ Subsignal("rx", DiffPairs("Y16", "Y17", dir="i")),
+ ),
+
+ Resource("serdes_clk", 0, DiffPairs("Y11", "Y12", dir="i")),
+ Resource("serdes_clk", 1, DiffPairs("Y19", "W20", dir="i")), # 200 MHz
+
+ # TODO: add other resources
+ ]
+ connectors = [
+ # Expansion connectors
+ Connector("J", 39, "- - - D15 B15 C15 B13 B20 D11 E11 B12 C12 D12 E12 C13 D13 E13 A14 A9 B10 - - - - - - - - E7 - A11 - A19 - - - - - - -"),
+ Connector("J", 40, "K2 - A15 F1 H2 G1 J4 J5 J3 K3 L4 L5 M4 N5 N4 P5 N3 M3 - - K5 - M5 - L3 - N2 M1 L2 - L1 N1 C14 - P1 E14 D14 - K4 -"),
+ # Arduino
+ Connector("J", 6, "K16 J16 H17 J17 H18 H16 - G18 G16 F17"),
+ Connector("J", 3, "F19 F20 E20 E19 D19 D20 C20 K17"),
+ Connector("J", 7, "C18 - D17 - - - - -"),
+ Connector("J", 4, "F18 E17 E18 D18 F16 E16"),
+ # Raspberry Pi
+ Connector("JP", 8, "- - T17 - U16 - U17 P18 - N20 N19 T16 M18 - N17 P17 - M17 U20 - T19 N18 R20 U19 - R18 L18 L17 U18 - T18 T20 P20 - R17 P19 N16 P16 - R16"),
+ # GPIO
+ Connector("J", 5, "- - H20 G19 - - K18 J18 - - K19 J19 - - K20 J20 - - G20 - - -"), # Contains 4 differential pairs
+ Connector("J", 8, "- - L19 M19 L20 M20 L16 -"),
+ Connector("J", 32, "- - - - A5 A4 - - C5 B5 - - B4 C4 - - B3 A3 - - D5 E4 - - D3 C3 - - E3 F4 - - F5 E5 - - B1 A2 - -"), # Contains 9 differential pairs
+ Connector("J", 33, "- - - - C2 B2 - - D1 C1 - - E1 D2 - - G5 H4 - - H3 H5 - - F3 G3 - - E2 F2 - -"), # Contains 7 differential pairs
+ # Mic
+ Connector("J", 30, "- B6 D9 C9 E9 D10 A6 E10 - -"),
+ # PMOD
+ Connector("J", 31, "C6 C7 E8 D8 - - C8 B8 A7 A8 - -"),
+ # JTAG
+ Connector("J", 1, "- V4 R5 - - U5 - T5"),
+ # Parallel configuration
+ Connector("J", 38, "W3 R2 T3 Y3 R1 V3 T1 V2 U1 W2 V1 T2 W1 U2 Y2 R2 U3 R3 - -"), # Connect pin 2 / R2 with jumper when needed
+ ]
+
+ @property
+ def file_templates(self):
+ return {
+ **super().file_templates,
+ "{{name}}-openocd.cfg": r"""
+ interface ftdi
+ ftdi_device_desc "Lattice ECP5 Evaluation Board"
+ ftdi_vid_pid 0x0403 0x6010
+ ftdi_channel 0
+ ftdi_layout_init 0xfff8 0xfffb
+ reset_config none
+ adapter_khz 25000
+
+ jtag newtap ecp5 tap -irlen 8 -expected-id 0x81113043
+ """
+ }
+
+ def toolchain_program(self, products, name):
+ openocd = os.environ.get("OPENOCD", "openocd")
+ with products.extract("{}-openocd.cfg".format(name), "{}.svf".format(name)) \
+ as (config_filename, vector_filename):
+ subprocess.check_call([openocd,
+ "-f", config_filename,
+ "-c", "transport select jtag; init; svf -quiet {}; exit".format(vector_filename)
+ ])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ECP55GEVNPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/ecpix5.py b/amaranth_boards/ecpix5.py
new file mode 100644
index 0000000..167e244
--- /dev/null
+++ b/amaranth_boards/ecpix5.py
@@ -0,0 +1,232 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = ["ECPIX585Platform", "ECPIX545Platform"]
+
+
+class _ECPIX5Platform(LatticeECP5Platform):
+ package = "BG554"
+ speed = "8"
+ default_clk = "clk100"
+ default_rst = "rst"
+
+ resources = [
+ Resource("rst", 0, PinsN("AB1", dir="i"), Attrs(IO_TYPE="LVCMOS33")),
+ Resource("clk100", 0, Pins("K23", dir="i"), Clock(100e6), Attrs(IO_TYPE="LVCMOS33")),
+
+ RGBLEDResource(0,
+ r="T23", g="R21", b="T22", invert=True,
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+ RGBLEDResource(1,
+ r="U21", g="W21", b="T24", invert=True,
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+ RGBLEDResource(2,
+ r="K21", g="K24", b="M21", invert=True,
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+ RGBLEDResource(3,
+ r="P21", g="R23", b="P22", invert=True,
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+
+ UARTResource(0,
+ rx="R26", tx="R24",
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="AA2", clk="AE3", cipo="AE2", copi="AD2", wp_n="AF2", hold_n="AE1",
+ attrs=Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ Resource("eth_rgmii", 0,
+ Subsignal("rst", PinsN("C13", dir="o")),
+ Subsignal("mdio", Pins("A13", dir="io")),
+ Subsignal("mdc", Pins("C11", dir="o")),
+ Subsignal("tx_clk", Pins("A12", dir="o")),
+ Subsignal("tx_ctrl", Pins("C9", dir="o")),
+ Subsignal("tx_data", Pins("D8 C8 B8 A8", dir="o")),
+ Subsignal("rx_clk", Pins("E11", dir="i")),
+ Subsignal("rx_ctrl", Pins("A11", dir="i")),
+ Subsignal("rx_data", Pins("B11 A10 B10 A9", dir="i")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+ Resource("eth_int", 0, PinsN("B13", dir="i"), Attrs(IO_TYPE="LVCMOS33")),
+
+ Resource("ddr3", 0,
+ Subsignal("clk", DiffPairs("H3", "J3", dir="o"), Attrs(IO_TYPE="SSTL15D_I")),
+ Subsignal("clk_en", Pins("P1", dir="o")),
+ Subsignal("we", PinsN("R3", dir="o")),
+ Subsignal("ras", PinsN("T3", dir="o")),
+ Subsignal("cas", PinsN("P2", dir="o")),
+ Subsignal("a", Pins("T5 M3 L3 V6 K2 W6 K3 L1 H2 L2 N1 J1 M1 K1 H1", dir="o")),
+ Subsignal("ba", Pins("U6 N3 N4", dir="o")),
+ Subsignal("dqs", DiffPairs("V4 V1", "U5 U2", dir="io"),
+ Attrs(IO_TYPE="SSTL15D_I", TERMINATION="OFF", DIFFRESISTOR="100")),
+ Subsignal("dq", Pins("T4 W4 R4 W5 R6 P6 P5 P4 R1 W3 T2 V3 U3 W1 T1 W2", dir="io"),
+ Attrs(TERMINATION="75")),
+ Subsignal("dm", Pins("U4 U1", dir="o")),
+ Subsignal("odt", Pins("P3", dir="o")),
+ Attrs(IO_TYPE="SSTL15_I", SLEWRATE="FAST")
+ ),
+
+ Resource("sata", 0,
+ Subsignal("tx", DiffPairs("AD16", "AD17", dir="o")),
+ Subsignal("rx", DiffPairs("AF15", "AF16", dir="i")),
+ Attrs(IO_TYPE="LVDS")
+ ),
+
+ Resource("ulpi", 0,
+ Subsignal("rst", Pins("E23", dir="o")),
+ Subsignal("clk", Pins("H24", dir="i")),
+ Subsignal("dir", Pins("F22", dir="i")),
+ Subsignal("nxt", Pins("F23", dir="i")),
+ Subsignal("stp", Pins("H23", dir="o")),
+ Subsignal("data", Pins("M26 L25 L26 K25 K26 J23 P25 H25", dir="io")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ Resource("usbc_cfg", 0,
+ Subsignal("scl", Pins("D24", dir="io")),
+ Subsignal("sda", Pins("C24", dir="io")),
+ Subsignal("dir", Pins("B23", dir="i")),
+ Subsignal("id", Pins("D23", dir="i")),
+ Subsignal("int", PinsN("B24", dir="i")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+ Resource("usbc_mux", 0,
+ Subsignal("en", Pins("C23", dir="oe")),
+ Subsignal("amsel", Pins("B26", dir="oe")),
+ Subsignal("pol", Pins("D26", dir="o")),
+ Subsignal("lna", DiffPairs( "AF9", "AF10", dir="i"), Attrs(IO_TYPE="LVCMOS18D")),
+ Subsignal("lnb", DiffPairs("AD10", "AD11", dir="o"), Attrs(IO_TYPE="LVCMOS18D")),
+ Subsignal("lnc", DiffPairs( "AD7", "AD8", dir="o"), Attrs(IO_TYPE="LVCMOS18D")),
+ Subsignal("lnd", DiffPairs( "AF6", "AF7", dir="i"), Attrs(IO_TYPE="LVCMOS18D")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+ ]
+
+ connectors = [
+ Connector("pmod", 0, "T25 U25 U24 V24 - - T26 U26 V26 W26 - -"),
+ Connector("pmod", 1, "U23 V23 U22 V21 - - W25 W24 W23 W22 - -"),
+ Connector("pmod", 2, "J24 H22 E21 D18 - - K22 J21 H21 D22 - -"),
+ Connector("pmod", 3, " E4 F4 E6 H4 - - F3 D4 D5 F5 - -"),
+ Connector("pmod", 4, "E26 D25 F26 F25 - - C26 C25 A25 A24 - -"),
+ Connector("pmod", 5, "D19 C21 B21 C22 - - D21 A21 A22 A23 - -"),
+ Connector("pmod", 6, "C16 B17 C18 B19 - - A17 A18 A19 C19 - -"),
+ Connector("pmod", 7, "D14 B14 E14 B16 - - C14 A14 A15 A16 - -"),
+ ]
+
+ @property
+ def file_templates(self):
+ return {
+ **super().file_templates,
+ "{{name}}-openocd.cfg": r"""
+ interface ftdi
+ ftdi_vid_pid 0x0403 0x6010
+ ftdi_channel 0
+ ftdi_layout_init 0xfff8 0xfffb
+ reset_config none
+ adapter_khz 25000
+
+ {% if "85F" in platform.device -%}
+ jtag newtap ecp5 tap -irlen 8 -expected-id 0x81113043 ; # LF5UM5G-85F
+ {% else -%}
+ jtag newtap ecp5 tap -irlen 8 -expected-id 0x81112043 ; # LF5UM5G-45F
+ {% endif %}
+ """
+ }
+
+ def toolchain_program(self, products, name):
+ openocd = os.environ.get("OPENOCD", "openocd")
+ with products.extract("{}-openocd.cfg".format(name), "{}.svf".format(name)) \
+ as (config_filename, vector_filename):
+ subprocess.check_call([openocd,
+ "-f", config_filename,
+ "-c", "transport select jtag; init; svf -quiet {}; exit".format(vector_filename)
+ ])
+
+
+class ECPIX545Platform(_ECPIX5Platform):
+ device = "LFE5UM5G-45F"
+
+ resources = [
+ *_ECPIX5Platform.resources,
+
+ # The IT6613E HDMI transmitter has access to 8 bits per color channel.
+ Resource("it6613e", 0,
+ Subsignal("rst", PinsN("N6", dir="o")),
+ Subsignal("scl", Pins("C17", dir="io")),
+ Subsignal("sda", Pins("E17", dir="io")),
+ Subsignal("pclk", Pins("C1", dir="o")),
+ Subsignal("vsync", Pins("A4", dir="o")),
+ Subsignal("hsync", Pins("B4", dir="o")),
+ Subsignal("de", Pins("A3", dir="o")),
+ Subsignal("d",
+ Subsignal("b", Pins(" B3 C3 D3 B1 C2 D2 D1 E3", dir="o")),
+ Subsignal("g", Pins(" E1 F2 F1 D17 D16 E16 J6 H6", dir="o")),
+ Subsignal("r", Pins("E10 D11 D10 C10 D9 E8 H5 J4", dir="o")),
+ ),
+ Subsignal("mclk", Pins("E19", dir="o")),
+ Subsignal("sck", Pins("D6", dir="o")),
+ Subsignal("ws", Pins("C6", dir="o")),
+ Subsignal("i2s", Pins("A6 B6 A5 C5", dir="o")),
+ Subsignal("int", PinsN("C4", dir="i")),
+ Attrs(IO_TYPE="LVTTL33")
+ ),
+ ]
+
+
+class ECPIX585Platform(_ECPIX5Platform):
+ device = "LFE5UM5G-85F"
+
+ resources = [
+ *_ECPIX5Platform.resources,
+
+ # The IT6613E HDMI transmitter has access to 12 bits per color channel. The LFE5UM5G-85F
+ # has an additional I/O bank which is used to provide the lower 4 bits of each channel.
+ Resource("it6613e", 0,
+ Subsignal("rst", PinsN("N6", dir="o")),
+ Subsignal("scl", Pins("C17", dir="io")),
+ Subsignal("sda", Pins("E17", dir="io")),
+ Subsignal("pclk", Pins("C1", dir="o")),
+ Subsignal("vsync", Pins("A4", dir="o")),
+ Subsignal("hsync", Pins("B4", dir="o")),
+ Subsignal("de", Pins("A3", dir="o")),
+ Subsignal("d",
+ Subsignal("b", Pins("AD25 AC26 AB24 AB25 B3 C3 D3 B1 C2 D2 D1 E3", dir="o")),
+ Subsignal("g", Pins("AA23 AA22 AA24 AA25 E1 F2 F1 D17 D16 E16 J6 H6", dir="o")),
+ Subsignal("r", Pins("AD26 AE25 AF25 AE26 E10 D11 D10 C10 D9 E8 H5 J4", dir="o")),
+ ),
+ Subsignal("mclk", Pins("E19", dir="o")),
+ Subsignal("sck", Pins("D6", dir="o")),
+ Subsignal("ws", Pins("C6", dir="o")),
+ Subsignal("i2s", Pins("A6 B6 A5 C5", dir="o")),
+ Subsignal("int", PinsN("C4", dir="i")),
+ Attrs(IO_TYPE="LVTTL33")
+ ),
+ ]
+
+
+if __name__ == "__main__":
+ import argparse
+ from .test.blinky import Blinky
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--variant", choices=("85", "45"), default="85",
+ help="platform variant (default: %(default)s)")
+
+ args = parser.parse_args()
+ if args.variant == "85":
+ platform = ECPIX585Platform()
+ else:
+ platform = ECPIX545Platform()
+
+ platform.build(Blinky(), do_program=True)
diff --git a/amaranth_boards/extensions/__init__.py b/amaranth_boards/extensions/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/amaranth_boards/extensions/__init__.py
diff --git a/amaranth_boards/extensions/pmod.py b/amaranth_boards/extensions/pmod.py
new file mode 100644
index 0000000..5443966
--- /dev/null
+++ b/amaranth_boards/extensions/pmod.py
@@ -0,0 +1,94 @@
+# Reference: https://www.digilentinc.com/Pmods/Digilent-Pmod_%20Interface_Specification.pdf
+
+from amaranth.build import *
+
+
+__all__ = [
+ "PmodGPIOType1Resource",
+ "PmodSPIType2Resource",
+ "PmodSPIType2AResource",
+ "PmodUARTType3Resource",
+ "PmodUARTType4Resource",
+ "PmodUARTType4AResource",
+ "PmodHBridgeType5Resource",
+ "PmodDualHBridgeType6Resource",
+]
+
+
+def PmodGPIOType1Resource(name, number, *args, pmod):
+ return Resource(name, number,
+ Pins("1 2 3 4", dir="io", conn=("pmod", pmod)),
+ *args
+ )
+
+
+def PmodSPIType2Resource(name, number, *args, pmod):
+ return Resource(name, number,
+ Subsignal("cs", PinsN("1", dir="o", conn=("pmod", pmod))),
+ Subsignal("clk", Pins("2", dir="o", conn=("pmod", pmod))),
+ Subsignal("copi", Pins("3", dir="o", conn=("pmod", pmod))),
+ Subsignal("cipo", Pins("4", dir="i", conn=("pmod", pmod))),
+ *args
+ )
+
+
+def PmodSPIType2AResource(name, number, *args, pmod):
+ return Resource(name, number,
+ Subsignal("cs", PinsN("1", dir="o", conn=("pmod", pmod))),
+ Subsignal("clk", Pins("2", dir="o", conn=("pmod", pmod))),
+ Subsignal("copi", Pins("3", dir="o", conn=("pmod", pmod))),
+ Subsignal("cipo", Pins("4", dir="i", conn=("pmod", pmod))),
+ Subsignal("int", Pins("7", dir="i", conn=("pmod", pmod))),
+ Subsignal("reset", Pins("8", dir="o", conn=("pmod", pmod))),
+ *args
+ )
+
+
+def PmodUARTType3Resource(name, number, *args, pmod):
+ return Resource(name, number,
+ Subsignal("cts", Pins("1", dir="o", conn=("pmod", pmod))),
+ Subsignal("rts", Pins("2", dir="i", conn=("pmod", pmod))),
+ Subsignal("rx", Pins("3", dir="i", conn=("pmod", pmod))),
+ Subsignal("tx", Pins("4", dir="o", conn=("pmod", pmod))),
+ *args
+ )
+
+
+def PmodUARTType4Resource(name, number, *args, pmod):
+ return Resource(name, number,
+ Subsignal("cts", Pins("1", dir="i", conn=("pmod", pmod))),
+ Subsignal("tx", Pins("2", dir="o", conn=("pmod", pmod))),
+ Subsignal("rx", Pins("3", dir="i", conn=("pmod", pmod))),
+ Subsignal("rts", Pins("4", dir="o", conn=("pmod", pmod))),
+ *args
+ )
+
+
+def PmodUARTType4AResource(name, number, *args, pmod):
+ return Resource(name, number,
+ Subsignal("cts", Pins("1", dir="i", conn=("pmod", pmod))),
+ Subsignal("tx", Pins("2", dir="o", conn=("pmod", pmod))),
+ Subsignal("rx", Pins("3", dir="i", conn=("pmod", pmod))),
+ Subsignal("rts", Pins("4", dir="o", conn=("pmod", pmod))),
+ Subsignal("int", Pins("7", dir="i", conn=("pmod", pmod))),
+ Subsignal("reset", Pins("8", dir="o", conn=("pmod", pmod))),
+ *args
+ )
+
+
+def PmodHBridgeType5Resource(name, number, *args, pmod):
+ return Resource(name, number,
+ Subsignal("dir", Pins("1", dir="o", conn=("pmod", pmod))),
+ Subsignal("en", Pins("2", dir="o", conn=("pmod", pmod))),
+ Subsignal("sa", Pins("3", dir="i", conn=("pmod", pmod))),
+ Subsignal("sb", Pins("4", dir="i", conn=("pmod", pmod))),
+ *args
+ )
+
+
+def PmodDualHBridgeType6Resource(name, number, *args, pmod):
+ return Resource(name, number,
+ Subsignal("dir", Pins("1 3", dir="o", conn=("pmod", pmod))),
+ Subsignal("en", Pins("2 4", dir="o", conn=("pmod", pmod))),
+ *args
+ )
diff --git a/amaranth_boards/fomu_hacker.py b/amaranth_boards/fomu_hacker.py
new file mode 100644
index 0000000..14fa8fc
--- /dev/null
+++ b/amaranth_boards/fomu_hacker.py
@@ -0,0 +1,51 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["FomuHackerPlatform"]
+
+
+class FomuHackerPlatform(LatticeICE40Platform):
+ device = "iCE40UP5K"
+ package = "UWG30"
+ default_clk = "clk48"
+ resources = [
+ Resource("clk48", 0, Pins("F5", dir="i"),
+ Clock(48e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(pins="A5", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ RGBLEDResource(0,
+ r="C5", g="B5", b="A5", invert=True,
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+
+ DirectUSBResource(0, d_p="A4", d_n="A2", pullup="D5",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS"),
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="C1", clk="D1", copi="F1", cipo="E1",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS"),
+ ),
+ ]
+
+ connectors = [
+ Connector("pin", 0, "F4"),
+ Connector("pin", 1, "E5"),
+ Connector("pin", 2, "E4"),
+ Connector("pin", 3, "F2"),
+ ]
+
+ def toolchain_program(self, products, name):
+ dfu_util = os.environ.get("DFU_UTIL", "dfu-util")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([dfu_util, "-D", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ FomuHackerPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/fomu_pvt.py b/amaranth_boards/fomu_pvt.py
new file mode 100644
index 0000000..ef27dbd
--- /dev/null
+++ b/amaranth_boards/fomu_pvt.py
@@ -0,0 +1,51 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["FomuPVTPlatform"]
+
+
+class FomuPVTPlatform(LatticeICE40Platform):
+ device = "iCE40UP5K"
+ package = "UWG30"
+ default_clk = "clk48"
+ resources = [
+ Resource("clk48", 0, Pins("F4", dir="i"),
+ Clock(48e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(pins="A5", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ RGBLEDResource(0,
+ r="B5", g="A5", b="C5", invert=True,
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+
+
+ DirectUSBResource(0, d_p="A1", d_n="A2", pullup="A4",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *SPIFlashResources(0,
+ cs_n="C1", clk="D1", copi="F1", cipo="E1",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS"),
+ ),
+
+ Resource("touch", 0, Pins("E4")),
+ Resource("touch", 1, Pins("D5")),
+ Resource("touch", 2, Pins("E5")),
+ Resource("touch", 3, Pins("F5")),
+ ]
+
+ connectors = []
+
+ def toolchain_program(self, products, name):
+ dfu_util = os.environ.get("DFU_UTIL", "dfu-util")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([dfu_util, "-D", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ FomuPVTPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/genesys2.py b/amaranth_boards/genesys2.py
new file mode 100644
index 0000000..008dced
--- /dev/null
+++ b/amaranth_boards/genesys2.py
@@ -0,0 +1,363 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["Genesys2Platform"]
+
+
+class Genesys2Platform(Xilinx7SeriesPlatform):
+ """Platform file for Diglient Genesys2 Kitex-7 board.
+ https://reference.digilentinc.com/reference/programmable-logic/genesys-2/start"""
+
+ device = "xc7k325t"
+ package = "ffg900"
+ speed = "2"
+
+ def __init__(self, JP6="2V5"):
+ super().__init__()
+
+ assert JP6 in ["1V2", "1V8", "2V5", "3V3"]
+ self._JP6 = JP6
+
+ def bank15_16_17_iostandard(self):
+ return "LVCMOS" + self._JP6.replace('V', '')
+
+ default_rst = "rst"
+ default_clk = "clk"
+ resources = [
+ Resource("rst", 0, PinsN("R19", dir="i"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("clk", 0, DiffPairs(p="AD12 ", n="AD11", dir="i"),
+ Clock(200e6), Attrs(IOSTANDARD="LVDS")),
+ *ButtonResources(pins={
+ "w": "M20",
+ "e": "C19",
+ "n": "B19",
+ "s": "M19",
+ "c": "E18"}, attrs=Attrs(IOSTANDARD=bank15_16_17_iostandard)),
+ *SwitchResources(pins="G19 G25 H24 K19 N19 P19",
+ attrs=Attrs(IOSTANDARD=bank15_16_17_iostandard)),
+ *SwitchResources(pins={
+ 6: "P26",
+ 7: "P27"}, attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ *LEDResources(pins="T28 V19 U30 U29 V20 V26 W24 W23",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("fan", 0,
+ Subsignal("pwm", Pins("W19", dir="o")),
+ Subsignal("tach", Pins("V21", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ UARTResource(0, rx="Y20", tx="Y23",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ I2CResource(0, scl="AE30", sda="AF30",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("ddr3", 0,
+ Subsignal("rst", PinsN("AG5", dir="o"),
+ Attrs(IOSTANDARD="SSTL15")),
+ Subsignal("clk",
+ DiffPairs(p="AB9", n="AC9", dir="o"),
+ Attrs(IOSTANDARD="DIFF_SSTL15_DCI")),
+ Subsignal("clk_en", Pins("AJ9", dir="o")),
+ Subsignal("cs", PinsN("AH12", dir="o")),
+ Subsignal("we", PinsN("AG13", dir="o")),
+ Subsignal("ras", PinsN("AE11", dir="o")),
+ Subsignal("cas", PinsN("AF11", dir="o")),
+ Subsignal("a", Pins(
+ "AC12 AE8 AD8 AC10 AD9 AA13 AA10 AA11 "
+ "Y10 Y11 AB8 AA8 AB12 AA12 AH9 AG9", dir="o")),
+ Subsignal("ba", Pins("AE9 AB10 AC11", dir="o")),
+ Subsignal("dqs",
+ DiffPairs(p="AD2 AG4 AG2 AH7",
+ n="AD1 AG3 AH1 AJ7", dir="io"),
+ Attrs(IOSTANDARD="DIFF_SSTL15_DCI", ODT="RTT_40")),
+ Subsignal("dq", Pins(
+ "AD3 AC2 AC1 AC5 AC4 AD6 AE6 AC7 "
+ "AF2 AE1 AF1 AE4 AE3 AE5 AF5 AF6 "
+ "AJ4 AH6 AH5 AH2 AJ2 AJ1 AK1 AJ3 "
+ "AF7 AG7 AJ6 AK6 AJ8 AK8 AK5 AK4", dir="io"),
+ Attrs(ODT="RTT_40")),
+ Subsignal("dm", Pins("AD4 AF3 AH4 AF8", dir="o")),
+ Subsignal("odt", Pins("AK9", dir="o")),
+ Attrs(IOSTANDARD="SSTL15_DCI", SLEW="FAST",
+ OUTPUT_IMPEDANCE="RDRV_40_40")),
+ Resource("audio_i2c", 0, # ADAU1761 I2C
+ Subsignal("scl", Pins("AE19", dir="io")),
+ Subsignal("sda", Pins("AF18", dir="io")),
+ Subsignal("adr", Pins("AD19 AG19", dir="o")),
+ Attrs(IOSTANDARD="LVCMOS18")),
+ Resource("audio_i2s", 0, # ADAU1761 ADC, I2S
+ Subsignal("clk", Pins("AG18", dir="o")), # BCLK
+ Subsignal("sd_adc", Pins("AH19", dir="o")), # ADC_SDATA
+ Subsignal("sd_dac", Pins("AJ19", dir="i")), # DAC_SDATA
+ Subsignal("ws", Pins("AJ18", dir="o")), # LRCLK
+ Attrs(IOSTANDARD="LVCMOS18")),
+ Resource("audio_clk", 0, # ADAU1761 MCLK
+ Pins("AK19", dir="o"), Attrs(IOSTANDARD="LVCMOS18")),
+ SPIResource(0, # OLED, SSD1306, 128 x 32
+ cs_n="dummy-cs0", clk="AF17", copi="Y15",
+ cipo="dummy-cipo0", reset="AB17",
+ attrs=Attrs(IOSTANDARD="LVCMOS18")),
+ Resource("oled", 0, # OLED, UG-2832HSWEG04
+ Subsignal("dc", Pins("AC17", dir="o")),
+ Subsignal("vdd_en", PinsN("AG17", dir="o")),
+ Subsignal("vbat_en", PinsN("AB22", dir="o"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ Attrs(IOSTANDARD="LVCMOS18")),
+ Resource("hdmi", 0, # HDMI TX, connector J4
+ Subsignal("scl", Pins("AF27", dir="io"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ Subsignal("sda", Pins("AF26", dir="io"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ Subsignal("clk",
+ DiffPairs(p="AA20", n="AB20", dir="o")),
+ Subsignal("d",
+ DiffPairs(p="AC20 AA22 AB24",
+ n="AC21 AA23 AC25", dir="o")),
+ Attrs(IOSTANDARD="TMDS_33")),
+ Resource("hdmi", 1, # HDMI RX, connector J5
+ Subsignal("scl", Pins("AJ28", dir="io"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ Subsignal("sda", Pins("AJ29", dir="io"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ Subsignal("clk", DiffPairs(p="AE28", n="AF28", dir="i")),
+ Subsignal("rx",
+ DiffPairs(p="AJ26 AG27 AH26",
+ n="AK26 AG28 AH27", dir="i")),
+ Attrs(IOSTANDARD="TMDS_33")),
+ VGAResource(0,
+ r="AK25 AG25 AH25 AK24 AJ24",
+ g="AJ23 AJ22 AH22 AK21 AJ21 AK23",
+ b="AH20 AG20 AF21 AK20 AG22",
+ hs="AF20", vs="AG23", invert_sync=True,
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ *SDCardResources(0, clk="R28", cmd="R29", dat0="R26", dat1="R30",
+ dat2="P29", dat3="T30", cd="P28",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("sd_card_rst", 0,
+ Pins("AE24", dir="o"), Attrs(IOSTANDARD="LVCMOS33")),
+ ULPIResource(0, data="AE14 AE15 AC15 AC16 AB15 AA15 AD14 AC14",
+ rst="AB14", clk="AD18", dir="Y16", stp="AA17", nxt="AA16",
+ clk_dir="i", rst_invert=True, attrs=Attrs(IOSTANDARD="LVCMOS18")),
+ Resource("vusb_oc", 0,
+ PinsN("AF16", dir="i"), Attrs(IOSTANDARD="LVCMOS18")),
+ Resource("eth_rgmii", 0,
+ Subsignal("rst", PinsN("AH24", dir="o"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+ Subsignal("mdc", Pins("AF12", dir="o")),
+ Subsignal("mdio", Pins("AG12", dir="io")),
+ Subsignal("tx_clk", Pins("AE10", dir="o")),
+ Subsignal("tx_ctl", Pins("AK14", dir="o")),
+ Subsignal("tx_data", Pins("AJ12 AK11 AJ11 AK10", dir="o")),
+ Subsignal("rx_clk", Pins("AG10", dir="i")),
+ Subsignal("rx_ctl", Pins("AH11", dir="i")),
+ Subsignal("rx_data", Pins("AJ14 AH14 AK13 AJ13", dir="i")),
+ Attrs(IOSTANDARD="LVCMOS15"))]
+
+ connectors = [
+ Connector("pmod", 0, # JA
+ "U27 U28 T26 T27 - - "
+ "T22 T23 T20 T21 - -"),
+ Connector("pmod", 1, # JB
+ "V29 V30 V25 W26 - - "
+ "T25 U25 U22 U23 - -"),
+ Connector("pmod", 2, # JC
+ "AC26 AJ27 AH30 AK29 - - "
+ "AD26 AG30 AK30 AK28 - -"),
+ Connector("pmod", 3, # JD
+ "V27 Y30 V24 W22 - - "
+ "U24 Y26 V22 W21 - -"),
+ Connector("pmod", 4, # JXADC
+ "J23 K23 L22 L21 - - "
+ "J24 K24 L23 K21 - -"),
+ Connector("hpc", 0,
+ {"dp1_m2c_p": "Y6",
+ "dp1_m2c_n": "Y5",
+ "dp2_m2c_p": "W4",
+ "dp2_m2c_n": "W3",
+ "dp3_m2c_p": "V6",
+ "dp3_m2c_n": "V5",
+ "dp1_c2m_p": "V2",
+ "dp1_c2m_n": "V1",
+ "dp2_c2m_p": "U4",
+ "dp2_c2m_n": "U3",
+ "dp3_c2m_p": "T2",
+ "dp3_c2m_n": "T1",
+ "dp0_c2m_p": "Y2",
+ "dp0_c2m_n": "Y1",
+ "dp0_m2c_p": "AA4",
+ "dp0_m2c_n": "AA3",
+ "la06_p": "D29",
+ "la06_n": "C30",
+ "la10_p": "B27",
+ "la10_n": "A27",
+ "la14_p": "C24",
+ "la14_n": "B24",
+ "la18_cc_p": "D17",
+ "la18_cc_n": "D18",
+ "la27_p": "A20",
+ "la27_n": "A21",
+ "ha01_cc_p": "M28",
+ "ha01_cc_n": "L28",
+ "ha05_p": "J29",
+ "ha05_n": "H29",
+ "ha09_p": "L30",
+ "ha09_n": "K30",
+ "ha13_p": "K26",
+ "ha13_n": "J26",
+ "ha16_p": "M22",
+ "ha16_n": "M23",
+ "ha20_p": "G27",
+ "ha20_n": "F27",
+ "clk1_m2c_p": "E28",
+ "clk1_m2c_n": "D28",
+ "la00_cc_p": "D27",
+ "la00_cc_n": "C27",
+ "la03_p": "E29",
+ "la03_n": "E30",
+ "la08_p": "C29",
+ "la08_n": "B29",
+ "la12_p": "F26",
+ "la12_n": "E26",
+ "la16_p": "E23",
+ "la16_n": "D23",
+ "la20_p": "G22",
+ "la20_n": "F22",
+ "la22_p": "J17",
+ "la22_n": "H17",
+ "la25_p": "D22",
+ "la25_n": "C22",
+ "la29_p": "B18",
+ "la29_n": "A18",
+ "la31_p": "C17",
+ "la31_n": "B17",
+ "la33_p": "D16",
+ "la33_n": "C16",
+ "ha03_p": "N25",
+ "ha03_n": "N26",
+ "ha07_p": "M29",
+ "ha07_n": "M30",
+ "ha11_p": "P23",
+ "ha11_n": "N24",
+ "ha14_p": "N27",
+ "ha14_n": "M27",
+ "ha18_p": "E19",
+ "ha18_n": "D19",
+ "ha22_p": "D21",
+ "ha22_n": "C21",
+ "gbtclk1_m2c_p": "N8",
+ "gbtclk1_m2c_n": "N7",
+ "gbtclk0_m2c_p": "L8",
+ "gbtclk0_m2c_n": "L7",
+ "la01_cc_p": "D26",
+ "la01_cc_n": "C26",
+ "la05_p": "B30",
+ "la05_n": "A30",
+ "la09_p": "B28",
+ "la09_n": "A28",
+ "la13_p": "E24",
+ "la13_n": "D24",
+ "la17_cc_p": "F21",
+ "la17_cc_n": "E21",
+ "la23_p": "G17",
+ "la23_n": "F17",
+ "la26_p": "B22",
+ "la26_n": "A22",
+ "pg_m2c": "AH21",
+ "ha00_cc_p": "K28",
+ "ha00_cc_n": "K29",
+ "ha04_p": "M24",
+ "ha04_n": "M25",
+ "ha08_p": "J27",
+ "ha08_n": "J28",
+ "ha12_p": "L26",
+ "ha12_n": "L27",
+ "ha15_p": "J21",
+ "ha15_n": "J22",
+ "ha19_p": "G29",
+ "ha19_n": "F30",
+ "prsnt_m2c_b": "AA21",
+ "clk0_m2c_p": "F20",
+ "clk0_m2c_n": "E20",
+ "la02_p": "H30",
+ "la02_n": "G30",
+ "la04_p": "H26",
+ "la04_n": "H27",
+ "la07_p": "F25",
+ "la07_n": "E25",
+ "la11_p": "A25",
+ "la11_n": "A26",
+ "la15_p": "B23",
+ "la15_n": "A23",
+ "la19_p": "H21",
+ "la19_n": "H22",
+ "la21_p": "L17",
+ "la21_n": "L18",
+ "la24_p": "H20",
+ "la24_n": "G20",
+ "la28_p": "J19",
+ "la28_n": "H19",
+ "la30_p": "A16",
+ "la30_n": "A17",
+ "la32_p": "K18",
+ "la32_n": "J18",
+ "ha02_p": "P21",
+ "ha02_n": "P22",
+ "ha06_p": "N29",
+ "ha06_n": "N30",
+ "ha10_p": "N21",
+ "ha10_n": "N22",
+ "ha17_cc_p": "C25",
+ "ha17_cc_n": "B25",
+ "ha21_p": "G28",
+ "ha21_n": "F28",
+ "ha23_p": "G18",
+ "ha23_n": "F18"})]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = {
+ "script_after_read": "auto_detect_xpm",
+ "script_before_bitstream":
+ "set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]",
+ "add_constraints": """
+ set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
+ set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
+ set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
+ set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
+ set_property CFGBVS VCCO [current_design]
+ set_property CONFIG_VOLTAGE 3.3 [current_design]
+ """}
+ return super().toolchain_prepare(
+ fragment, name, **overrides, **kwargs)
+
+ @property
+ def file_templates(self):
+ return {
+ **super().file_templates,
+ "{{name}}-openocd.cfg": r"""
+ source [find interface/ftdi/digilent-hs1.cfg]
+ # fix channel
+ ftdi_channel 1
+ adapter_khz 25000
+ transport select jtag
+ source [find cpld/xilinx-xc7.cfg]
+ source [find cpld/jtagspi.cfg]
+ """
+ }
+
+ def toolchain_program(self, products, name):
+ openocd = os.environ.get("OPENOCD", "openocd")
+ with products.extract("{}-openocd.cfg".format(name),
+ "{}.bit".format(name)) as (
+ config_filename, bitstream_filename):
+ subprocess.check_call([
+ openocd,
+ "-f", config_filename,
+ "-c", "init; pld load 0 {}; exit".format(bitstream_filename)])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ Genesys2Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/ice40_hx1k_blink_evn.py b/amaranth_boards/ice40_hx1k_blink_evn.py
new file mode 100644
index 0000000..5b61fb6
--- /dev/null
+++ b/amaranth_boards/ice40_hx1k_blink_evn.py
@@ -0,0 +1,48 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICE40HX1KBlinkEVNPlatform"]
+
+
+class ICE40HX1KBlinkEVNPlatform(LatticeICE40Platform):
+ device = "iCE40HX1K"
+ package = "VQ100"
+ default_clk = "clk3p3"
+ resources = [
+ Resource("clk3p3", 0, Pins("13", dir="i"), Clock(3.3e6),
+ Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(pins="59 56 53 51", attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ Resource("touch", 0, Pins("60"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("touch", 1, Pins("57"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("touch", 2, Pins("54"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("touch", 3, Pins("52"), Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *SPIFlashResources(0,
+ cs_n="49", clk="48", copi="45", cipo="46",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ ]
+ connectors = [
+ Connector("pmod", 1, "10 9 8 7 - - 4 3 2 1 - -"), # J1
+ Connector("pmod", 5, "40 42 62 64 - - 37 41 63 45 - -"), # J5
+ Connector("pmod", 6, "25 24 21 20 - - 26 27 28 33 - -"), # J6
+ Connector("pmod", 11, "49 45 46 48 - -"), # J11
+ Connector("pmod", 12, "59 56 53 51 - -"), # J12
+ ]
+
+ def toolchain_program(self, products, name):
+ iceburn = os.environ.get("ICEBURN", "iCEburn")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([iceburn, "-evw", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ICE40HX1KBlinkEVNPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/ice40_hx8k_b_evn.py b/amaranth_boards/ice40_hx8k_b_evn.py
new file mode 100644
index 0000000..da24c29
--- /dev/null
+++ b/amaranth_boards/ice40_hx8k_b_evn.py
@@ -0,0 +1,68 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICE40HX8KBEVNPlatform"]
+
+
+class ICE40HX8KBEVNPlatform(LatticeICE40Platform):
+ device = "iCE40HX8K"
+ package = "CT256"
+ default_clk = "clk12"
+ resources = [
+ Resource("clk12", 0, Pins("J3", dir="i"),
+ Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(
+ pins="C3 B3 C4 C5 A1 A2 B4 B5",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ), # D2..D9
+
+ UARTResource(0,
+ rx="B10", tx="B12", rts="B13", cts="A15", dtr="A16", dsr="B14", dcd="B15",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1),
+ role="dce"
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="R12", clk="R11", copi="P12", cipo="P11",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ ]
+ connectors = [
+ Connector("j", 1, # J1
+ "A16 - A15 B15 B13 B14 - - B12 B11 "
+ "A11 B10 A10 C9 - - A9 B9 B8 A7 "
+ "B7 C7 - - A6 C6 B6 C5 A5 C4 "
+ "- - B5 C3 B4 B3 A2 A1 - - "),
+ Connector("j", 2, # J2
+ "- - - R15 P16 P15 - - N16 M15 "
+ "M16 L16 K15 K16 - - K14 J14 G14 F14 "
+ "J15 H14 - - H16 G15 G16 F15 F16 E14 "
+ "- - E16 D15 D16 D14 C16 B16 - - "),
+ Connector("j", 3, # J3
+ "R16 - T15 T16 T13 T14 - - N12 P13 "
+ "N10 M11 T11 P10 - - T10 R10 P8 P9 "
+ "T9 R9 - - T7 T8 T6 R6 T5 R5 "
+ "- - R3 R4 R2 T3 T1 T2 - - "),
+ Connector("j", 4, # J4
+ "- - - R1 P1 P2 - - N3 N2 "
+ "M2 M1 L3 L1 - - K3 K1 J2 J1 "
+ "H2 J3 - - G2 H1 F2 G1 E2 F1 "
+ "- - D1 D2 C1 C2 B1 B2 - - "),
+ ]
+
+ def toolchain_program(self, products, name):
+ iceprog = os.environ.get("ICEPROG", "iceprog")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ # TODO: this should be factored out and made customizable
+ subprocess.check_call([iceprog, "-S", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ICE40HX8KBEVNPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/ice40_up5k_b_evn.py b/amaranth_boards/ice40_up5k_b_evn.py
new file mode 100644
index 0000000..10a100b
--- /dev/null
+++ b/amaranth_boards/ice40_up5k_b_evn.py
@@ -0,0 +1,66 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICE40UP5KBEVNPlatform"]
+
+
+class ICE40UP5KBEVNPlatform(LatticeICE40Platform):
+ device = "iCE40UP5K"
+ package = "SG48"
+ default_clk = "clk12"
+ resources = [
+ # J51 must be connected to use clk12 (it is by default)
+ Resource("clk12", 0, Pins("35", dir="i"),
+ Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ # 3 LEDs are present in an RGB common-anode package.
+ *LEDResources(
+ pins="39 40 41", invert=True,
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ Resource("led_b", 0, PinsN("39", dir="o"),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 0, PinsN("40", dir="o"),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_r", 0, PinsN("41", dir="o"),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ # 4 DIP switches are available, requiring internal pull-ups.
+ # The switches' "ON" label points to the position which
+ # connects them to ground, so invert the inputs.
+ *SwitchResources(pins="23 25 34 43", invert=True,
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1)
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="16", clk="15", copi="14", cipo="17",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ ]
+ connectors = [
+ Connector("aardvark", 0, # J1
+ "- - - - 14 - 15 17 16 -"),
+ Connector("pmod", 0, # U6 (board), U11 (schematic)
+ "16 14 17 15 - - 27 26 32 31 - -"),
+ Connector("j", 0, # 'Header A' (J52)
+ "- - 39 14 40 17 - 15 41 16 - -"),
+ Connector("j", 1, # 'Header B' (J2)
+ "- - 23 - 25 - 26 36 27 42 32 38 31 28 37 15 34 - 43 -"),
+ Connector("j", 2, # 'Header C' (J3)
+ "- 12 3 21 3 13 48 20 45 19 47 18 44 11 46 10 2 9 - 6"),
+ ]
+
+ def toolchain_program(self, products, name):
+ iceprog = os.environ.get("ICEPROG", "iceprog")
+ with products.extract("{}.bin".format(name)) as bitstream_fn:
+ subprocess.check_call([iceprog, bitstream_fn])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ICE40UP5KBEVNPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/icebreaker.py b/amaranth_boards/icebreaker.py
new file mode 100644
index 0000000..687ea16
--- /dev/null
+++ b/amaranth_boards/icebreaker.py
@@ -0,0 +1,75 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICEBreakerPlatform"]
+
+
+class ICEBreakerPlatform(LatticeICE40Platform):
+ device = "iCE40UP5K"
+ package = "SG48"
+ default_clk = "clk12"
+ resources = [
+ Resource("clk12", 0, Pins("35", dir="i"),
+ Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(pins="11 37", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ # Semantic aliases
+ Resource("led_r", 0, PinsN("11", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 0, PinsN("37", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *ButtonResources(pins="10", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ UARTResource(0,
+ rx="6", tx="9",
+ attrs=Attrs(IO_STANDARD="SB_LVTTL", PULLUP=1)
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="16", clk="15", copi="14", cipo="17", wp_n="12", hold_n="13",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ ]
+ connectors = [
+ Connector("pmod", 0, " 4 2 47 45 - - 3 48 46 44 - -"), # PMOD1A
+ Connector("pmod", 1, "43 38 34 31 - - 42 36 32 28 - -"), # PMOD1B
+ Connector("pmod", 2, "27 25 21 19 - - 26 23 20 18 - -"), # PMOD2
+ ]
+ # The attached LED/button section can be either used standalone or as a PMOD.
+ # Attach to platform using:
+ # p.add_resources(p.break_off_pmod)
+ # pmod_btn = plat.request("user_btn")
+ break_off_pmod = [
+ *LEDResources(pins={2: "7", 3: "1", 4: "2", 5: "8", 6: "3"}, conn=("pmod", 2),
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ # Semantic aliases
+ Resource("led_r", 1, Pins("7", dir="o", conn=("pmod", 2)),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 1, Pins("1", dir="o", conn=("pmod", 2)),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 2, Pins("2", dir="o", conn=("pmod", 2)),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 3, Pins("8", dir="o", conn=("pmod", 2)),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 4, Pins("3", dir="o", conn=("pmod", 2)),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *ButtonResources(pins={1: "9", 2: "4", 3: "10"}, conn=("pmod", 2),
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ ]
+
+ 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, bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ p = ICEBreakerPlatform()
+ p.add_resources(p.break_off_pmod)
+ p.build(Blinky(), do_program=True)
diff --git a/amaranth_boards/icebreaker_bitsy.py b/amaranth_boards/icebreaker_bitsy.py
new file mode 100644
index 0000000..218a1d1
--- /dev/null
+++ b/amaranth_boards/icebreaker_bitsy.py
@@ -0,0 +1,51 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICEBreakerBitsyPlatform"]
+
+
+class ICEBreakerBitsyPlatform(LatticeICE40Platform):
+ device = "iCE40UP5K"
+ package = "SG48"
+ default_clk = "clk12"
+ resources = [
+ Resource("clk12", 0, Pins("35", dir="i"),
+ Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ DirectUSBResource(0, d_p="42", d_n="38", pullup="37",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *SPIFlashResources(0,
+ cs_n="16", clk="15", copi="14", cipo="17", wp_n="18", hold_n="19",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+
+ RGBLEDResource(0, r="39", g="40", b="41", invert=True,
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ *LEDResources(pins="25 6", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_r", 0, PinsN("25", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 0, PinsN("6", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *ButtonResources(pins="2", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ ]
+ connectors = [
+ Connector("edge", 0, # Pins bottom P0 - P12,
+ "47 44 48 45 4 3 9 10 11 12 21 13"
+ "20 25 23 27 26 28 31 32 34 36 43 46"
+ )
+ ]
+
+ def toolchain_program(self, products, name):
+ dfu_util = os.environ.get("DFU_UTIL", "dfu-util")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([dfu_util, "-d", "1209:6146", "-a", "0", "-D", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ICEBreakerBitsyPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/icestick.py b/amaranth_boards/icestick.py
new file mode 100644
index 0000000..453d84f
--- /dev/null
+++ b/amaranth_boards/icestick.py
@@ -0,0 +1,53 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICEStickPlatform"]
+
+
+class ICEStickPlatform(LatticeICE40Platform):
+ device = "iCE40HX1K"
+ package = "TQ144"
+ default_clk = "clk12"
+ resources = [
+ Resource("clk12", 0, Pins("21", dir="i"),
+ Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(pins="99 98 97 96 95", attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ UARTResource(0,
+ rx="9", tx="8", rts="7", cts="4", dtr="3", dsr="2", dcd="1",
+ attrs=Attrs(IO_STANDARD="SB_LVTTL", PULLUP=1),
+ role="dce"
+ ),
+
+ IrDAResource(0,
+ rx="106", tx="105", sd="107",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="71", clk="70", copi="67", cipo="68",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ ]
+ connectors = [
+ Connector("pmod", 0, "78 79 80 81 - - 87 88 90 91 - -"), # J2
+
+ Connector("j", 1, "- - 112 113 114 115 116 117 118 119"), # J1
+ Connector("j", 3, "- - 62 61 60 56 48 47 45 44"), # J3
+ ]
+
+ 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, bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ICEStickPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/icesugar.py b/amaranth_boards/icesugar.py
new file mode 100644
index 0000000..d78c398
--- /dev/null
+++ b/amaranth_boards/icesugar.py
@@ -0,0 +1,64 @@
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICESugarPlatform"]
+
+
+class ICESugarPlatform(LatticeICE40Platform):
+ device = "iCE40UP5K"
+ package = "SG48"
+ default_clk = "clk12"
+
+ resources = [
+ Resource("clk12", 0, Pins("35", dir="i"),
+ Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="LVCMOS33")),
+
+ *LEDResources(pins="40 41 39", invert=True, attrs=Attrs(IO_STANDARD="LVCMOS33")),
+
+ # Semantic aliases
+ Resource("led_r", 0, PinsN("40", dir="o"), Attrs(IO_STANDARD="LVCMOS33")),
+ Resource("led_g", 0, PinsN("41", dir="o"), Attrs(IO_STANDARD="LVCMOS33")),
+ Resource("led_b", 0, PinsN("39", dir="o"), Attrs(IO_STANDARD="LVCMOS33")),
+
+ *SwitchResources(
+ pins="18 19 20 21",
+ attrs=Attrs(IO_STANDARD="LVCMOS33")
+ ),
+
+ UARTResource(0,
+ rx="4", tx="6",
+ attrs=Attrs(IO_STANDARD="LVTTL33", PULLUP=1)
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="16", clk="15", copi="14", cipo="17", wp_n="12", hold_n="13",
+ attrs=Attrs(IO_STANDARD="LVCMOS33")
+ ),
+
+ Resource("usb", 0,
+ Subsignal("d_p", Pins("10", dir="io")),
+ Subsignal("d_n", Pins("9", dir="io")),
+ Subsignal("pullup", Pins("11", dir="o")),
+ Attrs(IO_STANDARD="LVCMOS33")
+ ),
+ ]
+
+ connectors = [
+ Connector("pmod", 0, "10 6 3 48 - - 9 4 2 47 - -"), # PMOD1 - IO pins shared by USB
+ Connector("pmod", 1, "46 44 42 37 - - 45 43 38 36 - -"), # PMOD2
+ Connector("pmod", 2, "34 31 27 25 - - 32 28 26 23 - -"), # PMOD3
+ Connector("pmod", 3, "21 20 19 18 - - - - - - - -"), # PMOD4 - IO pins used for switches via jumpers
+ ]
+
+ def toolchain_program(self, products, name):
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call(["icesprog", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ICESugarPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/icesugar_nano.py b/amaranth_boards/icesugar_nano.py
new file mode 100644
index 0000000..1f2b07b
--- /dev/null
+++ b/amaranth_boards/icesugar_nano.py
@@ -0,0 +1,48 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["ICESugarNanoPlatform"]
+
+
+class ICESugarNanoPlatform(LatticeICE40Platform):
+ device = "iCE40LP1K"
+ package = "CM36"
+ default_clk = "clk12"
+
+ resources = [
+ Resource("clk12", 0, Pins("D1", dir="i"),
+ Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="LVCMOS33")),
+
+ *LEDResources(pins="B6", invert=False, attrs=Attrs(IO_STANDARD="LVCMOS33")),
+
+ UARTResource(0,
+ tx="B3", rx="A3",
+ attrs=Attrs(IO_STANDARD="LVTTL33", PULLUP=1)
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="D5", clk="E5", copi="E4", cipo="F5",
+ attrs=Attrs(IO_STANDARD="LVCMOS33")
+ ),
+ ]
+
+ connectors = [
+ Connector("pmod", 0, "E2 D1 B1 A1 - -"), # PMOD1
+ Connector("pmod", 1, "B3 A3 B6 C5 - -"), # PMOD2
+ Connector("pmod", 2, "B4 B5 E1 B1 - - C6 E3 C2 A1 - -"), # PMOD3
+ ]
+
+ def toolchain_program(self, products, name):
+ icesprog = os.environ.get("ICESPROG", "icesprog")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([icesprog, bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ ICESugarNanoPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/kc705.py b/amaranth_boards/kc705.py
new file mode 100644
index 0000000..d513da2
--- /dev/null
+++ b/amaranth_boards/kc705.py
@@ -0,0 +1,42 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["KC705Platform"]
+
+
+class KC705Platform(Xilinx7SeriesPlatform):
+ device = "xc7k325t"
+ package = "ffg900"
+ speed = "2"
+ default_clk = "clk156"
+ resources = [
+ Resource("clk156", 0, DiffPairs("K28", "K29", dir="i"),
+ Clock(156e6), Attrs(IOSTANDARD="LVDS_25")),
+
+ *LEDResources(pins="AB8 AA8 AC9 AB9 AE26 G19 E18 F16",
+ attrs=Attrs(IOSTANDARD="LVCMOS15")),
+
+ UARTResource(0,
+ rx="M19", tx="K24",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ ]
+ connectors = []
+
+ def toolchain_program(self, products, name):
+ openocd = os.environ.get("OPENOCD", "openocd")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([openocd,
+ "-c", "source [find board/kc705.cfg]; init; pld load 0 {}; exit"
+ .format(bitstream_filename)
+ ])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ KC705Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/kcu105.py b/amaranth_boards/kcu105.py
new file mode 100644
index 0000000..1a886d2
--- /dev/null
+++ b/amaranth_boards/kcu105.py
@@ -0,0 +1,37 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_ultrascale import *
+from .resources import *
+
+
+__all__ = ["KCU105Platform"]
+
+
+class KCU105Platform(XilinxUltraScalePlatform):
+ device = "xcku040"
+ package = "ffva1156"
+ speed = "2-e"
+ default_clk = "clk125"
+ resources = [
+ Resource("clk125", 0, DiffPairs("G10", "F10", dir="i"),
+ Clock(125e6), Attrs(IOSTANDARD="LVDS")),
+
+ *LEDResources(pins="AP8 H23 P20 P21 N22 M22 R23 P23",
+ attrs=Attrs(IOSTANDARD="LVCMOS18")),
+ ]
+ connectors = []
+
+ def toolchain_program(self, products, name):
+ openocd = os.environ.get("OPENOCD", "openocd")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([openocd,
+ "-c", "source [find board/kcu105.cfg]; init; pld load 0 {}; exit"
+ .format(bitstream_filename)
+ ])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ KCU105Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/machxo3_sk.py b/amaranth_boards/machxo3_sk.py
new file mode 100644
index 0000000..d4bba2b
--- /dev/null
+++ b/amaranth_boards/machxo3_sk.py
@@ -0,0 +1,74 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_machxo_2_3l import *
+from .resources import *
+
+
+__all__ = ["MachXO3SKPlatform"]
+
+
+class MachXO3SKPlatform(LatticeMachXO3LPlatform):
+ device = "LCMXO3LF-6900C"
+ package = "BG256"
+ speed = "5"
+ default_clk = "clk12"
+ resources = [
+ Resource("clk12", 0, Pins("C8", dir="i"),
+ Clock(12e6), Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ UARTResource(0,
+ rx="A11", tx="C11", rts="F10", cts="D11", dtr="B11", dsr="A12", dcd="B13", ri="A14",
+ attrs=Attrs(IO_TYPE="LVCMOS33"), role="dce"
+ ), # need to solder R14-R18, R20-R22
+
+ *LEDResources(
+ pins="H11 J13 J11 L12 K11 L13 N15 P16",
+ invert=True, attrs=Attrs(IO_TYPE="LVCMOS33")
+ ), # D9..D2
+
+ *ButtonResources(pins="B3", invert=True, attrs=Attrs(IO_TYPE="LVCMOS33")),
+
+ *SwitchResources(pins="N2 P1 M3 N1",
+ invert=True, attrs=Attrs(IO_TYPE="LVCMOS33")
+ ), # SW2
+
+ *SPIFlashResources(0,
+ cs_n="R5", clk="P6", copi="T13", cipo="T6",
+ attrs=Attrs(IO_TYPE="LVCMOS33")
+ ),
+ ]
+ connectors = [
+ Connector("j", 3, # J3
+ "- - A13 C13 F8 B12 C12 E11 E10 D10 "
+ "- - F9 C10 E8 E9 E7 D8 D7 C7 "
+ "- - C5 D6 E6 C4 A10 F7 D9 B9 "
+ "- - B6 B7 B5 A5 B4 A4 - A3 "),
+ Connector("j", 4, # J4
+ "- - K12 K13 M14 N14 L14 N16 M15 M16 "
+ "- - L15 L16 K14 K16 K15 J14 H14 J15 "
+ "- - J16 H15 H16 G15 G16 F15 F16 E15 "
+ "- - E16 E14 D16 C15 D14 F14 G14 B16 "),
+ Connector("j", 6, # J6
+ "- - T12 T14 R11 R13 T11 M11 P11 N10 "
+ "- - T10 P10 R9 R10 T9 N9 P9 M8 "
+ "- - T8 L8 P8 M6 R7 R8 P7 T7 "
+ "- - L7 R6 N6 T5 R4 P4 T3 T4 "),
+ Connector("j", 8, # J8
+ "- - H6 N3 M2 M1 L2 L1 L3 L5 "
+ "- - K4 J1 K1 J2 J3 H3 H2 H1 "
+ "- - G2 G1 F2 F1 E2 E1 D2 D1 "
+ "- - C2 C1 G3 B1 D3 E3 F3 F5 "),
+ ]
+
+ def toolchain_program(self, products, name):
+ openFPGALoader = os.environ.get("OPENFPGALOADER", "openFPGALoader")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([openFPGALoader, bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ MachXO3SKPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/mercury.py b/amaranth_boards/mercury.py
new file mode 100644
index 0000000..59b61c1
--- /dev/null
+++ b/amaranth_boards/mercury.py
@@ -0,0 +1,214 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_spartan_3_6 import *
+from .resources import *
+
+
+__all__ = ["MercuryPlatform"]
+
+
+class MercuryPlatform(XilinxSpartan3APlatform):
+ """
+ Original Mercury Board from Micro-Nova: https://www.micro-nova.com
+
+ Mercury Manual: https://www.micro-nova.com/s/mercury_rm.pdf
+ Mercury Schematic: https://www.micro-nova.com/s/mercury_schematic.pdf
+
+ The Mercury board is often paired with an extension board called the
+ Baseboard, which provides an ample set of I/O for FPGA beginners.
+
+ Baseboard Manual: https://www.micro-nova.com/s/baseboard_rm.pdf
+ Baseboard Schematics: https://www.micro-nova.com/s/baseboard_schematic.pdf
+
+ Mercury and Baseboard Resources: https://www.micro-nova.com/resources-mercury
+ """
+
+ device = "xc3s200a"
+ package = "vq100"
+ speed = "4"
+
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("P43", dir="i"),
+ Attrs(IOSTANDARD="LVCMOS33"), Clock(50e6)),
+
+ Resource("button", 0, Pins("P41", dir="i"),
+ Attrs(IOSTANDARD="LVTTL")),
+
+ # The serial interface and flash memory have a shared SPI bus.
+ # FPGA is secondary.
+ SPIResource("spi_serial", 0, role="peripheral",
+ cs_n="P39", clk="P53", copi="P46", cipo="P51",
+ attrs=Attrs(IOSTANDARD="LVTTL"),
+ ),
+
+ # FPGA is primary.
+ *SPIFlashResources(0,
+ cs_n="P27", clk="P53", copi="P46", cipo="P51",
+ attrs=Attrs(IOSTANDARD="LVTTL")
+ ),
+
+ # ADC over SPI- FPGA is primary.
+ SPIResource("spi_adc", 0, role="controller",
+ cs_n="P12", clk="P9", copi="P10", cipo="P21",
+ attrs=Attrs(IOSTANDARD="LVTTL"),
+ ),
+
+ # GPIO/SRAM Control
+ # 5V tolerant GPIO is shared w/ the SRAM (on 200k gate devices) using
+ # this pin. All GPIO except gpio:30 (and gpio:20, though see comment
+ # under SRAMResource) interface to the SRAM. On assertion, this signal
+ # will tristate the level-shifters, preventing any output on the 5V
+ # GPIO pins (including gpio:30 and gpio:20).
+ Resource("bussw_oe", 0, PinsN("P30N", dir="o"),
+ Attrs(IOSTANDARD="LVTTL"))
+ ]
+
+ # Perhaps define some connectors as having a specific purpose- i.e. a 5V GPIO
+ # bus with data, peripheral-select, and control signals?
+ connectors = [
+ Connector("gpio", 0, """P59 P60 P61 P62 P64 P57
+ P56 P52 P50 P49 P85 P84
+ P83 P78 P77 P65 P70 P71
+ P72 P73 P5 P4 P6 P98
+ P94 P93 P90 P89 P88 P86"""), # 5V I/O- LVTTL.
+ Connector("dio", 0, "P20 P32 P33 P34 P35 P36 P37"), # Fast 3.3V IO
+ # (Directly attached to FPGA)- LVCMOS33.
+ Connector("clkio", 0, "P40 P44"), # Clock IO (Can be used as GPIO)-
+ # LVCMOS33.
+ Connector("input", 0, "P68 P97 P7 P82"), # Input-only pins- LVCMOS33.
+ Connector("led", 0, "P13 P15 P16 P19"), # LEDs can be used as pins
+ # as well- LVTTL.
+ Connector("pmod", 0, "P5 P4 P6 P98 P94 P93 P90 P89") # Baseboard PMOD.
+ # Overlaps w/ GPIO bus.
+ ]
+
+ # Some default useful extensions. Attach to platform using:
+ # p.add_resources(p.leds)
+ # pmod_btn = plat.request("led")
+ leds = [
+ Resource("led", 0, Pins("1", dir="o", conn=("led", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("led", 1, Pins("2", dir="o", conn=("led", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("led", 2, Pins("3", dir="o", conn=("led", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("led", 3, Pins("4", dir="o", conn=("led", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ ]
+
+ sram = [
+ SRAMResource(0,
+ cs_n="P3", we_n="gpio_0:29",
+ # According to the schematic, A19/Pin 25 on the SRAM is wired to
+ # gpio-0:20. However, according to the SRAM's datasheet, pin 25 is
+ # a NC. Do not expose for now.
+ a=""" gpio_0:1 gpio_0:2 gpio_0:3 gpio_0:4 gpio_0:5 gpio_0:6
+ gpio_0:7 gpio_0:8 gpio_0:9 gpio_0:10 gpio_0:11 gpio_0:12
+ gpio_0:13 gpio_0:14 gpio_0:15 gpio_0:16 gpio_0:17 gpio_0:18
+ gpio_0:19""",
+ d="""gpio_0:21 gpio_0:22 gpio_0:23 gpio_0:24 gpio_0:25 gpio_0:26
+ gpio_0:27 gpio_0:28""",
+ attrs=Attrs(IOSTANDARD="LVTTL", SLEW="FAST")
+ )
+ ]
+
+ # The "serial port" is in fact over SPI. The creators of the board provide
+ # a VHDL file for talking over this interface. In light of space
+ # constraints and the fact that both the FT245RL and FPGA can BOTH be
+ # SPI primaries, however, it may be necessary to sacrifice two "high-speed"
+ # (DIO, INPUT) pins instead.
+ serial = [
+ # RX: FTDI D0, TX: FTDI D1
+ UARTResource(0, rx="input_0:1", tx="dio_0:1",
+ attrs=Attrs(IOSTANDARD="LVCMOS33"))
+ ]
+
+ # The remaining peripherals only make sense w/ the Baseboard installed.
+ # See: http://www.micro-nova.com/mercury-baseboard/
+ _switches = [
+ Resource("switch", 0, Pins("1", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("switch", 1, Pins("2", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("switch", 2, Pins("3", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("switch", 3, Pins("4", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("switch", 4, Pins("5", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("switch", 5, Pins("6", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("switch", 6, Pins("7", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("switch", 7, Pins("8", dir="i", conn=("gpio", 0)),
+ Attrs(IOSTANDARD="LVTTL"))
+ ]
+
+ _buttons = [
+ Resource("button", 1, Pins("1", dir="i", conn=("input", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("button", 2, Pins("2", dir="i", conn=("input", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("button", 3, Pins("3", dir="i", conn=("input", 0)),
+ Attrs(IOSTANDARD="LVTTL")),
+ Resource("button", 4, Pins("4", dir="i", conn=("input", 0)),
+ Attrs(IOSTANDARD="LVTTL"))
+ ]
+
+ _vga = [
+ VGAResource(0,
+ r="dio_0:1 dio_0:2 dio_0:3",
+ g="dio_0:4 dio_0:5 dio_0:6",
+ b="dio_0:7 clkio_0:1",
+ hs="led_0:3", vs="led_0:4", invert_sync=True,
+ attrs=Attrs(IOSTANDARD="LVCMOS33", SLEW="FAST"))
+ ]
+
+ _extclk = [
+ Resource("extclk", 0, Pins("1", dir="i", conn=("clkio", 1)),
+ Attrs(IOSTANDARD="LVCMOS33"))
+ ]
+
+ _sevenseg = [
+ Display7SegResource(0,
+ a="gpio_0:13", b="gpio_0:14", c="gpio_0:15", d="gpio_0:16",
+ e="gpio_0:17", f="gpio_0:18", g="gpio_0:19", dp="gpio_0:20",
+ invert=True, attrs=Attrs(IOSTANDARD="LVTTL")
+ ),
+ Resource("display_7seg_ctrl", 0,
+ Subsignal("en", Pins("9 10 11 12", dir="o", conn=("gpio", 0))),
+ Attrs(IOSTANDARD="LVTTL")
+ )
+ ]
+
+ _ps2 = [
+ PS2Resource(0,
+ clk="2", dat="1", conn=("led", 0), attrs=Attrs(IOSTANDARD="LVTTL")),
+ ]
+
+ _audio = [
+ Resource("audio", 0,
+ Subsignal("l", Pins("30", dir="o", conn=("gpio", 0))),
+ Subsignal("r", Pins("29", dir="o", conn=("gpio", 0))),
+ Attrs(IOSTANDARD="LVTTL")
+ )
+ ]
+
+ baseboard_sram = _buttons + _vga + _extclk + _ps2
+ baseboard_no_sram = baseboard_sram + _switches + _sevenseg + _audio
+
+ def toolchain_program(self, products, name):
+ # https://github.com/cr1901/mercpcl
+ mercpcl = os.environ.get("MERCPCL", "mercpcl")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([mercpcl, bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ plat = MercuryPlatform()
+ plat.add_resources(plat.leds)
+ plat.build(Blinky(), do_program=True)
diff --git a/amaranth_boards/microzed_z010.py b/amaranth_boards/microzed_z010.py
new file mode 100644
index 0000000..799720f
--- /dev/null
+++ b/amaranth_boards/microzed_z010.py
@@ -0,0 +1,116 @@
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+
+__all__ = ["MicroZedZ010Platform"]
+
+class MicroZedZ010Platform(Xilinx7SeriesPlatform):
+ device = "xc7z010"
+ package = "clg400"
+ speed = "1"
+ resources = []
+ connectors = [
+ Connector("JX1", 0,
+ "F9 J6 "
+ "F6 G6 "
+ "- - "
+ "- R11 "
+ "R19 T19 "
+ "T11 T12 "
+ "T10 U12 "
+ "- - "
+ "U13 V12 "
+ "V13 W13 "
+ "- - "
+ "T14 P14 "
+ "T15 R14 "
+ "- - "
+ "Y16 Y17 "
+ "W14 Y14 "
+ "- - "
+ "T16 V15 "
+ "U17 W15 "
+ "- - "
+ "U14 U18 "
+ "U15 U19 "
+ "- - "
+ "N18 N20 "
+ "P19 P20 "
+ "- - "
+ "T20 V20 "
+ "U20 W20 "
+ "- - "
+ "- - "
+ "Y18 V16 "
+ "Y19 W16 "
+ "- - "
+ "R16 T17 "
+ "R17 R18 "
+ "- - "
+ "V17 W18 "
+ "V18 W19 "
+ "- - "
+ "- - "
+ "N17 P15 "
+ "P18 P16 "
+ "- - "
+ "- - "
+ "- - "
+ "- - "
+ "- - "
+ "- - "
+ "K9 M9 "
+ "L10 M10 "
+ ),
+ Connector("JX2", 0,
+ "E8 E9 "
+ "C6 D9 "
+ "E6 B5 "
+ "C5 C8 "
+ "R10 - "
+ "C7 - "
+ "G14 J15 "
+ "- - "
+ "C20 B19 "
+ "B20 A20 "
+ "- - "
+ "E17 D19 "
+ "D18 D20 "
+ "- - "
+ "E18 F16 "
+ "E19 F17 "
+ "- - "
+ "L19 M19 "
+ "L20 M20 "
+ "- - "
+ "M17 K19 "
+ "M18 J19 "
+ "- - "
+ "L16 K17 "
+ "L17 K18 "
+ "- - "
+ "H16 J18 "
+ "H17 H18 "
+ "- - "
+ "- - "
+ "G17 F19 "
+ "G18 F20 "
+ "- - "
+ "G19 J20 "
+ "G20 H20 "
+ "- - "
+ "K14 H15 "
+ "J14 G15 "
+ "- - "
+ "- - "
+ "N15 L14 "
+ "N16 L15 "
+ "- - "
+ "M14 K16 "
+ "M15 J16 "
+ "- - "
+ "- - "
+ "- - "
+ "- - "
+ "- - "
+ ),
+ ]
diff --git a/amaranth_boards/microzed_z020.py b/amaranth_boards/microzed_z020.py
new file mode 100644
index 0000000..87b763a
--- /dev/null
+++ b/amaranth_boards/microzed_z020.py
@@ -0,0 +1,116 @@
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+
+__all__ = ["MicroZedZ020Platform"]
+
+class MicroZedZ020Platform(Xilinx7SeriesPlatform):
+ device = "xc7z020"
+ package = "clg400"
+ speed = "1"
+ resources = []
+ connectors = [
+ Connector("JX1", 0,
+ "F9 J6 "
+ "F6 G6 "
+ "- - "
+ "- R11 "
+ "R19 T19 "
+ "T11 T12 "
+ "T10 U12 "
+ "- - "
+ "U13 V12 "
+ "V13 W13 "
+ "- - "
+ "T14 P14 "
+ "T15 R14 "
+ "- - "
+ "Y16 Y17 "
+ "W14 Y14 "
+ "- - "
+ "T16 V15 "
+ "U17 W15 "
+ "- - "
+ "U14 U18 "
+ "U15 U19 "
+ "- - "
+ "N18 N20 "
+ "P19 P20 "
+ "- - "
+ "T20 V20 "
+ "U20 W20 "
+ "- - "
+ "- - "
+ "Y18 V16 "
+ "Y19 W16 "
+ "- - "
+ "R16 T17 "
+ "R17 R18 "
+ "- - "
+ "V17 W18 "
+ "V18 W19 "
+ "- - "
+ "- - "
+ "N17 P15 "
+ "P18 P16 "
+ "- - "
+ "U7 T9 "
+ "V7 U10 "
+ "V8 T5 "
+ "W8 U5 "
+ "- - "
+ "K9 M9 "
+ "L10 M10 "
+ ),
+ Connector("JX2", 0,
+ "E8 E9 "
+ "C6 D9 "
+ "E6 B5 "
+ "C5 C8 "
+ "R10 - "
+ "C7 - "
+ "G14 J15 "
+ "- - "
+ "C20 B19 "
+ "B20 A20 "
+ "- - "
+ "E17 D19 "
+ "D18 D20 "
+ "- - "
+ "E18 F16 "
+ "E19 F17 "
+ "- - "
+ "L19 M19 "
+ "L20 M20 "
+ "- - "
+ "M17 K19 "
+ "M18 J19 "
+ "- - "
+ "L16 K17 "
+ "L17 K18 "
+ "- - "
+ "H16 J18 "
+ "H17 H18 "
+ "- - "
+ "- - "
+ "G17 F19 "
+ "G18 F20 "
+ "- - "
+ "G19 J20 "
+ "G20 H20 "
+ "- - "
+ "K14 H15 "
+ "J14 G15 "
+ "- - "
+ "- - "
+ "N15 L14 "
+ "N16 L15 "
+ "- - "
+ "M14 K16 "
+ "M15 J16 "
+ "- - "
+ "Y12 V11 "
+ "Y13 V10 "
+ "V6 - "
+ "W6 V5 "
+ ),
+ ]
diff --git a/amaranth_boards/mister.py b/amaranth_boards/mister.py
new file mode 100644
index 0000000..d6217ff
--- /dev/null
+++ b/amaranth_boards/mister.py
@@ -0,0 +1,134 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["MisterPlatform"]
+
+
+# The MiSTer platform is built around the DE10-Nano; if you update one you should update the other.
+class MisterPlatform(IntelPlatform):
+ device = "5CSEBA6" # Cyclone V 110K LEs
+ package = "U23" # UBGA-484
+ speed = "I7"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("V11", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 1, Pins("Y13", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("clk50", 2, Pins("E11", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+
+ *LEDResources(
+ pins="W15 AA24 V16 V15 AF26 AE26 Y16 AA23",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *ButtonResources(
+ pins="AH17 AH16", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+ *SwitchResources(
+ pins="Y24 W24 W21 W20",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # Arduino header
+ UARTResource(0,
+ rx="AG13", tx="AF13",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # LTC2308 analogue-to-digital converter
+ SPIResource(0,
+ cs_n="U9", clk="V10", copi="AC4", cipo="AD4",
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # ADV7513 HDMI transmitter
+ # Note this has a lot of input formats for tx_d, but this defaults to RGB24
+ Resource("adv7513", 0,
+ Subsignal("tx_d_r", Pins("AD12 AE12 W8 Y8 AD11 AD10 AE11 Y5", dir="o")),
+ Subsignal("tx_d_g", Pins("AF10 Y4 AE9 AB4 AE7 AF6 AF8 AF5", dir="o")),
+ Subsignal("tx_d_b", Pins("AE4 AH2 AH4 AH5 AH6 AG6 AF9 AE8", dir="o")),
+ Subsignal("tx_clk", Pins("AG5", dir="o")),
+ Subsignal("tx_de", Pins("AD19", dir="o")),
+ Subsignal("tx_hs", Pins("T8", dir="o")),
+ Subsignal("tx_vs", Pins("V13", dir="o")),
+ Subsignal("tx_int", Pins("AF11", dir="i")),
+ Subsignal("i2s0", Pins("T13", dir="o")),
+ Subsignal("mclk", Pins("U11", dir="o")),
+ Subsignal("lrclk", Pins("T11", dir="o")),
+ Subsignal("sclk", Pins("T12", dir="o")),
+ Subsignal("scl", Pins("U10", dir="o")),
+ Subsignal("sda", Pins("AA4", dir="io")),
+ Attrs(io_standard="3.3-V LVTTL")),
+
+ # MiSTer SDRAM Board (required)
+ # https://github.com/MiSTer-devel/Hardware_MiSTer/blob/master/releases/sdram_xs_2.2.pdf
+ SDRAMResource(0,
+ clk="20", cs_n="33", we_n="27", ras_n="32", cas_n="31",
+ ba="34 35", a="37 38 39 40 28 25 26 23 24 21 36 22 19",
+ dq="1 2 3 4 5 6 7 8 18 17 16 15 14 13 9 10",
+ dqm="", conn=("gpio", 0), attrs=Attrs(io_standard="3.3-V LVCMOS")),
+
+ # MiSTer I/O Board (optional, but highly recommended)
+ # https://github.com/MiSTer-devel/Hardware_MiSTer/blob/master/releases/iobrd_6.0.pdf
+ Resource("power_led", 0, PinsN("1", dir="o", conn=("gpio", 1)), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("disk_led", 0, PinsN("3", dir="o", conn=("gpio", 1)), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("user_led", 0, PinsN("5", dir="o", conn=("gpio", 1)), Attrs(io_standard="3.3-V LVTTL")),
+
+ Resource("reset_switch", 0, PinsN("17", dir="i", conn=("gpio", 1)), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("osd_switch", 0, PinsN("13", dir="i", conn=("gpio", 1)), Attrs(io_standard="3.3-V LVTTL")),
+ Resource("user_switch", 0, PinsN("15", dir="i", conn=("gpio", 1)), Attrs(io_standard="3.3-V LVTTL")),
+
+ Resource("audio", 0,
+ Subsignal("l", Pins("2", dir="o", conn=("gpio", 1))),
+ Subsignal("r", Pins("7", dir="o", conn=("gpio", 1))),
+ Attrs(io_standard="3.3-V LVTTL")),
+
+ Resource("toslink", 0, Pins("9", dir="o", conn=("gpio", 1))),
+
+ *SDCardResources(0,
+ clk="13", cmd="8",
+ dat0="16", dat1="18", dat2="4", dat3="6",
+ conn=("gpio", 1), attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # The schematic is difficult to understand here...
+ VGAResource(0,
+ r="28 32 34 36 38 40",
+ g="27 31 33 35 37 39",
+ b="21 23 25 26 24 24",
+ hs="20", vs="19",
+ conn=("gpio", 1),
+ attrs=Attrs(io_standard="3.3-V LVTTL"))
+ ]
+ connectors = [
+ # Located on the top of the board, above the chip.
+ Connector("gpio", 0,
+ "V12 E8 W12 D11 D8 AH13 AF7 AH14 AF4 AH3 "
+ "- - AD5 AG14 AE23 AE6 AD23 AE24 D12 AD20 "
+ "C12 AD17 AC23 AC22 Y19 AB23 AA19 W11 - - "
+ "AA18 W14 Y18 Y17 AB25 AB26 Y11 AA26 AA13 AA11 "),
+ # Located on the bottom of the board.
+ Connector("gpio", 1,
+ "Y15 AC24 AA15 AD26 AG28 AF28 AE25 AF27 AG26 AH27 "
+ "- - AG25 AH26 AH24 AF25 AG23 AF23 AG24 AH22 "
+ "AH21 AG21 AH23 AA20 AF22 AE22 AG20 AF21 - - "
+ "AG19 AH19 AG18 AH18 AF18 AF20 AG15 AE20 AE19 AE17 "),
+ Connector("arduino", 0,
+ "AG13 AF13 AG10 AG9 U14 U13 AG8 AH8 "
+ "AF17 AE15 AF15 AG16 AH11 AH12 AH9 AG11 "
+ "AH7"),
+ ]
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ # The @2 selects the second device in the JTAG chain, because this chip
+ # puts the ARM cores first.
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename + "@2"])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ MisterPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/nandland_go.py b/amaranth_boards/nandland_go.py
new file mode 100644
index 0000000..d5c970a
--- /dev/null
+++ b/amaranth_boards/nandland_go.py
@@ -0,0 +1,50 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["NandlandGoPlatform"]
+
+
+class NandlandGoPlatform(LatticeICE40Platform):
+ device = "iCE40HX1K"
+ package = "VQ100"
+ default_clk = "clk25"
+ resources = [
+ Resource("clk25", 0, Pins("15", dir="i"),
+ Clock(25e6)),
+
+ *LEDResources(pins="56 57 59 60"),
+ *ButtonResources(pins="53 51 54 52"),
+
+ Display7SegResource(0,
+ a="3", b="4", c="93", d="91", e="90", f="1", g="2", invert=True),
+ Display7SegResource(1,
+ a="100", b="99", c="97", d="95", e="94", f="8", g="96", invert=True),
+
+ UARTResource(0, rx="73", tx="74"),
+
+ *SPIFlashResources(0, cs_n="49", clk="48", copi="45", cipo="46"),
+
+ VGAResource(0,
+ r="36 37 40",
+ g="29 30 33",
+ b="28 41 42",
+ hs="26", vs="27"),
+ ]
+ connectors = [
+ Connector("pmod", 0, "65 64 63 62 - - 78 79 80 81 - -"),
+ ]
+
+ 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, bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ NandlandGoPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/nexys4ddr.py b/amaranth_boards/nexys4ddr.py
new file mode 100644
index 0000000..b4e6a79
--- /dev/null
+++ b/amaranth_boards/nexys4ddr.py
@@ -0,0 +1,183 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["Nexys4DDRPlatform"]
+
+
+class Nexys4DDRPlatform(Xilinx7SeriesPlatform):
+ device = "xc7a100t"
+ package = "csg324"
+ speed = "1"
+ default_clk = "clk100"
+ default_rst = "rst"
+ resources = [
+ Resource("clk100", 0,
+ Pins("E3", dir="i"), Clock(100e6), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("rst", 0,
+ PinsN("C12", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+
+ *SwitchResources(
+ pins={0: 'J15', 1: 'L16', 2: 'M13', 3: 'R15', 4: 'R17', 5: 'T18',
+ 6: 'U18', 7: 'R13', 10: 'R16', 11: 'T13', 12: 'H6',
+ 13: 'U12', 14: 'U11', 15: 'V10'},
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ *SwitchResources(
+ pins={8: 'T8', 9: 'U8'},
+ attrs=Attrs(IOSTANDARD="LVCMOS18")),
+
+ *LEDResources(
+ pins="H17 K15 J13 N14 R18 V17 U17 U16 V16 T15 U14 T16 V15 V14 V12 V11",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ RGBLEDResource(0,
+ r="N15", g="M16", b="R12",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ RGBLEDResource(1,
+ r="N16", g="R11", b="G14",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ Display7SegResource(0,
+ a="T10", b="R10", c="K16", d="K13", e="P15",
+ f="T11", g="L18", dp="H15", invert=True,
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("display_7seg_an", 0,
+ PinsN("J17 J18 T9 J14 P14 T14 K2 U13", dir="o"),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("button_reset", 0,
+ PinsN("C12", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("button_center", 0,
+ Pins("N17", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("button_up", 0,
+ Pins("M18", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("button_left", 0,
+ Pins("P17", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("button_right", 0,
+ Pins("M17", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("button_down", 0,
+ Pins("P18", dir="i"), Attrs(IOSTANDARD="LVCMOS33")),
+
+ VGAResource(0,
+ r="A3 B4 C5 A4",
+ g="C6 A5 B6 A6",
+ b="B7 C7 D7 D8",
+ hs="B11", vs="B12",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ *SDCardResources(0,
+ clk="B1", cmd="C1", cd="A1",
+ dat0="C2", dat1="E1", dat2="F1", dat3="D2",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ Resource("sd_card_reset", 0,
+ Pins("E2", dir="o"), Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("accelerometer", 0, # ADXL362
+ Subsignal("cs", PinsN("D15", dir="o")),
+ Subsignal("clk", Pins("F15", dir="o")),
+ Subsignal("copi", Pins("F14", dir="o")),
+ Subsignal("cipo", Pins("E15", dir="i")),
+ Subsignal("int", Pins("B13 C16", dir="i"),
+ Attrs(IOSTANDARD="LVCMOS33", PULLUP="TRUE")),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("temp_sensor", 0, # ADT7420
+ Subsignal("scl", Pins("C14", dir="o")),
+ Subsignal("sda", Pins("C15", dir="io")),
+ Subsignal("int", Pins("D13", dir="i"), Attrs(PULLUP="TRUE")),
+ Subsignal("ct", Pins("B14", dir="i"), Attrs(PULLUP="TRUE")),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("microphone", 0, # ADMP421
+ Subsignal("clk", Pins("J5", dir="o")),
+ Subsignal("data", Pins("H5", dir="i")),
+ Subsignal("lr_sel", Pins("F5", dir="o")),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("audio", 0,
+ Subsignal("pwm", Pins("A11", dir="o")),
+ Subsignal("sd", PinsN("D12", dir="o")),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ UARTResource(0,
+ rx="C4", tx="D4", rts="E5", cts="D3",
+ attrs=Attrs(IOSTANDARD="LVCMOS33"),
+ role="dce"),
+
+ PS2Resource(0,
+ clk="F4", dat="B2",
+ attrs=Attrs(IOSTANDARD="LVCMOS33", PULLUP="TRUE")),
+
+ Resource("eth", 0, # LAN8720A
+ Subsignal("mdio", Pins("A9", dir="io")),
+ Subsignal("mdc", Pins("C9", dir="o")),
+ Subsignal("reset", Pins("B3", dir="o")),
+ Subsignal("rxd", Pins("C11 D10", dir="io")),
+ Subsignal("rxerr", Pins("C10", dir="io")),
+ Subsignal("txd", Pins("A10 A8", dir="o")),
+ Subsignal("txen", Pins("B9", dir="o")),
+ Subsignal("crs_dv", Pins("D9", dir="io")),
+ Subsignal("int", PinsN("B8", dir="io")),
+ Subsignal("clk", Pins("D5", dir="o"), Clock(50e6)),
+ Attrs(IOSTANDARD="LVCMOS33")),
+
+ *SPIFlashResources(0,
+ cs_n="L13", clk="E9", copi="K17", cipo="K18", wp_n="L14", hold_n="M14",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+
+ Resource("ddr2", 0, # MT47H64M16HR-25:H
+ Subsignal("a",
+ Pins("M4 P4 M6 T1 L3 P5 M2 N1 L4 N5 R2 K5 N6 K3", dir="o")),
+ Subsignal("dq",
+ Pins("R7 V6 R8 U7 V7 R6 U6 R5 T5 U3 V5 U4 V4 T4 V1 T3", dir="io"),
+ Attrs(IN_TERM="UNTUNED_SPLIT_50")),
+ Subsignal("ba", Pins("P2 P3 R1", dir="o")),
+ Subsignal("clk", DiffPairs("L6", "L5", dir="o"),
+ Attrs(IOSTANDARD="DIFF_SSTL18_I")),
+ Subsignal("clk_en", Pins("M1", dir="o")),
+ Subsignal("cs", PinsN("K6", dir="o")),
+ Subsignal("we", PinsN("N2", dir="o")),
+ Subsignal("ras", PinsN("N4", dir="o")),
+ Subsignal("cas", PinsN("L1", dir="o")),
+ Subsignal("dqs", DiffPairs("U9 U2", "V9 V2", dir="o"),
+ Attrs(IOSTANDARD="DIFF_SSTL18_I")),
+ Subsignal("dm", Pins("T6 U1", dir="o")),
+ Subsignal("odt", Pins("R5", dir="o")),
+ Attrs(IOSTANDARD="SSTL18_I", SLEW="FAST"))
+ ]
+ connectors = [
+ Connector("pmod", 0, "C17 D18 E18 G17 - - D17 E17 F18 G18 - -"), # JA
+ Connector("pmod", 1, "D14 F16 G16 H14 - - E16 F13 G13 H16 - -"), # JB
+ Connector("pmod", 2, "K1 F6 J2 G6 - - E7 J3 J4 E6 - -"), # JC
+ Connector("pmod", 3, "H4 H1 G1 G3 - - H2 G4 G2 F3 - -") # JD
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = {
+ "script_before_bitstream":
+ "set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]",
+ "script_after_bitstream":
+ "write_cfgmem -force -format bin -interface spix4 -size 16 "
+ "-loadbit \"up 0x0 {name}.bit\" -file {name}.bin".format(name=name),
+ "add_constraints":
+ """
+ set_property INTERNAL_VREF 0.9 [get_iobanks 34]
+ set_property CFGBVS VCCO [current_design]
+ set_property CONFIG_VOLTAGE 3.3 [current_design]
+ """
+ }
+ return super().toolchain_prepare(fragment, name, **overrides, **kwargs)
+
+ def toolchain_program(self, products, name):
+ xc3sprog = os.environ.get("XC3SPROG", "xc3sprog")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.run([xc3sprog, "-c", "nexys4", bitstream_filename], check=True)
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ Nexys4DDRPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/numato_mimas.py b/amaranth_boards/numato_mimas.py
new file mode 100644
index 0000000..a3f8930
--- /dev/null
+++ b/amaranth_boards/numato_mimas.py
@@ -0,0 +1,51 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_spartan_3_6 import *
+from .resources import *
+
+
+__all__ = ["NumatoMimasPlatform"]
+
+
+class NumatoMimasPlatform(XilinxSpartan6Platform):
+ device = "xc6slx9"
+ package = "tqg144"
+ speed = "2"
+ default_clk = "clk100"
+ resources = [
+ Resource("clk100", 0, Pins("P126", dir="i"),
+ Clock(100e6), Attrs(IOSTANDARD="LVCMOS33")),
+
+ *LEDResources(pins="P119 P118 P117 P116 P115 P114 P112 P111",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")),
+ *ButtonResources(pins="P124 P123 P121 P120",
+ attrs=Attrs(IOSTANDARD="LVCMOS33", PULLUP="TRUE")),
+
+ *SPIFlashResources(0,
+ cs_n="P38", clk="P70", copi="P64", cipo="65",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ ]
+ connectors = [
+ Connector("p", 1,
+ "- - P35 P34 P33 P32 P30 P29 P27 P26 "
+ "P24 P23 P22 P21 P17 P16 P15 P14 P12 P11 "
+ "P10 P9 P8 P7 P6 P5 P2 P1 P142 P141 "
+ "P140 P139 P138 P137 P134 P133 P132 P131 - - "
+ ),
+ Connector("p", 2,
+ "- - P43 P44 P45 P46 P47 P48 P50 P51 "
+ "P55 P56 P74 P75 P78 P79 P80 P81 - - "
+ "P82 P83 P84 P85 P87 P88 P92 P93 P94 P95 "
+ "P97 P98 P99 P100 P101 P102 P104 P105 - - "
+ )
+ ]
+
+ # Programming this board is not currently supported.
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ NumatoMimasPlatform().build(Blinky())
diff --git a/amaranth_boards/orangecrab_r0_1.py b/amaranth_boards/orangecrab_r0_1.py
new file mode 100644
index 0000000..2316461
--- /dev/null
+++ b/amaranth_boards/orangecrab_r0_1.py
@@ -0,0 +1,122 @@
+import os
+import subprocess
+import shutil
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = ["OrangeCrabR0_1Platform"]
+
+
+class OrangeCrabR0_1Platform(LatticeECP5Platform):
+ device = "LFE5U-25F"
+ package = "MG285"
+ speed = "8"
+ default_clk = "clk"
+ resources = [
+ Resource("clk", 0, Pins("A9", dir="i"),
+ Clock(48e6), Attrs(IO_TYPE="LVCMOS33")),
+
+ # Used to reload FPGA configuration.
+ # Can enter USB bootloader by assigning button 0 to program.
+ Resource("program", 0, PinsN("R16", dir="o"), Attrs(IO_TYPE="LVCMOS33")),
+
+ RGBLEDResource(0,
+ r="V17", g="T17", b="J3", invert=True,
+ attrs=Attrs(IO_TYPE="LVCMOS33")),
+
+ *SPIFlashResources(0,
+ cs_n="U17", clk="U16", cipo="T18", copi="U18", wp_n="R18", hold_n="N18",
+ attrs=Attrs(IO_TYPE="LVCMOS33"),
+ ),
+
+ Resource("ddr3", 0,
+ Subsignal("rst", PinsN("B1", dir="o")),
+ Subsignal("clk", DiffPairs("J18", "K18", dir="o"), Attrs(IO_TYPE="SSTL135D_I")),
+ Subsignal("clk_en", Pins("D6", dir="o")),
+ Subsignal("cs", PinsN("A12", dir="o")),
+ Subsignal("we", PinsN("B12", dir="o")),
+ Subsignal("ras", PinsN("C12", dir="o")),
+ Subsignal("cas", PinsN("D13", dir="o")),
+ Subsignal("a", Pins("A4 D2 C3 C7 D3 D4 D1 B2 C1 A2 A7 C2 C4", dir="o")),
+ Subsignal("ba", Pins("B6 B7 A6", dir="o")),
+ Subsignal("dqs", DiffPairs("G18 H17", "B15 A16", dir="io"),
+ Attrs(IO_TYPE="SSTL135D_I", TERMINATION="OFF",
+ DIFFRESISTOR="100")),
+ Subsignal("dq", Pins("F17 F16 G15 F15 J16 C18 H16 F18 C17 D15 B17 C16 A15 B13 A17 A13", dir="io"),
+ Attrs(TERMINATION="75")),
+ Subsignal("dm", Pins("G16 D16", dir="o")),
+ Subsignal("odt", Pins("C13", dir="o")),
+ Attrs(IO_TYPE="SSTL135_I", SLEWRATE="FAST")
+ ),
+
+ Resource("ddr3_pseudo_power", 0,
+ # pseudo power pins, leave these at their default value
+ Subsignal("vcc_virtual", PinsN("A3 B18 C6 C15 D17 D18 K15 K16 K17", dir="o")),
+ Subsignal("gnd_virtual", Pins("L15 L16 L18", dir="o")),
+ Attrs(IO_TYPE="SSTL135_II", SLEWRATE="FAST")
+ ),
+
+ *SDCardResources(0,
+ dat0="J1", dat1="K3", dat2="L3", dat3="M1", clk="K1", cmd="K2", cd="L1",
+ attrs=Attrs(IO_TYPE="LVCMOS33", SLEWRATE="FAST")
+ ),
+
+ DirectUSBResource(0, d_p="N1", d_n="M2", pullup="N2", attrs=Attrs(IO_TYPE="LVCMOS33"))
+ ]
+ connectors = [
+ Connector("io", 0, {
+ "0": "N17",
+ "1": "M18",
+ "5": "B10",
+ "6": "B9",
+ "9": "C8",
+ "10": "B8",
+ "11": "A8",
+ "12": "H2",
+ "13": "J2",
+ "cipo": "N15",
+ "copi": "N16",
+ "sck": "R17",
+ "scl": "C9",
+ "sda": "C10"
+ }),
+ Connector("mcu", 0, {
+ "0": "A10",
+ "1": "C11",
+ "2": "A11",
+ "3": "B11",
+ }),
+ ]
+
+ @property
+ def required_tools(self):
+ return super().required_tools + [
+ "dfu-suffix"
+ ]
+
+ @property
+ def command_templates(self):
+ return super().command_templates + [
+ r"""
+ {{invoke_tool("dfu-suffix")}}
+ -v 1209 -p 5af0 -a {{name}}.bit
+ """
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = dict(ecppack_opts="--compress --freq 38.8")
+ overrides.update(kwargs)
+ return super().toolchain_prepare(fragment, name, **overrides)
+
+ def toolchain_program(self, products, name):
+ dfu_util = os.environ.get("DFU_UTIL", "dfu-util")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([dfu_util, "-D", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ OrangeCrabR0_1Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/orangecrab_r0_2.py b/amaranth_boards/orangecrab_r0_2.py
new file mode 100644
index 0000000..75bac4a
--- /dev/null
+++ b/amaranth_boards/orangecrab_r0_2.py
@@ -0,0 +1,132 @@
+import os
+import subprocess
+import shutil
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = ["OrangeCrabR0_2Platform"]
+
+
+class OrangeCrabR0_2Platform(LatticeECP5Platform):
+ device = "LFE5U-25F"
+ package = "MG285"
+ speed = "8"
+ default_clk = "clk"
+ resources = [
+ Resource("clk", 0, Pins("A9", dir="i"),
+ Clock(48e6), Attrs(IO_TYPE="LVCMOS33")),
+
+ # Used to reload FPGA configuration.
+ # Can enter USB bootloader by assigning button 0 to program.
+ Resource("program", 0, PinsN("V17", dir="o"), Attrs(IO_TYPE="LVCMOS33")),
+
+ RGBLEDResource(0,
+ r="K4", g="M3", b="J3", invert=True,
+ attrs=Attrs(IO_TYPE="LVCMOS33")),
+
+ *ButtonResources(
+ pins={0: "J17" }, invert=True,
+ attrs=Attrs(IO_TYPE="SSTL135_I")),
+
+ *SPIFlashResources(0,
+ cs_n="U17", clk="U16", cipo="T18", copi="U18", wp_n="R18", hold_n="N18",
+ attrs=Attrs(IO_TYPE="LVCMOS33"),
+ ),
+
+ Resource("ddr3", 0,
+ Subsignal("rst", PinsN("L18", dir="o")),
+ Subsignal("clk", DiffPairs("J18", "K18", dir="o"), Attrs(IO_TYPE="SSTL135D_I")),
+ Subsignal("clk_en", Pins("D18", dir="o")),
+ Subsignal("cs", PinsN("A12", dir="o")),
+ Subsignal("we", PinsN("B12", dir="o")),
+ Subsignal("ras", PinsN("C12", dir="o")),
+ Subsignal("cas", PinsN("D13", dir="o")),
+ Subsignal("a", Pins("C4 D2 D3 A3 A4 D4 C3 B2 B1 D1 A7 C2 B6 C1 A2 C7", dir="o")),
+ Subsignal("ba", Pins("P5 N3 M3", dir="o")),
+ Subsignal("dqs", DiffPairs("G18 H17", "B15 A16", dir="io"),
+ Attrs(IO_TYPE="SSTL135D_I", TERMINATION="OFF",
+ DIFFRESISTOR="100")),
+ Subsignal("dq", Pins("C17 D15 B17 C16 A15 B13 A17 A13 F17 F16 G15 F15 J16 C18 H16 F18",
+ dir="io"), Attrs(TERMINATION="75")),
+ Subsignal("dm", Pins("G16 D16", dir="o")),
+ Subsignal("odt", Pins("C13", dir="o")),
+ Attrs(IO_TYPE="SSTL135_I", SLEWRATE="FAST")
+ ),
+
+ Resource("ddr3_pseudo_power", 0,
+ # pseudo power pins, leave these at their default value
+ Subsignal("vcc_virtual", PinsN("K16 D17 K15 K17 B18 C6", dir="o")),
+ Subsignal("gnd_virtual", Pins("L15 L16", dir="o")),
+ Attrs(IO_TYPE="SSTL135_II", SLEWRATE="FAST")
+ ),
+
+ Resource("adc", 0,
+ Subsignal("ctrl", Pins("G1 F1", dir="o")),
+ Subsignal("mux", Pins("F4 F3 F2 H1", dir="o")),
+ Subsignal("sense", DiffPairs("H3", "G3", dir="i"), Attrs(IO_TYPE="LVCMOS33D")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ *SDCardResources(0,
+ dat0="J1", dat1="K3", dat2="L3", dat3="M1", clk="K1", cmd="K2", cd="L1",
+ attrs=Attrs(IO_TYPE="LVCMOS33", SLEWRATE="FAST")
+ ),
+
+ DirectUSBResource(0, d_p="N1", d_n="M2", pullup="N2", attrs=Attrs(IO_TYPE="LVCMOS33"))
+ ]
+ connectors = [
+ Connector("io", 0, {
+ "0": "N17",
+ "1": "M18",
+ "5": "B10",
+ "6": "B9",
+ "9": "C8",
+ "10": "B8",
+ "11": "A8",
+ "12": "H2",
+ "13": "J2",
+ "a0": "L4",
+ "a1": "N3",
+ "a2": "N4",
+ "a3": "H4",
+ "a4": "G4",
+ "cipo": "N15",
+ "copi": "N16",
+ "sck": "R17",
+ "scl": "C9",
+ "sda": "C10"
+ })
+ ]
+
+ @property
+ def required_tools(self):
+ return super().required_tools + [
+ "dfu-suffix"
+ ]
+
+ @property
+ def command_templates(self):
+ return super().command_templates + [
+ r"""
+ {{invoke_tool("dfu-suffix")}}
+ -v 1209 -p 5af0 -a {{name}}.bit
+ """
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = dict(ecppack_opts="--compress --freq 38.8")
+ overrides.update(kwargs)
+ return super().toolchain_prepare(fragment, name, **overrides)
+
+ def toolchain_program(self, products, name):
+ dfu_util = os.environ.get("DFU_UTIL", "dfu-util")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([dfu_util, "-D", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ OrangeCrabR0_2Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/quickfeather.py b/amaranth_boards/quickfeather.py
new file mode 100644
index 0000000..26ef4dd
--- /dev/null
+++ b/amaranth_boards/quickfeather.py
@@ -0,0 +1,82 @@
+import os
+import sys
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.quicklogic import *
+from amaranth_boards.resources import *
+
+
+__all__ = ["QuickfeatherPlatform"]
+
+
+class QuickfeatherPlatform(QuicklogicPlatform):
+ device = "ql-eos-s3_wlcsp"
+ package = "PU64"
+ default_clk = "sys_clk0"
+ # It is possible to configure both oscillator frequency and
+ # clock divider. Resulting frequency is: 60MHz / 12 = 5MHz
+ osc_freq = int(60e6)
+ osc_div = 12
+ connectors = [
+ Connector("J", 2, "- 28 22 21 37 36 42 40 7 2 4 5"),
+ Connector("J", 3, "- 8 9 17 16 20 6 55 31 25 47 - - - - 41"),
+ Connector("J", 8, "27 26 33 32 23 57 56 3 64 62 63 61 59 - - -"),
+ ]
+ resources = [
+ *ButtonResources(pins="62"),
+
+ RGBLEDResource(0, r="34", g="39", b="38"),
+
+ UARTResource(0,
+ rx="9", tx="8",
+ ),
+
+ SPIResource(0,
+ cs_n="11", clk="20", copi="16", cipo="17"
+ ),
+ SPIResource(1,
+ cs_n="37", clk="40", copi="36", cipo="42",
+ role="peripheral"
+ ),
+
+ I2CResource(0,
+ scl="4", sda="5"
+ ),
+ I2CResource(1,
+ scl="22", sda="21"
+ ),
+
+ DirectUSBResource(0, d_p="10", d_n="14"),
+
+ Resource("swd", 0,
+ Subsignal("clk", Pins("54", dir="io")),
+ Subsignal("io", Pins("53", dir="io")),
+ ),
+ ]
+
+ # This programmer requires OpenOCD with support for eos-s3:
+ # https://github.com/antmicro/openocd/tree/eos-s3-support
+ def toolchain_program(self, products, name):
+ openocd = os.environ.get("OPENOCD", "openocd")
+ with products.extract("{}.openocd".format(name),
+ "{}_iomux.openocd".format(name)) as \
+ (bitstream_openocd_filename, iomux_openocd_filename):
+ subprocess.check_call([
+ openocd,
+ "-s", "tcl",
+ "-f", "interface/ftdi/antmicro-ftdi-adapter.cfg",
+ "-f", "interface/ftdi/swd-resistor-hack.cfg",
+ "-f", "board/quicklogic_quickfeather.cfg",
+ "-f", bitstream_openocd_filename,
+ "-c", "init",
+ "-c", "reset halt",
+ "-c", "load_bitstream",
+ "-f", iomux_openocd_filename,
+ "-c", "exit"
+ ])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ QuickfeatherPlatform().build(Blinky())
diff --git a/amaranth_boards/resources/__init__.py b/amaranth_boards/resources/__init__.py
new file mode 100644
index 0000000..531eb5e
--- /dev/null
+++ b/amaranth_boards/resources/__init__.py
@@ -0,0 +1,4 @@
+from .display import *
+from .interface import *
+from .memory import *
+from .user import *
diff --git a/amaranth_boards/resources/display.py b/amaranth_boards/resources/display.py
new file mode 100644
index 0000000..cf245e8
--- /dev/null
+++ b/amaranth_boards/resources/display.py
@@ -0,0 +1,36 @@
+from amaranth.build import *
+
+
+__all__ = ["Display7SegResource", "VGAResource"]
+
+
+def Display7SegResource(*args, a, b, c, d, e, f, g, dp=None, invert=False,
+ conn=None, attrs=None):
+ ios = []
+ ios.append(Subsignal("a", Pins(a, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("b", Pins(b, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("c", Pins(c, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("d", Pins(d, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("e", Pins(e, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("f", Pins(f, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("g", Pins(g, dir="o", invert=invert, conn=conn, assert_width=1)))
+ if dp is not None:
+ ios.append(Subsignal("dp", Pins(dp, dir="o", invert=invert, conn=conn, assert_width=1)))
+ if attrs is not None:
+ ios.append(attrs)
+ return Resource.family(*args, default_name="display_7seg", ios=ios)
+
+
+def VGAResource(*args, r, g, b, vs, hs, invert_sync=False, conn=None, attrs=None):
+ ios = []
+
+ ios.append(Subsignal("r", Pins(r, dir="o", conn=conn)))
+ ios.append(Subsignal("g", Pins(g, dir="o", conn=conn)))
+ ios.append(Subsignal("b", Pins(b, dir="o", conn=conn)))
+ ios.append(Subsignal("hs", Pins(hs, dir="o", invert=invert_sync, conn=conn, assert_width=1)))
+ ios.append(Subsignal("vs", Pins(vs, dir="o", invert=invert_sync, conn=conn, assert_width=1)))
+
+ if attrs is not None:
+ ios.append(attrs)
+
+ return Resource.family(*args, default_name="vga", ios=ios)
diff --git a/amaranth_boards/resources/interface.py b/amaranth_boards/resources/interface.py
new file mode 100644
index 0000000..8941be1
--- /dev/null
+++ b/amaranth_boards/resources/interface.py
@@ -0,0 +1,144 @@
+from amaranth.build import *
+
+
+__all__ = [
+ "UARTResource", "IrDAResource", "SPIResource", "I2CResource",
+ "DirectUSBResource", "ULPIResource", "PS2Resource",
+]
+
+
+def UARTResource(*args, rx, tx, rts=None, cts=None, dtr=None, dsr=None, dcd=None, ri=None,
+ conn=None, attrs=None, role=None):
+ if any(line is not None for line in (rts, cts, dtr, dsr, dcd, ri)):
+ assert role in ("dce", "dte")
+ if role == "dte":
+ dce_to_dte = "i"
+ dte_to_dce = "o"
+ else:
+ dce_to_dte = "o"
+ dte_to_dce = "i"
+
+ io = []
+ io.append(Subsignal("rx", Pins(rx, dir="i", conn=conn, assert_width=1)))
+ io.append(Subsignal("tx", Pins(tx, dir="o", conn=conn, assert_width=1)))
+ if rts is not None:
+ io.append(Subsignal("rts", Pins(rts, dir=dte_to_dce, conn=conn, assert_width=1)))
+ if cts is not None:
+ io.append(Subsignal("cts", Pins(cts, dir=dce_to_dte, conn=conn, assert_width=1)))
+ if dtr is not None:
+ io.append(Subsignal("dtr", Pins(dtr, dir=dte_to_dce, conn=conn, assert_width=1)))
+ if dsr is not None:
+ io.append(Subsignal("dsr", Pins(dsr, dir=dce_to_dte, conn=conn, assert_width=1)))
+ if dcd is not None:
+ io.append(Subsignal("dcd", Pins(dcd, dir=dce_to_dte, conn=conn, assert_width=1)))
+ if ri is not None:
+ io.append(Subsignal("ri", Pins(ri, dir=dce_to_dte, conn=conn, assert_width=1)))
+ if attrs is not None:
+ io.append(attrs)
+ return Resource.family(*args, default_name="uart", ios=io)
+
+
+def IrDAResource(number, *, rx, tx, en=None, sd=None,
+ conn=None, attrs=None):
+ # Exactly one of en (active-high enable) or sd (shutdown, active-low enable) should
+ # be specified, and it is mapped to a logic level en subsignal.
+ assert (en is not None) ^ (sd is not None)
+
+ io = []
+ io.append(Subsignal("rx", Pins(rx, dir="i", conn=conn, assert_width=1)))
+ io.append(Subsignal("tx", Pins(tx, dir="o", conn=conn, assert_width=1)))
+ if en is not None:
+ io.append(Subsignal("en", Pins(en, dir="o", conn=conn, assert_width=1)))
+ if sd is not None:
+ io.append(Subsignal("en", PinsN(sd, dir="o", conn=conn, assert_width=1)))
+ if attrs is not None:
+ io.append(attrs)
+ return Resource("irda", number, *io)
+
+
+def SPIResource(*args, cs_n, clk, copi, cipo, int=None, reset=None,
+ conn=None, attrs=None, role="controller"):
+ assert role in ("controller", "peripheral")
+ assert copi is not None or cipo is not None # support unidirectional SPI
+
+ io = []
+ if role == "controller":
+ io.append(Subsignal("cs", PinsN(cs_n, dir="o", conn=conn)))
+ io.append(Subsignal("clk", Pins(clk, dir="o", conn=conn, assert_width=1)))
+ if copi is not None:
+ io.append(Subsignal("copi", Pins(copi, dir="o", conn=conn, assert_width=1)))
+ if cipo is not None:
+ io.append(Subsignal("cipo", Pins(cipo, dir="i", conn=conn, assert_width=1)))
+ else: # peripheral
+ io.append(Subsignal("cs", PinsN(cs_n, dir="i", conn=conn, assert_width=1)))
+ io.append(Subsignal("clk", Pins(clk, dir="i", conn=conn, assert_width=1)))
+ if copi is not None:
+ io.append(Subsignal("copi", Pins(copi, dir="i", conn=conn, assert_width=1)))
+ if cipo is not None:
+ io.append(Subsignal("cipo", Pins(cipo, dir="oe", conn=conn, assert_width=1)))
+ if int is not None:
+ if role == "controller":
+ io.append(Subsignal("int", Pins(int, dir="i", conn=conn)))
+ else:
+ io.append(Subsignal("int", Pins(int, dir="oe", conn=conn, assert_width=1)))
+ if reset is not None:
+ if role == "controller":
+ io.append(Subsignal("reset", Pins(reset, dir="o", conn=conn)))
+ else:
+ io.append(Subsignal("reset", Pins(reset, dir="i", conn=conn, assert_width=1)))
+ if attrs is not None:
+ io.append(attrs)
+ return Resource.family(*args, default_name="spi", ios=io)
+
+
+def I2CResource(*args, scl, sda, conn=None, attrs=None):
+ io = []
+ io.append(Subsignal("scl", Pins(scl, dir="io", conn=conn, assert_width=1)))
+ io.append(Subsignal("sda", Pins(sda, dir="io", conn=conn, assert_width=1)))
+ if attrs is not None:
+ io.append(attrs)
+ return Resource.family(*args, default_name="i2c", ios=io)
+
+
+def DirectUSBResource(*args, d_p, d_n, pullup=None, vbus_valid=None, conn=None, attrs=None):
+
+ io = []
+ io.append(Subsignal("d_p", Pins(d_p, dir="io", conn=conn, assert_width=1)))
+ io.append(Subsignal("d_n", Pins(d_n, dir="io", conn=conn, assert_width=1)))
+ if pullup:
+ io.append(Subsignal("pullup", Pins(pullup, dir="o", conn=conn, assert_width=1)))
+ if vbus_valid:
+ io.append(Subsignal("vbus_valid", Pins(vbus_valid, dir="i", conn=conn, assert_width=1)))
+ if attrs is not None:
+ io.append(attrs)
+ return Resource.family(*args, default_name="usb", ios=io)
+
+
+def ULPIResource(*args, data, clk, dir, nxt, stp, rst=None,
+ clk_dir='i', rst_invert=False, attrs=None, conn=None):
+ assert clk_dir in ('i', 'o',)
+
+ io = []
+ io.append(Subsignal("data", Pins(data, dir="io", conn=conn, assert_width=8)))
+ io.append(Subsignal("clk", Pins(clk, dir=clk_dir, conn=conn, assert_width=1)))
+ io.append(Subsignal("dir", Pins(dir, dir="i", conn=conn, assert_width=1)))
+ io.append(Subsignal("nxt", Pins(nxt, dir="i", conn=conn, assert_width=1)))
+ io.append(Subsignal("stp", Pins(stp, dir="o", conn=conn, assert_width=1)))
+ if rst is not None:
+ io.append(Subsignal("rst", Pins(rst, dir="o", invert=rst_invert,
+ conn=conn, assert_width=1)))
+ if attrs is not None:
+ io.append(attrs)
+ return Resource.family(*args, default_name="usb", ios=io)
+
+
+def PS2Resource(*args, clk, dat, conn=None, attrs=None):
+ ios = []
+
+ ios.append(Subsignal("clk", Pins(clk, dir="i", conn=conn, assert_width=1))),
+ ios.append(Subsignal("dat", Pins(dat, dir="io", conn=conn, assert_width=1))),
+
+ if attrs is not None:
+ ios.append(attrs)
+
+ return Resource.family(*args, default_name="ps2", ios=ios)
diff --git a/amaranth_boards/resources/memory.py b/amaranth_boards/resources/memory.py
new file mode 100644
index 0000000..65eb5d5
--- /dev/null
+++ b/amaranth_boards/resources/memory.py
@@ -0,0 +1,190 @@
+from amaranth.build import *
+
+
+__all__ = [
+ "SPIFlashResources", "SDCardResources",
+ "SRAMResource", "SDRAMResource", "NORFlashResources",
+ "DDR3Resource",
+]
+
+
+def SPIFlashResources(*args, cs_n, clk, copi, cipo, wp_n=None, hold_n=None,
+ conn=None, attrs=None):
+ resources = []
+
+ io_all = []
+ if attrs is not None:
+ io_all.append(attrs)
+ io_all.append(Subsignal("cs", PinsN(cs_n, dir="o", conn=conn)))
+ io_all.append(Subsignal("clk", Pins(clk, dir="o", conn=conn, assert_width=1)))
+
+ io_1x = list(io_all)
+ io_1x.append(Subsignal("copi", Pins(copi, dir="o", conn=conn, assert_width=1)))
+ io_1x.append(Subsignal("cipo", Pins(cipo, dir="i", conn=conn, assert_width=1)))
+ if wp_n is not None and hold_n is not None:
+ io_1x.append(Subsignal("wp", PinsN(wp_n, dir="o", conn=conn, assert_width=1)))
+ io_1x.append(Subsignal("hold", PinsN(hold_n, dir="o", conn=conn, assert_width=1)))
+ resources.append(Resource.family(*args, default_name="spi_flash", ios=io_1x,
+ name_suffix="1x"))
+
+ io_2x = list(io_all)
+ io_2x.append(Subsignal("dq", Pins(" ".join([copi, cipo]), dir="io", conn=conn,
+ assert_width=2)))
+ resources.append(Resource.family(*args, default_name="spi_flash", ios=io_2x,
+ name_suffix="2x"))
+
+ if wp_n is not None and hold_n is not None:
+ io_4x = list(io_all)
+ io_4x.append(Subsignal("dq", Pins(" ".join([copi, cipo, wp_n, hold_n]), dir="io", conn=conn,
+ assert_width=4)))
+ resources.append(Resource.family(*args, default_name="spi_flash", ios=io_4x,
+ name_suffix="4x"))
+
+ return resources
+
+
+def SDCardResources(*args, clk, cmd, dat0, dat1=None, dat2=None, dat3=None, cd=None, wp_n=None,
+ conn=None, attrs=None):
+ resources = []
+
+ io_common = []
+ if attrs is not None:
+ io_common.append(attrs)
+ if cd is not None:
+ io_common.append(Subsignal("cd", Pins(cd, dir="i", conn=conn, assert_width=1)))
+ if wp_n is not None:
+ io_common.append(Subsignal("wp", PinsN(wp_n, dir="i", conn=conn, assert_width=1)))
+
+ io_native = list(io_common)
+ io_native.append(Subsignal("clk", Pins(clk, dir="o", conn=conn, assert_width=1)))
+ io_native.append(Subsignal("cmd", Pins(cmd, dir="o", conn=conn, assert_width=1)))
+
+ io_1bit = list(io_native)
+ io_1bit.append(Subsignal("dat", Pins(dat0, dir="io", conn=conn, assert_width=1)))
+ if dat3 is not None:
+ # DAT3 has a pullup and works as electronic card detect
+ io_1bit.append(Subsignal("ecd", Pins(dat3, dir="i", conn=conn, assert_width=1)))
+ resources.append(Resource.family(*args, default_name="sd_card", ios=io_1bit,
+ name_suffix="1bit"))
+
+ if dat1 is not None and dat2 is not None and dat3 is not None:
+ io_4bit = list(io_native)
+ io_4bit.append(Subsignal("dat", Pins(" ".join((dat0, dat1, dat2, dat3)), dir="io",
+ conn=conn, assert_width=4)))
+ resources.append(Resource.family(*args, default_name="sd_card", ios=io_4bit,
+ name_suffix="4bit"))
+
+ if dat3 is not None:
+ io_spi = list(io_common)
+ # DAT3/CS# has a pullup and doubles as electronic card detect
+ io_spi.append(Subsignal("cs", PinsN(dat3, dir="io", conn=conn, assert_width=1)))
+ io_spi.append(Subsignal("clk", Pins(clk, dir="o", conn=conn, assert_width=1)))
+ io_spi.append(Subsignal("copi", Pins(cmd, dir="o", conn=conn, assert_width=1)))
+ io_spi.append(Subsignal("cipo", Pins(dat0, dir="i", conn=conn, assert_width=1)))
+ resources.append(Resource.family(*args, default_name="sd_card", ios=io_spi,
+ name_suffix="spi"))
+
+ return resources
+
+
+def SRAMResource(*args, cs_n, oe_n=None, we_n, a, d, dm_n=None,
+ conn=None, attrs=None):
+ io = []
+ io.append(Subsignal("cs", PinsN(cs_n, dir="o", conn=conn, assert_width=1)))
+ if oe_n is not None:
+ # Asserted WE# deactivates the D output buffers, so WE# can be used to replace OE#.
+ io.append(Subsignal("oe", PinsN(oe_n, dir="o", conn=conn, assert_width=1)))
+ io.append(Subsignal("we", PinsN(we_n, dir="o", conn=conn, assert_width=1)))
+ io.append(Subsignal("a", Pins(a, dir="o", conn=conn)))
+ io.append(Subsignal("d", Pins(d, dir="io", conn=conn)))
+ if dm_n is not None:
+ io.append(Subsignal("dm", PinsN(dm_n, dir="o", conn=conn))) # dm="LB# UB#"
+ if attrs is not None:
+ io.append(attrs)
+ return Resource.family(*args, default_name="sram", ios=io)
+
+
+def SDRAMResource(*args, clk, cke=None, cs_n=None, we_n, ras_n, cas_n, ba, a, dq, dqm=None,
+ conn=None, attrs=None):
+ io = []
+ io.append(Subsignal("clk", Pins(clk, dir="o", conn=conn, assert_width=1)))
+ if cke is not None:
+ io.append(Subsignal("clk_en", Pins(cke, dir="o", conn=conn, assert_width=1)))
+ if cs_n is not None:
+ io.append(Subsignal("cs", PinsN(cs_n, dir="o", conn=conn, assert_width=1)))
+ io.append(Subsignal("we", PinsN(we_n, dir="o", conn=conn, assert_width=1)))
+ io.append(Subsignal("ras", PinsN(ras_n, dir="o", conn=conn, assert_width=1)))
+ io.append(Subsignal("cas", PinsN(cas_n, dir="o", conn=conn, assert_width=1)))
+ io.append(Subsignal("ba", Pins(ba, dir="o", conn=conn)))
+ io.append(Subsignal("a", Pins(a, dir="o", conn=conn)))
+ io.append(Subsignal("dq", Pins(dq, dir="io", conn=conn)))
+ if dqm is not None:
+ io.append(Subsignal("dqm", Pins(dqm, dir="o", conn=conn))) # dqm="LDQM# UDQM#"
+ if attrs is not None:
+ io.append(attrs)
+ return Resource.family(*args, default_name="sdram", ios=io)
+
+
+def NORFlashResources(*args, rst=None, byte_n=None, cs_n, oe_n, we_n, wp_n, by, a, dq,
+ conn=None, attrs=None):
+ resources = []
+
+ io_common = []
+ if rst is not None:
+ io_common.append(Subsignal("rst", Pins(rst, dir="o", conn=conn, assert_width=1)))
+ io_common.append(Subsignal("cs", PinsN(cs_n, dir="o", conn=conn, assert_width=1)))
+ io_common.append(Subsignal("oe", PinsN(oe_n, dir="o", conn=conn, assert_width=1)))
+ io_common.append(Subsignal("we", PinsN(we_n, dir="o", conn=conn, assert_width=1)))
+ io_common.append(Subsignal("wp", PinsN(wp_n, dir="o", conn=conn, assert_width=1)))
+ io_common.append(Subsignal("rdy", Pins(by, dir="i", conn=conn, assert_width=1)))
+
+ if byte_n is None:
+ io_8bit = list(io_common)
+ io_8bit.append(Subsignal("a", Pins(a, dir="o", conn=conn)))
+ io_8bit.append(Subsignal("dq", Pins(dq, dir="io", conn=conn, assert_width=8)))
+ resources.append(Resource.family(*args, default_name="nor_flash", ios=io_8bit,
+ name_suffix="8bit"))
+ else:
+ *dq_0_14, dq15_am1 = dq.split()
+
+ # If present in a requested resource, this pin needs to be strapped correctly.
+ io_common.append(Subsignal("byte", PinsN(byte_n, dir="o", conn=conn, assert_width=1)))
+
+ io_8bit = list(io_common)
+ io_8bit.append(Subsignal("a", Pins(" ".join((dq15_am1, a)), dir="o", conn=conn)))
+ io_8bit.append(Subsignal("dq", Pins(" ".join(dq_0_14[:8]), dir="io", conn=conn,
+ assert_width=8)))
+ resources.append(Resource.family(*args, default_name="nor_flash", ios=io_8bit,
+ name_suffix="8bit"))
+
+ io_16bit = list(io_common)
+ io_16bit.append(Subsignal("a", Pins(a, dir="o", conn=conn)))
+ io_16bit.append(Subsignal("dq", Pins(dq, dir="io", conn=conn, assert_width=16)))
+ resources.append(Resource.family(*args, default_name="nor_flash", ios=io_16bit,
+ name_suffix="16bit"))
+
+ return resources
+
+
+def DDR3Resource(*args, rst_n=None, clk_p, clk_n, clk_en, cs_n, we_n, ras_n, cas_n, a, ba, dqs_p, dqs_n, dq, dm, odt,
+ conn=None, diff_attrs=None, attrs=None):
+ ios = []
+
+ ios.append(Subsignal("rst", PinsN(rst_n, dir="o", conn=conn, assert_width=1)))
+ ios.append(Subsignal("clk", DiffPairs(clk_p, clk_n, dir="o", conn=conn, assert_width=1), diff_attrs))
+ ios.append(Subsignal("clk_en", Pins(clk_en, dir="o", conn=conn, assert_width=1)))
+ ios.append(Subsignal("cs", PinsN(cs_n, dir="o", conn=conn, assert_width=1)))
+ ios.append(Subsignal("we", PinsN(we_n, dir="o", conn=conn, assert_width=1)))
+ ios.append(Subsignal("ras", PinsN(ras_n, dir="o", conn=conn, assert_width=1)))
+ ios.append(Subsignal("cas", PinsN(cas_n, dir="o", conn=conn, assert_width=1)))
+ ios.append(Subsignal("a", Pins(a, dir="o", conn=conn)))
+ ios.append(Subsignal("ba", Pins(ba, dir="o", conn=conn)))
+ ios.append(Subsignal("dqs", DiffPairs(dqs_p, dqs_n, dir="io", conn=conn), diff_attrs))
+ ios.append(Subsignal("dq", Pins(dq, dir="io", conn=conn)))
+ ios.append(Subsignal("dm", Pins(dm, dir="o", conn=conn)))
+ ios.append(Subsignal("odt", Pins(odt, dir="o", conn=conn, assert_width=1)))
+
+ if attrs is not None:
+ ios.append(attrs)
+
+ return Resource.family(*args, default_name="ddr3", ios=ios)
diff --git a/amaranth_boards/resources/user.py b/amaranth_boards/resources/user.py
new file mode 100644
index 0000000..046f122
--- /dev/null
+++ b/amaranth_boards/resources/user.py
@@ -0,0 +1,43 @@
+from amaranth.build import *
+
+
+__all__ = ["LEDResources", "RGBLEDResource", "ButtonResources", "SwitchResources"]
+
+
+def _SplitResources(*args, pins, invert=False, conn=None, attrs=None, default_name, dir):
+ assert isinstance(pins, (str, list, dict))
+
+ if isinstance(pins, str):
+ pins = pins.split()
+ if isinstance(pins, list):
+ pins = dict(enumerate(pins))
+
+ resources = []
+ for number, pin in pins.items():
+ ios = [Pins(pin, dir=dir, invert=invert, conn=conn)]
+ if attrs is not None:
+ ios.append(attrs)
+ resources.append(Resource.family(*args, number, default_name=default_name, ios=ios))
+ return resources
+
+
+def LEDResources(*args, **kwargs):
+ return _SplitResources(*args, **kwargs, default_name="led", dir="o")
+
+
+def RGBLEDResource(*args, r, g, b, invert=False, conn=None, attrs=None):
+ ios = []
+ ios.append(Subsignal("r", Pins(r, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("g", Pins(g, dir="o", invert=invert, conn=conn, assert_width=1)))
+ ios.append(Subsignal("b", Pins(b, dir="o", invert=invert, conn=conn, assert_width=1)))
+ if attrs is not None:
+ ios.append(attrs)
+ return Resource.family(*args, default_name="rgb_led", ios=ios)
+
+
+def ButtonResources(*args, **kwargs):
+ return _SplitResources(*args, **kwargs, default_name="button", dir="i")
+
+
+def SwitchResources(*args, **kwargs):
+ return _SplitResources(*args, **kwargs, default_name="switch", dir="i")
diff --git a/amaranth_boards/rz_easyfpga_a2_2.py b/amaranth_boards/rz_easyfpga_a2_2.py
new file mode 100644
index 0000000..8c313ef
--- /dev/null
+++ b/amaranth_boards/rz_easyfpga_a2_2.py
@@ -0,0 +1,126 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.intel import *
+from .resources import *
+
+
+__all__ = ["RZEasyFPGAA2_2Platform"]
+
+
+class RZEasyFPGAA2_2Platform(IntelPlatform):
+ device = "EP4CE6" # Cyclone IV 6K LEs
+ package = "E22" # EQFP 144 pins
+ speed = "C8"
+ default_clk = "clk50" # 50MHz builtin clock
+ default_rst = "rst"
+ resources = [
+ # Clock
+ Resource("clk50", 0, Pins("23", dir="i"),
+ Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
+
+ # Reset switch, located on the lower left of the board.
+ Resource("rst", 0, PinsN("25", dir="i"), Attrs(io_standard="3.3-V LVTTL")),
+
+ # LEDs, located on the bottom of the board.
+ *LEDResources(
+ pins="87 86 85 84", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # Buttons, located on the bottom of the board, right of the LEDs.
+ *ButtonResources(
+ pins="88 89 90 91", invert=True,
+ attrs=Attrs(io_standard="3.3-V LVTTL")),
+
+ # Connections to the SKHynix RAM chip on board.
+ SDRAMResource(0,
+ clk="43", cs_n="72", we_n="69", ras_n="71", cas_n="70",
+ ba="73 74", a="76 77 80 83 68 67 66 65 64 60 75 59",
+ dq="28 30 31 32 33 34 38 39 54 53 52 51 50 49 46 44",
+ dqm="42 55", attrs=Attrs(io_standard="3.3-V LVCMOS")),
+
+ # VGA connector, located on the right of the board.
+ VGAResource(0,
+ r="106", g="105", b="104",
+ hs="101", vs="103"),
+
+ # 4 digit 7 segment display, located on top of the board.
+ Display7SegResource(0,
+ a="128", b="121", c="125", d="129", e="132", f="126", g="124", dp="127",
+ invert=True),
+ Resource("display_7seg_ctrl", 0,
+ Subsignal("en", Pins("133 135 136 137", dir="o", invert=True)),
+ ),
+
+ # PS2 port, located on upper right of the board.
+ PS2Resource(0, clk="119", dat="120"),
+
+ # LM75 temperature sensor
+ I2CResource(0, scl="112", sda="113"),
+
+ # AT24C08 EEPROM
+ I2CResource(1, scl="99" , sda="98" ),
+
+ # Buzzer
+ Resource("buzzer", 0, PinsN("110", dir="o")),
+
+ # Serial port, located above the VGA port.
+ UARTResource(0, tx="114", rx="115"),
+
+ # LCD connector, located above the 7 segment display.
+ Resource("lcd_hd44780", 0,
+ Subsignal("rs", Pins("141", dir="o")),
+ Subsignal("rw", Pins("138", dir="o")),
+ Subsignal("e" , Pins("143", dir="o")),
+ Subsignal("d" , Pins("142 1 144 3 2 10 7 11", dir="io")),
+ ),
+
+ # IR receiver, located right of the buttons.
+ Resource("cir", 0,
+ Subsignal("rx", Pins("100", dir="i"))
+ ),
+ ]
+
+ connectors = [
+ # Located above the chip.
+ Connector("gpio", 0,
+ "- - 11 7 2 144 142 138 136 133 129 127 125 121 119 114 112 110 - "
+ "- - 24 10 3 1 143 141 137 135 132 128 126 124 120 115 113 111 - "),
+
+ # Located right of the chip.
+ Connector("gpio", 1,
+ "- - "
+ "106 105"
+ "104 103"
+ "101 100"
+ "99 98 "
+ "91 90 "
+ "89 88 "
+ "87 86 "
+ "85 84 "
+ "- - "),
+
+ # Located below the chip.
+ Connector("gpio", 2,
+ "30 32 34 39 43 46 50 52 54 58 60 65 67 71 73 75 77 83 - - - "
+ "28 31 33 38 42 44 51 53 55 59 64 66 68 70 72 74 76 80 - - - "),
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = {
+ "add_settings":
+ '''set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"'''
+ }
+ return super().toolchain_prepare(fragment, name, **overrides, **kwargs)
+
+ def toolchain_program(self, products, name):
+ quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
+ with products.extract("{}.sof".format(name)) as bitstream_filename:
+ subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
+ "--operation", "P;" + bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ RZEasyFPGAA2_2Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/sk_xc6slx9.py b/amaranth_boards/sk_xc6slx9.py
new file mode 100644
index 0000000..7e77314
--- /dev/null
+++ b/amaranth_boards/sk_xc6slx9.py
@@ -0,0 +1,55 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.xilinx_spartan_3_6 import *
+from .resources import *
+
+
+__all__ = ["SK_XC6SLX9Platform"]
+
+
+class SK_XC6SLX9Platform(XilinxSpartan6Platform):
+ device = "xc6slx9"
+ package = "tqg144"
+ speed = "2"
+ default_clk = "clk50"
+ resources = [
+ Resource("clk50", 0, Pins("P134", dir="i"),
+ Clock(50e6), Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="P38", clk="P70", copi="P64", cipo="65",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+
+ SRAMResource(0,
+ cs_n="P97", oe_n="P45", we_n="P51",
+ a="P39 P40 P41 P43 P44 P55 P56 P57 P58 P59 P82 P81 P80 P79 P78 P66 P62 P61 P60",
+ d="P46 P47 P48 P50 P75 P74 P69 P67",
+ attrs=Attrs(IOSTANDARD="LVCMOS33")
+ ),
+ ]
+ connectors = [
+ Connector("x", 7,
+ "- - P34 - P33 P32 P30 P29 P27 P26 "
+ "P24 P23 P22 P21 P17 P16 P15 P14 P12 P11 "
+ "P10 P9 P8 P7 P6 P5 P2 P1 P143 P144 "
+ "P141 P142 P139 P140 P137 P138 P132 P133 P127 P131 "
+ ),
+ Connector("x", 9,
+ "- - P93 - P92 P88 P87 P85 P84 P83 "
+ "P74 P75 P78 P79 P81 P80 P69 P82 P66 P67 "
+ "P61 P62 P59 P60 P58 P57 P55 P56 P50 P51 "
+ "P47 P48 P44 P46 P45 P43 P40 P41 P35 P39 "
+ ),
+ Connector("x", 8,
+ "- - P126 - P123 P124 P120 P121 P118 P119 "
+ "P116 P117 P114 P115 P111 P112 P104 P105 P101 P102 "
+ "P99 P100 P97 P98 P94 P95 - - - - "
+ "- - - - - - - - - - "
+ ),
+ ]
+
+ # This board doesn't have an integrated programmer.
diff --git a/amaranth_boards/supercon19badge.py b/amaranth_boards/supercon19badge.py
new file mode 100644
index 0000000..c6aab63
--- /dev/null
+++ b/amaranth_boards/supercon19badge.py
@@ -0,0 +1,167 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = ["Supercon19BadgePlatform"]
+
+
+class Supercon19BadgePlatform(LatticeECP5Platform):
+ device = "LFE5U-45F"
+ package = "BG381"
+ speed = "8"
+ default_clk = "clk8"
+
+ # The badge's LEDs are wired in a non-straightforward way. Here, the
+ # LEDResources represent each of the common anodes of a collection of RGB LEDs.
+ # A single one of their cathodes defaults to connected via a FET; the other
+ # cathodes are normally-off. Accordingly, they act as normal single-color LEDs
+ # unless the cathode signals are explicitly driven.
+ #
+ # The LEDs on the badge were meant to be a puzzle; so each cathode signal
+ # corresponds to a different color on each LED. This means there's no
+ # straightforward way of creating pin definitions; you'll need to use the
+ # following mapping to find the cathode pin number below.
+ led_cathode_mappings = [
+ {'r': 0, 'g': 1, 'b': 2}, # LED1: by default, red
+ {'r': 2, 'g': 1, 'b': 0}, # LED2: by default, blue
+ {'r': 0, 'g': 1, 'b': 2}, # LED3: by default, red
+ {'r': 2, 'g': 1, 'b': 0}, # LED4: by default, blue
+ {'r': 0, 'g': 1, 'b': 2}, # LED5: by default, red
+ {'r': 2, 'g': 1, 'b': 0}, # LED6: by default, blue
+ {'r': 2, 'g': 0, 'b': 1}, # LED7: by default, green
+ {'r': 0, 'g': 1, 'b': 2}, # LED8: by default, red
+ {'r': 0, 'g': 1, 'b': 2}, # LED9: by default, red
+ # Note: [LED10 is disconnected by default; bridge R60 to make things work]
+ {'r': 2, 'g': 1, 'b': 0}, # LED10: by default, blue
+ {'r': 1, 'g': 0, 'b': 2}, # LED11: by default, green
+ ]
+
+ resources = [
+ Resource("clk8", 0, Pins("U18"), Clock(8e6), Attrs(IO_TYPE="LVCMOS33")),
+
+ # Used to trigger FPGA reconfiguration.
+ Resource("program", 0, PinsN("R1"), Attrs(IO_TYPE="LVCMOS33")),
+
+ # See note above for LED anode/cathode information.
+ # Short version is: these work as normal LEDs until you touch their cathodes.
+ *LEDResources(pins="E3 D3 C3 C4 C2 B1 B20 B19 A18 K20 K19",
+ attrs=Attrs(IO_TYPE="LVCMOS33")),
+ Resource("led_cathodes", 0, Pins("P19 L18 K18"), Attrs(IO_TYPE="LVCMOS33")),
+
+ UARTResource(0, rx="U2", tx="U1", attrs=Attrs(IO_TYPE="LVCMOS33")),
+
+ DirectUSBResource(0, d_p="F3", d_n="G3", pullup="E4", vbus_valid="F4",
+ attrs=Attrs(IO_TYPE="LVCMOS33")),
+
+ # Buttons, with semantic aliases.
+ *ButtonResources(pins="G2 F2 F1 C1 E1 D2 D1 E2",
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+ Resource("keypad", 0,
+ Subsignal("left", Pins("G2", dir="i")),
+ Subsignal("right", Pins("F2", dir="i")),
+ Subsignal("up", Pins("F1", dir="i")),
+ Subsignal("down", Pins("C1", dir="i")),
+ Subsignal("start", Pins("E1", dir="i")),
+ Subsignal("select",Pins("D2", dir="i")),
+ Subsignal("a", Pins("D1", dir="i")),
+ Subsignal("b", Pins("E2", dir="i")),
+ Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+
+ # Direct HDMI on the bottom of the board.
+ Resource("hdmi", 0,
+ Subsignal("clk", DiffPairsN("P20", "R20"), Attrs(IO_TYPE="TMDS_33")),
+ Subsignal("d", DiffPairs("N19 L20 L16", "N20 M20 L17"), Attrs(IO_TYPE="TMDS_33")),
+ Subsignal("hpd", PinsN("R18"), Attrs(IO_TYPE="LVCMOS33")),# Also called HDMI_HEAC_n
+ Subsignal("hdmi_heac_p", PinsN("T19"), Attrs(IO_TYPE="LVCMOS33")),
+ Attrs(DRIVE="4"),
+ ),
+
+ Resource("lcd", 0,
+ Subsignal("db",
+ Pins("J3 H1 K4 J1 K3 K2 L4 K1 L3 L2 M4 L1 M3 M1 N4 N2 N3 N1"),
+ ),
+ Subsignal("rd", Pins("P2")),
+ Subsignal("wr", Pins("P4")),
+ Subsignal("rs", Pins("P1")),
+ Subsignal("cs", Pins("P3")),
+ Subsignal("id", Pins("J4")),
+ Subsignal("rst", Pins("H2")),
+ Subsignal("fmark", Pins("G1")),
+ Subsignal("blen", Pins("P5")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ Resource("spi_flash", 0, # clock needs to be accessed through USRMCLK
+ Subsignal("cs", PinsN("R2")),
+ Subsignal("copi", Pins("W2")),
+ Subsignal("cipo", Pins("V2")),
+ Subsignal("wp", Pins("Y2")),
+ Subsignal("hold", Pins("W1")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+ Resource("spi_flash_4x", 0, # clock needs to be accessed through USRMCLK
+ Subsignal("cs", PinsN("R2")),
+ Subsignal("dq", Pins("W2 V2 Y2 W1")),
+ Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ # SPI-connected PSRAM.
+ Resource("spi_psram_4x", 0,
+ Subsignal("cs", PinsN("D20")),
+ Subsignal("clk", Pins("E20")),
+ Subsignal("dq", Pins("E19 D19 C20 F19"), Attrs(PULLMODE="UP")),
+ Attrs(IO_TYPE="LVCMOS33", SLEWRATE="SLOW")
+ ),
+ Resource("spi_psram_4x", 1,
+ Subsignal("cs", PinsN("F20")),
+ Subsignal("clk", Pins("J19")),
+ Subsignal("dq", Pins("J20 G19 G20 H20"), Attrs(PULLMODE="UP")),
+ Attrs(IO_TYPE="LVCMOS33", SLEWRATE="SLOW")
+ ),
+
+ SDRAMResource(0, clk="D11", cke="C11", cs_n="C7", we_n="B6", ras_n="D6", cas_n="A6",
+ ba="A7 C8", a="A8 D9 C9 B9 C14 E17 A12 B12 H17 G18 B8 A11 B11",
+ dq="C5 B5 A5 C6 B10 C10 D10 A9", dqm="A10",
+ attrs=Attrs(IO_TYPE="LVCMOS33", SLEWRATE="FAST")
+ )
+ ]
+
+ connectors = [
+ Connector("pmod", 0, "A15 C16 A14 D16 B15 C15 A13 B13"),
+ Connector("cartridge", 0,
+ "- - - - - - - - C5 B5 A5 C6 B6 A6 D6 C7 A7 C8 B8 A8 D9 C9 B9 A9" # continued:
+ " D10 C10 B10 A10 D11 C11 B11 A11 G18 H17 B12 A12 E17 C14"
+ ),
+
+ # SAO connectors names are compliant with the, erm, SAO 1.69 X-TREME standard.
+ # See: https://hackaday.com/2019/03/20/introducing-the-shitty-add-on-v1-69bis-standard/
+ Connector("sao", 0, {
+ "sda": "B3", "scl": "B2", "gpio0": "A2",
+ "gpio1": "A3", "gpio2": "B4", "gpio3": "A4"
+ }),
+ Connector("sao", 1, {
+ "sda": "A16", "scl": "B17", "gpio0": "B18",
+ "gpio1": "A17", "gpio2": "B16", "gpio3": "C17"
+ })
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = dict(ecppack_opts="--compress --freq 38.8")
+ overrides.update(kwargs)
+ return super().toolchain_prepare(fragment, name, **overrides, **kwargs)
+
+ def toolchain_program(self, products, name):
+ dfu_util = os.environ.get("DFU_UTIL", "dfu-util")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([dfu_util, "-d", "1d50:614b", "-a", "0", "-D", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ Supercon19BadgePlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/te0714_03_50_2I.py b/amaranth_boards/te0714_03_50_2I.py
new file mode 100644
index 0000000..c7c015c
--- /dev/null
+++ b/amaranth_boards/te0714_03_50_2I.py
@@ -0,0 +1,132 @@
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+from .resources import *
+
+
+__all__ = ["TE0714_03_50_2IPlatform"]
+
+
+class TE0714_03_50_2IPlatform(Xilinx7SeriesPlatform):
+ device = "xc7a50t"
+ package = "csg325"
+ speed = "2"
+ default_clk = "clk25"
+ resources = [
+ Resource("clk25", 0, Pins("T14", dir="i"), Clock(25e6), Attrs(IOSTANDARD="LVCMOS18")),
+ *LEDResources(pins="K18", attrs=Attrs(IOSTANDARD="LVCMOS18")),
+ *SPIFlashResources(0,
+ cs_n="L15", clk="E8", copi="K16", cipo="K17", wp_n="J15", hold_n="J16",
+ attrs=Attrs(IOSTANDARD="LVCMOS18")
+ )
+ ]
+ connectors = [
+ Connector("JM1", 0,
+ "G4 D6 "
+ "G3 D5 "
+ "- - "
+ "C4 B2 "
+ "C3 B1 "
+ "- - "
+ "A4 D2 "
+ "A3 D1 "
+ "- - "
+ "E4 F2 "
+ "E3 F1 "
+ "- - "
+ "K10 H2 "
+ "L9 H1 "
+ "- - "
+ "J5 L5 "
+ "J4 M5 "
+ "K6 M2 "
+ "K5 M1 "
+ "K3 K2 "
+ "L2 K1 "
+ "L4 N1 "
+ "L3 P1 "
+ "- - "
+ "M4 M6 "
+ "N4 N6 "
+ "N2 R2 "
+ "N3 R1 "
+ "P3 R3 "
+ "P4 T2 "
+ "L6 U1 "
+ "T3 U2 "
+ "T4 - "
+ "R5 V2 "
+ "T5 V3 "
+ "P5 U4 "
+ "P6 V4 "
+ "T7 U5 "
+ "R7 U6 "
+ "V6 V7 "
+ "U7 V8 "
+ "- - "
+ "V9 T9 "
+ "U9 T8 "
+ "V11 F8 "
+ "U11 R8 "
+ "V12 - "
+ "V13 F12 "
+ "- - "
+ "- - "
+ ),
+ Connector("JM2", 0,
+ "A12 B9 "
+ "B12 A9 "
+ "A13 B10 "
+ "A14 A10 "
+ "B14 B11 "
+ "A15 C11 "
+ "C14 C8 "
+ "B15 D8 "
+ "- E11 "
+ "A17 C9 "
+ "B16 D9 "
+ "B17 D11 "
+ "C16 C12 "
+ "C18 D13 "
+ "C17 C13 "
+ "D18 E13 "
+ "E17 D14 "
+ "- - "
+ "E18 D15 "
+ "F17 E15 "
+ "F18 D16 "
+ "G17 E16 "
+ "F15 F14 "
+ "G15 G14 "
+ "H17 G16 "
+ "H18 H16 "
+ "- A16 "
+ "K17 J14 "
+ "L18 K15 "
+ "M17 M14 "
+ "M16 N14 "
+ "R18 N16 "
+ "T18 N17 "
+ "E8 K16 "
+ "L15 J16 "
+ "L17 - "
+ "J15 P16 "
+ "N18 P15 "
+ "P18 R17 "
+ "T17 R16 "
+ "U17 P14 "
+ "- R15 "
+ "V17 T15 "
+ "V16 T14 "
+ "U16 - "
+ "U15 R13 "
+ "U14 T13 "
+ "V14 U12 "
+ "U10 T12 "
+ "L14 R12 "
+ )
+ ]
+
+
+if __name__ == "__main__":
+ from .test.blinky import Blinky
+ TE0714_03_50_2IPlatform().build(Blinky(), do_program=False)
diff --git a/amaranth_boards/test/__init__.py b/amaranth_boards/test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/amaranth_boards/test/__init__.py
diff --git a/amaranth_boards/test/blinky.py b/amaranth_boards/test/blinky.py
new file mode 100644
index 0000000..9999246
--- /dev/null
+++ b/amaranth_boards/test/blinky.py
@@ -0,0 +1,48 @@
+import itertools
+
+from amaranth import *
+from amaranth.build import ResourceError
+
+
+__all__ = ["Blinky"]
+
+
+class Blinky(Elaboratable):
+ def elaborate(self, platform):
+ m = Module()
+
+ def get_all_resources(name):
+ resources = []
+ for number in itertools.count():
+ try:
+ resources.append(platform.request(name, number))
+ except ResourceError:
+ break
+ return resources
+
+ rgb_leds = [res for res in get_all_resources("rgb_led")]
+ leds = [res.o for res in get_all_resources("led")]
+ leds.extend([led.r.o for led in rgb_leds])
+ leds.extend([led.g.o for led in rgb_leds])
+ leds.extend([led.b.o for led in rgb_leds])
+ buttons = [res.i for res in get_all_resources("button")]
+ switches = [res.i for res in get_all_resources("switch")]
+
+ inverts = [0 for _ in leds]
+ for index, button in zip(itertools.cycle(range(len(inverts))), buttons):
+ inverts[index] ^= button
+ for index, switch in zip(itertools.cycle(range(len(inverts))), switches):
+ inverts[index] ^= switch
+
+ clk_freq = platform.default_clk_frequency
+ timer = Signal(range(int(clk_freq//2)), reset=int(clk_freq//2) - 1)
+ flops = Signal(len(leds))
+
+ m.d.comb += Cat(leds).eq(flops ^ Cat(inverts))
+ with m.If(timer == 0):
+ m.d.sync += timer.eq(timer.reset)
+ m.d.sync += flops.eq(~flops)
+ with m.Else():
+ m.d.sync += timer.eq(timer - 1)
+
+ return m
diff --git a/amaranth_boards/tinyfpga_ax1.py b/amaranth_boards/tinyfpga_ax1.py
new file mode 100644
index 0000000..7c76768
--- /dev/null
+++ b/amaranth_boards/tinyfpga_ax1.py
@@ -0,0 +1,24 @@
+from amaranth.build import *
+from amaranth.vendor.lattice_machxo2 import *
+from .resources import *
+
+
+__all__ = ["TinyFPGAAX1Platform"]
+
+
+class TinyFPGAAX1Platform(LatticeMachXO2Platform):
+ device = "LCMXO2-256HC"
+ package = "SG32"
+ speed = "4"
+ connectors = [
+ Connector("gpio", 0,
+ # Left side of the board
+ # 1 2 3 4 5 6 7 8 9 10 11
+ "13 14 16 17 20 21 23 25 26 27 28 "
+ # Right side of the board
+ # 12 13 14 15 16 17 18 19 20 21 22
+ "- - - - 4 5 8 9 10 11 12 "
+ ),
+ ]
+ resources = []
+ # This board doesn't have an integrated programmer.
diff --git a/amaranth_boards/tinyfpga_ax2.py b/amaranth_boards/tinyfpga_ax2.py
new file mode 100644
index 0000000..3e9e989
--- /dev/null
+++ b/amaranth_boards/tinyfpga_ax2.py
@@ -0,0 +1,24 @@
+from amaranth.build import *
+from amaranth.vendor.lattice_machxo2 import *
+from .resources import *
+
+
+__all__ = ["TinyFPGAAX2Platform"]
+
+
+class TinyFPGAAX2Platform(LatticeMachXO2Platform):
+ device = "LCMXO2-1200HC"
+ package = "SG32"
+ speed = "4"
+ connectors = [
+ Connector("gpio", 0,
+ # Left side of the board
+ # 1 2 3 4 5 6 7 8 9 10 11
+ "13 14 16 17 20 21 23 25 26 27 28 "
+ # Right side of the board
+ # 12 13 14 15 16 17 18 19 20 21 22
+ "- - - - 4 5 8 9 10 11 12 "
+ ),
+ ]
+ resources = []
+ # This board doesn't have an integrated programmer.
diff --git a/amaranth_boards/tinyfpga_bx.py b/amaranth_boards/tinyfpga_bx.py
new file mode 100644
index 0000000..b8ce12f
--- /dev/null
+++ b/amaranth_boards/tinyfpga_bx.py
@@ -0,0 +1,53 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["TinyFPGABXPlatform"]
+
+
+class TinyFPGABXPlatform(LatticeICE40Platform):
+ device = "iCE40LP8K"
+ package = "CM81"
+ default_clk = "clk16"
+ resources = [
+ Resource("clk16", 0, Pins("B2", dir="i"),
+ Clock(16e6), Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *LEDResources(pins="B3", attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ DirectUSBResource(0, d_p="B4", d_n="A4", pullup="A3",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="F7", clk="G7", copi="G6", cipo="H7", wp_n="H4", hold_n="J8",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ ]
+ connectors = [
+ Connector("gpio", 0,
+ # Left side of the board
+ # 1 2 3 4 5 6 7 8 9 10 11 12 13
+ " A2 A1 B1 C2 C1 D2 D1 E2 E1 G2 H1 J1 H2 "
+ # Right side of the board
+ # 14 15 16 17 18 19 20 21 22 23 24
+ " H9 D9 D8 C9 A9 B8 A8 B7 A7 B6 A6 "
+ # Bottom of the board
+ # 25 26 27 28 29 30 31
+ "G1 J3 J4 G9 J9 E8 J2"
+ ),
+ ]
+
+ def toolchain_program(self, products, name):
+ tinyprog = os.environ.get("TINYPROG", "tinyprog")
+ with products.extract("{}.bin".format(name)) as bitstream_filename:
+ subprocess.check_call([tinyprog, "-p", bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ TinyFPGABXPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/ulx3s.py b/amaranth_boards/ulx3s.py
new file mode 100644
index 0000000..ae07b15
--- /dev/null
+++ b/amaranth_boards/ulx3s.py
@@ -0,0 +1,197 @@
+import os
+import argparse
+import subprocess
+import shutil
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = [
+ "ULX3S_12F_Platform", "ULX3S_25F_Platform",
+ "ULX3S_45F_Platform", "ULX3S_85F_Platform"
+]
+
+
+class _ULX3SPlatform(LatticeECP5Platform):
+ package = "BG381"
+ speed = "6"
+ default_clk = "clk25"
+
+ resources = [
+ Resource("clk25", 0, Pins("G2", dir="i"), Clock(25e6), Attrs(IO_TYPE="LVCMOS33")),
+
+ # Used to reload FPGA configuration.
+ Resource("program", 0, PinsN("M4", dir="o"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")),
+
+ *LEDResources(pins="B2 C2 C1 D2 D1 E2 E1 H3",
+ attrs=Attrs(IO_TYPE="LVCMOS33", DRIVE="4")),
+ *ButtonResources(pins="R1 T1 R18 V1 U1 H16",
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")
+ ),
+ *ButtonResources("switch", pins="E8 D8 D7 E7",
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")
+ ),
+
+ # Semantic aliases by button label.
+ Resource("button_pwr", 0, PinsN("D6", dir="i"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")),
+ Resource("button_fire", 0, Pins("R1", dir="i"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")),
+ Resource("button_fire", 1, Pins("T1", dir="i"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")),
+ Resource("button_up", 0, Pins("R18", dir="i"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")),
+ Resource("button_down", 0, Pins("V1", dir="i"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")),
+ Resource("button_left", 0, Pins("U1", dir="i"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")),
+ Resource("button_right", 0, Pins("H16", dir="i"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="DOWN")),
+
+ # FTDI connection.
+ UARTResource(0,
+ rx="M1", tx="L4", rts="M3", dtr="N1", role="dce",
+ attrs=Attrs(IO_TYPE="LVCMOS33")
+ ),
+ Resource("uart_tx_enable", 0, Pins("L3", dir="o"), Attrs(IO_TYPE="LVCMOS33")),
+
+ *SDCardResources(0,
+ clk="J1", cmd="J3", dat0="K2", dat1="K1", dat2="H2", dat3="H1",
+ attrs=Attrs(IO_TYPE="LVCMOS33", SLEW="FAST")
+ ),
+
+ # SPI Flash clock is accessed via USR_MCLK instance.
+ Resource("spi_flash", 0,
+ Subsignal("cs", PinsN("R2", dir="o")),
+ Subsignal("copi", Pins("W2", dir="o")),
+ Subsignal("cipo", Pins("V2", dir="i")),
+ Subsignal("hold", PinsN("W1", dir="o")),
+ Subsignal("wp", PinsN("Y2", dir="o")),
+ Attrs(PULLMODE="NONE", DRIVE="4", IO_TYPE="LVCMOS33")
+ ),
+
+ SDRAMResource(0,
+ clk="F19", cke="F20", cs_n="P20", we_n="T20", cas_n="T19", ras_n="R20", dqm="U19 E20",
+ ba="P19 N20", a="M20 M19 L20 L19 K20 K19 K18 J20 J19 H20 N19 G20 G19",
+ dq="J16 L18 M18 N18 P18 T18 T17 U20 E19 D20 D19 C20 E18 F18 J18 J17",
+ attrs=Attrs(PULLMODE="NONE", DRIVE="4", SLEWRATE="FAST", IO_TYPE="LVCMOS33")
+ ),
+
+ # SPI bus for ADC.
+ SPIResource("adc", cs_n="R17", copi="R16", cipo="U16", clk="P17",
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")),
+
+ # TRRS audio jack
+ Resource("audio", 0,
+ Subsignal("l", Pins("E4 D3 C3 B3", dir="o")),
+ Subsignal("r", Pins("A3 B5 D5 C5", dir="o")),
+ Subsignal("ring2", Pins("H5 F2 F5 E5", dir="o")), # extra ring out for video adapters
+ ),
+
+ # ESP-32 connections
+ Resource("esp32", 0,
+ Subsignal("en", Pins("F1", dir="o"), Attrs(PULLMODE="UP")),
+ Subsignal("tx", Pins("K3", dir="o"), Attrs(PULLMODE="UP")),
+ Subsignal("rx", Pins("K4", dir="i"), Attrs(PULLMODE="UP")),
+ Subsignal("gpio0", Pins("L2"), Attrs(PULLMODE="UP")),
+ Subsignal("gpio5", Pins("N4")),
+ Subsignal("gpio16", Pins("L1"), Attrs(PULLMODE="UP")),
+ Subsignal("gpio17", Pins("N3"), Attrs(PULLMODE="UP")),
+ Attrs(IO_TYPE="LVCMOS33", DRIVE="4")
+ ),
+
+ # PCB antenna, tuned to 433MHz
+ Resource("ant", 0, Pins("G1", dir="o"), Attrs(IO_TYPE="LVCMOS33")),
+
+ # Differential versions of our connector I/O.
+ Resource("diff_gpio", 0, DiffPairs("B11", "C11"), Attrs(IO_TYPE="LVCMOS33")),
+ Resource("diff_gpio", 1, DiffPairs("A10", "A11"), Attrs(IO_TYPE="LVCMOS33")),
+ Resource("diff_gpio", 2, DiffPairs("A9", "B10"), Attrs(IO_TYPE="LVCMOS33")),
+ Resource("diff_gpio", 3, DiffPairs("B9", "C10"), Attrs(IO_TYPE="LVCMOS33")),
+
+ # HDMI (only TX, due to the top bank of ECP5 only supporting diff. outputs)
+ Resource("hdmi", 0,
+ Subsignal("cec", Pins("A18", dir="io"),
+ Attrs(IO_TYPE="LVCMOS33", DRIVE="4", PULLMODE="UP")),
+ Subsignal("clk", DiffPairs("A17", "B18", dir="o"),
+ Attrs(IO_TYPE="LVCMOS33D", DRIVE="4")),
+ Subsignal("d", DiffPairs("A16 A14 A12", "B16 C14 A13", dir="o"),
+ Attrs(IO_TYPE="LVCMOS33D", DRIVE="4")),
+ Subsignal("eth", DiffPairs("A19", "B20", dir="o"),
+ Attrs(IO_TYPE="LVCMOS33D", DRIVE="4")),
+ Subsignal("scl", Pins("E12", dir="io"),
+ Attrs(IO_TYPE="LVCMOS33", DRIVE="4", PULLMODE="UP")),
+ Subsignal("sda", Pins("B19", dir="io"),
+ Attrs(IO_TYPE="LVCMOS33", DRIVE="4", PULLMODE="UP"))),
+
+ DirectUSBResource(0,
+ d_p="D15", d_n="E15", pullup="B12",
+ attrs=Attrs(IO_TYPE="LVCMOS33")
+ )
+ ]
+
+ connectors = [
+ Connector("gpio", 0, {
+ "0+": "B11", "0-": "C11", "1+": "A10", "1-": "A11",
+ "2+": "A9", "2-": "B10", "3+": "B9", "3-": "C10",
+ "4+": "A7", "4-": "A8", "5+": "C8", "5-": "B8",
+ "6+": "C6", "6-": "C7", "7+": "A6", "7-": "B6",
+ "8+": "A4", "8-": "A5", "9+": "A2", "9-": "B1",
+ "10+": "C4", "10-": "B4", "11+": "F4", "11-": "E3",
+ "12+": "G3", "12-": "F3", "13+": "H4", "13-": "G5",
+ "14+": "U18", "14-": "U17", "15+": "N17", "15-": "P16",
+ "16+": "N16", "16-": "M17", "17+": "L16", "17-": "L17",
+ "18+": "H18", "18-": "H17", "19+": "F17", "19-": "G18",
+ "20+": "D18", "20-": "E17", "21+": "C18", "21-": "D17",
+ "22+": "B15", "22-": "C15", "23+": "B17", "23-": "C17",
+ "24+": "C16", "24-": "D16", "25+": "D14", "25-": "E14",
+ "26+": "B13", "26-": "C13", "27+": "D13", "27-": "E13",
+ })
+ ]
+
+ @property
+ def required_tools(self):
+ return super().required_tools + [
+ "openFPGALoader"
+ ]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ overrides = dict(ecppack_opts="--compress")
+ overrides.update(kwargs)
+ return super().toolchain_prepare(fragment, name, **overrides)
+
+ def toolchain_program(self, products, name):
+ tool = os.environ.get("OPENFPGALOADER", "openFPGALoader")
+ with products.extract("{}.bit".format(name)) as bitstream_filename:
+ subprocess.check_call([tool, "-b", "ulx3s", '-m', bitstream_filename])
+
+
+class ULX3S_12F_Platform(_ULX3SPlatform):
+ device = "LFE5U-12F"
+
+
+class ULX3S_25F_Platform(_ULX3SPlatform):
+ device = "LFE5U-25F"
+
+
+class ULX3S_45F_Platform(_ULX3SPlatform):
+ device = "LFE5U-45F"
+
+
+class ULX3S_85F_Platform(_ULX3SPlatform):
+ device = "LFE5U-85F"
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+
+ variants = {
+ '12F': ULX3S_12F_Platform,
+ '25F': ULX3S_25F_Platform,
+ '45F': ULX3S_45F_Platform,
+ '85F': ULX3S_85F_Platform
+ }
+
+ # Figure out which FPGA variant we want to target...
+ parser = argparse.ArgumentParser()
+ parser.add_argument('variant', choices=variants.keys())
+ args = parser.parse_args()
+
+ # ... and run Blinky on it.
+ platform = variants[args.variant]
+ platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/upduino_v1.py b/amaranth_boards/upduino_v1.py
new file mode 100644
index 0000000..3089e78
--- /dev/null
+++ b/amaranth_boards/upduino_v1.py
@@ -0,0 +1,36 @@
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+
+
+__all__ = ["UpduinoV1Platform"]
+
+
+class UpduinoV1Platform(LatticeICE40Platform):
+ device = "iCE40UP5K"
+ package = "SG48"
+ default_clk = "SB_HFOSC"
+ hfosc_div = 0
+ resources = [
+ *LEDResources(pins="39 40 41", invert=True,
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_g", 0, PinsN("39", dir="o"),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_b", 0, PinsN("40", dir="o"),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+ Resource("led_r", 0, PinsN("41", dir="o"),
+ Attrs(IO_STANDARD="SB_LVCMOS")),
+
+ *SPIFlashResources(0,
+ cs_n="16", clk="15", cipo="17", copi="14",
+ attrs=Attrs(IO_STANDARD="SB_LVCMOS")
+ ),
+ ]
+ connectors = [
+ # "Left" row of header pins (JP5 on the schematic)
+ Connector("j", 0, "- - 23 25 26 27 32 35 31 37 34 43 36 42 38 28"),
+ # "Right" row of header pins (JP6 on the schematic)
+ Connector("j", 1, "12 21 13 19 18 11 9 6 44 4 3 48 45 47 46 2")
+ ]
+
+ # This board doesn't have an integrated programmer.
diff --git a/amaranth_boards/upduino_v2.py b/amaranth_boards/upduino_v2.py
new file mode 100644
index 0000000..b6be916
--- /dev/null
+++ b/amaranth_boards/upduino_v2.py
@@ -0,0 +1,30 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ice40 import *
+from .resources import *
+from .upduino_v1 import UpduinoV1Platform
+
+
+__all__ = ["UpduinoV2Platform"]
+
+
+class UpduinoV2Platform(UpduinoV1Platform):
+ # Mostly identical to the V1 board, but it has an integrated
+ # programmer and a 12MHz oscillator which is NC by default.
+ resources = UpduinoV1Platform.resources + [
+ # Solder pin 12 to the adjacent 'J8' osc_out pin to enable.
+ Resource("clk12", 0, Pins("12", dir="i"),
+ Clock(12e6), Attrs(IO_STANDARD="SB_LVCMOS")),
+ ]
+
+ 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, bitstream_filename])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ UpduinoV2Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/versa_ecp5.py b/amaranth_boards/versa_ecp5.py
new file mode 100644
index 0000000..9001a8e
--- /dev/null
+++ b/amaranth_boards/versa_ecp5.py
@@ -0,0 +1,176 @@
+import os
+import subprocess
+
+from amaranth.build import *
+from amaranth.vendor.lattice_ecp5 import *
+from .resources import *
+
+
+__all__ = ["VersaECP5Platform"]
+
+
+class VersaECP5Platform(LatticeECP5Platform):
+ device = "LFE5UM-45F"
+ package = "BG381"
+ speed = "8"
+ default_clk = "clk100"
+ default_rst = "rst"
+ resources = [
+ Resource("rst", 0, PinsN("T1", dir="i"), Attrs(IO_TYPE="LVCMOS33")),
+ Resource("clk100", 0, DiffPairs("P3", "P4", dir="i"),
+ Clock(100e6), Attrs(IO_TYPE="LVDS")),
+ Resource("pclk", 0, DiffPairs("A4", "A5", dir="i"),
+ Attrs(IO_TYPE="LVDS")),
+
+ *LEDResources(pins="E16 D17 D18 E18 F17 F18 E17 F16",
+ attrs=Attrs(IO_TYPE="LVCMOS25")),
+
+ Resource("alnum_led", 0,
+ Subsignal("a", PinsN("M20", dir="o")),
+ Subsignal("b", PinsN("L18", dir="o")),
+ Subsignal("c", PinsN("M19", dir="o")),
+ Subsignal("d", PinsN("L16", dir="o")),
+ Subsignal("e", PinsN("L17", dir="o")),
+ Subsignal("f", PinsN("M18", dir="o")),
+ Subsignal("g", PinsN("N16", dir="o")),
+ Subsignal("h", PinsN("M17", dir="o")),
+ Subsignal("j", PinsN("N18", dir="o")),
+ Subsignal("k", PinsN("P17", dir="o")),
+ Subsignal("l", PinsN("N17", dir="o")),
+ Subsignal("m", PinsN("P16", dir="o")),
+ Subsignal("n", PinsN("R16", dir="o")),
+ Subsignal("p", PinsN("R17", dir="o")),
+ Subsignal("dp", PinsN("U1", dir="o")),
+ Attrs(IO_TYPE="LVCMOS25")
+ ),
+
+ *SwitchResources(pins={0: "H2", 1: "K3", 2: "G3", 3: "F2" },
+ attrs=Attrs(IO_TYPE="LVCMOS15")),
+ *SwitchResources(pins={4: "J18", 5: "K18", 6: "K19", 7: "K20"},
+ attrs=Attrs(IO_TYPE="LVCMOS25")),
+
+ UARTResource(0,
+ rx="C11", tx="A11",
+ attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
+ ),
+
+ *SPIFlashResources(0,
+ cs_n="R2", clk="U3", cipo="W2", copi="V2", wp_n="Y2", hold_n="W1",
+ attrs=Attrs(IO_TYPE="LVCMOS33")
+ ),
+
+ Resource("eth_clk125", 0, Pins("L19", dir="i"),
+ Clock(125e6), Attrs(IO_TYPE="LVCMOS25")),
+ Resource("eth_clk125_pll", 0, Pins("U16", dir="i"),
+ Clock(125e6), Attrs(IO_TYPE="LVCMOS25")), # NC by default
+ Resource("eth_rgmii", 0,
+ Subsignal("rst", PinsN("U17", dir="o")),
+ Subsignal("mdc", Pins("T18", dir="o")),
+ Subsignal("mdio", Pins("U18", dir="io")),
+ Subsignal("tx_clk", Pins("P19", dir="o")),
+ Subsignal("tx_ctl", Pins("R20", dir="o")),
+ Subsignal("tx_data", Pins("N19 N20 P18 P20", dir="o")),
+ Subsignal("rx_clk", Pins("L20", dir="i")),
+ Subsignal("rx_ctl", Pins("U19", dir="i")),
+ Subsignal("rx_data", Pins("T20 U20 T19 R18", dir="i")),
+ Attrs(IO_TYPE="LVCMOS25")
+ ),
+ Resource("eth_sgmii", 0,
+ Subsignal("rst", PinsN("U17", dir="o"), Attrs(IO_TYPE="LVCMOS25")),
+ Subsignal("mdc", Pins("T18", dir="o"), Attrs(IO_TYPE="LVCMOS25")),
+ Subsignal("mdio", Pins("U18", dir="io"), Attrs(IO_TYPE="LVCMOS25")),
+ Subsignal("tx", DiffPairs("W13", "W14", dir="o")),
+ Subsignal("rx", DiffPairs("Y14", "Y15", dir="i")),
+ ),
+
+ Resource("eth_clk125", 1, Pins("J20", dir="i"),
+ Clock(125e6), Attrs(IO_TYPE="LVCMOS25")),
+ Resource("eth_clk125_pll", 1, Pins("C18", dir="i"),
+ Clock(125e6), Attrs(IO_TYPE="LVCMOS25")), # NC by default
+ Resource("eth_rgmii", 1,
+ Subsignal("rst", PinsN("F20", dir="o")),
+ Subsignal("mdc", Pins("G19", dir="o")),
+ Subsignal("mdio", Pins("H20", dir="io")),
+ Subsignal("tx_clk", Pins("C20", dir="o")),
+ Subsignal("tx_ctrl", Pins("E19", dir="o")),
+ Subsignal("tx_data", Pins("J17 J16 D19 D20", dir="o")),
+ Subsignal("rx_clk", Pins("J19", dir="i")),
+ Subsignal("rx_ctrl", Pins("F19", dir="i")),
+ Subsignal("rx_data", Pins("G18 G16 H18 H17", dir="i")),
+ Attrs(IO_TYPE="LVCMOS25")
+ ),
+ Resource("eth_sgmii", 1,
+ Subsignal("rst", PinsN("F20", dir="o"), Attrs(IO_TYPE="LVCMOS25")),
+ Subsignal("mdc", Pins("G19", dir="o"), Attrs(IO_TYPE="LVCMOS25")),
+ Subsignal("mdio", Pins("H20", dir="io"), Attrs(IO_TYPE="LVCMOS25")),
+ Subsignal("tx", DiffPairs("W17", "W18", dir="o")),
+ Subsignal("rx", DiffPairs("Y16", "Y17", dir="i")),
+ ),
+
+ Resource("ddr3", 0,
+ Subsignal("rst", PinsN("N4", dir="o")),
+ Subsignal("clk", DiffPairs("M4", "N5", dir="o"), Attrs(IO_TYPE="SSTL135D_I")),
+ Subsignal("clk_en", Pins("N2", dir="o")),
+ Subsignal("cs", PinsN("K1", dir="o")),
+ Subsignal("we", PinsN("M1", dir="o")),
+ Subsignal("ras", PinsN("P1", dir="o")),
+ Subsignal("cas", PinsN("L1", dir="o")),
+ Subsignal("a", Pins("P2 C4 E5 F5 B3 F4 B5 E4 C5 E3 D5 B4 C3", dir="o")),
+ Subsignal("ba", Pins("P5 N3 M3", dir="o")),
+ Subsignal("dqs", DiffPairs("K2 H4", "J1 G5", dir="io"), Attrs(IO_TYPE="SSTL135D_I", DIFFRESISTOR="100", TERMINATION="OFF")),
+ Subsignal("dq", Pins("L5 F1 K4 G1 L4 H1 G2 J3 D1 C1 E2 C2 F3 A2 E1 B1",
+ dir="io")), Attrs(TERMINATION="75"),
+ Subsignal("dm", Pins("J4 H5", dir="o")),
+ Subsignal("odt", Pins("L2", dir="o")),
+ Attrs(IO_TYPE="SSTL135_I", SLEWRATE="FAST")
+ )
+ ]
+ connectors = [
+ Connector("expcon", 1, """
+ - - - B19 B12 B9 E6 D6 E7 D7 B11 B6 E9 D9 B8 C8 D8 E8 C7 C6
+ - - - - - - - - - - - - - - - - - - - -
+ """), # X3
+ Connector("expcon", 2, """
+ A8 - A12 A13 B13 C13 D13 E13 A14 C14 D14 E14 D11 C10 A9 B10 D12 E12 - -
+ B15 - C15 - D15 - E15 A16 B16 - C16 D16 B17 - C17 A17 B18 A7 A18 -
+ """), # X4
+ ]
+
+ @property
+ def file_templates(self):
+ return {
+ **super().file_templates,
+ "{{name}}-openocd.cfg": r"""
+ interface ftdi
+ {# FTDI descriptors is identical between non-5G and 5G recent Versa boards #}
+ ftdi_device_desc "Lattice ECP5_5G VERSA Board"
+ ftdi_vid_pid 0x0403 0x6010
+ ftdi_channel 0
+ ftdi_layout_init 0xfff8 0xfffb
+ reset_config none
+ adapter_khz 25000
+
+ # ispCLOCK device (unusable with openocd and must be bypassed)
+ #jtag newtap ispclock tap -irlen 8 -expected-id 0x00191043
+ # ECP5 device
+ {% if "5G" in platform.device -%}
+ jtag newtap ecp5 tap -irlen 8 -expected-id 0x81112043 ; # LFE5UM5G-45F
+ {% else -%}
+ jtag newtap ecp5 tap -irlen 8 -expected-id 0x01112043 ; # LFE5UM-45F
+ {% endif %}
+ """
+ }
+
+ def toolchain_program(self, products, name):
+ openocd = os.environ.get("OPENOCD", "openocd")
+ with products.extract("{}-openocd.cfg".format(name), "{}.svf".format(name)) \
+ as (config_filename, vector_filename):
+ subprocess.check_call([openocd,
+ "-f", config_filename,
+ "-c", "transport select jtag; init; svf -quiet {}; exit".format(vector_filename)
+ ])
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ VersaECP5Platform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/versa_ecp5_5g.py b/amaranth_boards/versa_ecp5_5g.py
new file mode 100644
index 0000000..36e6997
--- /dev/null
+++ b/amaranth_boards/versa_ecp5_5g.py
@@ -0,0 +1,14 @@
+from .versa_ecp5 import VersaECP5Platform
+
+
+__all__ = ["VersaECP55GPlatform"]
+
+
+class VersaECP55GPlatform(VersaECP5Platform):
+ device = "LFE5UM5G-45F"
+ # Everything else is identical between 3G and 5G Versa boards.
+
+
+if __name__ == "__main__":
+ from .test.blinky import *
+ VersaECP55GPlatform().build(Blinky(), do_program=True)
diff --git a/amaranth_boards/zturn_lite_z007s.py b/amaranth_boards/zturn_lite_z007s.py
new file mode 100644
index 0000000..f732f9f
--- /dev/null
+++ b/amaranth_boards/zturn_lite_z007s.py
@@ -0,0 +1,76 @@
+from amaranth.build import *
+from amaranth.vendor.xilinx_7series import *
+
+
+__all__ = ["ZTurnLiteZ007SPlatform"]
+
+
+class ZTurnLiteZ007SPlatform(Xilinx7SeriesPlatform):
+ device = "xc7z007s"
+ package = "clg400"
+ speed = "1"
+ resources = []
+ connectors = [
+ Connector("expansion", 0,
+ "- - "
+ "B19 E17 "
+ "A20 D18 "
+ "- - "
+ "E18 D19 "
+ "E19 D20 "
+ "G17 F16 "
+ "G18 F17 "
+ "- - "
+ "- - "
+ "J18 J20 "
+ "H18 H20 "
+ "C20 K17 "
+ "B20 K18 "
+ "- - "
+ "G19 K19 "
+ "G20 J19 "
+ "F19 H15 "
+ "F20 G15 "
+ "- - "
+ "L16 K14 "
+ "L17 J14 "
+ "L19 H16 "
+ "L20 H17 "
+ "- - "
+ "K16 L14 "
+ "J16 L15 "
+ "M17 M14 "
+ "M18 M15 "
+ "- - "
+ "N17 P15 "
+ "P18 P16 "
+ "M19 N15 "
+ "M20 N16 "
+ "- - "
+ "N18 - "
+ "P19 R16 "
+ "N20 R17 "
+ "P20 T20 "
+ "- U20 "
+ "- - "
+ "T16 V20 "
+ "U17 W20 "
+ "U18 T17 "
+ "U19 R18 "
+ "- - "
+ "W18 V17 "
+ "W19 V18 "
+ "U14 V16 "
+ "U15 W16 "
+ "- - "
+ "V15 Y18 "
+ "W15 Y19 "
+ "Y16 W14 "
+ "Y17 Y14 "
+ "- - "
+ "- - "
+ "- - "
+ "- - "
+ "- - "
+ ),
+ ]
diff --git a/amaranth_boards/zturn_lite_z010.py b/amaranth_boards/zturn_lite_z010.py
new file mode 100644
index 0000000..d73de1a
--- /dev/null
+++ b/amaranth_boards/zturn_lite_z010.py
@@ -0,0 +1,8 @@
+from .zturn_lite_z007s import ZTurnLiteZ007SPlatform
+
+
+__all__ = ["ZTurnLiteZ010Platform"]
+
+
+class ZTurnLiteZ010Platform(ZTurnLiteZ007SPlatform):
+ device = "xc7z010"