@@ -25,7 +25,7 @@ def _format_cmd(cmd, spi_width):
25
25
return c
26
26
27
27
28
- class SpiFlash (Module , AutoCSR ):
28
+ class SpiFlashDualQuad (Module , AutoCSR ):
29
29
def __init__ (self , pads , dummy = 15 , div = 2 , with_bitbang = True ):
30
30
"""
31
31
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):
147
147
t += dt
148
148
149
149
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