--- /dev/null
+diff --git a/litex/build/altera/programmer.py b/litex/build/altera/programmer.py
+index c797c564f..e25af5565 100644
+--- a/litex/build/altera/programmer.py
++++ b/litex/build/altera/programmer.py
+@@ -4,20 +4,49 @@
+ # Copyright (c) 2015-2018 Florent Kermarrec <florent@enjoy-digital.fr>
+ # SPDX-License-Identifier: BSD-2-Clause
+
++import argparse
+ from litex.build.generic_programmer import GenericProgrammer
++from litex.build.altera import quartus
++from litex.build import tools
++
++_toolchain_args = None
++
++# called by quartus.py for win32 quartus args
++def set_toolchain_args(args_dict):
++ global _toolchain_args
++ _toolchain_args = args_dict
++
++def get_toolchain_args():
++ global _toolchain_args
++ if _toolchain_args is None:
++ parser = argparse.ArgumentParser(add_help=False)
++ quartus.fill_args(parser)
++ args, _ = parser.parse_known_args()
++ _toolchain_args = quartus.get_argdict(args)
++ return _toolchain_args
+
+ # USBBlaster ---------------------------------------------------------------------------------------
+
+ class USBBlaster(GenericProgrammer):
+ needs_bitreverse = False
+
+- def __init__(self, cable_name="USB-Blaster", device_id=1):
++ def __init__(self, prog_name="quartus_pgm", cable_name="USB-Blaster", device_id=1):
++ self.prog_name = prog_name
+ self.cable_name = cable_name
+ self.device_id = device_id
+
++ args = get_toolchain_args()
++ self.win32_quartus = args["win32_quartus"]
++ self.quartus_path = args["quartus_path"]
++ self.wsl_path = args["wsl_path"]
++
+ def load_bitstream(self, bitstream_file, cable_suffix=""):
+- self.call(["quartus_pgm",
++ if self.win32_quartus:
++ self.prog_name = f"{self.quartus_path}{self.prog_name}.exe"
++ bitstream_file = f"{self.wsl_path}{bitstream_file}"
++
++ self.call([self.prog_name,
+ "-m", "jtag",
+- "-c", "{}{}".format(self.cable_name, cable_suffix),
+- "-o", "p;{}@{}".format(bitstream_file, self.device_id)
++ "-c", f"{self.cable_name}{cable_suffix}"
++ "-o", f"p;{bitstream_file}@{self.device_id}"
+ ])
+diff --git a/litex/build/altera/quartus.py b/litex/build/altera/quartus.py
+index 786e89f3c..38b1b3932 100644
+--- a/litex/build/altera/quartus.py
++++ b/litex/build/altera/quartus.py
+@@ -18,6 +18,7 @@ from migen.fhdl.simplify import FullMemoryWE
+
+ from litex.build.generic_platform import Pins, IOStandard, Misc
+ from litex.build.generic_toolchain import GenericToolchain
++from litex.build.altera import programmer
+ from litex.build import tools
+
+ # AlteraQuartusToolchain ---------------------------------------------------------------------------
+@@ -32,19 +33,29 @@ class AlteraQuartusToolchain(GenericToolchain):
+ super().__init__()
+ self._synth_tool = "quartus_map"
+ self._conv_tool = "quartus_cpf"
++ self.win32_quartus = False
++ self.win32_quartus_path = ""
+ self.clock_constraints = []
+ self.additional_sdc_commands = []
+ self.additional_qsf_commands = []
+ self.cst = []
+
+ def build(self, platform, fragment,
+- synth_tool = "quartus_map",
+- conv_tool = "quartus_cpf",
++ synth_tool = "quartus_map",
++ conv_tool = "quartus_cpf",
++ win32_quartus = False,
++ win32_quartus_path = "",
++ quartus_path = "",
++ wsl_path = "",
+ **kwargs):
+
+- self._synth_tool = synth_tool
+- self._conv_tool = conv_tool
++ self._synth_tool = synth_tool
++ self._conv_tool = conv_tool
+
++ self.win32_quartus = win32_quartus
++ self.quartus_path = quartus_path
++ self.wsl_path = wsl_path
++
+ if not platform.device.startswith("10M"):
+ # Apply FullMemoryWE on Design (Quartus does not infer memories correctly otherwise).
+ FullMemoryWE()(fragment)
+@@ -152,10 +163,10 @@ class AlteraQuartusToolchain(GenericToolchain):
+ # Add sources
+ for filename, language, library, *copy in self.platform.sources:
+ if language == "verilog": language = "systemverilog" # Enforce use of SystemVerilog
+- tpl = "set_global_assignment -name {lang}_FILE {path} -library {lib}"
++ tpl = "set_global_assignment -name {lang}_FILE \"{wsl_path}{path}\" -library {lib}"
+ # Do not add None type files
+ if language is not None:
+- qsf.append(tpl.format(lang=language.upper(), path=filename.replace("\\", "/"), lib=library))
++ qsf.append(tpl.format(lang=language.upper(), wsl_path=self.wsl_path, path=filename.replace("\\", "/"), lib=library))
+ # Check if the file is a header. Those should not be explicitly added to qsf,
+ # but rather included in include search_path
+ else:
+@@ -167,11 +178,11 @@ class AlteraQuartusToolchain(GenericToolchain):
+ # Add IPs
+ for filename in self.platform.ips:
+ file_ext = os.path.splitext(filename)[1][1:].upper()
+- qsf.append(f"set_global_assignment -name {file_ext}_FILE " + filename.replace("\\", "/"))
++ qsf.append(f"set_global_assignment -name {file_ext}_FILE \"{self.wsl_path}" + filename.replace("\\", "/")) + "\""
+
+ # Add include paths
+ for path in self.platform.verilog_include_paths:
+- qsf.append("set_global_assignment -name SEARCH_PATH {}".format(path.replace("\\", "/")))
++ qsf.append("set_global_assignment -name SEARCH_PATH \"{}{}\"".format(self.wsl_path, path.replace("\\", "/")))
+
+ # Set top level
+ qsf.append("set_global_assignment -name top_level_entity " + self._build_name)
+@@ -195,6 +206,9 @@ class AlteraQuartusToolchain(GenericToolchain):
+
+ def build_script(self):
+ build_name = self._build_name
++ wsl_ext = ""
++ if self.win32_quartus:
++ wsl_ext = ".exe"
+
+ if sys.platform in ["win32", "cygwin"]:
+ script_file = "build_" + build_name + ".bat"
+@@ -205,10 +219,10 @@ class AlteraQuartusToolchain(GenericToolchain):
+ script_contents += "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n"
+ script_contents += "set -e -u -x -o pipefail\n"
+ script_contents += """
+-{synth_tool} --read_settings_files=on --write_settings_files=off {build_name} -c {build_name}
+-quartus_fit --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
+-quartus_asm --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
+-quartus_sta {build_name} -c {build_name}"""
++{quartus_path}{synth_tool}{wsl_ext} --read_settings_files=on --write_settings_files=off {build_name} -c {build_name}
++{quartus_path}quartus_fit{wsl_ext} --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
++{quartus_path}quartus_asm{wsl_ext} --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
++{quartus_path}quartus_sta{wsl_ext} {build_name} -c {build_name}"""
+
+ # Create .rbf.
+ if self.platform.create_rbf:
+@@ -222,7 +236,7 @@ if exist "{build_name}.sof" (
+ script_contents += """
+ if [ -f "{build_name}.sof" ]
+ then
+- {conv_tool} -c {build_name}.sof {build_name}.rbf
++ {quartus_path}{conv_tool}{wsl_ext} -c {build_name}.sof {build_name}.rbf
+ fi
+ """
+ # Create .svf.
+@@ -237,10 +251,10 @@ if exist "{build_name}.sof" (
+ script_contents += """
+ if [ -f "{build_name}.sof" ]
+ then
+- {conv_tool} -c -q \"12.0MHz\" -g 3.3 -n p {build_name}.sof {build_name}.svf
++ {quartus_path}{conv_tool}{wsl_ext} -c -q \"12.0MHz\" -g 3.3 -n p {build_name}.sof {build_name}.svf
+ fi
+ """
+- script_contents = script_contents.format(build_name=build_name, synth_tool=self._synth_tool, conv_tool=self._conv_tool)
++ script_contents = script_contents.format(build_name=build_name, quartus_path=self.quartus_path, wsl_ext=wsl_ext, synth_tool=self._synth_tool, conv_tool=self._conv_tool)
+ tools.write_to_file(script_file, script_contents, force_unix=True)
+
+ return script_file
+@@ -251,21 +265,45 @@ fi
+ else:
+ shell = ["bash"]
+
+- if which(self._synth_tool) is None:
++ if which(self._synth_tool) is None and not self.win32_quartus:
+ msg = "Unable to find Quartus toolchain, please:\n"
+ msg += "- Add Quartus toolchain to your $PATH."
+ raise OSError(msg)
+
++ testpath = "{}{}.exe".format(self.quartus_path, self._synth_tool)
++ if self.win32_quartus and not os.path.isfile(testpath):
++ msg = "Unable to find Quartus toolchain, please:\n"
++ msg += "- set $LITEX_WIN32_QUARTUS_PATH with the path accessible from within WSL\n"
++ msg += "- or use \"--win32-quartus-path\" flag to set the path"
++ raise OSError(msg)
++
+ if subprocess.call(shell + [script]) != 0:
+ raise OSError("Error occured during Quartus's script execution.")
+
+ def fill_args(parser):
+ toolchain_group = parser.add_argument_group(title="Quartus toolchain options")
+- toolchain_group.add_argument("--synth-tool", default="quartus_map", help="Synthesis mode (quartus_map or quartus_syn).")
+- toolchain_group.add_argument("--conv-tool", default="quartus_cpf", help="Quartus Prime Convert_programming_file (quartus_cpf or quartus_pfg).")
++ toolchain_group.add_argument("--synth-tool", default="quartus_map", help="Synthesis mode (quartus_map or quartus_syn).")
++ toolchain_group.add_argument("--conv-tool", default="quartus_cpf", help="Quartus Prime Convert_programming_file (quartus_cpf or quartus_pfg).")
++ toolchain_group.add_argument("--win32-quartus", action="store_true", help="Use the Windows install of Quartus.")
++ toolchain_group.add_argument("--win32-quartus-path", default="", help="Path to the Windows install of Quartus.")
+
+ def get_argdict(args):
+- return {
+- "synth_tool" : args.synth_tool,
+- "conv_tool" : args.conv_tool,
++ if args.win32_quartus:
++ if args.win32_quartus_path:
++ quartus_path = args.win32_quartus_path
++ else:
++ quartus_path = os.getenv("LITEX_WIN32_QUARTUS_PATH", "/mnt/c/altera_lite/25.1std/quartus/bin64")
++
++ quartus_path += "/" # Double slash is OK
++
++ args_dict = {
++ "synth_tool" : args.synth_tool,
++ "conv_tool" : args.conv_tool,
++ "win32_quartus" : args.win32_quartus,
++ "win32_quartus_path" : args.win32_quartus_path,
++ "quartus_path" : quartus_path,
++ "wsl_path" : f"//wsl.localhost/{os.getenv("WSL_DISTRO_NAME", "")}",
+ }
++
++ programmer.set_toolchain_args(args_dict)
++ return args_dict