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