fa4ec2ace6e22d3a69bf859464adfaab15a30811
[fw/openocd] / contrib / loaders / flash / fpga / xilinx_bscan_spi.py
1 #!/usr/bin/python3
2 #
3 #  Copyright (C) 2015 Robert Jordens <jordens@gmail.com>
4 #
5 #  This program is free software; you can redistribute it and/or modify
6 #  it under the terms of the GNU General Public License as published by
7 #  the Free Software Foundation; either version 2 of the License, or
8 #  (at your option) any later version.
9 #
10 #  This program is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #
15
16 from migen import *
17 from migen.build.generic_platform import *
18 from migen.build import xilinx
19
20
21 """
22 This migen script produces proxy bitstreams to allow programming SPI flashes
23 behind FPGAs.
24
25 Bitstream binaries built with this script are available at:
26 https://github.com/jordens/bscan_spi_bitstreams
27
28 JTAG signalling is connected directly to SPI signalling. CS_N is
29 asserted when the JTAG IR contains the USER1 instruction and the state is
30 SHIFT-DR. Xilinx bscan cells sample TDO on falling TCK and forward it.
31 MISO requires sampling on rising CLK and leads to one cycle of latency.
32
33 https://github.com/m-labs/migen
34 """
35
36
37 class Spartan3(Module):
38     macro = "BSCAN_SPARTAN3"
39     toolchain = "ise"
40
41     def __init__(self, platform):
42         platform.toolchain.bitgen_opt += " -g compress -g UnusedPin:Pullup"
43         self.clock_domains.cd_jtag = ClockDomain(reset_less=True)
44         spi = platform.request("spiflash")
45         shift = Signal()
46         tdo = Signal()
47         sel1 = Signal()
48         self.comb += [
49             self.cd_jtag.clk.eq(spi.clk),
50             spi.cs_n.eq(~shift | ~sel1),
51         ]
52         self.sync.jtag += tdo.eq(spi.miso)
53         self.specials += Instance(self.macro,
54                                   o_DRCK1=spi.clk, o_SHIFT=shift,
55                                   o_TDI=spi.mosi, i_TDO1=tdo, i_TDO2=0,
56                                   o_SEL1=sel1)
57
58
59 class Spartan3A(Spartan3):
60     macro = "BSCAN_SPARTAN3A"
61
62
63 class Spartan6(Module):
64     toolchain = "ise"
65
66     def __init__(self, platform):
67         platform.toolchain.bitgen_opt += " -g compress -g UnusedPin:Pullup"
68         self.clock_domains.cd_jtag = ClockDomain(reset_less=True)
69         spi = platform.request("spiflash")
70         shift = Signal()
71         tdo = Signal()
72         sel = Signal()
73         self.comb += self.cd_jtag.clk.eq(spi.clk), spi.cs_n.eq(~shift | ~sel)
74         self.sync.jtag += tdo.eq(spi.miso)
75         self.specials += Instance("BSCAN_SPARTAN6", p_JTAG_CHAIN=1,
76                                   o_TCK=spi.clk, o_SHIFT=shift, o_SEL=sel,
77                                   o_TDI=spi.mosi, i_TDO=tdo)
78
79
80 class Series7(Module):
81     toolchain = "vivado"
82
83     def __init__(self, platform):
84         platform.toolchain.bitstream_commands.extend([
85             "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
86             "set_property BITSTREAM.CONFIG.UNUSEDPIN Pullnone [current_design]",
87         ])
88         self.clock_domains.cd_jtag = ClockDomain(reset_less=True)
89         spi = platform.request("spiflash")
90         clk = Signal()
91         shift = Signal()
92         tdo = Signal()
93         sel = Signal()
94         self.comb += self.cd_jtag.clk.eq(clk), spi.cs_n.eq(~shift | ~sel)
95         self.sync.jtag += tdo.eq(spi.miso)
96         self.specials += Instance("BSCANE2", p_JTAG_CHAIN=1,
97                                   o_SHIFT=shift, o_TCK=clk, o_SEL=sel,
98                                   o_TDI=spi.mosi, i_TDO=tdo)
99         self.specials += Instance("STARTUPE2", i_CLK=0, i_GSR=0, i_GTS=0,
100                                   i_KEYCLEARB=0, i_PACK=1, i_USRCCLKO=clk,
101                                   i_USRCCLKTS=0, i_USRDONEO=1, i_USRDONETS=1)
102
103
104 class XilinxBscanSpi(xilinx.XilinxPlatform):
105     packages = {
106         # (package-speedgrade, id): [cs_n, clk, mosi, miso, *pullups]
107         ("cp132", 1): ["M2", "N12", "N2", "N8"],
108         ("fg320", 1): ["U3", "U16", "T4", "N10"],
109         ("fg320", 2): ["V3", "U16", "T11", "V16"],
110         ("fg484", 1): ["Y4", "AA20", "AB14", "AB20"],
111         ("fgg484", 1): ["Y4", "AA20", "AB14", "AB20"],
112         ("fgg400", 1): ["Y2", "Y19", "W12", "W18"],
113         ("ftg256", 1): ["T2", "R14", "P10", "T14"],
114         ("ft256", 1): ["T2", "R14", "P10", "T14"],
115         ("fg400", 1): ["Y2", "Y19", "W12", "W18"],
116         ("cs484", 1): ["U7", "V17", "V13", "W17"],
117         ("qg144-2", 1): ["P38", "P70", "P64", "P65", "P62", "P61"],
118         ("cpg196-2", 1): ["P2", "N13", "P11", "N11", "N10", "P10"],
119         ("cpg236-1", 1): ["K19", None, "D18", "D19", "G18", "F18"],
120         ("csg484-2", 1): ["AB5", "W17", "AB17", "Y17", "V13", "W13"],
121         ("csg324-2", 1): ["V3", "R15", "T13", "R13", "T14", "V14"],
122         ("csg324-1", 1): ["L13", None, "K17", "K18", "L14", "M14"],
123         ("fbg484-1", 1): ["T19", None, "P22", "R22", "P21", "R21"],
124         ("fbg484-1", 2): ["L16", None, "H18", "H19", "G18", "F19"],
125         ("fbg676-1", 1): ["C23", None, "B24", "A25", "B22", "A22"],
126         ("ffg901-1", 1): ["V26", None, "R30", "T30", "R28", "T28"],
127         ("ffg1156-1", 1): ["V30", None, "AA33", "AA34", "Y33", "Y34"],
128         ("ffg1157-1", 1): ["AL33", None, "AN33", "AN34", "AK34", "AL34"],
129         ("ffg1158-1", 1): ["C24", None, "A23", "A24", "B26", "A26"],
130         ("ffg1926-1", 1): ["AK33", None, "AN34", "AN35", "AJ34", "AK34"],
131         ("fhg1761-1", 1): ["AL36", None, "AM36", "AN36", "AJ36", "AJ37"],
132         ("flg1155-1", 1): ["AL28", None, "AE28", "AF28", "AJ29", "AJ30"],
133         ("flg1932-1", 1): ["V32", None, "T33", "R33", "U31", "T31"],
134         ("flg1926-1", 1): ["AK33", None, "AN34", "AN35", "AJ34", "AK34"],
135     }
136
137     pinouts = {
138         # bitstreams are named by die, package does not matter, speed grade
139         # should not matter.
140         #
141         # chip: (package, id, standard, class)
142         "xc3s100e": ("cp132", 1, "LVCMOS33", Spartan3),
143         "xc3s1200e": ("fg320", 1, "LVCMOS33", Spartan3),
144         "xc3s1400a": ("fg484", 1, "LVCMOS33", Spartan3A),
145         "xc3s1400an": ("fgg484", 1, "LVCMOS33", Spartan3A),
146         "xc3s1600e": ("fg320", 1, "LVCMOS33", Spartan3),
147         "xc3s200a": ("fg320", 2, "LVCMOS33", Spartan3A),
148         "xc3s200an": ("ftg256", 1, "LVCMOS33", Spartan3A),
149         "xc3s250e": ("cp132", 1, "LVCMOS33", Spartan3),
150         "xc3s400a": ("fg320", 2, "LVCMOS33", Spartan3A),
151         "xc3s400an": ("fgg400", 1, "LVCMOS33", Spartan3A),
152         "xc3s500e": ("cp132", 1, "LVCMOS33", Spartan3),
153         "xc3s50a": ("ft256", 1, "LVCMOS33", Spartan3A),
154         "xc3s50an": ("ftg256", 1, "LVCMOS33", Spartan3A),
155         "xc3s700a": ("fg400", 1, "LVCMOS33", Spartan3A),
156         "xc3s700an": ("fgg484", 1, "LVCMOS33", Spartan3A),
157         "xc3sd1800a": ("cs484", 1, "LVCMOS33", Spartan3A),
158         "xc3sd3400a": ("cs484", 1, "LVCMOS33", Spartan3A),
159
160         "xc6slx100": ("csg484-2", 1, "LVCMOS33", Spartan6),
161         "xc6slx100t": ("csg484-2", 1, "LVCMOS33", Spartan6),
162         "xc6slx150": ("csg484-2", 1, "LVCMOS33", Spartan6),
163         "xc6slx150t": ("csg484-2", 1, "LVCMOS33", Spartan6),
164         "xc6slx16": ("cpg196-2", 1, "LVCMOS33", Spartan6),
165         "xc6slx25": ("csg324-2", 1, "LVCMOS33", Spartan6),
166         "xc6slx25t": ("csg324-2", 1, "LVCMOS33", Spartan6),
167         "xc6slx45": ("csg324-2", 1, "LVCMOS33", Spartan6),
168         "xc6slx45t": ("csg324-2", 1, "LVCMOS33", Spartan6),
169         "xc6slx4": ("cpg196-2", 1, "LVCMOS33", Spartan6),
170         "xc6slx4t": ("qg144-2", 1, "LVCMOS33", Spartan6),
171         "xc6slx75": ("csg484-2", 1, "LVCMOS33", Spartan6),
172         "xc6slx75t": ("csg484-2", 1, "LVCMOS33", Spartan6),
173         "xc6slx9": ("cpg196-2", 1, "LVCMOS33", Spartan6),
174         "xc6slx9t": ("qg144-2", 1, "LVCMOS33", Spartan6),
175
176         "xc7a100t": ("csg324-1", 1, "LVCMOS25", Series7),
177         "xc7a15t": ("cpg236-1", 1, "LVCMOS25", Series7),
178         "xc7a200t": ("fbg484-1", 1, "LVCMOS25", Series7),
179         "xc7a35t": ("cpg236-1", 1, "LVCMOS25", Series7),
180         "xc7a50t": ("cpg236-1", 1, "LVCMOS25", Series7),
181         "xc7a75t": ("csg324-1", 1, "LVCMOS25", Series7),
182         "xc7k160t": ("fbg484-1", 2, "LVCMOS25", Series7),
183         "xc7k325t": ("fbg676-1", 1, "LVCMOS25", Series7),
184         "xc7k355t": ("ffg901-1", 1, "LVCMOS25", Series7),
185         "xc7k410t": ("fbg676-1", 1, "LVCMOS25", Series7),
186         "xc7k420t": ("ffg1156-1", 1, "LVCMOS25", Series7),
187         "xc7k480t": ("ffg1156-1", 1, "LVCMOS25", Series7),
188         "xc7k70t": ("fbg484-1", 2, "LVCMOS25", Series7),
189         "xc7v2000t": ("fhg1761-1", 1, "LVCMOS18", Series7),
190         "xc7v585t": ("ffg1157-1", 1, "LVCMOS18", Series7),
191         "xc7vh580t": ("flg1155-1", 1, "LVCMOS18", Series7),
192         "xc7vh870t": ("flg1932-1", 1, "LVCMOS18", Series7),
193         "xc7vx1140t": ("flg1926-1", 1, "LVCMOS18", Series7),
194         "xc7vx330t": ("ffg1157-1", 1, "LVCMOS18", Series7),
195         "xc7vx415t": ("ffg1157-1", 1, "LVCMOS18", Series7),
196         "xc7vx485t": ("ffg1157-1", 1, "LVCMOS18", Series7),
197         "xc7vx550t": ("ffg1158-1", 1, "LVCMOS18", Series7),
198         "xc7vx690t": ("ffg1157-1", 1, "LVCMOS18", Series7),
199         "xc7vx980t": ("ffg1926-1", 1, "LVCMOS18", Series7),
200     }
201
202     def __init__(self, device, pins, std, toolchain="ise"):
203         cs_n, clk, mosi, miso = pins[:4]
204         io = ["spiflash", 0,
205               Subsignal("cs_n", Pins(cs_n)),
206               Subsignal("mosi", Pins(mosi)),
207               Subsignal("miso", Pins(miso), Misc("PULLUP")),
208               IOStandard(std),
209               ]
210         if clk:
211             io.append(Subsignal("clk", Pins(clk)))
212         for i, p in enumerate(pins[4:]):
213             io.append(Subsignal("pullup{}".format(i), Pins(p), Misc("PULLUP")))
214         xilinx.XilinxPlatform.__init__(self, device, [io], toolchain=toolchain)
215
216     @classmethod
217     def make(cls, device, errors=False):
218         pkg, id, std, Top = cls.pinouts[device]
219         pins = cls.packages[(pkg, id)]
220         platform = cls("{}-{}".format(device, pkg), pins, std, Top.toolchain)
221         top = Top(platform)
222         name = "bscan_spi_{}".format(device)
223         dir = "build_{}".format(device)
224         try:
225             platform.build(top, build_name=name, build_dir=dir)
226         except Exception as e:
227             print(("ERROR: xilinx_bscan_spi build failed "
228                   "for {}: {}").format(device, e))
229             if errors:
230                 raise
231
232
233 if __name__ == "__main__":
234     import argparse
235     import multiprocessing
236     p = argparse.ArgumentParser(description="build bscan_spi bitstreams "
237                                 "for openocd jtagspi flash driver")
238     p.add_argument("device", nargs="*",
239                    default=sorted(list(XilinxBscanSpi.pinouts)),
240                    help="build for these devices (default: %(default)s)")
241     p.add_argument("-p", "--parallel", default=1, type=int,
242                    help="number of parallel builds (default: %(default)s)")
243     args = p.parse_args()
244     pool = multiprocessing.Pool(args.parallel)
245     pool.map(XilinxBscanSpi.make, args.device, chunksize=1)