From 4a52996106bece10c05a2f586953c147d571d6a8 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 24 Sep 2021 11:12:16 +1000 Subject: [PATCH] Wukong board improvements This adds support for v2 of the board via a --board-version argument and a way to select the FPGA speed grade via a --speed-grade argument. Note that the speed grade now defaults to -1. QMTech confirmed that V1 of the board were made in two batches, one with -1 and one with -2, while V2 of the board is all -1. So -1 is the safer default. This also fixes the inversion of j10 and j11 and a typo in the pin definition of jp3 Signed-off-by: Benjamin Herrenschmidt --- README.md | 2 + litex_boards/platforms/qmtech_wukong.py | 61 ++++++++++++++++++++----- litex_boards/targets/qmtech_wukong.py | 29 ++++++++---- 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 7e9acfa..45efc02 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,8 @@ The Colorlight5A is a very nice board to start with, cheap, powerful, easy to us | 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**| +| QMTech Wukong1 | Xilinx Artix7 | XC7A100T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 1Gbps GMII | 16MB QSPI | Yes**| +| QMTech Wukong2 | Xilinx Artix7 | XC7A100T/200T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 1Gbps GMII | 16MB QSPI | Yes | | RZ-EasyFPGA | Intel Cyclone4 | EP4CE6 | 25MHz | IOs | 16-bit 8MB SDR | No | No | No | No | | 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 | diff --git a/litex_boards/platforms/qmtech_wukong.py b/litex_boards/platforms/qmtech_wukong.py index 1257fcc..6f496c4 100644 --- a/litex_boards/platforms/qmtech_wukong.py +++ b/litex_boards/platforms/qmtech_wukong.py @@ -10,17 +10,46 @@ from litex.build.openocd import OpenOCD # IOs ---------------------------------------------------------------------------------------------- -_io = [ - # Clk / Rst - ("clk50", 0, Pins("M22"), IOStandard("LVCMOS33")), - ("cpu_reset", 0, Pins("J8"), IOStandard("LVCMOS33")), +# IOs specific to V1 of the board +_io_v1 = [ + # Reset (Key1 button) + ("cpu_reset", 0, Pins("J8"), IOStandard("LVCMOS33")), # key1 + + #Clock + ("clk50" , 0, Pins("M22"), IOStandard("LVCMOS33")), # Leds ("user_led", 0, Pins("J6"), IOStandard("LVCMOS33")), ("user_led", 1, Pins("H6"), IOStandard("LVCMOS33")), +] - # Buttons - ("user_btn", 0, Pins("H7"), IOStandard("LVCMOS33")), # Key0 +# IOs specific to V2 of the board +_io_v2 = [ + # Reset (Key1 button) + ("cpu_reset", 0, Pins("M6"), IOStandard("LVCMOS33")), + + # Clock + ("clk50" , 0, Pins("M21"), IOStandard("LVCMOS33")), + + # Leds + ("user_led", 0, Pins("V16"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("V17"), IOStandard("LVCMOS33")), + + # SD-Card + ("sdcard", 0, + Subsignal("data", Pins("M5 M7 H6 J6")), + Subsignal("cmd", Pins("J8")), + Subsignal("clk", Pins("L4")), + Subsignal("cd", Pins("N6")), + Misc("SLEW=FAST"), + IOStandard("LVCMOS33"), + ), +] + +# IO commons to both versions of the board +_io_common = [ + # Key0 button (Key1 is used as cpu reset and is version specific) + ("user_btn", 0, Pins("H7"), IOStandard("LVCMOS33")), # Serial ("serial", 0, @@ -56,6 +85,8 @@ _io = [ Subsignal("ras_n", Pins("A19"), IOStandard("SSTL135")), Subsignal("cas_n", Pins("B19"), IOStandard("SSTL135")), Subsignal("we_n", Pins("A18"), IOStandard("SSTL135")), + # cs_n is only wired on V1 of the board but E22 is unconnected on V2 + # so leaving this here shouldn't hurt Subsignal("cs_n", Pins("E22"), IOStandard("SSTL135")), Subsignal("dm", Pins("A22 C22"), IOStandard("SSTL135")), Subsignal("dq", Pins( @@ -119,8 +150,8 @@ _io = [ # Connectors --------------------------------------------------------------------------------------- _connectors = [ - ("j10", "H4 F4 A4 A5 J4 G4 B4 B5"), - ("j11", "D5 G5 G7 G8 E5 E6 D6 G6"), + ("j10", "D5 G5 G7 G8 E5 E6 D6 G6"), + ("j11", "H4 F4 A4 A5 J4 G4 B4 B5"), ("j12", "AB26 AC26 AB24 AC24 AA24 AB25 AA22 AA23", " Y25 AA25 W25 Y26 Y22 Y23 W21 Y21", " V26 W26 U25 U26 V24 W24 V23 W23", @@ -128,7 +159,7 @@ _connectors = [ " T19 U19"), ("jp2", "H21 H22 K21 J21 H26 G26 G25 F25", "G20 G21 F23 E23 E26 D26 E25 D25"), - ("jp3", " AF7 AE7 AD8 AC8 AF9 AE9 AD12 AC10", + ("jp3", " AF7 AE7 AD8 AC8 AF9 AE9 AD10 AC10", "AA11 AB11 AF11 AE11 AD14 AC14 AF13 AE13", "AD12 AC12"), ] @@ -169,15 +200,21 @@ class Platform(XilinxPlatform): default_clk_name = "clk50" default_clk_period = 1e9/50e6 - def __init__(self): - XilinxPlatform.__init__(self, "xc7a100t-2fgg676", _io, _connectors, toolchain="vivado") + def __init__(self, board_version=1, speed_grade=-2): + io = _io_common + if board_version < 2: + io.extend(_io_v1) + else: + io.extend(_io_v2) + XilinxPlatform.__init__(self, "xc7a100t{}fgg676".format(speed_grade), io, _connectors, toolchain="vivado") 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 16]") - self.add_platform_command("set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk50_IBUF]") + if board_version < 2: + self.add_platform_command("set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk50_IBUF]") self.add_platform_command("set_property CFGBVS VCCO [current_design]") self.add_platform_command("set_property CONFIG_VOLTAGE 3.3 [current_design]") diff --git a/litex_boards/targets/qmtech_wukong.py b/litex_boards/targets/qmtech_wukong.py index 709950e..c65fef9 100755 --- a/litex_boards/targets/qmtech_wukong.py +++ b/litex_boards/targets/qmtech_wukong.py @@ -31,7 +31,7 @@ from liteeth.phy import LiteEthPHYMII # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): - def __init__(self, platform, sys_clk_freq, with_video_pll=False, pix_clk=25.175e6): + def __init__(self, platform, speed_grade, sys_clk_freq, with_video_pll=False, pix_clk=25.175e6): self.rst = Signal() self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) @@ -46,7 +46,7 @@ class _CRG(Module): plls_reset = platform.request("cpu_reset") plls_clk50 = platform.request("clk50") - self.submodules.pll = pll = S7MMCM(speedgrade=-2) + self.submodules.pll = pll = S7MMCM(speedgrade=speed_grade) self.comb += pll.reset.eq(~plls_reset | self.rst) pll.register_clkin(plls_clk50, 50e6) pll.create_clkout(self.cd_sys, sys_clk_freq) @@ -55,7 +55,7 @@ class _CRG(Module): #pll.create_clkout(self.cd_idelay, 200e6) # idelay PLL - self.submodules.pll_idelay = pll_idelay = S7PLL(speedgrade=-2) + self.submodules.pll_idelay = pll_idelay = S7PLL(speedgrade=speed_grade) self.comb += pll_idelay.reset.eq(~plls_reset | self.rst) pll_idelay.register_clkin(plls_clk50, 50e6) pll_idelay.create_clkout(self.cd_idelay, 200e6) @@ -65,7 +65,7 @@ class _CRG(Module): # Video PLL. if with_video_pll: - self.submodules.video_pll = video_pll = S7MMCM(speedgrade=-2) + self.submodules.video_pll = video_pll = S7MMCM(speedgrade=speed_grade) self.comb += video_pll.reset.eq(~plls_reset | self.rst) video_pll.register_clkin(plls_clk50, 50e6) video_pll.create_clkout(self.cd_hdmi, pix_clk) @@ -74,10 +74,11 @@ class _CRG(Module): # BaseSoC ------------------------------------------------------------------------------------------ class BaseSoC(SoCCore): - def __init__(self, sys_clk_freq=int(100e6), with_ethernet=False, with_etherbone=False, + def __init__(self, sys_clk_freq=int(100e6), board_version=1, speed_grade=-2, + with_ethernet=False, with_etherbone=False, eth_ip="192.168.1.50", with_led_chaser=True, with_video_terminal=False, with_video_framebuffer=False, video_timing="640x480@60Hz", **kwargs): - platform = qmtech_wukong.Platform() + platform = qmtech_wukong.Platform(board_version=board_version,speed_grade=speed_grade) # SoCCore ---------------------------------------------------------------------------------- SoCCore.__init__(self, platform, sys_clk_freq, @@ -87,7 +88,8 @@ class BaseSoC(SoCCore): # CRG -------------------------------------------------------------------------------------- with_video_pll = (with_video_terminal or with_video_framebuffer) - self.submodules.crg = _CRG(platform, sys_clk_freq, with_video_pll=with_video_pll, pix_clk = video_timings[video_timing]["pix_clk"]) + self.submodules.crg = _CRG(platform, speed_grade, sys_clk_freq, with_video_pll=with_video_pll, + pix_clk = video_timings[video_timing]["pix_clk"]) # DDR3 SDRAM ------------------------------------------------------------------------------- if not self.integrated_main_ram_size: @@ -118,7 +120,7 @@ class BaseSoC(SoCCore): pads = platform.request_all("user_led"), sys_clk_freq = sys_clk_freq) - # Video ------------------------------------------------------------------------------------ + # Video ----------------------------------- ------------------------------------------------- if with_video_terminal or with_video_framebuffer: self.submodules.videophy = VideoS7HDMIPHY(platform.request("hdmi_out"), clock_domain="hdmi") if with_video_terminal: @@ -132,6 +134,8 @@ def main(): 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("--board-version", default=1, help="Board version 1 or 2 (default: 1)") + parser.add_argument("--speed-grade", default=-1, help="FPGA speed grade: -1 or -2 (default: -1)") 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") @@ -147,8 +151,14 @@ def main(): vivado_build_args(parser) args = parser.parse_args() + speed_grade = int(args.speed_grade) + if speed_grade not in [-1,-2]: + raise ValueError("Speed grade {} unsupported".format(speed_grade)) + soc = BaseSoC( sys_clk_freq = int(float(args.sys_clk_freq)), + board_version = int(args.board_version), + speed_grade = speed_grade, with_ethernet = args.with_ethernet, with_etherbone = args.with_etherbone, eth_ip = args.eth_ip, @@ -160,7 +170,8 @@ def main(): soc.platform.add_extension(qmtech_wukong._sdcard_pmod_io) soc.add_spi_sdcard() if args.with_sdcard: - soc.platform.add_extension(qmtech_wukong._sdcard_pmod_io) + if int(args.board_version) < 2: + soc.platform.add_extension(qmtech_wukong._sdcard_pmod_io) soc.add_sdcard() builder = Builder(soc, **builder_argdict(args))