From 291c43b89837e53dd8e506b397ca504e0ef2f4bd Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Mon, 13 Mar 2023 16:44:10 +0800 Subject: [PATCH] sipeed_tang_nano_20k: new board This board uses Gowin GW2AR series chip (which is GW2A with integrated RAM). Support for the integrated SDRAM on Tang Nano 20K is still TODO. Note: currently when the SD card is enabled, block 0 could be correctly read but block 1 will fail. Signed-off-by: Icenowy Zheng --- .../platforms/sipeed_tang_nano_20k.py | 94 +++++++++++++ litex_boards/targets/sipeed_tang_nano_20k.py | 129 ++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 litex_boards/platforms/sipeed_tang_nano_20k.py create mode 100755 litex_boards/targets/sipeed_tang_nano_20k.py diff --git a/litex_boards/platforms/sipeed_tang_nano_20k.py b/litex_boards/platforms/sipeed_tang_nano_20k.py new file mode 100644 index 0000000..80feef8 --- /dev/null +++ b/litex_boards/platforms/sipeed_tang_nano_20k.py @@ -0,0 +1,94 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2023 Icenowy Zheng +# SPDX-License-Identifier: BSD-2-Clause + +from migen import * + +from litex.build.generic_platform import * +from litex.build.gowin.platform import GowinPlatform +from litex.build.gowin.programmer import GowinProgrammer +from litex.build.openfpgaloader import OpenFPGALoader + + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + # Clk / Rst. + ("clk27", 0, Pins("4"), IOStandard("LVCMOS33")), + + # Serial. + ("serial", 0, + Subsignal("rx", Pins("70")), + Subsignal("tx", Pins("69")), + IOStandard("LVCMOS33") + ), + + # SPIFlash. + ("spiflash", 0, + Subsignal("cs_n", Pins("60"), IOStandard("LVCMOS33")), + Subsignal("clk", Pins("59"), IOStandard("LVCMOS33")), + Subsignal("miso", Pins("62"), IOStandard("LVCMOS33")), + Subsignal("mosi", Pins("61"), IOStandard("LVCMOS33")), + ), + + # SDCard. + ("spisdcard", 0, + Subsignal("clk", Pins("83")), + Subsignal("mosi", Pins("82")), + Subsignal("cs_n", Pins("81")), + Subsignal("miso", Pins("84")), + IOStandard("LVCMOS33"), + ), + ("sdcard", 0, + Subsignal("data", Pins("84 85 80 81")), + Subsignal("cmd", Pins("82")), + Subsignal("clk", Pins("83")), + IOStandard("LVCMOS33"), + ), + + # Leds + ("led_n", 0, Pins("15"), IOStandard("LVCMOS33")), + ("led_n", 1, Pins("16"), IOStandard("LVCMOS33")), + ("led_n", 2, Pins("17"), IOStandard("LVCMOS33")), + ("led_n", 3, Pins("18"), IOStandard("LVCMOS33")), + ("led_n", 4, Pins("19"), IOStandard("LVCMOS33")), + ("led_n", 5, Pins("20"), IOStandard("LVCMOS33")), + + # RGB Led. + ("rgb_led", 0, Pins("79"), IOStandard("LVCMOS33")), + + # Buttons. + ("btn", 0, Pins("88"), IOStandard("LVCMOS33")), + ("btn", 1, Pins("87"), IOStandard("LVCMOS33")), +] + +# Connectors --------------------------------------------------------------------------------------- + +_connectors = [ + # TODO +] + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(GowinPlatform): + default_clk_name = "clk27" + default_clk_period = 1e9/27e6 + + def __init__(self, dock="standard", toolchain="gowin"): + + GowinPlatform.__init__(self, "GW2AR-LV18QN88C8/I7", _io, _connectors, toolchain=toolchain, devicename="GW2AR-18C") + + self.toolchain.options["use_mspi_as_gpio"] = 1 + self.toolchain.options["use_sspi_as_gpio"] = 1 + self.toolchain.options["use_ready_as_gpio"] = 1 + self.toolchain.options["use_done_as_gpio"] = 1 + self.toolchain.options["rw_check_on_ram"] = 1 + + def create_programmer(self, kit="openfpgaloader"): + return OpenFPGALoader(cable="ft2232") + + def do_finalize(self, fragment): + GowinPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk27", loose=True), 1e9/27e6) diff --git a/litex_boards/targets/sipeed_tang_nano_20k.py b/litex_boards/targets/sipeed_tang_nano_20k.py new file mode 100755 index 0000000..32f8009 --- /dev/null +++ b/litex_boards/targets/sipeed_tang_nano_20k.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2022 Icenowy Zheng +# Copyright (c) 2022 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer + +from litex.gen import * + +from litex.build.io import DDROutput + +from litex.soc.cores.clock.gowin_gw2a import GW2APLL +from litex.soc.integration.soc_core import * +from litex.soc.integration.soc import SoCRegion +from litex.soc.integration.builder import * +from litex.soc.cores.gpio import GPIOIn +from litex.soc.cores.led import LedChaser, WS2812 + +from litex_boards.platforms import sipeed_tang_nano_20k + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(LiteXModule): + def __init__(self, platform, sys_clk_freq): + self.rst = Signal() + self.cd_sys = ClockDomain() + self.cd_por = ClockDomain() + + # Clk + clk27 = platform.request("clk27") + + # Power on reset + por_count = Signal(16, reset=2**16-1) + por_done = Signal() + self.comb += self.cd_por.clk.eq(clk27) + self.comb += por_done.eq(por_count == 0) + self.sync.por += If(~por_done, por_count.eq(por_count - 1)) + + # PLL + self.pll = pll = GW2APLL(devicename=platform.devicename, device=platform.device) + self.comb += pll.reset.eq(~por_done) + pll.register_clkin(clk27, 27e6) + pll.create_clkout(self.cd_sys, sys_clk_freq) + +# BaseSoC ------------------------------------------------------------------------------------------ + +class BaseSoC(SoCCore): + def __init__(self, sys_clk_freq=48e6, + with_led_chaser = True, + with_rgb_led = False, + with_buttons = True, + **kwargs): + + platform = sipeed_tang_nano_20k.Platform(toolchain="gowin") + + # CRG -------------------------------------------------------------------------------------- + self.crg = _CRG(platform, sys_clk_freq) + + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on Tang Nano 20K", **kwargs) + + # TODO: XTX SPI Flash + + # TODO: copackaged SDRAM + + # Leds ------------------------------------------------------------------------------------- + if with_led_chaser: + self.leds = LedChaser( + pads = platform.request_all("led_n"), + sys_clk_freq = sys_clk_freq + ) + + # RGB Led ---------------------------------------------------------------------------------- + if with_rgb_led: + self.rgb_led = WS2812( + pad = platform.request("rgb_led"), + nleds = 1, + sys_clk_freq = sys_clk_freq + ) + self.bus.add_slave(name="rgb_led", slave=self.rgb_led.bus, region=SoCRegion( + origin = 0x2000_0000, + size = 4, + )) + + # Buttons ---------------------------------------------------------------------------------- + if with_buttons: + self.buttons = GPIOIn(pads=~platform.request_all("btn")) + + +# Build -------------------------------------------------------------------------------------------- + +def main(): + from litex.build.parser import LiteXArgumentParser + parser = LiteXArgumentParser(platform=sipeed_tang_nano_20k.Platform, description="LiteX SoC on Tang Primer 20K.") + parser.add_target_argument("--flash", action="store_true", help="Flash Bitstream.") + parser.add_target_argument("--sys-clk-freq", default=48e6, type=float, help="System clock frequency.") + sdopts = parser.target_group.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.") + args = parser.parse_args() + + soc = BaseSoC( + sys_clk_freq = args.sys_clk_freq, + **parser.soc_argdict + ) + if args.with_spi_sdcard: + soc.add_spi_sdcard() + if args.with_sdcard: + soc.add_sdcard() + + builder = Builder(soc, **parser.builder_argdict) + if args.build: + builder.build(**parser.toolchain_argdict) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(builder.get_bitstream_filename(mode="sram")) + + if args.flash: + prog = soc.platform.create_programmer() + prog.flash(0, builder.get_bitstream_filename(mode="flash", ext=".fs"), external=True) + +if __name__ == "__main__": + main()