From d5ba26b1744a745f264f7a06087cce1fbcbe9a55 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Fran=C3=A7ois=20Nguyen?= Date: Fri, 7 Jun 2019 00:48:51 +0200 Subject: [PATCH] vendor.xilinx_spartan6: implement. --- nmigen/vendor/xilinx_spartan6.py | 267 +++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 nmigen/vendor/xilinx_spartan6.py diff --git a/nmigen/vendor/xilinx_spartan6.py b/nmigen/vendor/xilinx_spartan6.py new file mode 100644 index 0000000..9462217 --- /dev/null +++ b/nmigen/vendor/xilinx_spartan6.py @@ -0,0 +1,267 @@ +from abc import abstractproperty + +from ..hdl.ast import * +from ..hdl.dsl import * +from ..hdl.ir import * +from ..build import * + + +__all__ = ["XilinxSpartan6Platform"] + + +class XilinxSpartan6Platform(TemplatedPlatform): + """ + Required tools: + * ISE toolchain: + * ``xst`` + * ``ngdbuild`` + * ``map`` + * ``par`` + * ``bitgen`` + + Available overrides: + * ``script_after_run``: inserts commands after ``run`` in XST script. + * ``add_constraints``: inserts commands in UCF file. + * ``xst_opts``: adds extra options for XST. + * ``ngdbuild_opts``: adds extra options for NGDBuild. + * ``map_opts``: adds extra options for MAP. + * ``par_opts``: adds extra options for PAR. + * ``bitgen_opts``: adds extra options for BitGen. + + Build products: + * ``{{name}}.srp``: synthesis report. + * ``{{name}}.ngc``: synthesized RTL. + * ``{{name}}.bld``: NGDBuild log. + * ``{{name}}.ngd``: design database. + * ``{{name}}_map.map``: MAP log. + * ``{{name}}_map.mrp``: mapping report. + * ``{{name}}_map.ncd``: mapped netlist. + * ``{{name}}.pcf``: physical constraints. + * ``{{name}}_par.par``: PAR log. + * ``{{name}}_par_pad.txt``: I/O usage report. + * ``{{name}}_par.ncd``: place and routed netlist. + * ``{{name}}.drc``: DRC report. + * ``{{name}}.bgn``: BitGen log. + * ``{{name}}.bit``: binary bitstream. + """ + + device = abstractproperty() + package = abstractproperty() + speedgrade = abstractproperty() + + file_templates = { + **TemplatedPlatform.build_script_templates, + "{{name}}.v": r""" + /* {{autogenerated}} */ + {{emit_design("verilog")}} + """, + "{{name}}.prj": r""" + # {{autogenerated}} + {% for file in platform.extra_files -%} + {% if file.endswith(".v") %} + verilog work {{file}} + {% endif %} + {% endfor %} + verilog work {{name}}.v + """, + "{{name}}.xst": r""" + # {{autogenerated}} + run + -ifn {{name}}.prj + -ofn {{name}}.ngc + -top {{name}} + -p {{platform.device}}{{platform.package}}-{{platform.speedgrade}} + {{get_override("script_after_run")|default("# (script_after_run placeholder)")}} + """, + "{{name}}.ucf": r""" + # {{autogenerated}} + {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%} + {% set port_name = port_name|replace("[", "<")|replace("]", ">") -%} + NET "{{port_name}}" LOC={{pin_name}}; + {% for attr_name, attr_value in attrs.items() -%} + NET "{{port_name}}" {{attr_name}}={{attr_value}}; + {% endfor %} + {% endfor %} + {% for signal, frequency in platform.iter_clock_constraints() -%} + NET "{{signal.name}}" TNM_NET="PRD{{signal.name}}"; + TIMESPEC "TS{{signal.name}}"=PERIOD "PRD{{signal.name}}" {{1000000000/frequency}} ns HIGH 50%; + {% endfor %} + {{get_override("add_constraints")|default("# (add_constraints placeholder)")}} + """ + } + command_templates = [ + r""" + {{get_tool("xst")}} + {{get_override("xst_opts")|join(" ")}} + -ifn {{name}}.xst + """, + r""" + {{get_tool("ngdbuild")}} + {{quiet("-quiet")}} + {{verbose("-verbose")}} + {{get_override("ngdbuild_opts")|join(" ")}} + -uc {{name}}.ucf + {{name}}.ngc + """, + r""" + {{get_tool("map")}} + {{verbose("-detail")}} + {{get_override("map_opts")|default(["-w"])|join(" ")}} + -o {{name}}_map.ncd + {{name}}.ngd + {{name}}.pcf + """, + r""" + {{get_tool("par")}} + {{get_override("par_opts")|default(["-w"])|join(" ")}} + {{name}}_map.ncd + {{name}}_par.ncd + {{name}}.pcf + """, + r""" + {{get_tool("bitgen")}} + {{get_override("bitgen_opts")|default(["-w"])|join(" ")}} + {{name}}_par.ncd + {{name}}.bit + """ + ] + + def _get_dff(self, m, clk, d, q): + # SDR I/O is performed by packing a flip-flop into the pad IOB. + for bit in range(len(q)): + _q = Signal() + _q.attrs["IOB"] = "TRUE" + m.submodules += Instance("FDCE", + i_C=clk, + i_CE=Const(1), + i_CLR=Const(0), + i_D=d[bit], + o_Q=_q, + ) + m.d.comb += q[bit].eq(_q) + + def get_input(self, pin, port, attrs): + self._check_feature("single-ended input", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + self._get_dff(m, pin.i_clk, port, pin.i) + else: + m.d.comb += pin.i.eq(port) + return m + + def get_output(self, pin, port, attrs): + self._check_feature("single-ended output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + self._get_dff(m, pin.o_clk, pin.o, port) + else: + m.d.comb += port.eq(pin.o) + return m + + def get_tristate(self, pin, port, attrs): + self._check_feature("single-ended tristate", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + for bit in range(len(port)): + m.submodules += Instance("OBUFT", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=port[bit] + ) + return m + + def get_input_output(self, pin, port, attrs): + self._check_feature("single-ended input/output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + i_ff = Signal.like(pin.i, name="{}_ff".format(pin.i.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + self._get_dff(m, pin.i_clk, i_ff, pin.i) + for bit in range(len(port)): + m.submodules += Instance("IOBUF", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=i_ff[bit] if pin.xdr == 1 else pin.i[bit], + io_IO=port[bit] + ) + return m + + def get_diff_input(self, pin, p_port, n_port, attrs): + self._check_feature("differential input", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + i_ff = Signal.like(pin.i, name="{}_ff".format(pin.i.name)) + self._get_dff(m, pin.i_clk, i_ff, pin.i) + for bit in range(len(p_port)): + m.submodules += Instance("IBUFDS", + i_I=p_port[bit], + i_IB=n_port[bit], + o_O=i_ff[bit] if pin.xdr == 1 else pin.i[bit] + ) + return m + + def get_diff_output(self, pin, p_port, n_port, attrs): + self._check_feature("differential output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + for bit in range(len(p_port)): + m.submodules += Instance("OBUFDS", + o_O=p_port[bit], + o_OB=n_port[bit], + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit] + ) + return m + + def get_diff_tristate(self, pin, p_port, n_port, attrs): + self._check_feature("differential tristate", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + for bit in range(len(p_port)): + m.submodules += Instance("OBUFTDS", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=p_port[bit], + o_OB=n_port[bit] + ) + return m + + def get_diff_input_output(self, pin, p_port, n_port, attrs): + self._check_feature("differential input/output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + i_ff = Signal.like(pin.i, name="{}_ff".format(pin.i.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + self._get_dff(m, pin.i_clk, i_ff, pin.i) + for bit in range(len(p_port)): + m.submodules += Instance("IOBUFDS", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=i_ff[bit] if pin.xdr == 1 else pin.i[bit], + io_IO=p_port[bit], + io_IOB=n_port[bit] + ) + return m -- 2.30.2