diff --git a/README.md b/README.md index 321fd65..2c2cc67 100644 --- a/README.md +++ b/README.md @@ -119,39 +119,41 @@ The Colorlight5A is a very nice board to start with, cheap, powerful, easy to us [> Development boards --------------------- -| Name | FPGA Family | FPGA device | Sys-Clk | TTY | RAM | PCIe | Ethernet | Flash | SDCard | -|--------------|---------------------|---------------|---------|------|--------------------|-----------|----------------|-------------|--------| -| AC701 | Xilinx Artix7 | XC7A200T | 100MHz | FTDI | 64-bit ?MB DDR3 | Gen2 X4 | 1Gbps RGMII | 16MB QSPI | Yes* | -| Aller | Xilinx Artix7 | XC7A200T | 100MHz | PCIe | 16-bit 256MB DDR3 | Gen2 X4 | No | 128MB QSPI | No | -| Arty(A7) | Xilinx Artix7 | XC7A35T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 100Mbps MII | 16MB QSPI | No | -| ArtyS7 | Xilinx Spartan7 | XC7S50 | 100MHz | FTDI | 16-bit 256MB DDR3 | No | No | 16MB QSPI | No | -| Avalanche | Microsemi PolarFire | MPF300TS | 100MHz | IOs | 16-bit 256MB DDR3 | No | 1Gbps RGMII* | 8MB QSPI* | No | -| C10LPRefKit | Intel Cyclone10 | 10CL055 | 50MHz | FTDI | 16-bit 32MB SDR | No | 100Mbps MII | 16MB QSPI | No | -| De0Nano | Intel Cyclone4 | EP4CE22F | 50MHz | FTDI | 16-bit 32MB SDR | No | No | No | No | -| De10Lite | Intel MAX10 | 10M50DA | 50MHz | IOs | 16-bit 64MB SDR | No | No | No | No | -| DECA | Intel MAX10 | 10M50DA | 50MHz | JTAG | 16-bit 512MB DDR3* | No | Yes | No | Yes | -| De10Nano | Intel Cyclone5 | 5CSEBA6 | 50MHz | IOs | 16-bit 32MB SDR | No | No | No | Yes | -| Arrow SoCKit | Intel Cyclone5 | 5CSXFC6D6F31C8| 50MHz | JTAG | 32-bit 1GB DDR3* | No | No | No | No | -| De1SoC | Intel Cyclone5 | 5CSEMA5 | 50MHz | IOs | 16-bit 64MB SDR | No | ? | ? | ? | -| De2-115 | Intel Cyclone4 | EP4CE115 | 50MHz | IOs | 16-bit 128MB SDR | No | 1Gbps GMII* | 8MB QSPI | Yes* | -| ECP5-EVN | Lattice ECP5 | LFE5UM5G-85F | 50MHz | FTDI | No | No | ? | ? | ? | -| Genesys2 | Xilinx Kintex7 | XC7K325T | 125MHz | FTDI | 32-bit 1GB DDR3 | No | 1Gbps RGMII | 32MB QSPI* | Yes | -| KC705 | Xilinx Kintex7 | XC7K325T | 125MHz | FTDI | 64-bit 1GB DDR3 | Gen2 X8** | 1Gbps GMII | 32MB QSPI* | Yes | -| KCU105 | Xilinx KintexU | XCKU40 | 125MHz | FTDI | 64-bit 1GB DDR4 | Gen3 X8** | 1Gbps-BASE-X | 64MB QSPI* | Yes | -| KX2 | Xilinx Kintex7 | XC7K160T | 125MHz | FTDI | 64-bit 1GB DDR3 | No | No | 64MB QSPI* | No | -| LiteFury | Xilinx Artix7 | XC7A100T | 100MHz | PCIe | 16-bit 512MB DDR3 | Gen2 X4 | No | 32MB QSPI* | No | -| MachXO3 | Lattice MachXO3 | LCMXO3L-6900C | 125MHz | ? | ? | No | No | ? | No | -| Mercury XU5 | Xilinx ZynqU+ | XCZU2EG | 125MHz | FTDI | 16-bit 512MB DDR4 | No | No | 64MB QSPI* | No | -| Mimas A7 | Xilinx Artix7 | XC7A50T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 1Gbps RGMII | 16MB QSPI | No | -| Nereid | Xilinx Kintex7 | XC7K160T | 100MHz | PCIe | 64-bit 4GB DDR3 | Gen2 X4 | No | 16MB QSPI | No | -| Nexys4DDR | Xilinx Artix7 | XC7A100T | 100MHz | FTDI | 16-bit 128MB DDR2 | No | 100Mbps RMII | 16MB QSPI* | Yes | -| Nexys Video | Xilinx Artix7 | XC7A200T | 100MHz | FTDI | 16-bit 512MB DDR3 | No | 1Gbps RMII | 32MB QSPI* | Yes | -| SP605 | Xilinx Spartan6 | XC6SLX45T | 100MHz | FTDI | 16-bit 128MB DDR3* | Gen1 X1* | 1Gbps GMII | 8MB QSPI* | Yes* | -| Tagus | Xilinx Artix7 | XC7A200T | 100MHz | PCIe | 16-bit 256MB DDR3 | Gen2 X1 | 1Gbps-BASE-X* | 16MB QSPI* | No | -| VC707 | Xilinx Virex7 | XC7VX485T | 125MHz | FTDI | 64-bit 1GB DDR3 | Gen3 X8* | 1Gbps GMII | 16MB QSPI* | Yes* | -| VCU118 | Xilinx VirtexU+ | XCVU9P | 125MHz | FTDI | 2 x 64-bit 4GB DDR4| Gen3 X16*| 1Gbps SGMII | 16MB QSPI* | Yes* | -| Versa ECP5 | Lattice ECP5 | LFE5UM5G-45F | 75MHz | FTDI | 16-bit 128MB DDR3 | Gen1 X1* | 1Gbps RGMII | 16MB QSPI* | No | -| ZCU104 | Xilinx ZynqU+ | XCZU7EV | 125MHz | FTDI | 64-bit 1GB DDR4 | No | 1Gbps RGMII* | 64MB QSPI* | Yes* | -| Zybo Z7 | Xilinx ZynqU+ | XC7Z010 | 125MHz | FTDI | 64-bit 1GB DDR4 | No | 1Gbps RGMII* | 64MB QSPI* | Yes* | +| Name | FPGA Family | FPGA device | Sys-Clk | TTY | RAM | PCIe | Ethernet | Flash | SDCard | +|----------------|---------------------|---------------|---------|------|--------------------|-----------|----------------|-------------|--------| +| AC701 | Xilinx Artix7 | XC7A200T | 100MHz | FTDI | 64-bit ?MB DDR3 | Gen2 X4 | 1Gbps RGMII | 16MB QSPI | Yes* | +| Aller | Xilinx Artix7 | XC7A200T | 100MHz | PCIe | 16-bit 256MB DDR3 | Gen2 X4 | No | 128MB QSPI | No | +| Arty(A7) | Xilinx Artix7 | XC7A35T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 100Mbps MII | 16MB QSPI | No | +| ArtyS7 | Xilinx Spartan7 | XC7S50 | 100MHz | FTDI | 16-bit 256MB DDR3 | No | No | 16MB QSPI | No | +| Avalanche | Microsemi PolarFire | MPF300TS | 100MHz | IOs | 16-bit 256MB DDR3 | No | 1Gbps RGMII* | 8MB QSPI* | No | +| C10LPRefKit | Intel Cyclone10 | 10CL055 | 50MHz | FTDI | 16-bit 32MB SDR | No | 100Mbps MII | 16MB QSPI | No | +| De0Nano | Intel Cyclone4 | EP4CE22F | 50MHz | FTDI | 16-bit 32MB SDR | No | No | No | No | +| De10Lite | Intel MAX10 | 10M50DA | 50MHz | IOs | 16-bit 64MB SDR | No | No | No | No | +| DECA | Intel MAX10 | 10M50DA | 50MHz | JTAG | 16-bit 512MB DDR3* | No | Yes | No | Yes | +| De10Nano | Intel Cyclone5 | 5CSEBA6 | 50MHz | IOs | 16-bit 32MB SDR | No | No | No | Yes | +| Arrow SoCKit | Intel Cyclone5 | 5CSXFC6D6F31C8| 50MHz | JTAG | 32-bit 1GB DDR3* | No | No | No | No | +| De1SoC | Intel Cyclone5 | 5CSEMA5 | 50MHz | IOs | 16-bit 64MB SDR | No | ? | ? | ? | +| De2-115 | Intel Cyclone4 | EP4CE115 | 50MHz | IOs | 16-bit 128MB SDR | No | 1Gbps GMII* | 8MB QSPI | Yes* | +| ECP5-EVN | Lattice ECP5 | LFE5UM5G-85F | 50MHz | FTDI | No | No | ? | ? | ? | +| Genesys2 | Xilinx Kintex7 | XC7K325T | 125MHz | FTDI | 32-bit 1GB DDR3 | No | 1Gbps RGMII | 32MB QSPI* | Yes | +| KC705 | Xilinx Kintex7 | XC7K325T | 125MHz | FTDI | 64-bit 1GB DDR3 | Gen2 X8** | 1Gbps GMII | 32MB QSPI* | Yes | +| KCU105 | Xilinx KintexU | XCKU40 | 125MHz | FTDI | 64-bit 1GB DDR4 | Gen3 X8** | 1Gbps-BASE-X | 64MB QSPI* | Yes | +| KX2 | Xilinx Kintex7 | XC7K160T | 125MHz | FTDI | 64-bit 1GB DDR3 | No | No | 64MB QSPI* | No | +| LiteFury | Xilinx Artix7 | XC7A100T | 100MHz | PCIe | 16-bit 512MB DDR3 | Gen2 X4 | No | 32MB QSPI* | No | +| MachXO3 | Lattice MachXO3 | LCMXO3L-6900C | 125MHz | ? | ? | No | No | ? | No | +| Mercury XU5 | Xilinx ZynqU+ | XCZU2EG | 125MHz | FTDI | 16-bit 512MB DDR4 | No | No | 64MB QSPI* | No | +| Mimas A7 | Xilinx Artix7 | XC7A50T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 1Gbps RGMII | 16MB QSPI | No | +| Nereid | Xilinx Kintex7 | XC7K160T | 100MHz | PCIe | 64-bit 4GB DDR3 | Gen2 X4 | No | 16MB QSPI | No | +| Nexys4DDR | Xilinx Artix7 | XC7A100T | 100MHz | FTDI | 16-bit 128MB DDR2 | No | 100Mbps RMII | 16MB QSPI* | Yes | +| Nexys Video | Xilinx Artix7 | XC7A200T | 100MHz | FTDI | 16-bit 512MB DDR3 | No | 1Gbps RMII | 32MB QSPI* | Yes | +| QMTech XC7A35T | Xilinx Artix7 | XC7A35T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 1Gbps GMII** | 16MB QSPI | Yes**| +| SP605 | Xilinx Spartan6 | XC6SLX45T | 100MHz | FTDI | 16-bit 128MB DDR3* | Gen1 X1* | 1Gbps GMII | 8MB QSPI* | Yes* | +| Tagus | Xilinx Artix7 | XC7A200T | 100MHz | PCIe | 16-bit 256MB DDR3 | Gen2 X1 | 1Gbps-BASE-X* | 16MB QSPI* | No | +| VC707 | Xilinx Virex7 | XC7VX485T | 125MHz | FTDI | 64-bit 1GB DDR3 | Gen3 X8* | 1Gbps GMII | 16MB QSPI* | Yes* | +| VCU118 | Xilinx VirtexU+ | XCVU9P | 125MHz | FTDI | 2 x 64-bit 4GB DDR4| Gen3 X16*| 1Gbps SGMII | 16MB QSPI* | Yes* | +| Versa ECP5 | Lattice ECP5 | LFE5UM5G-45F | 75MHz | FTDI | 16-bit 128MB DDR3 | Gen1 X1* | 1Gbps RGMII | 16MB QSPI* | No | +| ZCU104 | Xilinx ZynqU+ | XCZU7EV | 125MHz | FTDI | 64-bit 1GB DDR4 | No | 1Gbps RGMII* | 64MB QSPI* | Yes* | +| Zybo Z7 | Xilinx ZynqU+ | XC7Z010 | 125MHz | FTDI | 64-bit 1GB DDR4 | No | 1Gbps RGMII* | 64MB QSPI* | Yes* | \* Present on the board but not yet supported or validated with LiteX. +\*\* available on the daughterboard diff --git a/litex_boards/platforms/qmtech_daughterboard.py b/litex_boards/platforms/qmtech_daughterboard.py new file mode 100644 index 0000000..12ceaf9 --- /dev/null +++ b/litex_boards/platforms/qmtech_daughterboard.py @@ -0,0 +1,106 @@ +from litex.build.generic_platform import Subsignal, Pins, IOStandard, Misc + +class QMTechDaughterboard: + """ + the QMTech daughterboard contains standard peripherals + and can be used with a number of different FPGA core boards + source: https://www.aliexpress.com/item/1005001829520314.html + """ + + def __init__(self, io_standard) -> None: + """ + because the board can be used with FPGAs core boards from + different vendors, the constructor needs the vendor specific IOStandard + """ + self.io = [ + ("serial", 0, + Subsignal("rx", Pins("J2:15")), + Subsignal("tx", Pins("J2:16")), + io_standard + ), + + ("user_led", 0, Pins("J2:40"), io_standard), + ("user_led", 1, Pins("J2:39"), io_standard), + ("user_led", 2, Pins("J2:38"), io_standard), + ("user_led", 3, Pins("J2:37"), io_standard), + ("user_led", 4, Pins("J2:36"), io_standard), + + ("user_btn", 0, Pins("J3:7"), io_standard), + ("user_btn", 1, Pins("J2:44"), io_standard), + ("user_btn", 2, Pins("J2:43"), io_standard), + ("user_btn", 3, Pins("J2:42"), io_standard), + ("user_btn", 4, Pins("J2:41"), io_standard), + + # GMII Ethernet + ("eth_clocks", 0, + Subsignal("tx", Pins("J3:22")), + Subsignal("gtx", Pins("J3:29")), + Subsignal("rx", Pins("J3:37")), + io_standard + ), + ("eth", 0, + # rst is hardwired on the board + #Subsignal("rst_n", Pins("-")), + Subsignal("int_n", Pins("J3:26")), + Subsignal("mdio", Pins("J3:15")), + Subsignal("mdc", Pins("J3:16")), + Subsignal("rx_dv", Pins("J3:42")), + Subsignal("rx_er", Pins("J3:32")), + Subsignal("rx_data", Pins("J3:41 J3:40 J3:39 J3:38 J3:36 J3:35 J3:34 J3:33")), + Subsignal("tx_en", Pins("J3:28")), + Subsignal("tx_er", Pins("J3:17")), + Subsignal("tx_data", Pins("J3:27 J3:25 J3:24 J3:23 J3:21 J3:20 J3:19 J3:18")), + Subsignal("col", Pins("J3:31")), + Subsignal("crs", Pins("J3:30")), + io_standard + ), + + # Seven Segment + ("seven_seg_ctl", 0, Pins("J2:33"), io_standard), + ("seven_seg_ctl", 1, Pins("J2:27"), io_standard), + ("seven_seg_ctl", 2, Pins("J2:35"), io_standard), + ("seven_seg", 0, Pins("J2:31 J2:26 J2:28 J2:32 J2:34 J2:29 J2:25 J2:30"), io_standard), + + # VGA + ("vga", 0, + Subsignal("hsync_n", Pins("J3:44")), + Subsignal("vsync_n", Pins("J3:43")), + Subsignal("r", Pins("J3:57 J3:56 J3:59 J3:58 J3:60")), + Subsignal("g", Pins("J3:51 J3:50 J3:53 J3:52 J3:54 J3:55")), + Subsignal("b", Pins("J3:46 J3:45 J3:48 J3:47 J3:49")), + io_standard + ), + + # PullUp resistors are on the board, so we don't need them in the FPGA + ("sdcard", 0, + Subsignal("data", Pins("J3:10 J3:9 J3:14 J3:13")), + Subsignal("cmd", Pins("J3:12")), + Subsignal("clk", Pins("J3:11")), + Subsignal("cd", Pins("J3:8")), + Misc("SLEW=FAST"), + io_standard, + ), + ] + + connectors = [ + ("pmoda", "J2:17 J2:19 J2:21 J2:23 J2:18 J2:20 J2:22 J2:24"), #J10 + ("pmodb", "J2:7 J2:9 J2:11 J2:13 J2:8 J2:10 J2:12 J2:14"), #J11 + ("J1", { + 3: "J2:60", + 4: "J2:59", + 5: "J2:58", + 6: "J2:57", + 7: "J2:56", + 8: "J2:55", + 9: "J2:54", + 10: "J2:53", + 11: "J2:52", + 12: "J2:51", + 13: "J2:50", + 14: "J2:49", + 15: "J2:48", + 16: "J2:47", + 17: "J2:46", + 18: "J2:45" + }), + ] \ No newline at end of file diff --git a/litex_boards/platforms/qmtech_xc7a35t.py b/litex_boards/platforms/qmtech_xc7a35t.py new file mode 100644 index 0000000..7fb34c5 --- /dev/null +++ b/litex_boards/platforms/qmtech_xc7a35t.py @@ -0,0 +1,179 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2021 Hans Baier +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import Pins, Subsignal, IOStandard, Misc +from litex.build.xilinx import XilinxPlatform +from litex.build.openocd import OpenOCD + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + # Clk / Rst + ("clk50", 0, Pins("N11"), IOStandard("LVCMOS33")), + + # The core board does not have a USB serial on it, + # so you will have to attach an USB to serial adapter + # on these pins + ("gpio_serial", 0, + Subsignal("tx", Pins("J2:7")), + Subsignal("rx", Pins("J2:8")), + IOStandard("LVCMOS33") + ), + + # SPIFlash + # MT25QL128 + ("spiflash4x", 0, # clock needs to be accessed through STARTUPE2 + Subsignal("cs_n", Pins("L12")), + Subsignal("clk", Pins("E8")), + Subsignal("dq", Pins("J13", "J14", "K15", "K16")), + IOStandard("LVCMOS33") + ), + + # DDR3 SDRAM + # MT41J128M16JT-125K + ("ddram", 0, + Subsignal("a", Pins("B14 C8 A14 C14 C9 B10 D9 A12 D8 A13 B12 A9 A8 B11"), + IOStandard("SSTL135")), + Subsignal("ba", Pins("C16 A15 B15"), IOStandard("SSTL135")), + Subsignal("ras_n", Pins("B16"), IOStandard("SSTL135")), + Subsignal("cas_n", Pins("C11"), IOStandard("SSTL135")), + Subsignal("we_n", Pins("C12"), IOStandard("SSTL135")), + # cs_n is hardwired on the board + #Subsignal("cs_n", Pins("-"), IOStandard("SSTL135")), + Subsignal("dm", Pins("F12 H11"), IOStandard("SSTL135")), + Subsignal("dq", Pins( + "F15 F13 E16 D11 E12 E13 D16 E11", + "G12 J16 G16 J15 H14 H12 H16 H13"), + IOStandard("SSTL135"), + Misc("IN_TERM=UNTUNED_SPLIT_40")), + Subsignal("dqs_p", Pins("D14 G14"), + IOStandard("DIFF_SSTL135"), + Misc("IN_TERM=UNTUNED_SPLIT_40")), + Subsignal("dqs_n", Pins("D15 F14"), + IOStandard("DIFF_SSTL135"), + Misc("IN_TERM=UNTUNED_SPLIT_40")), + Subsignal("clk_p", Pins("B9"), IOStandard("DIFF_SSTL135")), + Subsignal("clk_n", Pins("A10"), IOStandard("DIFF_SSTL135")), + Subsignal("cke", Pins("D13"), IOStandard("SSTL135")), + Subsignal("odt", Pins("C13"), IOStandard("SSTL135")), + Subsignal("reset_n", Pins("E15"), IOStandard("SSTL135")), + Misc("SLEW=FAST"), + ), +] + +# The connectors are named after the daughterboard, not the core board +# because on the different core boards the names vary, but on the +# daughterboard they stay the same, which we need to connect the +# daughterboard peripherals to the core board. +# On this board J2 is U7 and J3 is U8 +_connectors = [ + ("J2", { + # odd row even row + 7: "M12", 8: "N13", + 9: "N14", 10: "N16", + 11: "P15", 12: "P16", + 13: "R15", 14: "R16", + 15: "T14", 16: "T15", + 17: "P13", 18: "P14", + 19: "T13", 20: "R13", + 21: "T12", 22: "R12", + 23: "L13", 24: "N12", + 25: "K12", 26: "K13", + 27: "P10", 28: "P11", + 29: "N9", 30: "P9", + 31: "T10", 32: "R11", + 33: "T9", 34: "R10", + 35: "T8", 36: "R8", + 37: "T7", 38: "R7", + 39: "T5", 40: "R6", + 41: "P6", 42: "R5", + 43: "N6", 44: "M6", + 45: "L5", 46: "P5", + 47: "T4", 48: "T3", + 49: "R3", 50: "T2", + 51: "R2", 52: "R1", + 53: "M5", 54: "N4", + 55: "P4", 56: "P3", + 57: "N1", 58: "P1", + 59: "M2", 60: "M1", + }), + ("J3", { + # odd row even row + 7: "B7", 8: "A7", + 9: "B6", 10: "B5", + 11: "E6", 12: "K5", + 13: "J5", 14: "J4", + 15: "G5", 16: "G4", + 17: "C7", 18: "C6", + 19: "D6", 20: "D5", + 21: "A5", 22: "A4", + 23: "B4", 24: "A3", + 25: "D4", 26: "C4", + 27: "C3", 28: "C2", + 29: "B2", 30: "A2", + 31: "C1", 32: "B1", + 33: "E2", 34: "D1", + 35: "E3", 36: "D3", + 37: "F5", 38: "E5", + 39: "F2", 40: "E1", + 41: "F4", 42: "F3", + 43: "G2", 44: "G1", + 45: "H2", 46: "H1", + 47: "K1", 48: "J1", + 49: "L3", 50: "L2", + 51: "H5", 52: "H4", + 53: "J3", 54: "H3", + 55: "K3", 56: "K2", + 57: "L4", 58: "M4", + 59: "N3", 60: "N2", + }) +] + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(XilinxPlatform): + default_clk_name = "clk50" + default_clk_period = 1e9/50e6 + + # these resources conflict with daughterboard resources + # so they are only used if the daughterboard is not present + core_resources = [ + ("user_led", 0, Pins("E6"), IOStandard("LVCMOS33")), + ("cpu_reset", 0, Pins("K5"), IOStandard("LVCMOS33")), + ] + + def __init__(self, toolchain="vivado", with_daughterboard=False): + device = "xc7a35tftg256-1" + io = _io + connectors = _connectors + + if with_daughterboard: + from litex_boards.platforms.qmtech_daughterboard import QMTechDaughterboard + daughterboard = QMTechDaughterboard(IOStandard("LVCMOS33")) + io += daughterboard.io + connectors += daughterboard.connectors + else: + io += self.core_resources + + XilinxPlatform.__init__(self, device, io, connectors, toolchain=toolchain) + self.toolchain.bitstream_commands = \ + ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] + self.toolchain.additional_commands = \ + ["write_cfgmem -force -format bin -interface spix4 -size 16 " + "-loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] + self.add_platform_command("set_property INTERNAL_VREF 0.675 [get_iobanks 15]") + self.add_platform_command("set_property CFGBVS VCCO [current_design]") + self.add_platform_command("set_property CONFIG_VOLTAGE 3.3 [current_design]") + + def create_programmer(self): + bscan_spi = "bscan_spi_xc7a35t.bit" + return OpenOCD("openocd_xc7_ft2232.cfg", bscan_spi) + + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + from litex.build.xilinx import symbiflow + self.add_period_constraint(self.lookup_request("clk50", loose=True), 1e9/50e6) \ No newline at end of file diff --git a/litex_boards/targets/qmtech_xc7a35t.py b/litex_boards/targets/qmtech_xc7a35t.py new file mode 100755 index 0000000..804305e --- /dev/null +++ b/litex_boards/targets/qmtech_xc7a35t.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2021 Hans Baier +# SPDX-License-Identifier: BSD-2-Clause + +# https://www.aliexpress.com/item/1000006630084.html + +import os +import argparse + +from migen import * + +from litex_boards.platforms import qmtech_xc7a35t +from litex.build.xilinx.vivado import vivado_build_args, vivado_build_argdict + +from litex.soc.cores.clock import * +from litex.soc.integration.soc import SoCRegion +from litex.soc.integration.soc_core import * +from litex.soc.integration.builder import * +from litex.soc.cores.video import VideoVGAPHY +from litex.soc.cores.led import LedChaser + +from litedram.modules import MT41J128M16 +from litedram.phy import s7ddrphy + +from litespi.modules import MT25QL128 +from litespi.opcodes import SpiNorFlashOpCodes as Codes +from litespi.phy.generic import LiteSPIPHY +from litespi import LiteSPI + +from liteeth.phy.mii import LiteEthPHYMII + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq, with_ethernet, with_vga): + self.rst = Signal() + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) + self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True) + self.clock_domains.cd_idelay = ClockDomain() + self.clock_domains.cd_eth = ClockDomain() + if with_ethernet: + self.clock_domains.cd_eth = ClockDomain() + if with_vga: + self.clock_domains.cd_vga = ClockDomain(reset_less=True) + + # # # + + self.submodules.pll = pll = S7PLL(speedgrade=-1) + try: + reset_button = platform.request("cpu_reset") + self.comb += pll.reset.eq(~reset_button | self.rst) + except: + self.comb += pll.reset.eq(self.rst) + + pll.register_clkin(platform.request("clk50"), 50e6) + pll.create_clkout(self.cd_sys, sys_clk_freq) + pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq) + pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90) + pll.create_clkout(self.cd_idelay, 200e6) + if with_ethernet: + pll.create_clkout(self.cd_eth, 25e6) + if with_vga: + pll.create_clkout(self.cd_vga, 40e6) + + platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) # Ignore sys_clk to pll.clkin path created by SoC's rst. + + self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_idelay) + +# BaseSoC ------------------------------------------------------------------------------------------ + +class BaseSoC(SoCCore): + def __init__(self, toolchain="vivado", sys_clk_freq=int(100e6), with_daughterboard=False, + with_ethernet=False, with_etherbone=False, eth_ip="192.168.1.50", eth_dynamic_ip=False, + with_video_terminal=False, with_video_framebuffer=False, + ident_version=True, with_jtagbone=True, with_mapped_flash=False, **kwargs): + platform = qmtech_xc7a35t.Platform(toolchain=toolchain, with_daughterboard=with_daughterboard) + + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, sys_clk_freq, + ident = "LiteX SoC on QMTech XC7A35T" + (" + Daughterboard" if with_daughterboard else ""), + ident_version = ident_version, + **kwargs) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq, with_ethernet or with_etherbone, with_video_terminal or with_video_framebuffer) + + # DDR3 SDRAM ------------------------------------------------------------------------------- + if not self.integrated_main_ram_size: + self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"), + memtype = "DDR3", + nphases = 4, + sys_clk_freq = sys_clk_freq) + self.add_sdram("sdram", + phy = self.ddrphy, + module = MT41J128M16(sys_clk_freq, "1:4"), + l2_cache_size = kwargs.get("l2_size", 8192) + ) + + # Ethernet / Etherbone --------------------------------------------------------------------- + if with_ethernet or with_etherbone: + self.submodules.ethphy = LiteEthPHYMII( + clock_pads = self.platform.request("eth_clocks"), + pads = self.platform.request("eth")) + if with_ethernet: + self.add_ethernet(phy=self.ethphy, dynamic_ip=eth_dynamic_ip) + if with_etherbone: + self.add_etherbone(phy=self.ethphy, ip_address=eth_ip) + # The daughterboard has the tx clock wired to a non-clock pin, so we can't help it + self.platform.add_platform_command("set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets eth_clocks_tx_IBUF]") + + # Jtagbone --------------------------------------------------------------------------------- + if with_jtagbone: + self.add_jtagbone() + + # Flash (through LiteSPI, experimental). + if with_mapped_flash: + self.submodules.spiflash_phy = LiteSPIPHY(platform.request("spiflash4x"), MT25QL128(Codes.READ_1_1_1)) + self.submodules.spiflash_mmap = LiteSPI(self.spiflash_phy, clk_freq=sys_clk_freq, mmap_endianness=self.cpu.endianness) + spiflash_region = SoCRegion(origin=self.mem_map.get("spiflash", None), size=MT25QL128.total_size, cached=False) + self.bus.add_slave(name="spiflash", slave=self.spiflash_mmap.bus, region=spiflash_region) + + # Video ------------------------------------------------------------------------------------ + if with_video_terminal or with_video_framebuffer: + self.submodules.videophy = VideoVGAPHY(platform.request("vga"), clock_domain="vga") + if with_video_terminal: + self.add_video_terminal(phy=self.videophy, timings="800x600@60Hz", clock_domain="vga") + if with_video_framebuffer: + self.add_video_framebuffer(phy=self.videophy, timings="800x600@60Hz", clock_domain="vga") + + # Leds ------------------------------------------------------------------------------------- + self.submodules.leds = LedChaser( + pads = platform.request_all("user_led"), + sys_clk_freq = sys_clk_freq) + + if not with_daughterboard and kwargs["uart_name"] == "serial": + kwargs["uart_name"] = "jtag_serial" + +# Build -------------------------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser(description="LiteX SoC on Arty A7") + parser.add_argument("--toolchain", default="vivado", help="Toolchain use to build (default: vivado)") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--sys-clk-freq", default=100e6, help="System clock frequency (default: 100MHz)") + parser.add_argument("--with-daughterboard", action="store_true", help="Whether the core board is plugged into the QMTech daughterboard") + ethopts = parser.add_mutually_exclusive_group() + ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") + ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support") + parser.add_argument("--eth-ip", default="192.168.1.50", type=str, help="Ethernet/Etherbone IP address") + parser.add_argument("--eth-dynamic-ip", action="store_true", help="Enable dynamic Ethernet IP addresses setting") + sdopts = parser.add_mutually_exclusive_group() + sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support") + sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support") + parser.add_argument("--no-ident-version", action="store_false", help="Disable build time output") + parser.add_argument("--with-jtagbone", action="store_true", help="Enable Jtagbone support") + parser.add_argument("--with-mapped-flash", action="store_true", help="Enable Memory Mapped Flash") + viopts = parser.add_mutually_exclusive_group() + viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (VGA)") + viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (VGA)") + builder_args(parser) + soc_core_args(parser) + vivado_build_args(parser) + args = parser.parse_args() + + soc = BaseSoC( + toolchain = args.toolchain, + sys_clk_freq = int(float(args.sys_clk_freq)), + with_daughterboard = args.with_daughterboard, + with_ethernet = args.with_ethernet, + with_etherbone = args.with_etherbone, + eth_ip = args.eth_ip, + eth_dynamic_ip = args.eth_dynamic_ip, + ident_version = args.no_ident_version, + with_jtagbone = args.with_jtagbone, + with_mapped_flash = args.with_mapped_flash, + with_video_terminal = args.with_video_terminal, + with_video_framebuffer = args.with_video_framebuffer, + **soc_core_argdict(args) + ) + + if args.with_spi_sdcard: + soc.add_spi_sdcard() + if args.with_sdcard: + soc.add_sdcard() + + builder = Builder(soc, **builder_argdict(args)) + builder_kwargs = vivado_build_argdict(args) if args.toolchain == "vivado" else {} + builder.build(**builder_kwargs, run=args.build) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".bit")) + +if __name__ == "__main__": + main() diff --git a/test/test_targets.py b/test/test_targets.py index 03b62ab..def6615 100644 --- a/test/test_targets.py +++ b/test/test_targets.py @@ -51,6 +51,7 @@ class TestTargets(unittest.TestCase): platforms.append("acorn") platforms.append("marblemini") platforms.append("qmtech_wukong") + platforms.append("qmtech_xc7a35t") # Xilinx Kintex7 platforms.append("genesys2")