diff --git a/litex_boards/platforms/qmtech_ep4ce55.py b/litex_boards/platforms/qmtech_ep4ce55.py
deleted file mode 100644
index ad83e1b..0000000
--- a/litex_boards/platforms/qmtech_ep4ce55.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#
-# This file is part of LiteX-Boards.
-#
-# Copyright (c) 2020 Basel Sayeh <Basel.Sayeh@hotmail.com>
-# Copyright (c) 2021 Hans Baier <hansfbaier@gmail.com>
-# SPDX-License-Identifier: BSD-2-Clause
-
-from litex.build.generic_platform import *
-from litex.build.altera import AlteraPlatform
-from litex.build.altera.programmer import USBBlaster
-
-# IOs ----------------------------------------------------------------------------------------------
-
-_io = [
-    # Clk
-    ("clk50", 0, Pins("T2"), IOStandard("3.3-V LVTTL")),
-
-    # Button
-    ("key", 0, Pins("Y13"),  IOStandard("3.3-V LVTTL")),
-    ("key", 1, Pins("W13"),  IOStandard("3.3-V LVTTL")),
-
-    # SPIFlash (W25Q64)
-    ("spiflash", 0,
-        # clk
-        Subsignal("cs_n", Pins("E2")),
-        Subsignal("clk",  Pins("K2")),
-        Subsignal("mosi", Pins("D1")),
-        Subsignal("miso", Pins("E2")),
-        IOStandard("3.3-V LVTTL"),
-    ),
-
-    # SDR SDRAM
-    ("sdram_clock", 0, Pins("Y6"), IOStandard("3.3-V LVTTL")),
-    ("sdram", 0,
-        Subsignal("a",     Pins(
-            "V2 V1 U2 U1 V3 V4 Y2 AA1",
-            "Y3 V5 W1 Y4 V6")),
-        Subsignal("ba",    Pins("Y1 W2")),
-        Subsignal("cs_n",  Pins("AA3")),
-        Subsignal("cke",   Pins("W6")),
-        Subsignal("ras_n", Pins("AB3")),
-        Subsignal("cas_n", Pins("AA4")),
-        Subsignal("we_n",  Pins("AB4")),
-        Subsignal("dq", Pins(
-            "AA10 AB9 AA9 AB8 AA8 AB7 AA7 AB5",
-            "Y7 W8 Y8 V9 V10 Y10 W10 V11")),
-        Subsignal("dm", Pins("AA5 W7")),
-        IOStandard("3.3-V LVTTL")
-    ),
-]
-
-# The connectors are named after the daughterboard, not the core board
-# because on the different core boards the names vary, but on the
-# daughterboard they stay the same, which we need to connect the
-# daughterboard peripherals to the core board.
-# On this board J2 is U7 and J3 is U8
-_connectors = [
-    ("J2", {
-         # odd row     even row
-          7: "R1",   8: "R2",
-          9: "P1",  10: "P2",
-         11: "N1",  12: "N2",
-         13: "M1",  14: "M2",
-         15: "J1",  16: "J2",
-         17: "H1",  18: "H2",
-         19: "F1",  20: "F2",
-         21: "E1",  22: "D2",
-         23: "C1",  24: "C2",
-         25: "B1",  26: "B2",
-         27: "B3",  28: "A3",
-         29: "B4",  30: "A4",
-         31: "C4",  32: "C3",
-         33: "B5",  34: "A5",
-         35: "B6",  36: "A6",
-         37: "B7",  38: "A7",
-         39: "B8",  40: "A8",
-         41: "B9",  42: "A9",
-         43: "B10", 44: "A10",
-         45: "B13", 46: "A13",
-         47: "B14", 48: "A14",
-         49: "B15", 50: "A15",
-         51: "B16", 52: "A16",
-         53: "B17", 54: "A17",
-         55: "B18", 56: "A18",
-         57: "B19", 58: "A19",
-         59: "B20", 60: "A20",
-    }),
-    ("J3", {
-        # odd row     even row
-         7: "AA13",   8: "AB13",
-         9: "AA14",  10: "AB14",
-        11: "AA15",  12: "AB15",
-        13: "AA16",  14: "AB16",
-        15: "AA17",  16: "AB17",
-        17: "AA18",  18: "AB18",
-        19: "AA19",  20: "AB19",
-        21: "AA20",  22: "AB20",
-        23: "Y22",   24: "Y21",
-        25: "W22",   26: "W21",
-        27: "V22",   28: "V21",
-        29: "U22",   30: "U21",
-        31: "R22",   32: "R21",
-        33: "P22",   34: "P21",
-        35: "N22",   36: "N21",
-        37: "M22",   38: "M21",
-        39: "L22",   40: "L21",
-        41: "K22",   42: "K21",
-        43: "J22",   44: "J21",
-        45: "H22",   46: "H21",
-        47: "F22",   48: "F21",
-        49: "E22",   50: "E21",
-        51: "D22",   52: "D21",
-        53: "C22",   54: "C21",
-        55: "B22",   56: "B21",
-        57: "N20",   58: "N19",
-        59: "M20",   60: "M19",
-    })
-]
-
-# Platform -----------------------------------------------------------------------------------------
-
-class Platform(AlteraPlatform):
-    default_clk_name   = "clk50"
-    default_clk_period = 1e9/50e6
-    core_resources = [
-        ("user_led", 0, Pins("E4"), IOStandard("3.3-V LVTTL")),
-        ("serial", 0,
-            Subsignal("tx", Pins("J3:7"), IOStandard("3.3-V LVTTL")),
-            Subsignal("rx", Pins("J3:8"), IOStandard("3.3-V LVTTL"))
-        ),
-    ]
-
-    def __init__(self, with_daughterboard=False):
-        device = "EP4CE55F23C8"
-        io = _io
-        connectors = _connectors
-
-        if with_daughterboard:
-            from litex_boards.platforms.qmtech_daughterboard import QMTechDaughterboard
-            daughterboard = QMTechDaughterboard(IOStandard("3.3-V LVTTL"))
-            io += daughterboard.io
-            connectors += daughterboard.connectors
-        else:
-            io += self.core_resources
-
-        AlteraPlatform.__init__(self, device, io, connectors)
-
-        if with_daughterboard:
-            # an ethernet pin takes K22, so make it available
-            self.add_platform_command("set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION \"USE AS REGULAR IO\"")
-
-    def create_programmer(self):
-        return USBBlaster()
-
-    def do_finalize(self, fragment):
-        AlteraPlatform.do_finalize(self, fragment)
-        self.add_period_constraint(self.lookup_request("clk50", loose=True), 1e9/50e6)
diff --git a/litex_boards/platforms/qmtech_ep4ce15.py b/litex_boards/platforms/qmtech_ep4cex5.py
similarity index 96%
rename from litex_boards/platforms/qmtech_ep4ce15.py
rename to litex_boards/platforms/qmtech_ep4cex5.py
index cb51234..d7292b5 100644
--- a/litex_boards/platforms/qmtech_ep4ce15.py
+++ b/litex_boards/platforms/qmtech_ep4cex5.py
@@ -130,8 +130,11 @@ class Platform(AlteraPlatform):
         ),
     ]
 
-    def __init__(self, with_daughterboard=False):
-        device = "EP4CE15F23C8"
+    def __init__(self, variant="ep4ce15", with_daughterboard=False):
+        device = {
+            "ep4ce15": "EP4CE15F23C8",
+            "ep4ce55": "EP4CE55F23C8"
+        }[variant]
         io = _io
         connectors = _connectors
 
diff --git a/litex_boards/targets/qmtech_ep4ce55.py b/litex_boards/targets/qmtech_ep4ce55.py
deleted file mode 100755
index 51c7f81..0000000
--- a/litex_boards/targets/qmtech_ep4ce55.py
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/usr/bin/env python3
-
-#
-# This file is part of LiteX-Boards.
-#
-# Copyright (c) 2020 Basel Sayeh <Basel.Sayeh@hotmail.com>
-# SPDX-License-Identifier: BSD-2-Clause
-
-import os
-import argparse
-
-from migen import *
-from migen.genlib.resetsync import AsyncResetSynchronizer
-
-from litex.build.io import DDROutput
-
-from litex_boards.platforms import qmtech_ep4ce55
-
-from litex.soc.cores.clock import CycloneIVPLL
-from litex.soc.integration.soc_core import *
-from litex.soc.integration.builder import *
-from litex.soc.cores.led import LedChaser
-
-from litedram.modules import W9825G6KH6
-from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY
-
-from litex.soc.cores.video import VideoVGAPHY
-from liteeth.phy.mii import LiteEthPHYMII
-
-# CRG ----------------------------------------------------------------------------------------------
-
-class _CRG(Module):
-    def __init__(self, platform, sys_clk_freq, with_ethernet, with_vga, sdram_rate="1:1"):
-        self.rst = Signal()
-        self.clock_domains.cd_sys    = ClockDomain()
-        if sdram_rate == "1:2":
-            self.clock_domains.cd_sys2x    = ClockDomain()
-            self.clock_domains.cd_sys2x_ps = ClockDomain(reset_less=True)
-        else:
-            self.clock_domains.cd_sys_ps = ClockDomain(reset_less=True)
-
-        if with_ethernet:
-            self.clock_domains.cd_eth   = ClockDomain()
-        if with_vga:
-            self.clock_domains.cd_vga   = ClockDomain(reset_less=True)
-
-        # # #
-
-        # Clk / Rst
-        clk50 = platform.request("clk50")
-
-        # PLL
-        self.submodules.pll = pll = CycloneIVPLL(speedgrade="-6")
-        self.comb += pll.reset.eq(self.rst)
-        pll.register_clkin(clk50, 50e6)
-        pll.create_clkout(self.cd_sys,    sys_clk_freq)
-        if sdram_rate == "1:2":
-            pll.create_clkout(self.cd_sys2x,    2*sys_clk_freq)
-            # theoretically 90 degrees, but increase to relax timing
-            pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180)
-        else:
-            pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90)
-
-        if with_ethernet:
-            pll.create_clkout(self.cd_eth,   25e6)
-        if with_vga:
-            pll.create_clkout(self.cd_vga,   40e6)
-
-        # SDRAM clock
-        sdram_clk = ClockSignal("sys2x_ps" if sdram_rate == "1:2" else "sys_ps")
-        self.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk)
-
-# BaseSoC ------------------------------------------------------------------------------------------
-
-class BaseSoC(SoCCore):
-    def __init__(self, sys_clk_freq=int(50e6), with_daughterboard=False,
-                 with_ethernet=False, with_etherbone=False, eth_ip="192.168.1.50", eth_dynamic_ip=False,
-                 with_led_chaser=True, with_video_terminal=False, with_video_framebuffer=False,
-                 ident_version=True, sdram_rate="1:1", **kwargs):
-        platform = qmtech_ep4ce55.Platform(with_daughterboard=with_daughterboard)
-
-        # SoCCore ----------------------------------------------------------------------------------
-        SoCCore.__init__(self, platform, sys_clk_freq,
-            ident          = "LiteX SoC on QMTECH EP4CE55" + (" + Daughterboard" if with_daughterboard else ""),
-            ident_version  = ident_version,
-            **kwargs)
-
-        # CRG --------------------------------------------------------------------------------------
-        self.submodules.crg = _CRG(platform,
-                                   sys_clk_freq, with_ethernet or with_etherbone,
-                                   with_video_terminal or with_video_framebuffer,
-                                   sdram_rate=sdram_rate)
-
-        # SDR SDRAM --------------------------------------------------------------------------------
-        if not self.integrated_main_ram_size:
-            sdrphy_cls = HalfRateGENSDRPHY if sdram_rate == "1:2" else GENSDRPHY
-            self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"), sys_clk_freq)
-            self.add_sdram("sdram",
-                phy           = self.sdrphy,
-                module        = W9825G6KH6(sys_clk_freq, sdram_rate),
-                l2_cache_size = kwargs.get("l2_size", 8192)
-            )
-
-        # Ethernet / Etherbone ---------------------------------------------------------------------
-        if with_ethernet or with_etherbone:
-            self.submodules.ethphy = LiteEthPHYMII(
-                clock_pads = self.platform.request("eth_clocks"),
-                pads       = self.platform.request("eth"))
-            if with_ethernet:
-                self.add_ethernet(phy=self.ethphy, dynamic_ip=eth_dynamic_ip)
-            if with_etherbone:
-                self.add_etherbone(phy=self.ethphy, ip_address=eth_ip)
-
-        # Video ------------------------------------------------------------------------------------
-        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")
-
-        # Leds -------------------------------------------------------------------------------------
-        if with_led_chaser:
-            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 QMTECH EP4CE55")
-    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=50e6,        help="System clock frequency.")
-    parser.add_argument("--sdram-rate",   default="1:1",       help="SDRAM Rate (1:1 Full Rate or 1:2 Half Rate).")
-    parser.add_argument("--with-daughterboard",  action="store_true",              help="Board plugged into the QMTech daughterboard.")
-    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.")
-    parser.add_argument("--eth-ip",              default="192.168.1.50", type=str, help="Ethernet/Etherbone IP address.")
-    parser.add_argument("--eth-dynamic-ip",      action="store_true",              help="Enable dynamic Ethernet IP addresses setting.")
-    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("--no-ident-version",    action="store_false",             help="Disable build time output.")
-    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_daughterboard     = args.with_daughterboard,
-        with_ethernet          = args.with_ethernet,
-        with_etherbone         = args.with_etherbone,
-        eth_ip                 = args.eth_ip,
-        eth_dynamic_ip         = args.eth_dynamic_ip,
-        ident_version          = args.no_ident_version,
-        with_video_terminal    = args.with_video_terminal,
-        with_video_framebuffer = args.with_video_framebuffer,
-        sdram_rate             = args.sdram_rate,
-        **soc_core_argdict(args)
-    )
-
-    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 + ".sof"))
-
-if __name__ == "__main__":
-    main()
diff --git a/litex_boards/targets/qmtech_ep4ce15.py b/litex_boards/targets/qmtech_ep4cex5.py
similarity index 94%
rename from litex_boards/targets/qmtech_ep4ce15.py
rename to litex_boards/targets/qmtech_ep4cex5.py
index c932a8a..5600cd8 100755
--- a/litex_boards/targets/qmtech_ep4ce15.py
+++ b/litex_boards/targets/qmtech_ep4cex5.py
@@ -14,7 +14,7 @@ from migen.genlib.resetsync import AsyncResetSynchronizer
 
 from litex.build.io import DDROutput
 
-from litex_boards.platforms import qmtech_ep4ce15
+from litex_boards.platforms import qmtech_ep4cex5
 
 from litex.soc.cores.clock import CycloneIVPLL
 from litex.soc.integration.soc_core import *
@@ -73,11 +73,11 @@ class _CRG(Module):
 # BaseSoC ------------------------------------------------------------------------------------------
 
 class BaseSoC(SoCCore):
-    def __init__(self, sys_clk_freq=int(50e6), with_daughterboard=False,
+    def __init__(self, variant="ep4ce15", sys_clk_freq=int(50e6), with_daughterboard=False,
                  with_ethernet=False, with_etherbone=False, eth_ip="192.168.1.50", eth_dynamic_ip=False,
                  with_led_chaser=True, with_video_terminal=False, with_video_framebuffer=False,
                  ident_version=True, sdram_rate="1:1", **kwargs):
-        platform = qmtech_ep4ce15.Platform(with_daughterboard=with_daughterboard)
+        platform = qmtech_ep4cex5.Platform(variant=variant, with_daughterboard=with_daughterboard)
 
         # SoCCore ----------------------------------------------------------------------------------
         SoCCore.__init__(self, platform, sys_clk_freq,
@@ -131,6 +131,7 @@ def main():
     parser = argparse.ArgumentParser(description="LiteX SoC on QMTECH EP4CE15")
     parser.add_argument("--build",        action="store_true", help="Build bitstream.")
     parser.add_argument("--load",         action="store_true", help="Load bitstream.")
+    parser.add_argument("--variant",      default="ep4ce15",   help="Board variant (ep4ce15 or ep4ce55).")
     parser.add_argument("--sys-clk-freq", default=50e6,        help="System clock frequency.")
     parser.add_argument("--sdram-rate",   default="1:1",       help="SDRAM Rate (1:1 Full Rate or 1:2 Half Rate).")
     parser.add_argument("--with-daughterboard",  action="store_true",              help="Board plugged into the QMTech daughterboard.")
@@ -152,7 +153,8 @@ def main():
     args = parser.parse_args()
 
     soc = BaseSoC(
-        sys_clk_freq = int(float(args.sys_clk_freq)),
+        variant                = args.variant,
+        sys_clk_freq           = int(float(args.sys_clk_freq)),
         with_daughterboard     = args.with_daughterboard,
         with_ethernet          = args.with_ethernet,
         with_etherbone         = args.with_etherbone,