Skip to content

Commit 0d326d4

Browse files
committed
Merge pull request #252 from mithro/spi
Adding support for SPI flash on Pipistrello and Opsis board. Working on #237
2 parents bca243b + 08ec6ae commit 0d326d4

File tree

4 files changed

+219
-25
lines changed

4 files changed

+219
-25
lines changed

platforms/opsis.py

+20-3
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,27 @@ class Platform(XilinxPlatform):
357357
default_clk_period = 10.0
358358
hdmi_infos = _hdmi_infos
359359

360+
# W25Q128FVEIG - component U3
361+
# 128M (16M x 8) - 104MHz
362+
# Pretends to be a Micron N25Q128 (ID 0x0018ba20)
363+
# FIXME: Create a "spi flash module" object in the same way we have SDRAM
364+
# module objects.
365+
spiflash_read_dummy_bits = 10
366+
spiflash_clock_div = 4
367+
spiflash_total_size = int((128/8)*1024*1024) # 128Mbit
368+
spiflash_page_size = 256
369+
spiflash_sector_size = 0x10000
370+
371+
372+
# The Opsis has a XC6SLX45 which bitstream takes up ~12Mbit (1484472 bytes)
373+
# 0x200000 offset (16Mbit) gives plenty of space
374+
gateware_size = 0x200000
375+
376+
360377
def __init__(self, programmer="openocd"):
361378
# XC6SLX45T-3FGG484C
362379
XilinxPlatform.__init__(self, "xc6slx45t-fgg484-3", _io, _connectors)
380+
self.programmer = programmer
363381

364382
pins = {
365383
'ProgPin': 'PullUp',
@@ -373,15 +391,14 @@ def __init__(self, programmer="openocd"):
373391
for pin, config in pins.items():
374392
self.toolchain.bitgen_opt += " -g %s:%s " % (pin, config)
375393

376-
self.programmer = programmer
377-
378394
# FPGA AUX is connected to the 3.3V supply
379395
self.add_platform_command("""CONFIG VCCAUX="3.3";""")
380396

381397
def create_programmer(self):
382398
# Preferred programmer - Needs ixo-usb-jtag and latest openocd.
399+
proxy="bscan_spi_{}.bit".format(self.device.split('-')[0])
383400
if self.programmer == "openocd":
384-
return OpenOCD(config="board/numato_opsis.cfg")
401+
return OpenOCD(config="board/numato_opsis.cfg", flash_proxy_basename=proxy)
385402
# Alternative programmers - not regularly tested.
386403
elif self.programmer == "urjtag":
387404
return UrJTAG(cable="USBBlaster")

platforms/pipistrello.py

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
from mibuild.generic_platform import *
2+
from mibuild.xilinx import XilinxPlatform
3+
4+
from mibuild.openocd import OpenOCD
5+
# Alternative programmers
6+
from mibuild.xilinx import UrJTAG
7+
from mibuild.xilinx.programmer import XC3SProg
8+
9+
_io = [
10+
("user_led", 0, Pins("V16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # green at hdmi
11+
("user_led", 1, Pins("U16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at hdmi
12+
("user_led", 2, Pins("A16"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # green at msd
13+
("user_led", 3, Pins("A15"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at msd
14+
("user_led", 4, Pins("A12"), IOStandard("LVTTL"), Drive(8), Misc("SLEW=QUIETIO")), # red at usb
15+
16+
("user_btn", 0, Pins("N14"), IOStandard("LVTTL"), Misc("PULLDOWN")),
17+
18+
("clk50", 0, Pins("H17"), IOStandard("LVTTL")),
19+
20+
("serial", 0,
21+
Subsignal("tx", Pins("A10")),
22+
Subsignal("rx", Pins("A11"), Misc("PULLUP")),
23+
Subsignal("cts", Pins("C10"), Misc("PULLUP")),
24+
Subsignal("rts", Pins("A9"), Misc("PULLUP")),
25+
IOStandard("LVTTL"),
26+
),
27+
28+
("usb_fifo", 0,
29+
Subsignal("data", Pins("A11 A10 C10 A9 B9 A8 B8 A7")),
30+
Subsignal("rxf_n", Pins("C7")),
31+
Subsignal("txe_n", Pins("A6")),
32+
Subsignal("rd_n", Pins("B6")),
33+
Subsignal("wr_n", Pins("A5")),
34+
Subsignal("siwua", Pins("C5")),
35+
IOStandard("LVTTL"),
36+
),
37+
38+
("hdmi", 0,
39+
Subsignal("clk_p", Pins("U5"), IOStandard("TMDS_33")),
40+
Subsignal("clk_n", Pins("V5"), IOStandard("TMDS_33")),
41+
Subsignal("data0_p", Pins("T6"), IOStandard("TMDS_33")),
42+
Subsignal("data0_n", Pins("V6"), IOStandard("TMDS_33")),
43+
Subsignal("data1_p", Pins("U7"), IOStandard("TMDS_33")),
44+
Subsignal("data1_n", Pins("V7"), IOStandard("TMDS_33")),
45+
Subsignal("data2_p", Pins("U8"), IOStandard("TMDS_33")),
46+
Subsignal("data2_n", Pins("V8"), IOStandard("TMDS_33")),
47+
Subsignal("scl", Pins("V9"), IOStandard("I2C")),
48+
Subsignal("sda", Pins("T9"), IOStandard("I2C")),
49+
Subsignal("hpd_notif", Pins("R8"), IOStandard("LVTTL")),
50+
),
51+
52+
("spiflash", 0,
53+
Subsignal("cs_n", Pins("V3")),
54+
Subsignal("clk", Pins("R15")),
55+
Subsignal("mosi", Pins("T13")),
56+
Subsignal("miso", Pins("R13"), Misc("PULLUP")),
57+
Subsignal("wp", Pins("T14")),
58+
Subsignal("hold", Pins("V14")),
59+
IOStandard("LVTTL"), Misc("SLEW=FAST")
60+
),
61+
62+
("spiflash2x", 0,
63+
Subsignal("cs_n", Pins("V3")),
64+
Subsignal("clk", Pins("R15")),
65+
Subsignal("dq", Pins("T13 R13"), Misc("PULLUP")),
66+
Subsignal("wp", Pins("T14")),
67+
Subsignal("hold", Pins("V14")),
68+
IOStandard("LVTTL"), Misc("SLEW=FAST")
69+
),
70+
71+
("spiflash4x", 0,
72+
Subsignal("cs_n", Pins("V3")),
73+
Subsignal("clk", Pins("R15")),
74+
Subsignal("dq", Pins("T13 R13 T14 V14"), Misc("PULLUP")),
75+
IOStandard("LVTTL"), Misc("SLEW=FAST")
76+
),
77+
78+
("mmc", 0,
79+
Subsignal("clk", Pins("A3")),
80+
Subsignal("cmd", Pins("B3"), Misc("PULLUP")),
81+
Subsignal("dat", Pins("B4 A4 B2 A2"), Misc("PULLUP")),
82+
IOStandard("SDIO")
83+
),
84+
85+
("mmc_spi", 0,
86+
Subsignal("cs_n", Pins("A2"), Misc("PULLUP")),
87+
Subsignal("clk", Pins("A3")),
88+
Subsignal("mosi", Pins("B3")),
89+
Subsignal("miso", Pins("B4"), Misc("PULLUP")),
90+
IOStandard("SDIO")
91+
),
92+
93+
("audio", 0,
94+
Subsignal("l", Pins("R7"), Misc("SLEW=SLOW")),
95+
Subsignal("r", Pins("T7"), Misc("SLEW=SLOW")),
96+
IOStandard("LVTTL"),
97+
),
98+
99+
("pmod", 0,
100+
Subsignal("d", Pins("D9 C8 D6 C4 B11 C9 D8 C6")),
101+
IOStandard("LVTTL")
102+
),
103+
104+
("ddram_clock", 0,
105+
Subsignal("p", Pins("G3")),
106+
Subsignal("n", Pins("G1")),
107+
IOStandard("MOBILE_DDR")
108+
),
109+
110+
("ddram", 0,
111+
Subsignal("a", Pins("J7 J6 H5 L7 F3 H4 H3 H6 D2 D1 F4 D3 G6")),
112+
Subsignal("ba", Pins("F2 F1")),
113+
Subsignal("cke", Pins("H7")),
114+
Subsignal("ras_n", Pins("L5")),
115+
Subsignal("cas_n", Pins("K5")),
116+
Subsignal("we_n", Pins("E3")),
117+
Subsignal("dq", Pins("L2 L1 K2 K1 H2 H1 J3 J1 M3 M1 N2 N1 T2 T1 U2 U1")),
118+
Subsignal("dqs", Pins("L4 P2")),
119+
Subsignal("dm", Pins("K3 K4")),
120+
IOStandard("MOBILE_DDR")
121+
)
122+
]
123+
124+
_connectors = [
125+
("A", "U18 T17 P17 P16 N16 N17 M16 L15 L17 K15 K17 J16 H15 H18 F18 D18"),
126+
("B", "C18 E18 G18 H16 J18 K18 K16 L18 L16 M18 N18 N15 P15 P18 T18 U17"),
127+
("C", "F17 F16 E16 G16 F15 G14 F14 H14 H13 J13 G13 H12 K14 K13 K12 L12"),
128+
]
129+
130+
131+
_hdmi_infos = {
132+
"HDMI_OUT0_MNEMONIC": "J4",
133+
"HDMI_OUT0_DESCRIPTION" : (
134+
" Type A connector, marked as J4.\\r\\n"
135+
)
136+
}
137+
class Platform(XilinxPlatform):
138+
identifier = 0x5049
139+
default_clk_name = "clk50"
140+
default_clk_period = 20
141+
hdmi_infos = _hdmi_infos
142+
143+
# Micron N25Q128 (ID 0x0018ba20)
144+
# FIXME: Create a "spi flash module" object in the same way we have SDRAM
145+
# module objects.
146+
spiflash_read_dummy_bits = 10
147+
spiflash_clock_div = 4
148+
spiflash_total_size = int((128/8)*1024*1024) # 128Mbit
149+
spiflash_page_size = 256
150+
spiflash_sector_size = 0x10000
151+
152+
# The Pipistrello has a XC6SLX45 which bitstream takes up ~12Mbit (1484472 bytes)
153+
# 0x200000 offset (16Mbit) gives plenty of space
154+
gateware_size = 0x200000
155+
156+
def __init__(self, programmer="openocd"):
157+
XilinxPlatform.__init__(self, "xc6slx45-csg324-3", _io, _connectors)
158+
self.toolchain.bitgen_opt += " -g Compress -g ConfigRate:6"
159+
self.programmer = programmer
160+
161+
def create_programmer(self):
162+
proxy="bscan_spi_{}.bit".format(self.device.split('-')[0])
163+
if self.programmer == "openocd":
164+
return OpenOCD(config="board/pipistrello.cfg", flash_proxy_basename=proxy)
165+
# Alternative programmers - not regularly tested.
166+
elif self.programmer == "xc3sprog":
167+
return XC3SProg("papilio", "bscan_spi_lx45_csg324.bit")
168+
else:
169+
raise ValueError("{} programmer is not supported".format(self.programmer))

targets/opsis_base.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from migen.genlib.record import Record
1010

1111
from misoclib.com import gpio
12+
from misoclib.mem.flash import spiflash
1213
from misoclib.mem.sdram.module import MT41J128M16
1314
from misoclib.mem.sdram.phy import s6ddrphy
1415
from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
@@ -135,6 +136,7 @@ class BaseSoC(SDRAMSoC):
135136
default_platform = "opsis"
136137

137138
csr_peripherals = (
139+
"spiflash",
138140
"ddrphy",
139141
"dna",
140142
"git_info",
@@ -148,6 +150,7 @@ class BaseSoC(SDRAMSoC):
148150

149151
mem_map = {
150152
"firmware_ram": 0x20000000, # (default shadow @0xa0000000)
153+
"spiflash": 0x30000000, # (default shadow @0xb0000000)
151154
}
152155
mem_map.update(SDRAMSoC.mem_map)
153156

@@ -203,6 +206,13 @@ def __init__(self, platform,
203206
]
204207
self.register_sdram_phy(self.ddrphy)
205208

209+
self.submodules.spiflash = spiflash.SpiFlash(
210+
platform.request("spiflash4x"), dummy=platform.spiflash_read_dummy_bits, div=platform.spiflash_clock_div)
211+
self.add_constant("SPIFLASH_PAGE_SIZE", platform.spiflash_page_size)
212+
self.add_constant("SPIFLASH_SECTOR_SIZE", platform.spiflash_sector_size)
213+
self.flash_boot_address = self.mem_map["spiflash"]+platform.gateware_size
214+
self.register_mem("spiflash", self.mem_map["spiflash"], self.spiflash.bus, size=platform.gateware_size)
215+
206216
self.specials += Keep(self.crg.cd_sys.clk)
207217
platform.add_platform_command("""
208218
NET "{sys_clk}" TNM_NET = "GRPsys_clk";
@@ -222,7 +232,7 @@ class MiniSoC(BaseSoC):
222232
interrupt_map.update(BaseSoC.interrupt_map)
223233

224234
mem_map = {
225-
"ethmac": 0x30000000, # (shadow @0xb0000000)
235+
"ethmac": 0x40000000, # (shadow @0xc0000000)
226236
}
227237
mem_map.update(BaseSoC.mem_map)
228238

targets/pipistrello_base.py

+19-21
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1+
# Support for the Pipistrello - http://pipistrello.saanlima.com/
12
from fractions import Fraction
2-
import struct
33

44
from migen.fhdl.std import *
55
from migen.genlib.resetsync import AsyncResetSynchronizer
66
from migen.bus import wishbone
77

88
from misoclib.com import gpio
9+
from misoclib.mem.flash import spiflash
910
from misoclib.mem.sdram.module import MT46H32M16
1011
from misoclib.mem.sdram.phy import s6ddrphy
1112
from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
12-
from misoclib.mem.flash import spiflash
1313
from misoclib.soc.sdram import SDRAMSoC
1414

1515
from gateware import dna
1616
from gateware import firmware
1717
from gateware import git_info
1818
from gateware import hdmi_out
19+
from gateware import i2c
1920
from gateware import i2c_hack
2021
from gateware import platform_info
2122

@@ -133,16 +134,18 @@ class BaseSoC(SDRAMSoC):
133134

134135
mem_map = {
135136
"firmware_ram": 0x20000000, # (default shadow @0xa0000000)
137+
"spiflash": 0x30000000, # (default shadow @0xb0000000)
136138
}
137139
mem_map.update(SDRAMSoC.mem_map)
138140

139-
def __init__(self, platform, clk_freq=(83 + Fraction(1, 3))*1000*1000,
140-
sdram_controller_settings=LASMIconSettings(l2_size=32,
141-
with_bandwidth=True),
142-
firmware_ram_size=0xa000, firmware_filename=None, **kwargs):
141+
def __init__(self, platform,
142+
firmware_ram_size=0xa000,
143+
firmware_filename=None,
144+
**kwargs):
145+
clk_freq = (83 + Fraction(1, 3))*1000*1000
143146
SDRAMSoC.__init__(self, platform, clk_freq,
144147
integrated_rom_size=0x8000,
145-
sdram_controller_settings=sdram_controller_settings,
148+
sdram_controller_settings=LASMIconSettings(l2_size=32, with_bandwidth=True),
146149
**kwargs)
147150

148151
platform.add_extension(PipistrelloCustom)
@@ -169,19 +172,12 @@ def __init__(self, platform, clk_freq=(83 + Fraction(1, 3))*1000*1000,
169172
]
170173
self.register_sdram_phy(self.ddrphy)
171174

172-
if not self.integrated_rom_size:
173-
self.submodules.spiflash = spiflash.SpiFlash(platform.request("spiflash4x"),
174-
dummy=10, div=4)
175-
self.add_constant("SPIFLASH_PAGE_SIZE", 256)
176-
self.add_constant("SPIFLASH_SECTOR_SIZE", 0x10000)
177-
self.flash_boot_address = 0x180000
178-
self.register_rom(self.spiflash.bus, 0x1000000)
179-
platform.add_platform_command("""PIN "hdmi_out_pix_bufg.O" CLOCK_DEDICATED_ROUTE = FALSE;""")
180-
181-
_hdmi_infos = {
182-
"HDMI_OUT0_MNEMONIC": "J4",
183-
"HDMI_OUT0_DESCRIPTION": "XXX",
184-
}
175+
self.submodules.spiflash = spiflash.SpiFlash(
176+
platform.request("spiflash4x"), dummy=platform.spiflash_read_dummy_bits, div=platform.spiflash_clock_div)
177+
self.add_constant("SPIFLASH_PAGE_SIZE", platform.spiflash_page_size)
178+
self.add_constant("SPIFLASH_SECTOR_SIZE", platform.spiflash_sector_size)
179+
self.flash_boot_address = self.mem_map["spiflash"]+platform.gateware_size
180+
self.register_mem("spiflash", self.mem_map["spiflash"], self.spiflash.bus, size=platform.gateware_size)
185181

186182

187183
class VideomixerSoC(BaseSoC):
@@ -196,7 +192,9 @@ def __init__(self, platform, **kwargs):
196192
self.submodules.hdmi_out0 = hdmi_out.HDMIOut(
197193
platform.request("hdmi", 0), self.sdram.crossbar.get_master())
198194

199-
for k, v in _hdmi_infos.items():
195+
platform.add_platform_command("""PIN "hdmi_out_pix_bufg.O" CLOCK_DEDICATED_ROUTE = FALSE;""")
196+
197+
for k, v in platform.hdmi_infos.items():
200198
self.add_constant(k, v)
201199

202200
default_subtarget = VideomixerSoC

0 commit comments

Comments
 (0)