1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
import os
import subprocess
from nmigen.build import *
from nmigen.vendor.lattice_ecp5 import *
from .resources import *
__all__ = ["Supercon19BadgePlatform"]
class Supercon19BadgePlatform(LatticeECP5Platform):
device = "LFE5U-45F"
package = "BG381"
speed = "8"
default_clk = "clk8"
# The badge's LEDs are wired in a non-straightforward way. Here, the
# LEDResources represent each of the common anodes of a collection of RGB LEDs.
# A single one of their cathodes defaults to connected via a FET; the other
# cathodes are normally-off. Accordingly, they act as normal single-color LEDs
# unless the cathode signals are explicitly driven.
#
# The LEDs on the badge were meant to be a puzzle; so each cathode signal
# corresponds to a different color on each LED. This means there's no
# straightforward way of creating pin definitions; you'll need to use the
# following mapping to find the cathode pin number below.
led_cathode_mappings = [
{'r': 0, 'g': 1, 'b': 2}, # LED1: by default, red
{'r': 2, 'g': 1, 'b': 0}, # LED2: by default, blue
{'r': 0, 'g': 1, 'b': 2}, # LED3: by default, red
{'r': 2, 'g': 1, 'b': 0}, # LED4: by default, blue
{'r': 0, 'g': 1, 'b': 2}, # LED5: by default, red
{'r': 2, 'g': 1, 'b': 0}, # LED6: by default, blue
{'r': 2, 'g': 0, 'b': 1}, # LED7: by default, green
{'r': 0, 'g': 1, 'b': 2}, # LED8: by default, red
{'r': 0, 'g': 1, 'b': 2}, # LED9: by default, red
# Note: [LED10 is disconnected by default; bridge R60 to make things work]
{'r': 2, 'g': 1, 'b': 0}, # LED10: by default, blue
{'r': 1, 'g': 0, 'b': 2}, # LED11: by default, green
]
resources = [
Resource("clk8", 0, Pins("U18"), Clock(8e6), Attrs(IO_TYPE="LVCMOS33")),
# Used to trigger FPGA reconfiguration.
Resource("program", 0, PinsN("R1"), Attrs(IO_TYPE="LVCMOS33")),
# See note above for LED anode/cathode information.
# Short version is: these work as normal LEDs until you touch their cathodes.
*LEDResources(pins="E3 D3 C3 C4 C2 B1 B20 B19 A18 K20 K19",
attrs=Attrs(IO_TYPE="LVCMOS33")),
Resource("led_cathodes", 0, Pins("P19 L18 K18"), Attrs(IO_TYPE="LVCMOS33")),
UARTResource(0, rx="U2", tx="U1", attrs=Attrs(IO_TYPE="LVCMOS33")),
DirectUSBResource(0, d_p="F3", d_n="G3", pullup="E4", vbus_valid="F4",
attrs=Attrs(IO_TYPE="LVCMOS33")),
# Buttons, with semantic aliases.
*ButtonResources(pins="G2 F2 F1 C1 E1 D2 D1 E2",
attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
),
Resource("keypad", 0,
Subsignal("left", Pins("G2", dir="i")),
Subsignal("right", Pins("F2", dir="i")),
Subsignal("up", Pins("F1", dir="i")),
Subsignal("down", Pins("C1", dir="i")),
Subsignal("start", Pins("E1", dir="i")),
Subsignal("select",Pins("D2", dir="i")),
Subsignal("a", Pins("D1", dir="i")),
Subsignal("b", Pins("E2", dir="i")),
Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")
),
# Direct HDMI on the bottom of the board.
Resource("hdmi", 0,
Subsignal("clk", DiffPairsN("P20", "R20"), Attrs(IO_TYPE="TMDS_33")),
Subsignal("d", DiffPairs("N19 L20 L16", "N20 M20 L17"), Attrs(IO_TYPE="TMDS_33")),
Subsignal("hpd", PinsN("R18"), Attrs(IO_TYPE="LVCMOS33")),# Also called HDMI_HEAC_n
Subsignal("hdmi_heac_p", PinsN("T19"), Attrs(IO_TYPE="LVCMOS33")),
Attrs(DRIVE="4"),
),
Resource("lcd", 0,
Subsignal("db",
Pins("J3 H1 K4 J1 K3 K2 L4 K1 L3 L2 M4 L1 M3 M1 N4 N2 N3 N1"),
),
Subsignal("rd", Pins("P2")),
Subsignal("wr", Pins("P4")),
Subsignal("rs", Pins("P1")),
Subsignal("cs", Pins("P3")),
Subsignal("id", Pins("J4")),
Subsignal("rst", Pins("H2")),
Subsignal("fmark", Pins("G1")),
Subsignal("blen", Pins("P5")),
Attrs(IO_TYPE="LVCMOS33")
),
Resource("spi_flash", 0, # clock needs to be accessed through USRMCLK
Subsignal("cs", PinsN("R2")),
Subsignal("copi", Pins("W2")),
Subsignal("cipo", Pins("V2")),
Subsignal("wp", Pins("Y2")),
Subsignal("hold", Pins("W1")),
Attrs(IO_TYPE="LVCMOS33")
),
Resource("spi_flash_4x", 0, # clock needs to be accessed through USRMCLK
Subsignal("cs", PinsN("R2")),
Subsignal("dq", Pins("W2 V2 Y2 W1")),
Attrs(IO_TYPE="LVCMOS33")
),
# SPI-connected PSRAM.
Resource("spi_psram_4x", 0,
Subsignal("cs", PinsN("D20")),
Subsignal("clk", Pins("E20")),
Subsignal("dq", Pins("E19 D19 C20 F19"), Attrs(PULLMODE="UP")),
Attrs(IO_TYPE="LVCMOS33", SLEWRATE="SLOW")
),
Resource("spi_psram_4x", 1,
Subsignal("cs", PinsN("F20")),
Subsignal("clk", Pins("J19")),
Subsignal("dq", Pins("J20 G19 G20 H20"), Attrs(PULLMODE="UP")),
Attrs(IO_TYPE="LVCMOS33", SLEWRATE="SLOW")
),
SDRAMResource(0, clk="D11", cke="C11", cs="C7", we="B6", ras="D6", cas="A6",
ba="A7 C8", a="A8 D9 C9 B9 C14 E17 A12 B12 H17 G18 B8 A11 B11",
dq="C5 B5 A5 C6 B10 C10 D10 A9", dqm="A10",
attrs=Attrs(IO_TYPE="LVCMOS33", SLEWRATE="FAST")
)
]
connectors = [
Connector("pmod", 0, "A15 C16 A14 D16 B15 C15 A13 B13"),
Connector("cartridge", 0,
"- - - - - - - - C5 B5 A5 C6 B6 A6 D6 C7 A7 C8 B8 A8 D9 C9 B9 A9" # continued:
" D10 C10 B10 A10 D11 C11 B11 A11 G18 H17 B12 A12 E17 C14"
),
# SAO connectors names are compliant with the, erm, SAO 1.69 X-TREME standard.
# See: https://hackaday.com/2019/03/20/introducing-the-shitty-add-on-v1-69bis-standard/
Connector("sao", 0, {
"sda": "B3", "scl": "B2", "gpio0": "A2",
"gpio1": "A3", "gpio2": "B4", "gpio3": "A4"
}),
Connector("sao", 1, {
"sda": "A16", "scl": "B17", "gpio0": "B18",
"gpio1": "A17", "gpio2": "B16", "gpio3": "C17"
})
]
def toolchain_prepare(self, fragment, name, **kwargs):
overrides = dict(ecppack_opts="--compress --freq 38.8")
overrides.update(kwargs)
return super().toolchain_prepare(fragment, name, **overrides, **kwargs)
def toolchain_program(self, products, name):
dfu_util = os.environ.get("DFU_UTIL", "dfu-util")
with products.extract("{}.bit".format(name)) as bitstream_filename:
subprocess.check_call([dfu_util, "-d", "1d50:614b", "-a", "0", "-D", bitstream_filename])
if __name__ == "__main__":
from .test.blinky import *
Supercon19BadgePlatform().build(Blinky(), do_program=True)
|