Skip to content

Commit f7bfa13

Browse files
committedMar 16, 2015
mibuild: add initial Lattice Diamond support (with ECP3 Versa board platform skeleton)
1 parent beeaefc commit f7bfa13

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed
 

‎mibuild/lattice/__init__.py

Whitespace-only changes.

‎mibuild/lattice/diamond.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
2+
# License: BSD
3+
4+
import os, subprocess, shutil
5+
6+
from migen.fhdl.structure import _Fragment
7+
from mibuild.generic_platform import *
8+
from mibuild import tools
9+
10+
def _format_constraint(c):
11+
if isinstance(c, Pins):
12+
return ("LOCATE COMP ", " SITE " + "\"" + c.identifiers[0] + "\"")
13+
elif isinstance(c, IOStandard):
14+
return ("IOBUF PORT ", " IO_TYPE=" + c.name)
15+
elif isinstance(c, Misc):
16+
return c.misc
17+
18+
def _format_lpf(signame, pin, others, resname):
19+
fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)]
20+
r = ""
21+
for pre, suf in fmt_c:
22+
r += pre + "\""+ signame +"\"" + suf + ";\n"
23+
return r
24+
25+
def _build_lpf(named_sc, named_pc):
26+
r = "BLOCK RESETPATHS;\n"
27+
r += "BLOCK ASYNCPATHS;\n"
28+
for sig, pins, others, resname in named_sc:
29+
if len(pins) > 1:
30+
for i, p in enumerate(pins):
31+
r += _format_lpf(sig + "[" + str(i) + "]", p, others, resname)
32+
else:
33+
r += _format_lpf(sig, pins[0], others, resname)
34+
if named_pc:
35+
r += "\n" + "\n\n".join(named_pc)
36+
return r
37+
38+
def _build_files(device, sources, vincpaths, build_name):
39+
tcl = []
40+
tcl.append("prj_project new -name \"%s\" -impl \"implementation\" -dev %s -synthesis \"synplify\"" %(build_name, device))
41+
for filename, language in sources:
42+
tcl.append("prj_src add \"" + filename.replace("\\", "/") + "\"")
43+
tcl.append("prj_run Synthesis -impl implementation -forceOne")
44+
tcl.append("prj_run Translate -impl implementation")
45+
tcl.append("prj_run Map -impl implementation")
46+
tcl.append("prj_run PAR -impl implementation")
47+
tcl.append("prj_run Export -impl implementation -task Bitgen")
48+
tools.write_to_file(build_name + ".tcl", "\n".join(tcl))
49+
50+
def _run_diamond(build_name, source, ver=None):
51+
if sys.platform == "win32" or sys.platform == "cygwin":
52+
build_script_contents = "REM Autogenerated by mibuild\n"
53+
build_script_contents = "pnmainc " + build_name + ".tcl\n"
54+
build_script_file = "build_" + build_name + ".bat"
55+
tools.write_to_file(build_script_file, build_script_contents)
56+
r = subprocess.call([build_script_file])
57+
shutil.copy(os.path.join("implementation", build_name + "_implementation.bit"), build_name + ".bit")
58+
else:
59+
raise NotImplementedError()
60+
61+
if r != 0:
62+
raise OSError("Subprocess failed")
63+
64+
class LatticeDiamondPlatform(GenericPlatform):
65+
bitstream_ext = ".bit"
66+
def build(self, fragment, build_dir="build", build_name="top",
67+
diamond_path="/opt/Diamond", run=True):
68+
tools.mkdir_noerror(build_dir)
69+
os.chdir(build_dir)
70+
71+
if not isinstance(fragment, _Fragment):
72+
fragment = fragment.get_fragment()
73+
self.finalize(fragment)
74+
75+
v_src, vns = self.get_verilog(fragment)
76+
named_sc, named_pc = self.resolve_signals(vns)
77+
v_file = build_name + ".v"
78+
tools.write_to_file(v_file, v_src)
79+
sources = self.sources + [(v_file, "verilog")]
80+
_build_files(self.device, sources, self.verilog_include_paths, build_name)
81+
82+
tools.write_to_file(build_name + ".lpf", _build_lpf(named_sc, named_pc))
83+
84+
if run:
85+
_run_diamond(build_name, diamond_path)
86+
87+
os.chdir("..")
88+
89+
return vns
90+
91+
def add_period_constraint(self, clk, period):
92+
# TODO: handle differential clk
93+
self.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk)

‎mibuild/lattice/programmer.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import os, subprocess
2+
3+
from mibuild.generic_programmer import GenericProgrammer
4+
from mibuild import tools
5+
6+
# XXX Lattice programmer need an .xcf file, will need clean up and support for more parameters
7+
_xcf_template = """
8+
<?xml version='1.0' encoding='utf-8' ?>
9+
<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
10+
<ispXCF version="3.4.1">
11+
<Comment></Comment>
12+
<Chain>
13+
<Comm>JTAG</Comm>
14+
<Device>
15+
<SelectedProg value="TRUE"/>
16+
<Pos>1</Pos>
17+
<Vendor>Lattice</Vendor>
18+
<Family>LatticeECP3</Family>
19+
<Name>LFE3-35EA</Name>
20+
<File>{bitstream_file}</File>
21+
<Operation>Fast Program</Operation>
22+
</Device>
23+
</Chain>
24+
<ProjectOptions>
25+
<Program>SEQUENTIAL</Program>
26+
<Process>ENTIRED CHAIN</Process>
27+
<OperationOverride>No Override</OperationOverride>
28+
<StartTAP>TLR</StartTAP>
29+
<EndTAP>TLR</EndTAP>
30+
<VerifyUsercode value="FALSE"/>
31+
</ProjectOptions>
32+
<CableOptions>
33+
<CableName>USB2</CableName>
34+
<PortAdd>FTUSB-0</PortAdd>
35+
<USBID>Dual RS232-HS A Location 0000 Serial A</USBID>
36+
<JTAGPinSetting>
37+
TRST ABSENT;
38+
ISPEN ABSENT;
39+
</JTAGPinSetting>
40+
</CableOptions>
41+
</ispXCF>
42+
"""
43+
44+
class LatticeProgrammer(GenericProgrammer):
45+
needs_bitreverse = False
46+
47+
def load_bitstream(self, bitstream_file):
48+
xcf_file = bitstream_file.replace(".bit", ".xcf")
49+
xcf_content = _xcf_template.format(bitstream_file=bitstream_file)
50+
tools.write_to_file(xcf_file, xcf_content)
51+
subprocess.call(["pgrcmd", "-infile", xcf_file])

‎mibuild/platforms/versa.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
2+
# License: BSD
3+
4+
from mibuild.generic_platform import *
5+
from mibuild.lattice.diamond import LatticeDiamondPlatform
6+
from mibuild.lattice.programmer import LatticeProgrammer
7+
8+
_io = [
9+
("clk100", 0, Pins("L5"), IOStandard("LVDS25")),
10+
11+
("user_led", 0, Pins("Y20"), IOStandard("LVCMOS33")),
12+
("user_led", 1, Pins("AA21"), IOStandard("LVCMOS33")),
13+
("user_led", 2, Pins("U18"), IOStandard("LVCMOS33")),
14+
("user_led", 3, Pins("U19"), IOStandard("LVCMOS33")),
15+
("user_led", 4, Pins("W19"), IOStandard("LVCMOS33")),
16+
("user_led", 5, Pins("V19"), IOStandard("LVCMOS33")),
17+
("user_led", 6, Pins("AB20"), IOStandard("LVCMOS33")),
18+
("user_led", 7, Pins("AA20"), IOStandard("LVCMOS33")),
19+
20+
("serial", 0,
21+
Subsignal("tx", Pins("B11"), IOStandard("LVCMOS33")), # X4 IO0
22+
Subsignal("rx", Pins("B12"), IOStandard("LVCMOS33")), # X4 IO1
23+
),
24+
]
25+
26+
class Platform(LatticeDiamondPlatform):
27+
default_clk_name = "clk100"
28+
default_clk_period = 10
29+
30+
def __init__(self):
31+
LatticeDiamondPlatform.__init__(self, "LFE3-35EA-6FN484C", _io)
32+
33+
def create_programmer(self):
34+
return LatticeProgrammer()

0 commit comments

Comments
 (0)
Please sign in to comment.