diff --git a/mibuild/.gitignore b/mibuild/.gitignore new file mode 100644 index 000000000..8d35cb327 --- /dev/null +++ b/mibuild/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +*.pyc diff --git a/mibuild/LICENSE b/mibuild/LICENSE new file mode 100644 index 000000000..cdc6303bf --- /dev/null +++ b/mibuild/LICENSE @@ -0,0 +1,29 @@ +Unless otherwise noted, Mibuild is copyright (C) 2013 Sebastien Bourdeauducq. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Other authors retain ownership of their contributions. If a submission can +reasonably be considered independently copyrightable, it's yours and we +encourage you to claim it with appropriate copyright notices. This submission +then falls under the "otherwise noted" category. All submissions are strongly +encouraged to use the two-clause BSD license reproduced above. diff --git a/mibuild/README b/mibuild/README new file mode 100644 index 000000000..df95d062c --- /dev/null +++ b/mibuild/README @@ -0,0 +1,27 @@ +Mibuild (Milkymist Build system) + a build system and board database for Migen-based FPGA designs + +Quick intro: + +from migen.fhdl.std import * +from mibuild.platforms import m1 +plat = m1.Platform() +led = plat.request("user_led") +m = Module() +counter = Signal(26) +m.comb += led.eq(counter[25]) +m.sync += counter.eq(counter + 1) +plat.build_cmdline(m) + +Code repository: +https://github.com/milkymist/mibuild +Migen: +https://github.com/milkymist/migen +Experimental version of the Milkymist SoC based on Migen: +https://github.com/milkymist/milkymist-ng + +Mibuild is designed for Python 3.3. + +Send questions, comments and patches to devel [AT] lists.milkymist.org +Description files for new boards welcome. +We are also on IRC: #milkymist on the Freenode network. diff --git a/mibuild/mibuild/__init__.py b/mibuild/mibuild/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/mibuild/mibuild/altera_quartus.py b/mibuild/mibuild/altera_quartus.py new file mode 100644 index 000000000..781b104ff --- /dev/null +++ b/mibuild/mibuild/altera_quartus.py @@ -0,0 +1,105 @@ +# This file is Copyright (c) 2013 Florent Kermarrec +# License: BSD + +import os, subprocess + +from migen.fhdl.structure import _Fragment +from mibuild.generic_platform import * +from mibuild.crg import SimpleCRG +from mibuild import tools + +def _add_period_constraint(platform, clk, period): + platform.add_platform_command("""set_global_assignment -name DUTY_CYCLE 50 -section_id {clk}""", clk=clk) + platform.add_platform_command("""set_global_assignment -name FMAX_REQUIREMENT "{freq} MHz" -section_id {clk}\n""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) + +class CRG_SE(SimpleCRG): + def __init__(self, platform, clk_name, rst_name, period, rst_invert=False): + SimpleCRG.__init__(self, platform, clk_name, rst_name, rst_invert) + _add_period_constraint(platform, self.cd_sys.clk, period) + +def _format_constraint(c): + if isinstance(c, Pins): + return "set_location_assignment PIN_" + c.identifiers[0] + elif isinstance(c, IOStandard): + return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\"" + elif isinstance(c, Misc): + return c.misc + +def _format_qsf(signame, pin, others, resname): + fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)] + fmt_r = resname[0] + ":" + str(resname[1]) + if resname[2] is not None: + fmt_r += "." + resname[2] + r = "" + for c in fmt_c: + r += c + " -to " + signame + " # " + fmt_r + "\n" + return r + +def _build_qsf(named_sc, named_pc): + r = "" + for sig, pins, others, resname in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + r += _format_qsf(sig + "[" + str(i) + "]", p, others, resname) + else: + r += _format_qsf(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + return r + +def _build_files(device, sources, named_sc, named_pc, build_name): + qsf_contents = "" + for filename, language in sources: + qsf_contents += "set_global_assignment -name "+language.upper()+"_FILE " + filename.replace("\\","/") + "\n" + + qsf_contents += _build_qsf(named_sc, named_pc) + qsf_contents += "set_global_assignment -name DEVICE " + device + tools.write_to_file(build_name + ".qsf", qsf_contents) + +def _run_quartus(build_name, quartus_path): + build_script_contents = """# Autogenerated by mibuild + +quartus_map {build_name}.qpf +quartus_fit {build_name}.qpf +quartus_asm {build_name}.qpf +quartus_sta {build_name}.qpf + +""".format(build_name=build_name) + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents) + + r = subprocess.call(["bash", build_script_file]) + if r != 0: + raise OSError("Subprocess failed") + +class AlteraQuartusPlatform(GenericPlatform): + def build(self, fragment, build_dir="build", build_name="top", + quartus_path="/opt/Altera", run=True): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + self.finalize(fragment) + + v_src, named_sc, named_pc = self.get_verilog(fragment) + v_file = build_name + ".v" + tools.write_to_file(v_file, v_src) + sources = self.sources + [(v_file, "verilog")] + _build_files(self.device, sources, named_sc, named_pc, build_name) + if run: + _run_quartus(build_name, quartus_path) + + os.chdir("..") + + def build_arg_ns(self, ns, *args, **kwargs): + for n in ["build_dir", "build_name", "quartus_path"]: + kwargs[n] = getattr(ns, n) + kwargs["run"] = not ns.no_run + self.build(*args, **kwargs) + + def add_arguments(self, parser): + parser.add_argument("--build-dir", default="build", help="Set the directory in which to generate files and run Quartus") + parser.add_argument("--build-name", default="top", help="Base name for the generated files") + parser.add_argument("--quartus-path", default="/opt/Altera", help="Quartus installation path (without version directory)") + parser.add_argument("--no-run", action="store_true", help="Only generate files, do not run Quartus") diff --git a/mibuild/mibuild/crg.py b/mibuild/mibuild/crg.py new file mode 100644 index 000000000..5d51a13b9 --- /dev/null +++ b/mibuild/mibuild/crg.py @@ -0,0 +1,14 @@ +from migen.fhdl.std import * + +class SimpleCRG(Module): + def __init__(self, platform, clk_name, rst_name, rst_invert=False): + reset_less = rst_name is None + self.clock_domains.cd_sys = ClockDomain(reset_less=reset_less) + self._clk = platform.request(clk_name) + self.comb += self.cd_sys.clk.eq(self._clk) + + if not reset_less: + if rst_invert: + self.comb += self.cd_sys.rst.eq(~platform.request(rst_name)) + else: + self.comb += self.cd_sys.rst.eq(platform.request(rst_name)) diff --git a/mibuild/mibuild/generic_platform.py b/mibuild/mibuild/generic_platform.py new file mode 100644 index 000000000..17c8752a2 --- /dev/null +++ b/mibuild/mibuild/generic_platform.py @@ -0,0 +1,238 @@ +import os, argparse + +from migen.fhdl.std import * +from migen.fhdl.structure import _Fragment +from migen.genlib.record import Record +from migen.fhdl import verilog, edif + +from mibuild import tools + +class ConstraintError(Exception): + pass + +class Pins: + def __init__(self, *identifiers): + self.identifiers = [] + for i in identifiers: + self.identifiers += i.split() + +class IOStandard: + def __init__(self, name): + self.name = name + +class Drive: + def __init__(self, strength): + self.strength = strength + +class Misc: + def __init__(self, misc): + self.misc = misc + +class Subsignal: + def __init__(self, name, *constraints): + self.name = name + self.constraints = list(constraints) + +class PlatformInfo: + def __init__(self, info): + self.info = info + +def _lookup(description, name, number): + for resource in description: + if resource[0] == name and (number is None or resource[1] == number): + return resource + raise ConstraintError("Resource not found: " + name + ":" + str(number)) + +def _resource_type(resource): + t = None + for element in resource[2:]: + if isinstance(element, Pins): + assert(t is None) + t = len(element.identifiers) + elif isinstance(element, Subsignal): + if t is None: + t = [] + assert(isinstance(t, list)) + n_bits = None + for c in element.constraints: + if isinstance(c, Pins): + assert(n_bits is None) + n_bits = len(c.identifiers) + t.append((element.name, n_bits)) + return t + +def _separate_pins(constraints): + pins = None + others = [] + for c in constraints: + if isinstance(c, Pins): + assert(pins is None) + pins = c.identifiers + else: + others.append(c) + return pins, others + +class ConstraintManager: + def __init__(self, description): + self.available = list(description) + self.matched = [] + self.platform_commands = [] + + def request(self, name, number=None): + resource = _lookup(self.available, name, number) + rt = _resource_type(resource) + if isinstance(rt, int): + obj = Signal(rt, name_override=resource[0]) + else: + obj = Record(rt, name=resource[0]) + for element in resource[2:]: + if isinstance(element, PlatformInfo): + obj.platform_info = element.info + break + self.available.remove(resource) + self.matched.append((resource, obj)) + return obj + + def lookup_request(self, name, number=None): + for resource, obj in self.matched: + if resource[0] == name and (number is None or resource[1] == number): + return obj + raise ConstraintError("Resource not found: " + name + ":" + str(number)) + + def add_platform_command(self, command, **signals): + self.platform_commands.append((command, signals)) + + def get_io_signals(self): + r = set() + for resource, obj in self.matched: + if isinstance(obj, Signal): + r.add(obj) + else: + r.update(obj.flatten()) + return r + + def get_sig_constraints(self): + r = [] + for resource, obj in self.matched: + name = resource[0] + number = resource[1] + has_subsignals = False + top_constraints = [] + for element in resource[2:]: + if isinstance(element, Subsignal): + has_subsignals = True + else: + top_constraints.append(element) + if has_subsignals: + for element in resource[2:]: + if isinstance(element, Subsignal): + sig = getattr(obj, element.name) + pins, others = _separate_pins(top_constraints + element.constraints) + r.append((sig, pins, others, (name, number, element.name))) + else: + pins, others = _separate_pins(top_constraints) + r.append((obj, pins, others, (name, number, None))) + return r + + def get_platform_commands(self): + return self.platform_commands + + +class GenericPlatform: + def __init__(self, device, io, default_crg_factory=None, name=None): + self.device = device + self.constraint_manager = ConstraintManager(io) + self.default_crg_factory = default_crg_factory + if name is None: + name = self.__module__.split(".")[-1] + self.name = name + self.sources = [] + self.finalized = False + + def request(self, *args, **kwargs): + return self.constraint_manager.request(*args, **kwargs) + + def lookup_request(self, *args, **kwargs): + return self.constraint_manager.lookup_request(*args, **kwargs) + + def add_platform_command(self, *args, **kwargs): + return self.constraint_manager.add_platform_command(*args, **kwargs) + + def finalize(self, fragment, *args, **kwargs): + if self.finalized: + raise ConstraintError("Already finalized") + # if none exists, create a default clock domain and drive it + if not fragment.clock_domains: + if self.default_crg_factory is None: + raise NotImplementedError("No clock/reset generator defined by either platform or user") + crg = self.default_crg_factory(self) + fragment += crg.get_fragment() + self.do_finalize(fragment, *args, **kwargs) + self.finalized = True + + def do_finalize(self, fragment, *args, **kwargs): + """overload this and e.g. add_platform_command()'s after the + modules had their say""" + pass + + def add_source(self, filename, language=None): + if language is None: + language = tools.language_by_filename(filename) + if language is None: + language = "verilog" # default to Verilog + filename = os.path.abspath(filename) + self.sources.append((filename, language)) + + def add_sources(self, path, *filenames, language=None): + for f in filenames: + self.add_source(os.path.join(path, f), language) + + def add_source_dir(self, path): + for root, dirs, files in os.walk(path): + for filename in files: + language = tools.language_by_filename(filename) + if language is not None: + self.add_source(os.path.join(root, filename), language) + + def _resolve_signals(self, vns): + # resolve signal names in constraints + sc = self.constraint_manager.get_sig_constraints() + named_sc = [(vns.get_name(sig), pins, others, resource) for sig, pins, others, resource in sc] + # resolve signal names in platform commands + pc = self.constraint_manager.get_platform_commands() + named_pc = [] + for template, args in pc: + name_dict = dict((k, vns.get_name(sig)) for k, sig in args.items()) + named_pc.append(template.format(**name_dict)) + return named_sc, named_pc + + def _get_source(self, fragment, gen_fn): + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + # generate source + src, vns = gen_fn(fragment) + named_sc, named_pc = self._resolve_signals(vns) + return src, named_sc, named_pc + + def get_verilog(self, fragment, **kwargs): + return self._get_source(fragment, lambda f: verilog.convert(f, self.constraint_manager.get_io_signals(), + return_ns=True, create_clock_domains=False, **kwargs)) + + def get_edif(self, fragment, cell_library, vendor, device, **kwargs): + return self._get_source(fragment, lambda f: edif.convert(f, self.constraint_manager.get_io_signals(), + cell_library, vendor, device, return_ns=True, **kwargs)) + + def build(self, fragment): + raise NotImplementedError("GenericPlatform.build must be overloaded") + + def add_arguments(self, parser): + pass # default: no arguments + + def build_arg_ns(self, ns, *args, **kwargs): + self.build(*args, **kwargs) + + def build_cmdline(self, *args, **kwargs): + parser = argparse.ArgumentParser(description="FPGA bitstream build system") + self.add_arguments(parser) + ns = parser.parse_args() + self.build_arg_ns(ns, *args, **kwargs) diff --git a/mibuild/mibuild/platforms/__init__.py b/mibuild/mibuild/platforms/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/mibuild/mibuild/platforms/de0nano.py b/mibuild/mibuild/platforms/de0nano.py new file mode 100644 index 000000000..567f87499 --- /dev/null +++ b/mibuild/mibuild/platforms/de0nano.py @@ -0,0 +1,95 @@ +# This file is Copyright (c) 2013 Florent Kermarrec +# License: BSD + +from mibuild.generic_platform import * +from mibuild.altera_quartus import AlteraQuartusPlatform, CRG_SE + +_io = [ + ("clk50", 0, Pins("R8"), IOStandard("3.3-V LVTTL")), + + ("user_led", 0, Pins("A15"), IOStandard("3.3-V LVTTL")), + ("user_led", 1, Pins("A13"), IOStandard("3.3-V LVTTL")), + ("user_led", 2, Pins("B13"), IOStandard("3.3-V LVTTL")), + ("user_led", 3, Pins("A11"), IOStandard("3.3-V LVTTL")), + ("user_led", 4, Pins("D1"), IOStandard("3.3-V LVTTL")), + ("user_led", 5, Pins("F3"), IOStandard("3.3-V LVTTL")), + ("user_led", 6, Pins("B1"), IOStandard("3.3-V LVTTL")), + ("user_led", 7, Pins("L3"), IOStandard("3.3-V LVTTL")), + + ("key", 0, Pins("J15"), IOStandard("3.3-V LVTTL")), + ("key", 1, Pins("E1"), IOStandard("3.3-V LVTTL")), + + ("sw", 0, Pins("M1"), IOStandard("3.3-V LVTTL")), + ("sw", 1, Pins("T9"), IOStandard("3.3-V LVTTL")), + ("sw", 2, Pins("B9"), IOStandard("3.3-V LVTTL")), + ("sw", 3, Pins("M15"), IOStandard("3.3-V LVTTL")), + + ("serial", 0, + Subsignal("tx", Pins("D3"), IOStandard("3.3-V LVTTL")), + Subsignal("rx", Pins("C3"), IOStandard("3.3-V LVTTL")) + ), + + ("sdram_clock", 0, Pins("R4"), IOStandard("3.3-V LVTTL")), + ("sdram", 0, + Subsignal("a", Pins("P2 N5 N6 M8 P8 T7 N8 T6 R1 P1 N2 N1 L4")), + Subsignal("ba", Pins("M7 M6")), + Subsignal("cs_n", Pins("P6")), + Subsignal("cke", Pins("L7")), + Subsignal("ras_n", Pins("L2")), + Subsignal("cas_n", Pins("L1")), + Subsignal("we_n", Pins("C2")), + Subsignal("dq", Pins("G2 G1 L8 K5 K2 J2 J1 R7 T4 T2 T3 R3 R5 P3 N3 K1")), + Subsignal("dqm", Pins("R6","T5")), + IOStandard("3.3-V LVTTL") + ), + + ("epcs", 0, + Subsignal("data0", Pins("H2")), + Subsignal("dclk", Pins("H1")), + Subsignal("ncs0", Pins("D2")), + Subsignal("asd0", Pins("C1")), + IOStandard("3.3-V LVTTL") + ), + + ("i2c", 0, + Subsignal("sclk", Pins("F2")), + Subsignal("sdat", Pins("F1")), + IOStandard("3.3-V LVTTL") + ), + + ("g_sensor", 0, + Subsignal("cs_n", Pins("G5")), + Subsignal("int", Pins("M2")), + IOStandard("3.3-V LVTTL") + ), + + ("adc", 0, + Subsignal("cs_n", Pins("A10")), + Subsignal("saddr", Pins("B10")), + Subsignal("sclk", Pins("B14")), + Subsignal("sdat", Pins("A9")), + IOStandard("3.3-V LVTTL") + ), + + ("gpio_0", 0, + Pins("D3 C3 A2 A3 B3 B4 A4 B5 A5 D5 B6 A6 B7 D6 A7 C6", + "C8 E6 E7 D8 E8 F8 F9 E9 C9 D9 E11 E10 C11 B11 A12 D11", + "D12 B12"), + IOStandard("3.3-V LVTTL") + ), + ("gpio_1", 0, + Pins("F13 T15 T14 T13 R13 T12 R12 T11 T10 R11 P11 R10 N12 P9 N9 N11", + "L16 K16 R16 L15 P15 P16 R14 N16 N15 P14 L14 N14 M10 L13 J16 K15", + "J13 J14"), + IOStandard("3.3-V LVTTL") + ), + ("gpio_2", 0, + Pins("A14 B16 C14 C16 C15 D16 D15 D14 F15 F16 F14 G16 G15"), + IOStandard("3.3-V LVTTL") + ), +] + +class Platform(AlteraQuartusPlatform): + def __init__(self): + AlteraQuartusPlatform.__init__(self, "EP4CE22F17C6", _io, + lambda p: CRG_SE(p, "clk50", "key", 20.0, True)) diff --git a/mibuild/mibuild/platforms/kc705.py b/mibuild/mibuild/platforms/kc705.py new file mode 100644 index 000000000..bb47edccb --- /dev/null +++ b/mibuild/mibuild/platforms/kc705.py @@ -0,0 +1,84 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS + +_io = [ + ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")), + ("user_led", 1, Pins("AA8"), IOStandard("LVCMOS15")), + ("user_led", 2, Pins("AC9"), IOStandard("LVCMOS15")), + ("user_led", 3, Pins("AB9"), IOStandard("LVCMOS15")), + ("user_led", 4, Pins("AE26"), IOStandard("LVCMOS25")), + ("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")), + ("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")), + ("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")), + + ("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")), + + ("user_btn_c", 0, Pins("G12"), IOStandard("LVCMOS25")), + ("user_btn_n", 0, Pins("AA12"), IOStandard("LVCMOS15")), + ("user_btn_s", 0, Pins("AB12"), IOStandard("LVCMOS15")), + ("user_btn_w", 0, Pins("AC6"), IOStandard("LVCMOS15")), + ("user_btn_e", 0, Pins("AG5"), IOStandard("LVCMOS15")), + + ("user_dip_btn", 0, Pins("Y29"), IOStandard("LVCMOS25")), + ("user_dip_btn", 1, Pins("W29"), IOStandard("LVCMOS25")), + ("user_dip_btn", 2, Pins("AA28"), IOStandard("LVCMOS25")), + ("user_dip_btn", 3, Pins("Y28"), IOStandard("LVCMOS25")), + + ("clk200", 0, + Subsignal("p", Pins("AD12"), IOStandard("LVDS")), + Subsignal("n", Pins("AD11"), IOStandard("LVDS")) + ), + + ("clk156", 0, + Subsignal("p", Pins("K28"), IOStandard("LVDS_25")), + Subsignal("n", Pins("K29"), IOStandard("LVDS_25")) + ), + + ("i2c", 0, + Subsignal("scl", Pins("K21")), + Subsignal("sda", Pins("L21")), + IOStandard("LVCMOS25")), + + ("serial", 0, + Subsignal("cts", Pins("L27")), + Subsignal("rts", Pins("K23")), + Subsignal("tx", Pins("K24")), + Subsignal("rx", Pins("M19")), + IOStandard("LVCMOS25")), + + ("mmc", 0, + Subsignal("wp", Pins("Y21")), + Subsignal("det", Pins("AA21")), + Subsignal("cmd", Pins("AB22")), + Subsignal("clk", Pins("AB23")), + Subsignal("dat", Pins("AC20 AA23 AA22 AC21")), + IOStandard("LVCMOS25")), + + ("lcd", 0, + Subsignal("db", Pins("AA13 AA10 AA11 Y10")), + Subsignal("e", Pins("AB10")), + Subsignal("rs", Pins("Y11")), + Subsignal("rw", Pins("AB13")), + IOStandard("LVCMOS15")), + + ("rotary", 0, + Subsignal("a", Pins("Y26")), + Subsignal("b", Pins("Y25")), + Subsignal("push", Pins("AA26")), + IOStandard("LVCMOS25")), + + ("hdmi", 0, + Subsignal("d", Pins("B23 A23 E23 D23 F25 E25 E24 D24 F26 E26 G23 G24 J19 H19 L17 L18 K19 K20")), + Subsignal("de", Pins("H17")), + Subsignal("clk", Pins("K18")), + Subsignal("vsync", Pins("H20")), + Subsignal("hsync", Pins("J18")), + Subsignal("int", Pins("AH24")), + Subsignal("spdif", Pins("J17")), + Subsignal("spdif_out", Pins("G20")), + IOStandard("LVCMOS25")), +] + +class Platform(XilinxISEPlatform): + def __init__(self, crg_factory=lambda p: CRG_DS(p, "user_clk", "cpu_reset", 6.4)): + XilinxISEPlatform.__init__(self, "xc7k325t-ffg900-1", _io, crg_factory) diff --git a/mibuild/mibuild/platforms/lx9_microboard.py b/mibuild/mibuild/platforms/lx9_microboard.py new file mode 100644 index 000000000..955aea528 --- /dev/null +++ b/mibuild/mibuild/platforms/lx9_microboard.py @@ -0,0 +1,119 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE + +_io = [ + ("user_btn", 0, Pins("V4"), IOStandard("LVCMOS33"), + Misc("PULLDOWN"), Misc("TIG")), + + ("user_led", 0, Pins("P4"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + ("user_led", 1, Pins("L6"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + ("user_led", 2, Pins("F5"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + ("user_led", 3, Pins("C2"), Misc("SLEW=QUIETIO"), IOStandard("LVCMOS18")), + + ("user_dip", 0, Pins("B3"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + ("user_dip", 1, Pins("A3"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + ("user_dip", 2, Pins("B4"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + ("user_dip", 3, Pins("A4"), Misc("PULLDOWN"), IOStandard("LVCMOS33")), + + # TI CDCE913 programmable triple-output PLL + ("clk_y1", 0, Pins("V10"), IOStandard("LVCMOS33")), # default: 40 MHz + ("clk_y2", 0, Pins("K15"), IOStandard("LVCMOS33")), # default: 66 2/3 MHz + ("clk_y3", 0, Pins("C10"), IOStandard("LVCMOS33")), # default: 100 MHz + + # Maxim DS1088LU oscillator, not populated + ("clk_backup", 0, Pins("R8"), IOStandard("LVCMOS33")), + + # TI CDCE913 PLL I2C control + ("pll", 0, + Subsignal("scl", Pins("P12")), + Subsignal("sda", Pins("U13")), + Misc("PULLUP"), + IOStandard("LVCMOS33")), + + # Micron N25Q128 SPI Flash + ("spiflash", 0, + Subsignal("clk", Pins("R15")), + Subsignal("cs_n", Pins("V3")), + Subsignal("dq", Pins("T13 R13 T14 V14")), + IOStandard("LVCMOS33")), + + # PMOD extension connectors + ("pmod", 0, + Subsignal("d", Pins("F15 F16 C17 C18 F14 G14 D17 D18")), + IOStandard("LVCMOS33")), + ("pmod", 1, + Subsignal("d", Pins("H12 G13 E16 E18 K12 K13 F17 F18")), + IOStandard("LVCMOS33")), + + ("serial", 0, + Subsignal("tx", Pins("T7"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("R7"), Misc("PULLUP")), + IOStandard("LVCMOS33")), + + ("ddram_clock", 0, + Subsignal("p", Pins("G3")), + Subsignal("n", Pins("G1")), + IOStandard("MOBILE_DDR")), # actually DIFF_ + + # Micron MT46H32M16LFBF-5 LPDDR + ("ddram", 0, + Subsignal("a", Pins("J7 J6 H5 L7 F3 H4 H3 H6 " + "D2 D1 F4 D3 G6")), + Subsignal("ba", Pins("F2 F1")), + Subsignal("dq", Pins("L2 L1 K2 K1 H2 H1 J3 J1 " + "M3 M1 N2 N1 T2 T1 U2 U1")), + Subsignal("cke", Pins("H7")), + Subsignal("we_n", Pins("E3")), + Subsignal("cs_n", Pins("K6")), # NC! + Subsignal("cas_n", Pins("K5")), + Subsignal("ras_n", Pins("L5")), + Subsignal("dm", Pins("K3", "K4")), + Subsignal("dqs", Pins("L4", "P2")), + Subsignal("rzq", Pins("N4")), + IOStandard("MOBILE_DDR")), + + # Nat Semi DP83848J 10/100 Ethernet PHY + # pull-ups on rx_data set phy addr to 11110b + # and prevent isolate mode (addr 00000b) + ("eth_clocks", 0, + Subsignal("rx", Pins("L15")), + Subsignal("tx", Pins("H17")), + IOStandard("LVCMOS33")), + + ("eth", 0, + Subsignal("col", Pins("M18"), Misc("PULLDOWN")), + Subsignal("crs", Pins("N17"), Misc("PULLDOWN")), + Subsignal("mdc", Pins("M16")), + Subsignal("mdio", Pins("L18")), + Subsignal("rst_n", Pins("T18"), Misc("TIG")), + Subsignal("rx_data", Pins("T17 N16 N15 P18"), Misc("PULLUP")), + Subsignal("dv", Pins("P17")), + Subsignal("rx_er", Pins("N18")), + Subsignal("tx_data", Pins("K18 K17 J18 J16")), + Subsignal("tx_en", Pins("L17")), + Subsignal("tx_er", Pins("L16")), # NC! + IOStandard("LVCMOS33")), + ] + + +class Platform(XilinxISEPlatform): + def __init__(self): + XilinxISEPlatform.__init__(self, "xc6slx9-2csg324", _io, + lambda p: CRG_SE(p, "clk_y3", "user_btn", 10.)) + self.add_platform_command(""" +CONFIG VCCAUX = "3.3"; +""") + + def do_finalize(self, fragment): + try: + eth_clocks = self.lookup_request("eth_clocks") + self.add_platform_command(""" +NET "{phy_rx_clk}" TNM_NET = "GRPphy_rx_clk"; +NET "{phy_tx_clk}" TNM_NET = "GRPphy_tx_clk"; +TIMESPEC "TSphy_rx_clk" = PERIOD "GRPphy_rx_clk" 40 ns HIGH 50%; +TIMESPEC "TSphy_tx_clk" = PERIOD "GRPphy_tx_clk" 40 ns HIGH 50%; +TIMESPEC "TSphy_tx_clk_io" = FROM "GRPphy_tx_clk" TO "PADS" 10 ns; +TIMESPEC "TSphy_rx_clk_io" = FROM "PADS" TO "GRPphy_rx_clk" 10 ns; +""", phy_rx_clk=eth_clocks.rx, phy_tx_clk=eth_clocks.tx) + except ContraintError: + pass diff --git a/mibuild/mibuild/platforms/m1.py b/mibuild/mibuild/platforms/m1.py new file mode 100644 index 000000000..d72a6bde1 --- /dev/null +++ b/mibuild/mibuild/platforms/m1.py @@ -0,0 +1,155 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE + +_io = [ + ("user_led", 0, Pins("B16"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + ("user_led", 1, Pins("A16"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + + ("user_btn", 0, Pins("AB4"), IOStandard("LVCMOS33")), + ("user_btn", 1, Pins("AA4"), IOStandard("LVCMOS33")), + ("user_btn", 2, Pins("AB5"), IOStandard("LVCMOS33")), + + ("clk50", 0, Pins("AB11"), IOStandard("LVCMOS33")), + + # When executing softcore code in-place from the flash, we want + # the flash reset to be released before the system reset. + ("norflash_rst_n", 0, Pins("P22"), IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)), + ("norflash", 0, + Subsignal("adr", Pins("L22 L20 K22 K21 J19 H20 F22", + "F21 K17 J17 E22 E20 H18 H19 F20", + "G19 C22 C20 D22 D21 F19 F18 D20 D19")), + Subsignal("d", Pins("AA20 U14 U13 AA6 AB6 W4 Y4 Y7", + "AA2 AB2 V15 AA18 AB18 Y13 AA12 AB12"), Misc("PULLDOWN")), + Subsignal("oe_n", Pins("M22")), + Subsignal("we_n", Pins("N20")), + Subsignal("ce_n", Pins("M21")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8) + ), + + ("serial", 0, + Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP")) + ), + + ("ddram_clock", 0, + Subsignal("p", Pins("M3")), + Subsignal("n", Pins("L4")), + IOStandard("SSTL2_I") + ), + ("ddram", 0, + Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")), + Subsignal("ba", Pins("A2 E6")), + Subsignal("cs_n", Pins("F7")), + Subsignal("cke", Pins("G7")), + Subsignal("ras_n", Pins("E5")), + Subsignal("cas_n", Pins("C4")), + Subsignal("we_n", Pins("D3")), + Subsignal("dq", Pins("Y2 W3 W1 P8 P7 P6 P5 T4 T3", + "U4 V3 N6 N7 M7 M8 R4 P4 M6 L6 P3 N4", + "M5 V2 V1 U3 U1 T2 T1 R3 R1 P2 P1")), + Subsignal("dm", Pins("E1 E3 F3 G4")), + Subsignal("dqs", Pins("F1 F2 H5 H6")), + IOStandard("SSTL2_I") + ), + + ("eth_clocks", 0, + Subsignal("phy", Pins("M20")), + Subsignal("rx", Pins("H22")), + Subsignal("tx", Pins("H21")), + IOStandard("LVCMOS33") + ), + ("eth", 0, + Subsignal("rst_n", Pins("R22")), + Subsignal("dv", Pins("V21")), + Subsignal("rx_er", Pins("V22")), + Subsignal("rx_data", Pins("U22 U20 T22 T21")), + Subsignal("tx_en", Pins("N19")), + Subsignal("tx_er", Pins("M19")), + Subsignal("tx_data", Pins("M16 L15 P19 P20")), + Subsignal("col", Pins("W20")), + Subsignal("crs", Pins("W22")), + IOStandard("LVCMOS33") + ), + + ("vga_clock", 0, Pins("A11"), IOStandard("LVCMOS33")), + ("vga", 0, + Subsignal("r", Pins("C6 B6 A6 C7 A7 B8 A8 D9")), + Subsignal("g", Pins("C8 C9 A9 D7 D8 D10 C10 B10")), + Subsignal("b", Pins("D11 C12 B12 A12 C13 A13 D14 C14")), + Subsignal("hsync_n", Pins("A14")), + Subsignal("vsync_n", Pins("C15")), + Subsignal("psave_n", Pins("B14")), + IOStandard("LVCMOS33") + ), + + ("mmc", 0, + Subsignal("clk", Pins("A10")), + Subsignal("cmd", Pins("B18")), + Subsignal("dat", Pins("A18 E16 C17 A17")), + IOStandard("LVCMOS33") + ), + + # Digital video mixer extension board + ("dvi_in", 0, + Subsignal("clk", Pins("A20")), + Subsignal("data0_n", Pins("A21")), + Subsignal("data1", Pins("B21")), + Subsignal("data2_n", Pins("B22")), + Subsignal("scl", Pins("G16")), + Subsignal("sda", Pins("G17")), + IOStandard("LVCMOS33") + ), + ("dvi_in", 1, + Subsignal("clk", Pins("H17")), + Subsignal("data0_n", Pins("H16")), + Subsignal("data1", Pins("F17")), + Subsignal("data2_n", Pins("F16")), + Subsignal("scl", Pins("J16")), + Subsignal("sda", Pins("K16")), + IOStandard("LVCMOS33") + ), + ("dvi_pots", 0, + Subsignal("charge", Pins("A18")), # SD_DAT0 + Subsignal("blackout", Pins("C17")), # SD_DAT2 + Subsignal("crossfade", Pins("A17")), # SD_DAT3 + IOStandard("LVCMOS33") + ) +] + +class Platform(XilinxISEPlatform): + def __init__(self): + XilinxISEPlatform.__init__(self, "xc6slx45-fgg484-2", _io, + lambda p: CRG_SE(p, "clk50", None)) + + def do_finalize(self, fragment): + try: + self.add_platform_command(""" +NET "{clk50}" TNM_NET = "GRPclk50"; +TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%; +""", clk50=self.lookup_request("clk50")) + except ConstraintError: + pass + + try: + eth_clocks = self.lookup_request("eth_clocks") + self.add_platform_command(""" +NET "{phy_rx_clk}" TNM_NET = "GRPphy_rx_clk"; +NET "{phy_tx_clk}" TNM_NET = "GRPphy_tx_clk"; +TIMESPEC "TSphy_rx_clk" = PERIOD "GRPphy_rx_clk" 40 ns HIGH 50%; +TIMESPEC "TSphy_tx_clk" = PERIOD "GRPphy_tx_clk" 40 ns HIGH 50%; +TIMESPEC "TSphy_tx_clk_io" = FROM "GRPphy_tx_clk" TO "PADS" 10 ns; +TIMESPEC "TSphy_rx_clk_io" = FROM "PADS" TO "GRPphy_rx_clk" 10 ns; +""", phy_rx_clk=eth_clocks.rx, phy_tx_clk=eth_clocks.tx) + except ConstraintError: + pass + + for i in range(2): + si = "dviclk"+str(i) + try: + self.add_platform_command(""" +NET "{dviclk}" TNM_NET = "GRP"""+si+""""; +NET "{dviclk}" CLOCK_DEDICATED_ROUTE = FALSE; +TIMESPEC "TS"""+si+"""" = PERIOD "GRP"""+si+"""" 26.7 ns HIGH 50%; +""", dviclk=self.lookup_request("dvi_in", i).clk) + except ConstraintError: + pass diff --git a/mibuild/mibuild/platforms/mixxeo.py b/mibuild/mibuild/platforms/mixxeo.py new file mode 100644 index 000000000..12b242fb8 --- /dev/null +++ b/mibuild/mibuild/platforms/mixxeo.py @@ -0,0 +1,191 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE + +_io = [ + ("user_led", 0, Pins("V5"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + + ("clk50", 0, Pins("AB13"), IOStandard("LVCMOS33")), + + # When executing softcore code in-place from the flash, we want + # the flash reset to be released before the system reset. + ("norflash_rst_n", 0, Pins("P22"), IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)), + ("norflash", 0, + Subsignal("adr", Pins("L22 L20 K22 K21 J19 H20 F22", + "F21 K17 J17 E22 E20 H18 H19 F20", + "G19 C22 C20 D22 D21 F19 F18 D20 D19")), + Subsignal("d", Pins("AA20 U14 U13 AA6 AB6 W4 Y4 Y7", + "AA2 AB2 V15 AA18 AB18 Y13 AA12 AB12"), Misc("PULLDOWN")), + Subsignal("oe_n", Pins("M22")), + Subsignal("we_n", Pins("N20")), + Subsignal("ce_n", Pins("M21")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8) + ), + + ("serial", 0, + Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP")) + ), + + ("ddram_clock", 0, + Subsignal("p", Pins("M3")), + Subsignal("n", Pins("L4")), + IOStandard("SSTL2_I") + ), + ("ddram", 0, + Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")), + Subsignal("ba", Pins("A2 E6")), + Subsignal("cs_n", Pins("F7")), + Subsignal("cke", Pins("G7")), + Subsignal("ras_n", Pins("E5")), + Subsignal("cas_n", Pins("C4")), + Subsignal("we_n", Pins("D3")), + Subsignal("dq", Pins("Y2 W3 W1 P8 P7 P6 P5 T4 T3", + "U4 V3 N6 N7 M7 M8 R4 P4 M6 L6 P3 N4", + "M5 V2 V1 U3 U1 T2 T1 R3 R1 P2 P1")), + Subsignal("dm", Pins("E1 E3 F3 G4")), + Subsignal("dqs", Pins("F1 F2 H5 H6")), + IOStandard("SSTL2_I") + ), + + ("eth_clocks", 0, + Subsignal("phy", Pins("M20")), + Subsignal("rx", Pins("H22")), + Subsignal("tx", Pins("H21")), + IOStandard("LVCMOS33") + ), + ("eth", 0, + Subsignal("rst_n", Pins("R22")), + Subsignal("dv", Pins("V21")), + Subsignal("rx_er", Pins("V22")), + Subsignal("rx_data", Pins("U22 U20 T22 T21")), + Subsignal("tx_en", Pins("N19")), + Subsignal("tx_er", Pins("M19")), + Subsignal("tx_data", Pins("M16 L15 P19 P20")), + Subsignal("col", Pins("W20")), + Subsignal("crs", Pins("W22")), + IOStandard("LVCMOS33") + ), + + ("vga_out", 0, + Subsignal("clk", Pins("A10")), + Subsignal("r", Pins("C6 B6 A6 C7 A7 B8 A8 D9")), + Subsignal("g", Pins("C8 C9 A9 D7 D8 D10 C10 B10")), + Subsignal("b", Pins("D11 C12 B12 A12 C13 A13 D14 C14")), + Subsignal("hsync_n", Pins("A14")), + Subsignal("vsync_n", Pins("C15")), + Subsignal("psave_n", Pins("B14")), + IOStandard("LVCMOS33") + ), + ("dvi_out", 0, + Subsignal("clk_p", Pins("W12"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("Y12"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("Y16"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("W15"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("AA16"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("AB16"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("Y15"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("AB15"), IOStandard("TMDS_33")), + ), + + ("mmc", 0, + Subsignal("clk", Pins("J3")), + Subsignal("cmd", Pins("K1")), + Subsignal("dat", Pins("J6 K6 N1 K5")), + IOStandard("LVCMOS33") + ), + + ("dvi_in", 0, + Subsignal("clk_p", Pins("K20"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("K19"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("B21"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("B22"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("A20"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("A21"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("K16"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("J16"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("G20"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("H16"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("G22"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("G17"), IOStandard("LVCMOS33")) + ), + ("dvi_in", 1, + Subsignal("clk_p", Pins("C11"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("A11"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("B18"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("A18"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("C17"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("A17"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("E16"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("D17"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("F17"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("F16"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("G16"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("B20"), IOStandard("LVCMOS33")) + ), + ("dvi_in", 2, + Subsignal("clk_p", Pins("Y11"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("AB11"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("V11"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("W11"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("AA10"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("AB10"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("R11"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("T11"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("C16"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("B16"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("D6"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("A4"), IOStandard("LVCMOS33")) + ), + ("dvi_in", 3, + Subsignal("clk_p", Pins("J20"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("J22"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("P18"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("R19"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("P17"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("N16"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("M17"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("M18"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("P21"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("N22"), IOStandard("LVCMOS33")), + Subsignal("hpd_notif", Pins("H17"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("C19"), IOStandard("LVCMOS33")) + ), +] + +class Platform(XilinxISEPlatform): + def __init__(self): + XilinxISEPlatform.__init__(self, "xc6slx45-fgg484-2", _io, + lambda p: CRG_SE(p, "clk50", None)) + self.add_platform_command("CONFIG VCCAUX=\"3.3\";\n") + + def do_finalize(self, fragment): + try: + self.add_platform_command(""" +NET "{clk50}" TNM_NET = "GRPclk50"; +TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%; +""", clk50=self.lookup_request("clk50")) + except ConstraintError: + pass + + try: + eth_clocks = self.lookup_request("eth_clocks") + self.add_platform_command(""" +NET "{phy_rx_clk}" TNM_NET = "GRPphy_rx_clk"; +NET "{phy_tx_clk}" TNM_NET = "GRPphy_tx_clk"; +TIMESPEC "TSphy_rx_clk" = PERIOD "GRPphy_rx_clk" 40 ns HIGH 50%; +TIMESPEC "TSphy_tx_clk" = PERIOD "GRPphy_tx_clk" 40 ns HIGH 50%; +TIMESPEC "TSphy_tx_clk_io" = FROM "GRPphy_tx_clk" TO "PADS" 10 ns; +TIMESPEC "TSphy_rx_clk_io" = FROM "PADS" TO "GRPphy_rx_clk" 10 ns; +""", phy_rx_clk=eth_clocks.rx, phy_tx_clk=eth_clocks.tx) + except ConstraintError: + pass + + for i in range(4): + si = "dviclk"+str(i) + try: + self.add_platform_command(""" +NET "{dviclk}" TNM_NET = "GRP"""+si+""""; +TIMESPEC "TS"""+si+"""" = PERIOD "GRP"""+si+"""" 12.00 ns HIGH 50%; +""", dviclk=self.lookup_request("dvi_in", i).clk_p) + except ConstraintError: + pass diff --git a/mibuild/mibuild/platforms/ml605.py b/mibuild/mibuild/platforms/ml605.py new file mode 100644 index 000000000..72c49e670 --- /dev/null +++ b/mibuild/mibuild/platforms/ml605.py @@ -0,0 +1,56 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS + +_io = [ + # System clock (Differential 200MHz) + ("clk200", 0, + Subsignal("p", Pins("J9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("n", Pins("H9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")) + ), + + # User clock (66MHz) + ("clk66", 0, Pins("U23"), IOStandard("LVCMOS25")), + + # CPU reset switch + ("cpu_reset", 0, Pins("H10"), IOStandard("SSTL15")), + + # LEDs + ("user_led", 0, Pins("AC22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 1, Pins("AC24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 2, Pins("AE22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 3, Pins("AE23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 4, Pins("AB23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 5, Pins("AG23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 6, Pins("AE24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + ("user_led", 7, Pins("AD24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")), + + # USB-to-UART + ("serial", 0, + Subsignal("tx", Pins("J25"), IOStandard("LVCMOS25")), + Subsignal("rx", Pins("J24"), IOStandard("LVCMOS25")) + ), + + # 10/100/1000 Tri-Speed Ethernet PHY + ("eth_clocks", 0, + Subsignal("rx", Pins("AP11")), + Subsignal("tx", Pins("AD12")), + IOStandard("LVCMOS25") + ), + ("eth", 0, + Subsignal("rst_n", Pins("AH13")), + Subsignal("dv", Pins("AM13")), + Subsignal("rx_er", Pins("AG12")), + Subsignal("rx_data", Pins("AN13 AF14 AE14 AN12 AM12 AD11 AC12 AC13")), + Subsignal("tx_en", Pins("AJ10")), + Subsignal("tx_er", Pins("AH10")), + Subsignal("tx_data", Pins("AM11 AL11 AG10 AG11 AL10 AM10 AE11 AF11")), + Subsignal("col", Pins("AK13")), + Subsignal("crs", Pins("AL13")), + IOStandard("LVCMOS25") + ) +] + +class Platform(XilinxISEPlatform): + def __init__(self): + XilinxISEPlatform.__init__(self, "xc6vlx240t-ff1156-1", _io, + lambda p: CRG_DS(p, "clk200", "user_btn", 5.0)) diff --git a/mibuild/mibuild/platforms/papilio_pro.py b/mibuild/mibuild/platforms/papilio_pro.py new file mode 100644 index 000000000..7c8a6316e --- /dev/null +++ b/mibuild/mibuild/platforms/papilio_pro.py @@ -0,0 +1,44 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE + +_io = [ + ("user_led", 0, Pins("P112"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), + + ("user_btn", 0, Pins("P114"), IOStandard("LVCMOS33")), # C0 + ("user_btn", 1, Pins("P115"), IOStandard("LVCMOS33")), # C1 + + ("clk32", 0, Pins("P94"), IOStandard("LVCMOS33")), + + ("serial", 0, + Subsignal("tx", Pins("P105"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")), + Subsignal("rx", Pins("P101"), IOStandard("LVCMOS33"), Misc("PULLUP")) + ), + + ("spiflash", 0, + Subsignal("cs", Pins("P38")), + Subsignal("clk", Pins("P70")), + Subsignal("mosi", Pins("P64")), + Subsignal("miso", Pins("P65"), Misc("PULLUP")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST") + ), + + ("sdram_clock", 0, Pins("P32"), IOStandard("LVCMOS33"), Misc("SLEW=FAST")), + ("sdram", 0, + Subsignal("a", Pins("P140 P139 P138 P137 P46 P45 P44", + "P43 P41 P40 P141 P35 P34")), + Subsignal("ba", Pins("P143 P142")), + Subsignal("cs_n", Pins("P1")), + Subsignal("cke", Pins("P33")), + Subsignal("ras_n", Pins("P2")), + Subsignal("cas_n", Pins("P5")), + Subsignal("we_n", Pins("P6")), + Subsignal("dq", Pins("P9 P10 P11 P12 P14 P15 P16 P8 P21 P22 P23 P24 P26 P27 P29 P30")), + Subsignal("dm", Pins("P7 P17")), + IOStandard("LVCMOS33"), Misc("SLEW=FAST") + ), +] + +class Platform(XilinxISEPlatform): + def __init__(self): + XilinxISEPlatform.__init__(self, "xc6slx9-tqg144-2", _io, + lambda p: CRG_SE(p, "clk32", None, 31.25)) diff --git a/mibuild/mibuild/platforms/rhino.py b/mibuild/mibuild/platforms/rhino.py new file mode 100644 index 000000000..4609d1bb8 --- /dev/null +++ b/mibuild/mibuild/platforms/rhino.py @@ -0,0 +1,137 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS + +_io = [ + ("user_led", 0, Pins("Y3")), + ("user_led", 1, Pins("Y1")), + ("user_led", 2, Pins("W2")), + ("user_led", 3, Pins("W1")), + ("user_led", 4, Pins("V3")), + ("user_led", 5, Pins("V1")), + ("user_led", 6, Pins("U2")), + ("user_led", 7, Pins("U1")), + + ("clk100", 0, + Subsignal("p", Pins("B14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("n", Pins("A14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")) + ), + + ("gpio", 0, Pins("R8")), + + ("gpmc", 0, + Subsignal("clk", Pins("R26")), + Subsignal("a", Pins("N17 N18 L23 L24 N19 N20 N21 N22 P17 P19")), + Subsignal("d", Pins("N23 N24 R18 R19 P21 P22 R20 R21 P24 P26 R23 R24 T22 T23 U23 R25")), + Subsignal("we_n", Pins("W26")), + Subsignal("oe_n", Pins("AA25")), + Subsignal("ale_n", Pins("AA26")), + IOStandard("LVCMOS33")), + # Warning: CS are numbered 1-7 on ARM side and 0-6 on FPGA side. + # Numbers here are given on the FPGA side. + ("gpmc_ce_n", 0, Pins("V23"), IOStandard("LVCMOS33")), # nCS0 + ("gpmc_ce_n", 1, Pins("U25"), IOStandard("LVCMOS33")), # nCS1 + ("gpmc_ce_n", 2, Pins("W25"), IOStandard("LVCMOS33")), # nCS6 + ("gpmc_dmareq_n", 0, Pins("T24"), IOStandard("LVCMOS33")), # nCS2 + ("gpmc_dmareq_n", 1, Pins("T26"), IOStandard("LVCMOS33")), # nCS3 + ("gpmc_dmareq_n", 2, Pins("V24"), IOStandard("LVCMOS33")), # nCS4 + ("gpmc_dmareq_n", 3, Pins("V26"), IOStandard("LVCMOS33")), # nCS5 + + # FMC150 + ("fmc150_ctrl", 0, + Subsignal("spi_sclk", Pins("AE5")), + Subsignal("spi_data", Pins("AF5")), + + Subsignal("adc_sdo", Pins("U13")), + Subsignal("adc_en_n", Pins("AA15")), + Subsignal("adc_reset", Pins("V13")), + + Subsignal("cdce_sdo", Pins("AA8")), + Subsignal("cdce_en_n", Pins("Y9")), + Subsignal("cdce_reset_n", Pins("AB7")), + Subsignal("cdce_pd_n", Pins("AC6")), + Subsignal("cdce_pll_status", Pins("W7")), + Subsignal("cdce_ref_en", Pins("W8")), + + Subsignal("dac_sdo", Pins("W9")), + Subsignal("dac_en_n", Pins("W10")), + + Subsignal("mon_sdo", Pins("AC5")), + Subsignal("mon_en_n", Pins("AD6")), + Subsignal("mon_reset_n", Pins("AF6")), + Subsignal("mon_int_n", Pins("AD5")), + + Subsignal("pg_c2m", Pins("AA23"), IOStandard("LVCMOS33")) + ), + ("ti_dac", 0, # DAC3283 + Subsignal("dat_p", Pins("AA10 AA9 V11 Y11 W14 Y12 AD14 AE13"), IOStandard("LVDS_25")), + Subsignal("dat_n", Pins("AB11 AB9 V10 AA11 Y13 AA12 AF14 AF13"), IOStandard("LVDS_25")), + Subsignal("frame_p", Pins("AB13"), IOStandard("LVDS_25")), + Subsignal("frame_n", Pins("AA13"), IOStandard("LVDS_25")), + Subsignal("txenable", Pins("AB15"), IOStandard("LVCMOS25")) + ), + ("ti_adc", 0, # ADS62P49 + Subsignal("dat_a_p", Pins("AB14 Y21 W20 AB22 V18 W17 AA21")), + Subsignal("dat_a_n", Pins("AC14 AA22 Y20 AC22 W19 W18 AB21")), + Subsignal("dat_b_p", Pins("Y17 U15 AA19 W16 AA18 Y15 V14")), + Subsignal("dat_b_n", Pins("AA17 V16 AB19 Y16 AB17 AA16 V15")), + IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE") + ), + ("fmc150_clocks", 0, + Subsignal("dac_clk_p", Pins("V12"), IOStandard("LVDS_25")), + Subsignal("dac_clk_n", Pins("W12"), IOStandard("LVDS_25")), + Subsignal("adc_clk_p", Pins("AE15"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("adc_clk_n", Pins("AF15"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")), + Subsignal("clk_to_fpga", Pins("W24"), IOStandard("LVCMOS25")) + ), + + ("fmc150_ext_trigger", 0, Pins("U26")), + + # Vermeer radar testbed + # Switch controller + ("pca9555", 0, + Subsignal("sda", Pins("C13")), + Subsignal("scl", Pins("G8")), + IOStandard("LVCMOS33") + ), + # TX path + ("pe43602", 0, + Subsignal("d", Pins("H8")), + Subsignal("clk", Pins("B3")), + Subsignal("le", Pins("F7")), + IOStandard("LVCMOS33") + ), + ("rfmd2081", 0, + Subsignal("enx", Pins("E5")), + Subsignal("sclk", Pins("G6")), + Subsignal("sdata", Pins("F5")), + Subsignal("locked", Pins("E6")), + IOStandard("LVCMOS33") + ), + # RX path + ("lmh6521", 0, + Subsignal("scsb", Pins("C5")), + Subsignal("sclk", Pins("G10")), + Subsignal("sdi", Pins("D5")), + Subsignal("sdo", Pins("F9")), + IOStandard("LVCMOS33") + ), + ("lmh6521", 1, + Subsignal("scsb", Pins("E10")), + Subsignal("sclk", Pins("A4")), + Subsignal("sdi", Pins("B4")), + Subsignal("sdo", Pins("H10")), + IOStandard("LVCMOS33") + ), + ("rffc5071", 0, + Subsignal("enx", Pins("A2")), + Subsignal("sclk", Pins("G9")), + Subsignal("sdata", Pins("H9")), + Subsignal("locked", Pins("A3")), + IOStandard("LVCMOS33") + ) +] + +class Platform(XilinxISEPlatform): + def __init__(self): + XilinxISEPlatform.__init__(self, "xc6slx150t-fgg676-3", _io, + lambda p: CRG_DS(p, "clk100", "gpio", 10.0)) diff --git a/mibuild/mibuild/platforms/roach.py b/mibuild/mibuild/platforms/roach.py new file mode 100644 index 000000000..a23bd90f7 --- /dev/null +++ b/mibuild/mibuild/platforms/roach.py @@ -0,0 +1,33 @@ +from mibuild.generic_platform import * +from mibuild.xilinx_ise import XilinxISEPlatform + +_io = [ + ("epb", 0, + Subsignal("cs_n", Pins("K13")), + Subsignal("r_w_n", Pins("AF20")), + Subsignal("be_n", Pins("AF14 AF18")), + Subsignal("oe_n", Pins("AF21")), + Subsignal("addr", Pins("AE23 AE22 AG18 AG12 AG15 AG23 AF19 AE12 AG16 AF13 AG20 AF23", + "AH17 AH15 L20 J22 H22 L15 L16 K22 K21 K16 J15")), + Subsignal("addr_gp", Pins("L21 G22 K23 K14 L14 J12")), + Subsignal("data", Pins("AF15 AE16 AE21 AD20 AF16 AE17 AE19 AD19 AG22 AH22 AH12 AG13", + "AH20 AH19 AH14 AH13")), + Subsignal("rdy", Pins("K12")), + IOStandard("LVCMOS33") + ), + ("roach_clocks", 0, + Subsignal("epb_clk", Pins("AH18"), IOStandard("LVCMOS33")), + Subsignal("sys_clk_n", Pins("H13")), + Subsignal("sys_clk_p", Pins("J14")), + Subsignal("aux0_clk_p", Pins("G15")), + Subsignal("aux0_clk_n", Pins("G16")), + Subsignal("aux1_clk_p", Pins("H14")), + Subsignal("aux1_clk_n", Pins("H15")), + Subsignal("dly_clk_n", Pins("J17")), + Subsignal("dly_clk_p", Pins("J16")), + ), +] + +class Platform(XilinxISEPlatform): + def __init__(self): + XilinxISEPlatform.__init__(self, "xc5vsx95t-ff1136-1", _io) diff --git a/mibuild/mibuild/tools.py b/mibuild/mibuild/tools.py new file mode 100644 index 000000000..1c2493e4e --- /dev/null +++ b/mibuild/mibuild/tools.py @@ -0,0 +1,20 @@ +import os + +def mkdir_noerror(d): + try: + os.mkdir(d) + except OSError: + pass + +def language_by_filename(name): + extension = name.rsplit(".")[-1] + if extension in ["v", "vh", "vo"]: + return "verilog" + if extension in ["vhd", "vhdl", "vho"]: + return "vhdl" + return None + +def write_to_file(filename, contents): + f = open(filename, "w") + f.write(contents) + f.close() diff --git a/mibuild/mibuild/xilinx_ise.py b/mibuild/mibuild/xilinx_ise.py new file mode 100644 index 000000000..8df2cfba2 --- /dev/null +++ b/mibuild/mibuild/xilinx_ise.py @@ -0,0 +1,215 @@ +import os, struct, subprocess, sys +from decimal import Decimal + +from migen.fhdl.std import * +from migen.fhdl.specials import SynthesisDirective +from migen.genlib.cdc import * +from migen.fhdl.structure import _Fragment + +from mibuild.generic_platform import * +from mibuild.crg import SimpleCRG +from mibuild import tools + +def _add_period_constraint(platform, clk, period): + if period is not None: + platform.add_platform_command("""NET "{clk}" TNM_NET = "GRPclk"; +TIMESPEC "TSclk" = PERIOD "GRPclk" """+str(period)+""" ns HIGH 50%;""", clk=clk) + +class CRG_SE(SimpleCRG): + def __init__(self, platform, clk_name, rst_name, period=None, rst_invert=False): + SimpleCRG.__init__(self, platform, clk_name, rst_name, rst_invert) + _add_period_constraint(platform, self._clk, period) + +class CRG_DS(Module): + def __init__(self, platform, clk_name, rst_name, period=None, rst_invert=False): + reset_less = rst_name is None + self.clock_domains.cd_sys = ClockDomain(reset_less=reset_less) + self._clk = platform.request(clk_name) + _add_period_constraint(platform, self._clk.p, period) + self.specials += Instance("IBUFGDS", + Instance.Input("I", self._clk.p), + Instance.Input("IB", self._clk.n), + Instance.Output("O", self.cd_sys.clk) + ) + if not reset_less: + if rst_invert: + self.comb += self.cd_sys.rst.eq(~platform.request(rst_name)) + else: + self.comb += self.cd_sys.rst.eq(platform.request(rst_name)) + +def _format_constraint(c): + if isinstance(c, Pins): + return "LOC=" + c.identifiers[0] + elif isinstance(c, IOStandard): + return "IOSTANDARD=" + c.name + elif isinstance(c, Drive): + return "DRIVE=" + str(c.strength) + elif isinstance(c, Misc): + return c.misc + +def _format_ucf(signame, pin, others, resname): + fmt_c = [] + for c in [Pins(pin)] + others: + fc = _format_constraint(c) + if fc is not None: + fmt_c.append(fc) + fmt_r = resname[0] + ":" + str(resname[1]) + if resname[2] is not None: + fmt_r += "." + resname[2] + return "NET \"" + signame + "\" " + " | ".join(fmt_c) + "; # " + fmt_r + "\n" + +def _build_ucf(named_sc, named_pc): + r = "" + for sig, pins, others, resname in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + r += _format_ucf(sig + "(" + str(i) + ")", p, others, resname) + else: + r += _format_ucf(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + return r + +def _build_files(device, sources, named_sc, named_pc, build_name): + tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc)) + + prj_contents = "" + for filename, language in sources: + prj_contents += language + " work " + filename + "\n" + tools.write_to_file(build_name + ".prj", prj_contents) + + xst_contents = """run +-ifn %s.prj +-top top +-ifmt MIXED +-opt_mode SPEED +-reduce_control_sets auto +-register_balancing yes +-ofn %s.ngc +-p %s""" % (build_name, build_name, device) + tools.write_to_file(build_name + ".xst", xst_contents) + +def _is_valid_version(path, v): + try: + Decimal(v) + return os.path.isdir(os.path.join(path, v)) + except: + return False + +def _run_ise(build_name, ise_path, source, mode="verilog"): + if sys.platform == "win32" or sys.platform == "cygwin": + source = False + build_script_contents = "# Autogenerated by mibuild\nset -e\n" + if source: + vers = [ver for ver in os.listdir(ise_path) if _is_valid_version(ise_path, ver)] + tools_version = max(vers) + bits = struct.calcsize("P")*8 + + xilinx_settings_file = os.path.join(ise_path, tools_version, "ISE_DS", "settings{0}.sh".format(bits)) + if not os.path.exists(xilinx_settings_file) and bits == 64: + # if we are on 64-bit system but the toolchain isn't, try the 32-bit env. + xilinx_settings_file = os.path.join(ise_path, tools_version, "ISE_DS", "settings32.sh") + build_script_contents += "source " + xilinx_settings_file + "\n" + if mode == "edif": + build_script_contents += """ +ngdbuild -uc {build_name}.ucf {build_name}.edif {build_name}.ngd""" + else: + build_script_contents += """ +xst -ifn {build_name}.xst +ngdbuild -uc {build_name}.ucf {build_name}.ngc {build_name}.ngd""" + + build_script_contents += """ +map -ol high -w -o {build_name}_map.ncd {build_name}.ngd {build_name}.pcf +par -ol high -w {build_name}_map.ncd {build_name}.ncd {build_name}.pcf +bitgen -g LCK_cycle:6 -g Binary:Yes -w {build_name}.ncd {build_name}.bit +""" + build_script_contents = build_script_contents.format(build_name=build_name) + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents) + + r = subprocess.call(["bash", build_script_file]) + if r != 0: + raise OSError("Subprocess failed") + +class XilinxNoRetimingImpl(Module): + def __init__(self, reg): + self.specials += SynthesisDirective("attribute register_balancing of {r} is no", r=reg) + +class XilinxNoRetiming: + @staticmethod + def lower(dr): + return XilinxNoRetimingImpl(dr.reg) + +class XilinxMultiRegImpl(MultiRegImpl): + def __init__(self, *args, **kwargs): + MultiRegImpl.__init__(self, *args, **kwargs) + self.specials += [SynthesisDirective("attribute shreg_extract of {r} is no", r=r) + for r in self.regs] + +class XilinxMultiReg: + @staticmethod + def lower(dr): + return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) + +class XilinxISEPlatform(GenericPlatform): + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = { + NoRetiming: XilinxNoRetiming, + MultiReg: XilinxMultiReg + } + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + + def get_edif(self, fragment, **kwargs): + return GenericPlatform.get_edif(self, fragment, "UNISIMS", "Xilinx", self.device, **kwargs) + + def build(self, fragment, build_dir="build", build_name="top", + ise_path="/opt/Xilinx", source=True, run=True, mode="verilog"): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + self.finalize(fragment) + + if mode == "verilog": + v_src, named_sc, named_pc = self.get_verilog(fragment) + v_file = build_name + ".v" + tools.write_to_file(v_file, v_src) + sources = self.sources + [(v_file, "verilog")] + _build_files(self.device, sources, named_sc, named_pc, build_name) + if run: + _run_ise(build_name, ise_path, source, mode="verilog") + + if mode == "mist": + from mist import synthesize + synthesize(fragment, self.constraint_manager.get_io_signals()) + + if mode == "edif" or mode == "mist": + e_src, named_sc, named_pc = self.get_edif(fragment) + e_file = build_name + ".edif" + tools.write_to_file(e_file, e_src) + sources = self.sources + [(e_file, "edif")] + tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc)) + if run: + _run_ise(build_name, ise_path, source, mode="edif") + + os.chdir("..") + + def build_arg_ns(self, ns, *args, **kwargs): + for n in ["build_dir", "build_name", "ise_path"]: + attr = getattr(ns, n) + if attr is not None: + kwargs[n] = attr + if ns.no_source: + kwargs["source"] = False + if ns.no_run: + kwargs["run"] = False + self.build(*args, **kwargs) + + def add_arguments(self, parser): + parser.add_argument("--build-dir", default=None, help="Set the directory in which to generate files and run ISE") + parser.add_argument("--build-name", default=None, help="Base name for the generated files") + parser.add_argument("--ise-path", default=None, help="ISE installation path (without version directory)") + parser.add_argument("--no-source", action="store_true", help="Do not source ISE settings file") + parser.add_argument("--no-run", action="store_true", help="Only generate files, do not run ISE") diff --git a/mibuild/setup.py b/mibuild/setup.py new file mode 100755 index 000000000..4322807b7 --- /dev/null +++ b/mibuild/setup.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import sys, os +from setuptools import setup +from setuptools import find_packages + +here = os.path.abspath(os.path.dirname(__file__)) +README = open(os.path.join(here, "README")).read() + +required_version = (3, 3) +if sys.version_info < required_version: + raise SystemExit("Mibuild requires python {0} or greater".format( + ".".join(map(str, required_version)))) + +setup( + name="mibuild", + version="unknown", + description="Build system and board definitions for Migen FPGA designs", + long_description=README, + author="Sebastien Bourdeauducq", + author_email="sebastien@milkymist.org", + url="http://www.milkymist.org", + download_url="https://github.com/milkymist/mibuild", + packages=find_packages(here), + license="BSD", + platforms=["Any"], + keywords="HDL ASIC FPGA hardware design", + classifiers=[ + "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", + "Environment :: Console", + "Development Status :: Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + ], +)