diff --git a/litex_boards/platforms/digilent_atlys.py b/litex_boards/platforms/digilent_atlys.py
new file mode 100644
index 0000000000000000000000000000000000000000..af73fc1f32e6da7604333cd3a69a6dd435cb569d
--- /dev/null
+++ b/litex_boards/platforms/digilent_atlys.py
@@ -0,0 +1,235 @@
+#
+# This file is part of LiteX-Boards.
+#
+# Copyright (c) 2015-2021 HDMI2USB/LiteX developers
+# SPDX-License-Identifier: BSD-2-Clause
+
+from litex.build.generic_platform import *
+from litex.build.xilinx import XilinxPlatform
+
+# IOs ----------------------------------------------------------------------------------------------
+
+_io = [
+    # Clk/Rst
+    ("clk100",    0, Pins("L15"), IOStandard("LVCMOS33")),
+    ("cpu_reset", 0, Pins("T15"), IOStandard("LVCMOS33")),
+
+    # Serial
+    ("serial", 0,
+        Subsignal("rx", Pins("A16"), IOStandard("LVCMOS33")),
+        Subsignal("tx", Pins("B16"), IOStandard("LVCMOS33")),
+    ),
+
+    # FX2
+    ("fx2", 0,
+        Subsignal("ifclk",    Pins("C10")),
+        Subsignal("data",     Pins("A2 D6 C6 B3 A3 B4 A4 C5")),
+        Subsignal("addr",     Pins("A14 B14"), Misc("DRIVE=12")),
+        Subsignal("flaga",    Pins("B9"),  Misc("DRIVE=12")),
+        Subsignal("flagb",    Pins("A9"),  Misc("DRIVE=12")),
+        Subsignal("flagc",    Pins("C15"), Misc("DRIVE=12")),
+        Subsignal("rd_n",     Pins("F13"), Misc("DRIVE=12")),
+        Subsignal("wr_n",     Pins("E13")),
+        Subsignal("oe_n",     Pins("A15"), Misc("DRIVE=12")),
+        Subsignal("cs_n",     Pins("B2")),
+        Subsignal("pktend_n", Pins("C4"), Misc("DRIVE=12")),
+        IOStandard("LVCMOS33")
+    ),
+
+    # SPI Flash
+    ("spiflash4x", 0,
+        Subsignal("cs_n", Pins("V3")),
+        Subsignal("clk",  Pins("R15")),
+        Subsignal("dq",   Pins("T13", "R13", "T14", "V14")),
+        IOStandard("LVCMOS33"),
+        Misc("SLEW=FAST"),
+    ),
+
+    # Leds
+    ("user_led", 0, Pins("U18"), IOStandard("LVCMOS33")),
+    ("user_led", 1, Pins("M14"), IOStandard("LVCMOS33")),
+    ("user_led", 2, Pins("N14"), IOStandard("LVCMOS33")),
+    ("user_led", 3, Pins("L14"), IOStandard("LVCMOS33")),
+    ("user_led", 4, Pins("M13"), IOStandard("LVCMOS33")),
+    ("user_led", 5, Pins("D4"),  IOStandard("LVCMOS33")),
+    ("user_led", 6, Pins("P16"), IOStandard("LVCMOS33")),
+    ("user_led", 7, Pins("N12"), IOStandard("LVCMOS33")),
+
+    # Buttons
+    ("user_btn", 0, Pins("N4"), IOStandard("LVCMOS18")), # North button
+    ("user_btn", 1, Pins("P4"), IOStandard("LVCMOS18")), # East button
+    ("user_btn", 2, Pins("P3"), IOStandard("LVCMOS18")), # South button
+    ("user_btn", 3, Pins("F6"), IOStandard("LVCMOS18")), # West button
+    ("user_btn", 4, Pins("F5"), IOStandard("LVCMOS18")), # Center button
+
+    # Switches.
+    ("user_sw", 0, Pins("A10"), IOStandard("LVCMOS33")),
+    ("user_sw", 1, Pins("D14"), IOStandard("LVCMOS33")),
+    ("user_sw", 2, Pins("C14"), IOStandard("LVCMOS33")),
+    ("user_sw", 3, Pins("P15"), IOStandard("LVCMOS33")),
+    ("user_sw", 4, Pins("P12"), IOStandard("LVCMOS33")),
+    ("user_sw", 5, Pins("R5"),  IOStandard("LVCMOS33")),
+    ("user_sw", 6, Pins("T5"),  IOStandard("LVCMOS33")),
+    ("user_sw", 7, Pins("E4"),  IOStandard("LVCMOS18")),
+
+    # GMII/MII Ethernet
+    ("eth_clocks", 0,
+        Subsignal("tx",  Pins("K16")),
+        Subsignal("gtx", Pins("L12")),
+        Subsignal("rx",  Pins("K15")),
+        IOStandard("LVCMOS33")
+    ),
+    ("eth", 0,
+        Subsignal("rst_n",   Pins("G13")),
+        Subsignal("int_n",   Pins("L16")),
+        Subsignal("mdio",    Pins("N17")),
+        Subsignal("mdc",     Pins("F16")),
+        Subsignal("rx_dv",   Pins("F17")),
+        Subsignal("rx_er",   Pins("F18")),
+        Subsignal("rx_data", Pins("G16 H14 E16 F15 F14 E18 D18 D17")),
+        Subsignal("tx_en",   Pins("H15")),
+        Subsignal("tx_er",   Pins("G18")),
+        Subsignal("tx_data", Pins("H16 H13 K14 K13 J13 G14 H12 K12")),
+        Subsignal("col",     Pins("C17")),
+        Subsignal("crs",     Pins("C18")),
+        IOStandard("LVCMOS33")
+    ),
+
+    # DDR2 SDRAM.
+    ("ddram_clock", 0,
+        Subsignal("p", Pins("G3")),
+        Subsignal("n", Pins("G1")),
+        IOStandard("DIFF_SSTL18_II"), Misc("IN_TERM=NONE")
+    ),
+    ("ddram", 0,
+        Subsignal("cke",   Pins("H7"), IOStandard("SSTL18_II")),
+        Subsignal("ras_n", Pins("L5"), IOStandard("SSTL18_II")),
+        Subsignal("cas_n", Pins("K5"), IOStandard("SSTL18_II")),
+        Subsignal("we_n",  Pins("E3"), IOStandard("SSTL18_II")),
+        Subsignal("ba",    Pins("F2 F1 E1"), IOStandard("SSTL18_II")),
+        Subsignal("a", Pins(
+            "J7 J6 H5 L7 F3 H4 H3 H6",
+            "D2 D1 F4 D3 G6"),
+            IOStandard("SSTL18_II")),
+        Subsignal("dq", Pins(
+            "L2 L1 K2 K1 H2 H1 J3 J1",
+            "M3 M1 N2 N1 T2 T1 U2 U1"),
+            IOStandard("SSTL18_II")),
+        Subsignal("dqs",   Pins("P2 L4"), IOStandard("DIFF_SSTL18_II")),
+        Subsignal("dqs_n", Pins("P1 L3"), IOStandard("DIFF_SSTL18_II")),
+        Subsignal("dm",    Pins("K4 K3"), IOStandard("SSTL18_II")),
+        Subsignal("odt",   Pins("K6"),    IOStandard("SSTL18_II"))
+    ),
+
+    # HDMI Out 0
+    ("hdmi_out", 0,
+        Subsignal("clk_p",   Pins("B6"), IOStandard("TMDS_33")),
+        Subsignal("clk_n",   Pins("A6"), IOStandard("TMDS_33")),
+        Subsignal("data0_p", Pins("D8"), IOStandard("TMDS_33")),
+        Subsignal("data0_n", Pins("C8"), IOStandard("TMDS_33")),
+        Subsignal("data1_p", Pins("C7"), IOStandard("TMDS_33")),
+        Subsignal("data1_n", Pins("A7"), IOStandard("TMDS_33")),
+        Subsignal("data2_p", Pins("B8"), IOStandard("TMDS_33")),
+        Subsignal("data2_n", Pins("A8"), IOStandard("TMDS_33")),
+        Subsignal("scl",     Pins("D9"), IOStandard("I2C")),
+        Subsignal("sda",     Pins("C9"), IOStandard("I2C")),
+    ),
+
+    # HDMI In 0
+    ("hdmi_in", 0,
+        Subsignal("clk_p",   Pins("D11")),
+        Subsignal("clk_n",   Pins("C11")),
+        Subsignal("data0_p", Pins("G9")),
+        Subsignal("data0_n", Pins("F9")),
+        Subsignal("data1_p", Pins("B11")),
+        Subsignal("data1_n", Pins("A11")),
+        Subsignal("data2_p", Pins("B12")),
+        Subsignal("data2_n", Pins("A12")),
+        Subsignal("scl",     Pins("C13"), IOStandard("LVCMOS33")),
+        Subsignal("sda",     Pins("A13"), IOStandard("LVCMOS33")),
+    ),
+
+    # HDMI In 1
+    ("hdmi_in", 1,
+        Subsignal("clk_p",   Pins("H17")),
+        Subsignal("clk_n",   Pins("H18")),
+        Subsignal("data0_p", Pins("K17")),
+        Subsignal("data0_n", Pins("K18")),
+        Subsignal("data1_p", Pins("L17")),
+        Subsignal("data1_n", Pins("L18")),
+        Subsignal("data2_p", Pins("J16")),
+        Subsignal("data2_n", Pins("J18")),
+        Subsignal("scl",     Pins("M16"), IOStandard("LVCMOS33")),
+        Subsignal("sda",     Pins("M18"), IOStandard("LVCMOS33")),
+    ),
+]
+
+# Connectors ---------------------------------------------------------------------------------------
+
+_connectors = [
+    ("VHDCI",
+        {
+        "EXP-IO1_P"  : "U16",
+        "EXP-IO2_P"  : "U15",
+        "EXP-IO3_P"  : "U13",
+        "EXP-IO4_P"  : "M11",
+        "EXP-IO5_P"  : "R11",
+        "EXP-IO6_P"  : "T12",
+        "EXP-IO7_P"  : "N10",
+        "EXP-IO8_P"  : "M10",
+        "EXP-IO9_P"  : "U11",
+        "EXP-IO10_P" : "R10",
+        "EXP-IO11_P" : "U10",
+        "EXP-IO12_P" :  "R8",
+        "EXP-IO13_P" :  "M8",
+        "EXP-IO14_P" :  "U8",
+        "EXP-IO15_P" :  "U7",
+        "EXP-IO16_P" :  "N7",
+        "EXP-IO17_P" :  "T6",
+        "EXP-IO18_P" :  "R7",
+        "EXP-IO19_P" :  "N6",
+        "EXP-IO20_P" :  "U5",
+        "EXP-IO1_N"  : "V16",
+        "EXP-IO2_N"  : "V15",
+        "EXP-IO3_N"  : "V13",
+        "EXP-IO4_N"  : "N11",
+        "EXP-IO5_N"  : "T11",
+        "EXP-IO6_N"  : "V12",
+        "EXP-IO7_N"  : "P11",
+        "EXP-IO8_N"  :  "N9",
+        "EXP-IO9_N"  : "V11",
+        "EXP-IO10_N" : "T10",
+        "EXP-IO11_N" : "V10",
+        "EXP-IO12_N" :  "T8",
+        "EXP-IO13_N" :  "N8",
+        "EXP-IO14_N" :  "V8",
+        "EXP-IO15_N" :  "V7",
+        "EXP-IO16_N" :  "P8",
+        "EXP-IO17_N" :  "V6",
+        "EXP-IO18_N" :  "T7",
+        "EXP-IO19_N" :  "P7",
+        "EXP-IO20_N" :  "V5",
+        }
+    ),
+]
+
+# Platform -----------------------------------------------------------------------------------------
+
+class Platform(XilinxPlatform):
+    default_clk_name   = "clk100"
+    default_clk_period = 1e9/100e6
+
+    def __init__(self,):
+        XilinxPlatform.__init__(self,  "xc6slx45-csg324-3", _io, _connectors)
+        self.add_platform_command("""CONFIG VCCAUX="3.3";""")
+
+    def create_programmer(self):
+        return iMPACT()
+
+    def do_finalize(self, fragment):
+        XilinxPlatform.do_finalize(self, fragment)
+        self.add_period_constraint(self.lookup_request("clk100",           loose=True),  1e9/100e6)
+        self.add_period_constraint(self.lookup_request("hdmi_in:clk_p", 0, loose=True),  1e9/74.25e6)
+        self.add_period_constraint(self.lookup_request("hdmi_in:clk_p", 1, loose=True),  1e9/74.25e6)
+        self.add_period_constraint(self.lookup_request("eth_clocks:rx",    loose=True),  1e9/25e6)
+        self.add_period_constraint(self.lookup_request("fx2:ifclk",        loose=True),  1e9/100e6)
diff --git a/litex_boards/targets/digilent_atlys.py b/litex_boards/targets/digilent_atlys.py
new file mode 100755
index 0000000000000000000000000000000000000000..f14e8dc055872aa7aabc92bcfc71fc566b245bc1
--- /dev/null
+++ b/litex_boards/targets/digilent_atlys.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python3
+
+#
+# This file is part of LiteX-Boards.
+#
+# Copyright (c) 2015 Robert Jordens <jordens@gmail.com>
+# Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
+# Copyright (c) 2015 Yann Sionneau <yann.sionneau@gmail.com>
+# Copyright (c) 2016-2017 Tim 'mithro' Ansell <mithro@mithis.com>
+# Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
+# SPDX-License-Identifier: BSD-2-Clause
+
+import os
+import argparse
+
+from fractions import Fraction
+
+from migen import *
+from migen.genlib.resetsync import AsyncResetSynchronizer
+
+from litex_boards.platforms import atlys
+
+from litex.soc.integration.soc_core import *
+from litex.soc.integration.builder import *
+from litex.soc.cores.led import LedChaser
+
+from litedram.modules import MT47H64M16
+from litedram.phy import s6ddrphy
+
+# CRG ----------------------------------------------------------------------------------------------
+
+class _CRG(Module):
+    def __init__(self, platform, sys_clk_freq):
+        self.clock_domains.cd_sys           = ClockDomain()
+        self.clock_domains.cd_sdram_half    = ClockDomain()
+        self.clock_domains.cd_sdram_full_wr = ClockDomain()
+        self.clock_domains.cd_sdram_full_rd = ClockDomain()
+
+        self.reset = Signal()
+
+        # # #
+
+        # Input clock ------------------------------------------------------------------------------
+        clk100_freq = int(100e6)
+        clk100      = platform.request("clk100")
+        clk100b     = Signal()
+        self.specials += Instance("BUFIO2",
+            p_DIVIDE=1, p_DIVIDE_BYPASS="TRUE",
+            p_I_INVERT="FALSE",
+            i_I=clk100, o_DIVCLK=clk100b)
+
+        # PLL --------------------------------------------------------------------------------------
+        pll_lckd         = Signal()
+        pll_fb           = Signal()
+        pll_sdram_full   = Signal()
+        pll_sdram_half_a = Signal()
+        pll_sdram_half_b = Signal()
+        pll_unused       = Signal()
+        pll_sys          = Signal()
+        pll_periph       = Signal()
+
+        f0 = clk100_freq
+        f = Fraction(int(sys_clk_freq), int(f0))
+        n, m = f.denominator, f.numerator
+        assert f0 / n * m == sys_clk_freq
+        p = 8
+
+        self.specials.pll = Instance(
+            "PLL_ADV",
+            name="crg_pll_adv",
+            p_SIM_DEVICE="SPARTAN6", p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL",
+            p_REF_JITTER=.01,
+            i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0,
+            p_DIVCLK_DIVIDE=1,
+            # Input Clocks (100MHz)
+            i_CLKIN1=clk100b,
+            p_CLKIN1_PERIOD=1e9/f0,
+            i_CLKIN2=0,
+            p_CLKIN2_PERIOD=0.,
+            i_CLKINSEL=1,
+            # Feedback
+            i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd,
+            p_CLK_FEEDBACK="CLKFBOUT",
+            p_CLKFBOUT_MULT=m*p//n, p_CLKFBOUT_PHASE=0.,
+            # (300MHz) sdram wr rd
+            o_CLKOUT0=pll_sdram_full, p_CLKOUT0_DUTY_CYCLE=.5,
+            p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p//4,
+            # unused?
+            o_CLKOUT1=pll_unused, p_CLKOUT1_DUTY_CYCLE=.5,
+            p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=15,
+            # (150MHz) sdram_half - sdram dqs adr ctrl
+            o_CLKOUT2=pll_sdram_half_a, p_CLKOUT2_DUTY_CYCLE=.5,
+            p_CLKOUT2_PHASE=270., p_CLKOUT2_DIVIDE=p//2,
+            # (150Mhz) off-chip ddr
+            o_CLKOUT3=pll_sdram_half_b, p_CLKOUT3_DUTY_CYCLE=.5,
+            p_CLKOUT3_PHASE=250., p_CLKOUT3_DIVIDE=p//2,
+            # ( 50MHz) periph
+            o_CLKOUT4=pll_periph, p_CLKOUT4_DUTY_CYCLE=.5,
+            p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=20,
+            # ( 75MHz) sysclk
+            o_CLKOUT5=pll_sys, p_CLKOUT5_DUTY_CYCLE=.5,
+            p_CLKOUT5_PHASE=0., p_CLKOUT5_DIVIDE=p//1,
+        )
+
+        # Power on reset
+        reset = ~platform.request("cpu_reset") | self.reset
+        self.clock_domains.cd_por = ClockDomain()
+        por = Signal(max=1 << 11, reset=(1 << 11) - 1)
+        self.sync.por += If(por != 0, por.eq(por - 1))
+        self.specials += AsyncResetSynchronizer(self.cd_por, reset)
+
+        # System clock
+        self.specials += Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk)
+        self.comb += self.cd_por.clk.eq(self.cd_sys.clk)
+        self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll_lckd | (por > 0))
+
+        # SDRAM clocks -----------------------------------------------------------------------------
+        self.clk4x_wr_strb = Signal()
+        self.clk4x_rd_strb = Signal()
+
+        # SDRAM full clock
+        self.specials += Instance("BUFPLL", name="sdram_full_bufpll",
+            p_DIVIDE       = 4,
+            i_PLLIN        = pll_sdram_full, i_GCLK=self.cd_sys.clk,
+            i_LOCKED       = pll_lckd,
+            o_IOCLK        = self.cd_sdram_full_wr.clk,
+            o_SERDESSTROBE = self.clk4x_wr_strb)
+        self.comb += [
+            self.cd_sdram_full_rd.clk.eq(self.cd_sdram_full_wr.clk),
+            self.clk4x_rd_strb.eq(self.clk4x_wr_strb),
+        ]
+        # SDRAM_half clock
+        self.specials += Instance("BUFG", name="sdram_half_a_bufpll",
+            i_I=pll_sdram_half_a, o_O=self.cd_sdram_half.clk)
+        clk_sdram_half_shifted = Signal()
+        self.specials += Instance("BUFG", name="sdram_half_b_bufpll",
+            i_I=pll_sdram_half_b, o_O=clk_sdram_half_shifted)
+
+        output_clk = Signal()
+        clk = platform.request("ddram_clock")
+        self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE",
+            p_INIT=0, p_SRTYPE="SYNC",
+            i_D0=1, i_D1=0, i_S=0, i_R=0, i_CE=1,
+            i_C0=clk_sdram_half_shifted,
+            i_C1=~clk_sdram_half_shifted,
+            o_Q=output_clk)
+        self.specials += Instance("OBUFDS", i_I=output_clk, o_O=clk.p, o_OB=clk.n)
+
+# BaseSoC ------------------------------------------------------------------------------------------
+
+class BaseSoC(SoCCore):
+    def __init__(self, with_ethernet=True, with_etherbone=False, eth_phy=0, **kwargs):
+        sys_clk_freq = int(75e6)
+        platform     = atlys.Platform()
+
+        # SoCCore ----------------------------------------------------------------------------------
+        SoCCore.__init__(self, platform, sys_clk_freq,
+            ident          = "LiteX SoC on Atlys",
+            ident_version  = True,
+            **kwargs)
+
+        # CRG --------------------------------------------------------------------------------------
+        self.submodules.crg = _CRG(platform, sys_clk_freq)
+        self.platform.add_period_constraint(self.crg.cd_sys.clk, 1e9/sys_clk_freq)
+
+        # DDR2 SDRAM -------------------------------------------------------------------------------
+        if not self.integrated_main_ram_size:
+            self.submodules.ddrphy = s6ddrphy.S6HalfRateDDRPHY(platform.request("ddram"),
+                memtype           = "DDR2",
+                rd_bitslip        = 0,
+                wr_bitslip        = 4,
+                dqs_ddr_alignment = "C0")
+            self.comb += [
+                self.ddrphy.clk4x_wr_strb.eq(self.crg.clk4x_wr_strb),
+                self.ddrphy.clk4x_rd_strb.eq(self.crg.clk4x_rd_strb),
+            ]
+            self.add_sdram("sdram",
+                phy           = self.ddrphy,
+                module        = MT47H64M16(sys_clk_freq, "1:2"),
+                l2_cache_size = kwargs.get("l2_size", 8192),
+            )
+
+        # Ethernet / Etherbone ---------------------------------------------------------------------
+        if with_ethernet or with_etherbone:
+            from liteeth.phy import LiteEthPHYGMIIMII
+            self.submodules.ethphy = LiteEthPHYGMIIMII(
+                clock_pads = self.platform.request("eth_clocks", eth_phy),
+                pads       = self.platform.request("eth", eth_phy),
+                clk_freq   = int(self.sys_clk_freq))
+            if with_ethernet:
+                self.add_ethernet(phy=self.ethphy)
+            if with_etherbone:
+                self.add_etherbone(phy=self.ethphy)
+            self.ethphy.crg.cd_eth_rx.clk.attr.add("keep")
+            self.ethphy.crg.cd_eth_tx.clk.attr.add("keep")
+            self.platform.add_platform_command("""
+NET "{eth_clocks_rx}" CLOCK_DEDICATED_ROUTE = FALSE;
+NET "{eth_clocks_tx}" CLOCK_DEDICATED_ROUTE = FALSE;
+""",
+            eth_clocks_rx=platform.lookup_request("eth_clocks").rx,
+            eth_clocks_tx=platform.lookup_request("eth_clocks").tx,
+            )
+
+        # Leds -------------------------------------------------------------------------------------
+        self.submodules.leds = LedChaser(
+            pads         = platform.request_all("user_led"),
+            sys_clk_freq = sys_clk_freq)
+        self.add_csr("leds")
+
+# Build --------------------------------------------------------------------------------------------
+
+def main():
+    parser = argparse.ArgumentParser(description="LiteX SoC on Atlys")
+    parser.add_argument("--build", action="store_true", help="Build bitstream")
+    parser.add_argument("--load",  action="store_true", help="Load bitstream")
+    parser.add_argument("--with-ethernet",  action="store_true", help="Enable Ethernet support")
+    parser.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support")
+
+    builder_args(parser)
+    soc_core_args(parser)
+    args = parser.parse_args()
+
+    soc = BaseSoC(**soc_core_argdict(args))
+    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()