diff --git a/.gitignore b/.gitignore
index ef6d2aca564ceab45ac390f54a4c38c82f98eea7..963297efbda4090ffb11a8ec732379c935fb334a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -91,3 +91,6 @@ ENV/
 
 # Rope project settings
 .ropeproject
+
+# VS Code project setting
+.vscode
\ No newline at end of file
diff --git a/README.md b/README.md
index f83e0353cdbfa8334e0f2588a477d4edeabf08a2..166f3c43d0800fe41dc1fe447154643cfc0d3046 100644
--- a/README.md
+++ b/README.md
@@ -127,6 +127,7 @@ The Colorlight5A is a very nice board to start with, cheap, powerful, easy to us
 | 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   |
+| Basys3         | Xilinx Artix7       | XC7A35T       | 100MHz  | FTDI |        No          |     No    |       No       |   4MB QSPI  |   No   |
 | C10LPRefKit    | Intel Cyclone10     | 10CL055       |  50MHz  | FTDI | 16-bit  32MB SDR   |     No    |  100Mbps MII   |  16MB QSPI  |   No   |
 | CYC1000        | Intel Cyclone10     | 10CL025       |  50MHz  | FTDI | 16-bit  64MB SDR   |     No    |       No       |  16MB QSPI* |   No   |
 | De0Nano        | Intel Cyclone4      | EP4CE22F      |  50MHz  | FTDI | 16-bit  32MB SDR   |     No    |       No       |      No     |   No   |
diff --git a/litex_boards/platforms/digilent_basys3.py b/litex_boards/platforms/digilent_basys3.py
new file mode 100644
index 0000000000000000000000000000000000000000..12249c99599bd99a3c4d9861055ce81c42f55867
--- /dev/null
+++ b/litex_boards/platforms/digilent_basys3.py
@@ -0,0 +1,132 @@
+#
+# This file is part of LiteX-Boards.
+#
+# Copyright (c) 2020-2021 Xuanyu Hu <xuanyu.hu@whu.edu.cn>
+# SPDX-License-Identifier: BSD-2-Clause
+
+from litex.build.generic_platform import *
+from litex.build.xilinx import XilinxPlatform, VivadoProgrammer
+from litex.build.openocd import OpenOCD
+
+# IOs ----------------------------------------------------------------------------------------------
+
+_io = [
+    # Clk / Rst
+    ("clk100", 0, Pins("W3"), IOStandard("LVCMOS33")),
+
+    # Leds
+    ("user_led",  0, Pins("U16"), IOStandard("LVCMOS33")),
+    ("user_led",  1, Pins("E19"), IOStandard("LVCMOS33")),
+    ("user_led",  2, Pins("U19"), IOStandard("LVCMOS33")),
+    ("user_led",  3, Pins("V19"), IOStandard("LVCMOS33")),
+    ("user_led",  4, Pins("W18"), IOStandard("LVCMOS33")),
+    ("user_led",  5, Pins("U15"), IOStandard("LVCMOS33")),
+    ("user_led",  6, Pins("U14"), IOStandard("LVCMOS33")),
+    ("user_led",  7, Pins("V14"), IOStandard("LVCMOS33")),
+    ("user_led",  8, Pins("V13"), IOStandard("LVCMOS33")),
+    ("user_led",  9, Pins("V3"), IOStandard("LVCMOS33")),
+    ("user_led", 10, Pins("W3"), IOStandard("LVCMOS33")),
+    ("user_led", 11, Pins("U3"), IOStandard("LVCMOS33")),
+    ("user_led", 12, Pins("P3"), IOStandard("LVCMOS33")),
+    ("user_led", 13, Pins("N3"), IOStandard("LVCMOS33")),
+    ("user_led", 14, Pins("P1"), IOStandard("LVCMOS33")),
+    ("user_led", 15, Pins("L1"), IOStandard("LVCMOS33")),
+
+    # Switches
+    ("user_sw",  0, Pins("V17"), IOStandard("LVCMOS33")),
+    ("user_sw",  1, Pins("V16"), IOStandard("LVCMOS33")),
+    ("user_sw",  2, Pins("W16"), IOStandard("LVCMOS33")),
+    ("user_sw",  3, Pins("W17"), IOStandard("LVCMOS33")),
+    ("user_sw",  4, Pins("W15"), IOStandard("LVCMOS33")),
+    ("user_sw",  5, Pins("V15"), IOStandard("LVCMOS33")),
+    ("user_sw",  6, Pins("W14"), IOStandard("LVCMOS33")),
+    ("user_sw",  7, Pins("W13"), IOStandard("LVCMOS33")),
+    ("user_sw",  8, Pins("V2"),  IOStandard("LVCMOS33")),
+    ("user_sw",  9, Pins("T3"),  IOStandard("LVCMOS33")),
+    ("user_sw", 10, Pins("T2"), IOStandard("LVCMOS33")),
+    ("user_sw", 11, Pins("R3"), IOStandard("LVCMOS33")),
+    ("user_sw", 12, Pins("W2"),  IOStandard("LVCMOS33")),
+    ("user_sw", 13, Pins("U1"), IOStandard("LVCMOS33")),
+    ("user_sw", 14, Pins("T1"), IOStandard("LVCMOS33")),
+    ("user_sw", 15, Pins("R2"), IOStandard("LVCMOS33")),  
+
+    # Buttons
+    ("user_btnu", 0, Pins("T18"), IOStandard("LVCMOS33")),
+    ("user_btnd", 0, Pins("U17"), IOStandard("LVCMOS33")),
+    ("user_btnl", 0, Pins("W19"), IOStandard("LVCMOS33")),
+    ("user_btnr", 0, Pins("T17"), IOStandard("LVCMOS33")),
+    ("user_btnc", 0, Pins("U18"), IOStandard("LVCMOS33")),
+
+    # Serial
+    ("serial", 0,
+        Subsignal("tx", Pins("A18")),
+        Subsignal("rx", Pins("B18")),
+        IOStandard("LVCMOS33"),
+    ),
+
+    # VGA
+     ("vga", 0,
+        Subsignal("hsync_n", Pins("P19")),
+        Subsignal("vsync_n", Pins("R18")),
+        Subsignal("r", Pins("G19 H19 J19 N19")),
+        Subsignal("g", Pins("J17 H17 G17 D17")),
+        Subsignal("b", Pins("N18 L18 K18 J18")),
+        IOStandard("LVCMOS33")
+    ),
+    
+    # USB PS/2
+    ("usbhost", 0,
+       Subsignal("ps2_clk", Pins("B6")),
+       Subsignal("ps2_data", Pins("A6")),
+       IOStandard("LVCMOS33"))
+
+]
+
+# Connectors ---------------------------------------------------------------------------------------
+
+_connectors = [
+    ("pmoda", "J1 L2 J2 G2 H1 K2 H2 G3"),
+    ("pmodb", "A14 A16 B15 B16 A15 A17 C15 C16"),
+    ("pmodc", "K17 M18 N17 P18 L17 M19 P17 R18"),
+    ("pmodxdac", "J3 L3 M2 N2 K3 M3 M1 N1"),
+]
+
+# PMODS --------------------------------------------------------------------------------------------
+
+def sdcard_pmod_io(pmod):
+    return [
+        # SDCard PMOD:
+        # - https://store.digilentinc.com/pmod-microsd-microsd-card-slot/
+        ("spisdcard", 0,
+            Subsignal("clk",  Pins(f"{pmod}:3")),
+            Subsignal("mosi", Pins(f"{pmod}:1"), Misc("PULLUP True")),
+            Subsignal("cs_n", Pins(f"{pmod}:0"), Misc("PULLUP True")),
+            Subsignal("miso", Pins(f"{pmod}:2"), Misc("PULLUP True")),
+            Misc("SLEW=FAST"),
+            IOStandard("LVCMOS33"),
+        ),
+        ("sdcard", 0,
+            Subsignal("data", Pins(f"{pmod}:2 {pmod}:4 {pmod}:5 {pmod}:0"), Misc("PULLUP True")),
+            Subsignal("cmd",  Pins(f"{pmod}:1"), Misc("PULLUP True")),
+            Subsignal("clk",  Pins(f"{pmod}:3")),
+            Subsignal("cd",   Pins(f"{pmod}:6")),
+            Misc("SLEW=FAST"),
+            IOStandard("LVCMOS33"),
+        ),
+
+]
+_sdcard_pmod_io = sdcard_pmod_io("pmoda") # SDCARD PMOD on JD.
+
+class Platform(XilinxPlatform):
+    default_clk_name   = "clk100"
+    default_clk_period = 1e9/100e6
+
+    def __init__(self):
+        XilinxPlatform.__init__(self, "xc7a35t-CPG236-1", _io, _connectors, toolchain="vivado")
+
+    def create_programmer(self):
+        return OpenOCD("openocd_xc7_ft2232.cfg", "bscan_spi_xc7a35t.bit")
+    
+    def do_finalize(self, fragment):
+        XilinxPlatform.do_finalize(self, fragment)
+        self.add_period_constraint(self.lookup_request("clk100",             loose=True), 1e9/100e6)
diff --git a/litex_boards/targets/digilent_basys3.py b/litex_boards/targets/digilent_basys3.py
new file mode 100644
index 0000000000000000000000000000000000000000..32b6c0c0f48f624126fe4ef9552014dcf4c3ab7e
--- /dev/null
+++ b/litex_boards/targets/digilent_basys3.py
@@ -0,0 +1,116 @@
+#
+# This file is part of LiteX-Boards.
+#
+# Copyright (c) 2020-2021 Xuanyu Hu <xuanyu.hu@whu.edu.cn>
+# SPDX-License-Identifier: BSD-2-Clause
+
+import os
+import argparse
+from litex.build.xilinx import platform
+
+from migen import *
+
+from litex_boards.platforms import basys3
+
+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 MT47H64M16
+from litedram.phy import s7ddrphy
+
+from liteeth.phy.rmii import LiteEthPHYRMII
+
+# CRG ----------------------------------------------------------------------------------------------
+
+class _CRG(Module):
+    def __init__(self, platform, sys_clk_freq):
+        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_vga       = ClockDomain(reset_less=True)
+
+        self.submodules.pll = pll = S7MMCM(speedgrade=-1)
+        self.comb += pll.reset.eq(~platform.request("user_btnc") | self.rst)
+
+        pll.register_clkin(platform.request("clk100"), 100e6)
+        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)
+        pll.create_clkout(self.cd_vga,       40e6)
+        platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin)
+
+        self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_idelay)
+
+# BaseSoC ------------------------------------------------------------------------------------------
+class BaseSoC(SoCCore):
+    def __init__(self, sys_clk_freq=int(75e6), with_video_terminal=False, with_video_framebuffer=False, **kwargs):
+        platform = basys3.Platform()
+
+        # SoCCore ----------------------------------_-----------------------------------------------
+        SoCCore.__init__(self, platform, sys_clk_freq,
+            ident          = "LiteX SoC on Basys3",
+            ident_version  = True,
+            **kwargs)
+
+        # CRG --------------------------------------------------------------------------------------
+        self.submodules.crg = _CRG(platform, sys_clk_freq)
+
+        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")
+
+        self.submodules.leds = LedChaser(
+            pads         = platform.request_all("user_led"),
+            sys_clk_freq = sys_clk_freq)
+
+# Build --------------------------------------------------------------------------------------------  
+def main():
+    parser = argparse.ArgumentParser(description="LiteX SoC on Basys3")
+    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=75e6,        help="System clock frequency (default: 75MHz)")
+    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("--sdcard-adapter",      type=str,                         help="SDCard PMOD adapter: digilent (default) or numato")
+    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)
+    args = parser.parse_args()
+
+    soc = BaseSoC(
+        sys_clk_freq           = int(float(args.sys_clk_freq)),
+        with_video_terminal    = args.with_video_terminal,
+        with_video_framebuffer = args.with_video_framebuffer,
+        **soc_core_argdict(args)
+    )
+    soc.platform.add_extension(basys3._sdcard_pmod_io)
+    if args.with_spi_sdcard:
+        soc.add_spi_sdcard()
+    if args.with_sdcard:
+        soc.add_sdcard()
+    if args.with_spi_sdcard:
+        soc.add_spi_sdcard()
+    if args.with_sdcard:
+        soc.add_sdcard()
+    builder = Builder(soc, **builder_argdict(args))
+    builder.build(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 be2a0e2a7e8b59232968fb78c494ae7342994b47..40e727446442ef1d78c717dc61235645dfb930ff 100644
--- a/test/test_targets.py
+++ b/test/test_targets.py
@@ -43,6 +43,7 @@ class TestTargets(unittest.TestCase):
         platforms.append("ac701")
         platforms.append("aller")
         platforms.append("arty")
+        platforms.append("basys3")
         platforms.append("mimas_a7")
         platforms.append("netv2")
         platforms.append("nexys4ddr")