@@ -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