Skip to content

Commit dae037c

Browse files
committed
added spi 1-bit mode, code from litex
1 parent 1325aff commit dae037c

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

misoc/cores/spi_flash.py

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def _format_cmd(cmd, spi_width):
2525
return c
2626

2727

28-
class SpiFlash(Module, AutoCSR):
28+
class SpiFlashDualQuad(Module, AutoCSR):
2929
def __init__(self, pads, dummy=15, div=2, with_bitbang=True):
3030
"""
3131
Simple SPI flash, e.g. N25Q128 on the LX9 Microboard.
@@ -147,3 +147,88 @@ def __init__(self, pads, dummy=15, div=2, with_bitbang=True):
147147
t += dt
148148

149149
self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
150+
151+
class SpiFlashSingle(Module, AutoCSR):
152+
def __init__(self, pads, dummy=15, div=2):
153+
"""
154+
Simple SPI flash.
155+
Supports 1-bit reads. Only supports mode0 (cpol=0, cpha=0).
156+
"""
157+
self.bus = bus = wishbone.Interface()
158+
159+
# # #
160+
161+
if hasattr(pads, "wp"):
162+
self.comb += pads.wp.eq(1)
163+
164+
if hasattr(pads, "hold"):
165+
self.comb += pads.hold.eq(1)
166+
167+
cs_n = Signal(reset=1)
168+
clk = Signal()
169+
wbone_width = len(bus.dat_r)
170+
171+
read_cmd = _FAST_READ
172+
cmd_width = 8
173+
addr_width = 24
174+
175+
sr = Signal(max(cmd_width, addr_width, wbone_width))
176+
self.comb += bus.dat_r.eq(sr)
177+
178+
self.comb += [
179+
pads.clk.eq(clk),
180+
pads.cs_n.eq(cs_n),
181+
pads.mosi.eq(sr[-1:])
182+
]
183+
184+
if div < 2:
185+
raise ValueError("Unsupported value \'{}\' for div parameter for SpiFlash core".format(div))
186+
else:
187+
i = Signal(max=div)
188+
miso = Signal()
189+
self.sync += [
190+
If(i == div//2 - 1,
191+
clk.eq(1),
192+
miso.eq(pads.miso),
193+
),
194+
If(i == div - 1,
195+
i.eq(0),
196+
clk.eq(0),
197+
sr.eq(Cat(miso, sr[:-1]))
198+
).Else(
199+
i.eq(i + 1),
200+
),
201+
]
202+
203+
# spi is byte-addressed, prefix by zeros
204+
z = Replicate(0, log2_int(wbone_width//8))
205+
206+
seq = [
207+
(cmd_width*div,
208+
[cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
209+
(addr_width*div,
210+
[sr[-addr_width:].eq(Cat(z, bus.adr))]),
211+
((dummy + wbone_width)*div,
212+
[]),
213+
(1,
214+
[bus.ack.eq(1), cs_n.eq(1)]),
215+
(div, # tSHSL!
216+
[bus.ack.eq(0)]),
217+
(0,
218+
[]),
219+
]
220+
221+
# accumulate timeline deltas
222+
t, tseq = 0, []
223+
for dt, a in seq:
224+
tseq.append((t, a))
225+
t += dt
226+
227+
self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
228+
229+
230+
def SpiFlash(pads, *args, **kw):
231+
if hasattr(pads, "mosi"):
232+
return SpiFlashSingle(pads, *args, **kw)
233+
else:
234+
return SpiFlashDualQuad(pads, *args, **kw)

0 commit comments

Comments
 (0)