8f072b09b2dddc170e8672d9a776c5ba9f7af420
[nmigen-boards.git] / nmigen_boards / mercury.py
1 import os
2 import subprocess
3
4 from nmigen.build import *
5 from nmigen.vendor.xilinx_spartan_3_6 import *
6 from .dev import *
7
8
9 __all__ = ["MercuryPlatform"]
10
11
12 class MercuryPlatform(XilinxSpartan3APlatform):
13 """
14 Original Mercury Board from Micro-Nova: https://www.micro-nova.com
15
16 Mercury Manual: https://www.micro-nova.com/s/mercury_rm.pdf
17 Mercury Schematic: https://www.micro-nova.com/s/mercury_schematic.pdf
18
19 The Mercury board is often paired with an extension board called the
20 Baseboard, which provides an ample set of I/O for FPGA beginners.
21
22 Baseboard Manual: https://www.micro-nova.com/s/baseboard_rm.pdf
23 Baseboard Schematics: https://www.micro-nova.com/s/baseboard_schematic.pdf
24
25 Mercury and Baseboard Resources: https://www.micro-nova.com/resources-mercury
26 """
27
28 device = "xc3s200a"
29 package = "vq100"
30 speed = "4"
31
32 default_clk = "clk50"
33 resources = [
34 Resource("clk50", 0, Pins("P43", dir="i"),
35 Attrs(IOSTANDARD="LVCMOS33"), Clock(50e6)),
36
37 Resource("user_btn", 0, Pins("P41", dir="i"),
38 Attrs(IOSTANDARD="LVTTL")),
39
40 # The serial interface and flash memory have a shared SPI bus.
41 # FPGA is secondary.
42 SPIResource("spi_serial", 0, role="device",
43 cs="P39", clk="P53", mosi="P46", miso="P51",
44 attrs=Attrs(IOSTANDARD="LVTTL"),
45 ),
46
47 # FPGA is primary.
48 *SPIFlashResources(0,
49 cs="P27", clk="P53", mosi="P46", miso="P51",
50 attrs=Attrs(IOSTANDARD="LVTTL")
51 ),
52
53 # ADC over SPI- FPGA is primary.
54 SPIResource("spi_adc", 0, role="host",
55 cs="P12", clk="P9", mosi="P10", miso="P21",
56 attrs=Attrs(IOSTANDARD="LVTTL"),
57 ),
58
59 # GPIO/SRAM Control
60 # 5V tolerant GPIO is shared w/ the SRAM (on 200k gate devices) using
61 # this pin. All GPIO except gpio:30 (and gpio:20, though see comment
62 # under SRAMResource) interface to the SRAM. On assertion, this signal
63 # will tristate the level-shifters, preventing any output on the 5V
64 # GPIO pins (including gpio:30 and gpio:20).
65 Resource("bussw_oe", 0, PinsN("P30N", dir="o"),
66 Attrs(IOSTANDARD="LVTTL"))
67 ]
68
69 # Perhaps define some connectors as having a specific purpose- i.e. a 5V GPIO
70 # bus with data, peripheral-select, and control signals?
71 connectors = [
72 Connector("gpio", 0, """P59 P60 P61 P62 P64 P57
73 P56 P52 P50 P49 P85 P84
74 P83 P78 P77 P65 P70 P71
75 P72 P73 P5 P4 P6 P98
76 P94 P93 P90 P89 P88 P86"""), # 5V I/O- LVTTL.
77 Connector("dio", 0, "P20 P32 P33 P34 P35 P36 P37"), # Fast 3.3V IO
78 # (Directly attached to FPGA)- LVCMOS33.
79 Connector("clkio", 0, "P40 P44"), # Clock IO (Can be used as GPIO)-
80 # LVCMOS33.
81 Connector("input", 0, "P68 P97 P7 P82"), # Input-only pins- LVCMOS33.
82 Connector("led", 0, "P13 P15 P16 P19"), # LEDs can be used as pins
83 # as well- LVTTL.
84 Connector("pmod", 0, "P5 P4 P6 P98 P94 P93 P90 P89") # Baseboard PMOD.
85 # Overlaps w/ GPIO bus.
86 ]
87
88 # Some default useful extensions. Attach to platform using:
89 # p.add_resources(p.leds)
90 # pmod_btn = plat.request("user_led")
91 leds = [
92 Resource("user_led", 0, Pins("1", dir="o", conn=("led", 0)),
93 Attrs(IOSTANDARD="LVTTL")),
94 Resource("user_led", 1, Pins("2", dir="o", conn=("led", 0)),
95 Attrs(IOSTANDARD="LVTTL")),
96 Resource("user_led", 2, Pins("3", dir="o", conn=("led", 0)),
97 Attrs(IOSTANDARD="LVTTL")),
98 Resource("user_led", 3, Pins("4", dir="o", conn=("led", 0)),
99 Attrs(IOSTANDARD="LVTTL")),
100 ]
101
102 sram = [
103 SRAMResource(0,
104 cs="P3", we="gpio_0:29",
105 # According to the schematic, A19/Pin 25 on the SRAM is wired to
106 # gpio-0:20. However, according to the SRAM's datasheet, pin 25 is
107 # a NC. Do not expose for now.
108 a=""" gpio_0:1 gpio_0:2 gpio_0:3 gpio_0:4 gpio_0:5 gpio_0:6
109 gpio_0:7 gpio_0:8 gpio_0:9 gpio_0:10 gpio_0:11 gpio_0:12
110 gpio_0:13 gpio_0:14 gpio_0:15 gpio_0:16 gpio_0:17 gpio_0:18
111 gpio_0:19""",
112 d="""gpio_0:21 gpio_0:22 gpio_0:23 gpio_0:24 gpio_0:25 gpio_0:26
113 gpio_0:27 gpio_0:28""",
114 attrs=Attrs(IOSTANDARD="LVTTL", SLEW="FAST")
115 )
116 ]
117
118 # The "serial port" is in fact over SPI. The creators of the board provide
119 # a VHDL file for talking over this interface. In light of space
120 # constraints and the fact that both the FT245RL and FPGA can BOTH be
121 # SPI primaries, however, it may be necessary to sacrifice two "high-speed"
122 # (DIO, INPUT) pins instead.
123 serial = [
124 # RX: FTDI D0, TX: FTDI D1
125 UARTResource(0, rx="input_0:1", tx="dio_0:1",
126 attrs=Attrs(IOSTANDARD="LVCMOS33"))
127 ]
128
129 # The remaining peripherals only make sense w/ the Baseboard installed.
130 # See: http://www.micro-nova.com/mercury-baseboard/
131 _user_sw = [
132 Resource("user_sw", 0, Pins("1", dir="i", conn=("gpio", 0)),
133 Attrs(IOSTANDARD="LVTTL")),
134 Resource("user_sw", 1, Pins("2", dir="i", conn=("gpio", 0)),
135 Attrs(IOSTANDARD="LVTTL")),
136 Resource("user_sw", 2, Pins("3", dir="i", conn=("gpio", 0)),
137 Attrs(IOSTANDARD="LVTTL")),
138 Resource("user_sw", 3, Pins("4", dir="i", conn=("gpio", 0)),
139 Attrs(IOSTANDARD="LVTTL")),
140 Resource("user_sw", 4, Pins("5", dir="i", conn=("gpio", 0)),
141 Attrs(IOSTANDARD="LVTTL")),
142 Resource("user_sw", 5, Pins("6", dir="i", conn=("gpio", 0)),
143 Attrs(IOSTANDARD="LVTTL")),
144 Resource("user_sw", 6, Pins("7", dir="i", conn=("gpio", 0)),
145 Attrs(IOSTANDARD="LVTTL")),
146 Resource("user_sw", 7, Pins("8", dir="i", conn=("gpio", 0)),
147 Attrs(IOSTANDARD="LVTTL"))
148 ]
149
150 _user_btn = [
151 Resource("user_btn", 1, Pins("1", dir="i", conn=("input", 0)),
152 Attrs(IOSTANDARD="LVTTL")),
153 Resource("user_btn", 2, Pins("2", dir="i", conn=("input", 0)),
154 Attrs(IOSTANDARD="LVTTL")),
155 Resource("user_btn", 3, Pins("3", dir="i", conn=("input", 0)),
156 Attrs(IOSTANDARD="LVTTL")),
157 Resource("user_btn", 4, Pins("4", dir="i", conn=("input", 0)),
158 Attrs(IOSTANDARD="LVTTL"))
159 ]
160
161 _vga = [
162 Resource("vga_out", 0,
163 Subsignal("hsync", PinsN("led_0:3", dir="o")),
164 Subsignal("vsync", PinsN("led_0:4", dir="o")),
165
166 Subsignal("r", Pins("dio_0:1 dio_0:2 dio_0:3", dir="o")),
167 Subsignal("g", Pins("dio_0:4 dio_0:5 dio_0:6", dir="o")),
168 Subsignal("b", Pins("dio_0:7 clkio_0:1", dir="o")),
169 Attrs(IOSTANDARD="LVCMOS33", SLEW="FAST")
170 )
171 ]
172
173 _extclk = [
174 Resource("extclk", 0, Pins("1", dir="i", conn=("clkio", 1)),
175 Attrs(IOSTANDARD="LVCMOS33"))
176 ]
177
178 _sevenseg = [
179 Resource("sevenseg", 0,
180 Subsignal("a", PinsN("13", dir="o", conn=("gpio", 0))),
181 Subsignal("b", PinsN("14", dir="o", conn=("gpio", 0))),
182 Subsignal("c", PinsN("15", dir="o", conn=("gpio", 0))),
183 Subsignal("d", PinsN("16", dir="o", conn=("gpio", 0))),
184 Subsignal("e", PinsN("17", dir="o", conn=("gpio", 0))),
185 Subsignal("f", PinsN("18", dir="o", conn=("gpio", 0))),
186 Subsignal("g", PinsN("19", dir="o", conn=("gpio", 0))),
187 Subsignal("dp", PinsN("20", dir="o", conn=("gpio", 0))),
188 Subsignal("en", Pins("9 10 11 12", dir="o",
189 conn=("gpio", 0))),
190 Attrs(IOSTANDARD="LVTTL")
191 )
192 ]
193
194 _ps2 = [
195 Resource("ps2", 0,
196 Subsignal("clk", Pins("2", dir="io", conn=("led", 0))),
197 Subsignal("data", Pins("1", dir="io", conn=("led", 0))),
198 Attrs(IOSTANDARD="LVTTL")
199 )
200 ]
201
202 _audio = [
203 Resource("audio", 0,
204 Subsignal("l", Pins("30", dir="o", conn=("gpio", 0))),
205 Subsignal("r", Pins("29", dir="o", conn=("gpio", 0))),
206 Attrs(IOSTANDARD="LVTTL")
207 )
208 ]
209
210 baseboard_sram = _user_btn + _vga + _extclk + _ps2
211 baseboard_no_sram = _user_btn + _vga + _extclk + _ps2 + \
212 _user_sw + _sevenseg + _audio
213
214 def toolchain_program(self, products, name):
215 # https://github.com/cr1901/mercpcl
216 mercpcl = os.environ.get("MERCPCL", "mercpcl")
217 with products.extract("{}.bin".format(name)) as bitstream_filename:
218 subprocess.check_call([mercpcl, bitstream_filename])
219
220
221 if __name__ == "__main__":
222 from ._blinky import Blinky
223 plat = MercuryPlatform()
224 plat.add_resources(plat.leds)
225 plat.build(Blinky(), do_program=True)