from migen.genlib.io import *
from migen.genlib.resetsync import AsyncResetSynchronizer
+# ECPX AsyncResetSynchronizer ----------------------------------------------------------------------
class LatticeECPXAsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset):
rst1 = Signal()
self.specials += [
- Instance("FD1S3BX", i_D=0, i_PD=async_reset,
- i_CK=cd.clk, o_Q=rst1),
- Instance("FD1S3BX", i_D=rst1, i_PD=async_reset,
- i_CK=cd.clk, o_Q=cd.rst)
+ Instance("FD1S3BX",
+ i_D = 0,
+ i_PD = async_reset,
+ i_CK = cd.clk,
+ o_Q = rst1),
+ Instance("FD1S3BX",
+ i_D = rst1,
+ i_PD = async_reset,
+ i_CK = cd.clk,
+ o_Q = cd.rst)
]
def lower(dr):
return LatticeECPXAsyncResetSynchronizerImpl(dr.cd, dr.async_reset)
+# ECPX Differential Output -------------------------------------------------------------------------
class LatticeECPXDDROutputImpl(Module):
def __init__(self, i1, i2, o, clk):
- self.specials += Instance("ODDRXD1",
- synthesis_directive="ODDRAPPS=\"SCLK_ALIGNED\"",
- i_SCLK=clk,
- i_DA=i1, i_DB=i2, o_Q=o)
+ self.specials += [
+ Instance("ODDRXD1",
+ synthesis_directive="ODDRAPPS=\"SCLK_ALIGNED\"",
+ i_SCLK = clk,
+ i_DA = i1,
+ i_DB = i2,
+ o_Q = o)
+ ]
class LatticeECPXDDROutput:
def lower(dr):
return LatticeECPXDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk)
+# ECPX Special Overrides ---------------------------------------------------------------------------
+
lattice_ecpx_special_overrides = {
AsyncResetSynchronizer: LatticeECPXAsyncResetSynchronizer,
- DDROutput: LatticeECPXDDROutput
+ DDROutput: LatticeECPXDDROutput
}
+# ECPX Trellis Tristate ----------------------------------------------------------------------------
class LatticeECPXTrellisTristateImpl(Module):
def __init__(self, io, o, oe, i):
nbits, sign = value_bits_sign(io)
if nbits == 1:
- # If `io` is an expression like `port[x]`, it is not legal to index further
- # into it if it is only 1 bit wide.
- self.specials += \
+ self.specials += [
Instance("TRELLIS_IO",
- p_DIR="BIDIR",
- i_B=io,
- i_I=o,
- o_O=i,
- i_T=~oe,
+ p_DIR = "BIDIR",
+ i_B = io,
+ i_I = o,
+ o_O = i,
+ i_T = ~oe
)
+ ]
else:
for bit in range(nbits):
- self.specials += \
+ self.specials += [
Instance("TRELLIS_IO",
p_DIR="BIDIR",
- i_B=io[bit],
- i_I=o[bit],
- o_O=i[bit],
- i_T=~oe,
+ i_B = io[bit],
+ i_I = o[bit],
+ o_O = i[bit],
+ i_T = ~oe
)
+ ]
class LatticeECPXTrellisTristate(Module):
def lower(dr):
return LatticeECPXTrellisTristateImpl(dr.target, dr.o, dr.oe, dr.i)
+# ECPX Trellis Special Overrides -------------------------------------------------------------------
+
lattice_ecpx_trellis_special_overrides = {
AsyncResetSynchronizer: LatticeECPXAsyncResetSynchronizer,
Tristate: LatticeECPXTrellisTristate,
DDROutput: LatticeECPXDDROutput
}
+# iCE40 AsyncResetSynchronizer ----------------------------------------------------------------------
class LatticeiCE40AsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset):
def lower(dr):
return LatticeiCE40AsyncResetSynchronizerImpl(dr.cd, dr.async_reset)
+# iCE40 Trellis Tristate ---------------------------------------------------------------------------
class LatticeiCE40TristateImpl(Module):
def __init__(self, io, o, oe, i):
nbits, sign = value_bits_sign(io)
if nbits == 1:
- # If `io` is an expression like `port[x]`, it is not legal to index further
- # into it if it is only 1 bit wide.
- self.specials += \
+ self.specials += [
Instance("SB_IO",
- p_PIN_TYPE=C(0b101001, 6),
- io_PACKAGE_PIN=io,
- i_OUTPUT_ENABLE=oe,
- i_D_OUT_0=o,
- o_D_IN_0=i,
+ p_PIN_TYPE = C(0b101001, 6),
+ io_PACKAGE_PIN = io,
+ i_OUTPUT_ENABLE = oe,
+ i_D_OUT_0 = o,
+ o_D_IN_0 = i
)
+ ]
else:
for bit in range(nbits):
- self.specials += \
+ self.specials += [
Instance("SB_IO",
- p_PIN_TYPE=C(0b101001, 6),
- io_PACKAGE_PIN=io[bit],
- i_OUTPUT_ENABLE=oe,
- i_D_OUT_0=o[bit],
- o_D_IN_0=i[bit],
+ p_PIN_TYPE = C(0b101001, 6),
+ io_PACKAGE_PIN = io[bit],
+ i_OUTPUT_ENABLE = oe,
+ i_D_OUT_0 = o[bit],
+ o_D_IN_0 = i[bit]
)
+ ]
class LatticeiCE40Tristate(Module):
def lower(dr):
return LatticeiCE40TristateImpl(dr.target, dr.o, dr.oe, dr.i)
+# iCE40 Differential Output ------------------------------------------------------------------------
class LatticeiCE40DifferentialOutputImpl(Module):
def __init__(self, i, o_p, o_n):
- self.specials += Instance("SB_IO",
- p_PIN_TYPE=C(0b011000, 6),
- p_IO_STANDARD="SB_LVCMOS",
- io_PACKAGE_PIN=o_p,
- i_D_OUT_0=i)
+ self.specials += [
+ Instance("SB_IO",
+ p_PIN_TYPE = C(0b011000, 6),
+ p_IO_STANDARD = "SB_LVCMOS",
+ io_PACKAGE_PIN = o_p,
+ i_D_OUT_0 = i
+ )
+ ]
- self.specials += Instance("SB_IO",
- p_PIN_TYPE=C(0b011000, 6),
- p_IO_STANDARD="SB_LVCMOS",
- io_PACKAGE_PIN=o_n,
- i_D_OUT_0=~i)
+ self.specials += [
+ Instance("SB_IO",
+ p_PIN_TYPE = C(0b011000, 6),
+ p_IO_STANDARD = "SB_LVCMOS",
+ io_PACKAGE_PIN = o_n,
+ i_D_OUT_0 = ~i
+ )
+ ]
class LatticeiCE40DifferentialOutput:
return LatticeiCE40DifferentialOutputImpl(dr.i, dr.o_p, dr.o_n)
+# iCE40 DDR Output ---------------------------------------------------------------------------------
+
class LatticeiCE40DDROutputImpl(Module):
def __init__(self, i1, i2, o, clk):
- self.specials += Instance("SB_IO",
- p_PIN_TYPE=C(0b010000, 6),
- p_IO_STANDARD="SB_LVCMOS",
- io_PACKAGE_PIN=o,
- i_CLOCK_ENABLE=1,
- i_OUTPUT_CLK=clk,
- i_OUTPUT_ENABLE=1,
- i_D_OUT_0=i1,
- i_D_OUT_1=i2)
+ self.specials += [
+ Instance("SB_IO",
+ p_PIN_TYPE = C(0b010000, 6),
+ p_IO_STANDARD = "SB_LVCMOS",
+ io_PACKAGE_PIN = o,
+ i_CLOCK_ENABLE = 1,
+ i_OUTPUT_CLK = clk,
+ i_OUTPUT_ENABLE = 1,
+ i_D_OUT_0 = i1,
+ i_D_OUT_1 = i2
+ )
+ ]
class LatticeiCE40DDROutput:
def lower(dr):
return LatticeiCE40DDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk)
+# iCE40 Trellis Special Overrides ------------------------------------------------------------------
lattice_ice40_special_overrides = {
AsyncResetSynchronizer: LatticeiCE40AsyncResetSynchronizer,
from litex.build import tools
from litex.build.lattice import common
+# Helpers ------------------------------------------------------------------------------------------
def _produces_jedec(device):
return device.startswith("LCMX")
+# IO Constraints (.lpf) ----------------------------------------------------------------------------
def _format_constraint(c):
if isinstance(c, Pins):
def _format_lpf(signame, pin, others, resname):
fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)]
- r = ""
+ lpf = []
for pre, suf in fmt_c:
- r += pre + "\"" + signame + "\"" + suf + ";\n"
- return r
+ lpf.append(pre + "\"" + signame + "\"" + suf + ";")
+ return "\n".join(lpf)
-def _build_lpf(named_sc, named_pc):
- r = "BLOCK RESETPATHS;\n"
- r += "BLOCK ASYNCPATHS;\n"
+def _build_lpf(named_sc, named_pc, build_name):
+ lpf = []
+ lpf.append("BLOCK RESETPATHS;")
+ lpf.append("BLOCK ASYNCPATHS;")
for sig, pins, others, resname in named_sc:
if len(pins) > 1:
for i, p in enumerate(pins):
- r += _format_lpf(sig + "[" + str(i) + "]", p, others, resname)
+ lpf.append(_format_lpf(sig + "[" + str(i) + "]", p, others, resname))
else:
- r += _format_lpf(sig, pins[0], others, resname)
+ lpf.append(_format_lpf(sig, pins[0], others, resname))
if named_pc:
- r += "\n" + "\n\n".join(named_pc)
- return r
+ lpf.append("\n\n".join(named_pc))
+ tools.write_to_file(build_name + ".lpf", "\n".join(lpf))
+# Project (.tcl) -----------------------------------------------------------------------------------
-def _build_files(device, sources, vincpaths, build_name):
+def _build_tcl(device, sources, vincpaths, build_name):
tcl = []
- tcl.append("prj_project new -name \"{}\" -impl \"impl\" -dev {} -synthesis \"synplify\"".format(build_name, device))
+ # Create project
+ tcl.append(" ".join([
+ "prj_project",
+ "new -name \"{}\"".format(build_name),
+ "-impl \"impl\"",
+ "-dev {}".format(device),
+ "-synthesis \"synplify\""
+ ]))
+
+ # Add include paths
for path in vincpaths:
tcl.append("prj_impl option {include path} {\"" + path + "\"}")
+
+ # Add sources
for filename, language, library in sources:
tcl.append("prj_src add \"" + filename.replace("\\", "/") + "\" -work " + library)
+
+ # Set top level
tcl.append("prj_impl option top \"{}\"".format(build_name))
+
+ # Save project
tcl.append("prj_project save")
+
+ # Build flow
tcl.append("prj_run Synthesis -impl impl -forceOne")
tcl.append("prj_run Translate -impl impl")
tcl.append("prj_run Map -impl impl")
tcl.append("prj_run Export -impl impl -task Jedecgen")
tools.write_to_file(build_name + ".tcl", "\n".join(tcl))
+# Script -------------------------------------------------------------------------------------------
def _build_script(build_name, device, toolchain_path, ver=None):
if sys.platform in ("win32", "cygwin"):
script_ext = ".bat"
- build_script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n"
+ script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n"
copy_stmt = "copy"
fail_stmt = " || exit /b"
else:
script_ext = ".sh"
- build_script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n"
+ script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n"
copy_stmt = "cp"
fail_stmt = ""
if sys.platform not in ("win32", "cygwin"):
- build_script_contents += "bindir={}\n".format(toolchain_path)
- build_script_contents += ". ${{bindir}}/diamond_env{fail_stmt}\n".format(
- fail_stmt=fail_stmt)
- build_script_contents += "{pnmainc} {tcl_script}{fail_stmt}\n".format(
- pnmainc=os.path.join(toolchain_path, "pnmainc"),
- tcl_script=build_name + ".tcl",
- fail_stmt=fail_stmt)
+ script_contents += "bindir={}\n".format(toolchain_path)
+ script_contents += ". ${{bindir}}/diamond_env{fail_stmt}\n".format(fail_stmt=fail_stmt)
+ script_contents += "{pnmainc} {tcl_script}{fail_stmt}\n".format(
+ pnmainc = os.path.join(toolchain_path, "pnmainc"),
+ tcl_script = build_name + ".tcl",
+ fail_stmt = fail_stmt)
for ext in (".bit", ".jed"):
if ext == ".jed" and not _produces_jedec(device):
continue
- build_script_contents += "{copy_stmt} {diamond_product} {migen_product}" \
- "{fail_stmt}\n".format(
- copy_stmt=copy_stmt,
- fail_stmt=fail_stmt,
- diamond_product=os.path.join("impl", build_name + "_impl" + ext),
- migen_product=build_name + ext)
+ script_contents += "{copy_stmt} {diamond_product} {migen_product} {fail_stmt}\n".format(
+ copy_stmt = copy_stmt,
+ fail_stmt = fail_stmt,
+ diamond_product = os.path.join("impl", build_name + "_impl" + ext),
+ migen_product = build_name + ext)
build_script_file = "build_" + build_name + script_ext
- tools.write_to_file(build_script_file, build_script_contents,
- force_unix=False)
+ tools.write_to_file(build_script_file, script_contents, force_unix=False)
return build_script_file
-
def _run_script(script):
if sys.platform in ("win32", "cygwin"):
shell = ["cmd", "/c"]
if subprocess.call(shell + [script]) != 0:
raise OSError("Subprocess failed")
+# LatticeDiamondToolchain --------------------------------------------------------------------------
class LatticeDiamondToolchain:
attr_translate = {
# FIXME: document
- "keep": ("syn_keep", "true"),
- "no_retiming": ("syn_no_retiming", "true"),
- "async_reg": None,
- "mr_ff": None,
- "mr_false_path": None,
- "ars_ff1": None,
- "ars_ff2": None,
- "ars_false_path": None,
+ "keep": ("syn_keep", "true"),
+ "no_retiming": ("syn_no_retiming", "true"),
+ "async_reg": None,
+ "mr_ff": None,
+ "mr_false_path": None,
+ "ars_ff1": None,
+ "ars_ff2": None,
+ "ars_false_path": None,
"no_shreg_extract": None
}
special_overrides = common.lattice_ecpx_special_overrides
- def build(self, platform, fragment, build_dir="build", build_name="top",
- toolchain_path=None, run=True, **kwargs):
+ def build(self, platform, fragment,
+ build_dir = "build",
+ build_name = "top",
+ toolchain_path = None,
+ run = True,
+ **kwargs):
+
+ # Create build directory
if toolchain_path is None:
toolchain_path = "/opt/Diamond"
os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd()
os.chdir(build_dir)
+ # Finalize design
if not isinstance(fragment, _Fragment):
fragment = fragment.get_fragment()
platform.finalize(fragment)
+ # Generate verilog
v_output = platform.get_verilog(fragment, name=build_name, **kwargs)
named_sc, named_pc = platform.resolve_signals(v_output.ns)
v_file = build_name + ".v"
v_output.write(v_file)
platform.add_source(v_file)
- _build_files(platform.device, platform.sources, platform.verilog_include_paths, build_name)
- tools.write_to_file(build_name + ".lpf", _build_lpf(named_sc, named_pc))
+ # Generate design script file (.tcl)
+ _build_tcl(platform.device, platform.sources, platform.verilog_include_paths, build_name)
+ # Generate design timing constraints file (.lpf)
+ _build_lpf(named_sc, named_pc, build_name)
+
+ # Generate build script
script = _build_script(build_name, platform.device, toolchain_path)
+
+ # Run
if run:
_run_script(script)
def add_period_constraint(self, platform, clk, period):
# TODO: handle differential clk
- platform.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk)
+ platform.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(
+ freq=str(float(1/period)*1000), clk="{clk}"), clk=clk)