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 <benh@kernel.crashing.org>
This commit is contained in:
Benjamin Herrenschmidt 2021-09-24 11:12:16 +10:00 committed by Benjamin Herrenschmidt
parent 610e82d774
commit 4a52996106
3 changed files with 71 additions and 21 deletions

View File

@ -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 | | 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 | | 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 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 | | 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* | | 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 | | Tagus | Xilinx Artix7 | XC7A200T | 100MHz | PCIe | 16-bit 256MB DDR3 | Gen2 X1 | 1Gbps-BASE-X* | 16MB QSPI* | No |

View File

@ -10,17 +10,46 @@ from litex.build.openocd import OpenOCD
# IOs ---------------------------------------------------------------------------------------------- # IOs ----------------------------------------------------------------------------------------------
_io = [ # IOs specific to V1 of the board
# Clk / Rst _io_v1 = [
("clk50", 0, Pins("M22"), IOStandard("LVCMOS33")), # Reset (Key1 button)
("cpu_reset", 0, Pins("J8"), IOStandard("LVCMOS33")), ("cpu_reset", 0, Pins("J8"), IOStandard("LVCMOS33")), # key1
#Clock
("clk50" , 0, Pins("M22"), IOStandard("LVCMOS33")),
# Leds # Leds
("user_led", 0, Pins("J6"), IOStandard("LVCMOS33")), ("user_led", 0, Pins("J6"), IOStandard("LVCMOS33")),
("user_led", 1, Pins("H6"), IOStandard("LVCMOS33")), ("user_led", 1, Pins("H6"), IOStandard("LVCMOS33")),
]
# Buttons # IOs specific to V2 of the board
("user_btn", 0, Pins("H7"), IOStandard("LVCMOS33")), # Key0 _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
("serial", 0, ("serial", 0,
@ -56,6 +85,8 @@ _io = [
Subsignal("ras_n", Pins("A19"), IOStandard("SSTL135")), Subsignal("ras_n", Pins("A19"), IOStandard("SSTL135")),
Subsignal("cas_n", Pins("B19"), IOStandard("SSTL135")), Subsignal("cas_n", Pins("B19"), IOStandard("SSTL135")),
Subsignal("we_n", Pins("A18"), 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("cs_n", Pins("E22"), IOStandard("SSTL135")),
Subsignal("dm", Pins("A22 C22"), IOStandard("SSTL135")), Subsignal("dm", Pins("A22 C22"), IOStandard("SSTL135")),
Subsignal("dq", Pins( Subsignal("dq", Pins(
@ -119,8 +150,8 @@ _io = [
# Connectors --------------------------------------------------------------------------------------- # Connectors ---------------------------------------------------------------------------------------
_connectors = [ _connectors = [
("j10", "H4 F4 A4 A5 J4 G4 B4 B5"), ("j10", "D5 G5 G7 G8 E5 E6 D6 G6"),
("j11", "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", ("j12", "AB26 AC26 AB24 AC24 AA24 AB25 AA22 AA23",
" Y25 AA25 W25 Y26 Y22 Y23 W21 Y21", " Y25 AA25 W25 Y26 Y22 Y23 W21 Y21",
" V26 W26 U25 U26 V24 W24 V23 W23", " V26 W26 U25 U26 V24 W24 V23 W23",
@ -128,7 +159,7 @@ _connectors = [
" T19 U19"), " T19 U19"),
("jp2", "H21 H22 K21 J21 H26 G26 G25 F25", ("jp2", "H21 H22 K21 J21 H26 G26 G25 F25",
"G20 G21 F23 E23 E26 D26 E25 D25"), "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", "AA11 AB11 AF11 AE11 AD14 AC14 AF13 AE13",
"AD12 AC12"), "AD12 AC12"),
] ]
@ -169,15 +200,21 @@ class Platform(XilinxPlatform):
default_clk_name = "clk50" default_clk_name = "clk50"
default_clk_period = 1e9/50e6 default_clk_period = 1e9/50e6
def __init__(self): def __init__(self, board_version=1, speed_grade=-2):
XilinxPlatform.__init__(self, "xc7a100t-2fgg676", _io, _connectors, toolchain="vivado") 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 = \ self.toolchain.bitstream_commands = \
["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"]
self.toolchain.additional_commands = \ self.toolchain.additional_commands = \
["write_cfgmem -force -format bin -interface spix4 -size 16 " ["write_cfgmem -force -format bin -interface spix4 -size 16 "
"-loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] "-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 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 CFGBVS VCCO [current_design]")
self.add_platform_command("set_property CONFIG_VOLTAGE 3.3 [current_design]") self.add_platform_command("set_property CONFIG_VOLTAGE 3.3 [current_design]")

View File

@ -31,7 +31,7 @@ from liteeth.phy import LiteEthPHYMII
# CRG ---------------------------------------------------------------------------------------------- # CRG ----------------------------------------------------------------------------------------------
class _CRG(Module): 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.rst = Signal()
self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
@ -46,7 +46,7 @@ class _CRG(Module):
plls_reset = platform.request("cpu_reset") plls_reset = platform.request("cpu_reset")
plls_clk50 = platform.request("clk50") 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) self.comb += pll.reset.eq(~plls_reset | self.rst)
pll.register_clkin(plls_clk50, 50e6) pll.register_clkin(plls_clk50, 50e6)
pll.create_clkout(self.cd_sys, sys_clk_freq) pll.create_clkout(self.cd_sys, sys_clk_freq)
@ -55,7 +55,7 @@ class _CRG(Module):
#pll.create_clkout(self.cd_idelay, 200e6) #pll.create_clkout(self.cd_idelay, 200e6)
# idelay PLL # 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) self.comb += pll_idelay.reset.eq(~plls_reset | self.rst)
pll_idelay.register_clkin(plls_clk50, 50e6) pll_idelay.register_clkin(plls_clk50, 50e6)
pll_idelay.create_clkout(self.cd_idelay, 200e6) pll_idelay.create_clkout(self.cd_idelay, 200e6)
@ -65,7 +65,7 @@ class _CRG(Module):
# Video PLL. # Video PLL.
if with_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) self.comb += video_pll.reset.eq(~plls_reset | self.rst)
video_pll.register_clkin(plls_clk50, 50e6) video_pll.register_clkin(plls_clk50, 50e6)
video_pll.create_clkout(self.cd_hdmi, pix_clk) video_pll.create_clkout(self.cd_hdmi, pix_clk)
@ -74,10 +74,11 @@ class _CRG(Module):
# BaseSoC ------------------------------------------------------------------------------------------ # BaseSoC ------------------------------------------------------------------------------------------
class BaseSoC(SoCCore): 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, eth_ip="192.168.1.50", with_led_chaser=True, with_video_terminal=False,
with_video_framebuffer=False, video_timing="640x480@60Hz", **kwargs): 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 ----------------------------------------------------------------------------------
SoCCore.__init__(self, platform, sys_clk_freq, SoCCore.__init__(self, platform, sys_clk_freq,
@ -87,7 +88,8 @@ class BaseSoC(SoCCore):
# CRG -------------------------------------------------------------------------------------- # CRG --------------------------------------------------------------------------------------
with_video_pll = (with_video_terminal or with_video_framebuffer) 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 ------------------------------------------------------------------------------- # DDR3 SDRAM -------------------------------------------------------------------------------
if not self.integrated_main_ram_size: if not self.integrated_main_ram_size:
@ -118,7 +120,7 @@ class BaseSoC(SoCCore):
pads = platform.request_all("user_led"), pads = platform.request_all("user_led"),
sys_clk_freq = sys_clk_freq) sys_clk_freq = sys_clk_freq)
# Video ------------------------------------------------------------------------------------ # Video ----------------------------------- -------------------------------------------------
if with_video_terminal or with_video_framebuffer: if with_video_terminal or with_video_framebuffer:
self.submodules.videophy = VideoS7HDMIPHY(platform.request("hdmi_out"), clock_domain="hdmi") self.submodules.videophy = VideoS7HDMIPHY(platform.request("hdmi_out"), clock_domain="hdmi")
if with_video_terminal: if with_video_terminal:
@ -132,6 +134,8 @@ def main():
parser.add_argument("--build", action="store_true", help="Build bitstream") parser.add_argument("--build", action="store_true", help="Build bitstream")
parser.add_argument("--load", action="store_true", help="Load 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("--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 = parser.add_mutually_exclusive_group()
ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support")
ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support") ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support")
@ -147,8 +151,14 @@ def main():
vivado_build_args(parser) vivado_build_args(parser)
args = parser.parse_args() 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( soc = BaseSoC(
sys_clk_freq = int(float(args.sys_clk_freq)), 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_ethernet = args.with_ethernet,
with_etherbone = args.with_etherbone, with_etherbone = args.with_etherbone,
eth_ip = args.eth_ip, eth_ip = args.eth_ip,
@ -160,7 +170,8 @@ def main():
soc.platform.add_extension(qmtech_wukong._sdcard_pmod_io) soc.platform.add_extension(qmtech_wukong._sdcard_pmod_io)
soc.add_spi_sdcard() soc.add_spi_sdcard()
if args.with_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() soc.add_sdcard()
builder = Builder(soc, **builder_argdict(args)) builder = Builder(soc, **builder_argdict(args))