Skip to content

Commit dc29516

Browse files
committed
core: fix LiteSPI MMAP write command phases
Decode the configured program opcode so MMAP writes use program command, address, data widths, and 4-byte address length independently from the selected read opcode. Acknowledge CSR-disabled writes as no-op Wishbone transactions and keep skipped byte lanes aligned by shifting write data when advancing the byte-select mask. Validated with: pytest -q test/test_spi_mmap.py; pytest -q
1 parent adcccca commit dc29516

1 file changed

Lines changed: 32 additions & 9 deletions

File tree

litespi/core/mmap.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,27 @@
1616
from litex.soc.interconnect.csr import *
1717

1818
from litespi.common import *
19+
from litespi.opcodes import SpiNorFlashOpCodes
1920
from migen.genlib.cdc import MultiReg
2021

21-
cmd_oe_mask = {
22-
1: 0b00000001,
23-
2: 0b00000011,
24-
4: 0b00001111,
25-
8: 0b11111111,
26-
}
27-
addr_oe_mask = {
22+
oe_mask = {
2823
1: 0b00000001,
2924
2: 0b00000011,
3025
4: 0b00001111,
3126
8: 0b11111111,
3227
}
28+
cmd_oe_mask = oe_mask
29+
addr_oe_mask = oe_mask
30+
31+
def get_opcode_widths(opcode):
32+
cfg = SpiNorFlashOpCodes()
33+
cfg.name = SpiNorFlashOpCodes.name_from_value(SpiNorFlashOpCodes, opcode)
34+
return (
35+
int(cfg.cmd_width),
36+
int(cfg.addr_width),
37+
int(cfg.data_width),
38+
32 if "4B" in cfg.name else 24,
39+
)
3340

3441
class LiteSPIMMAP(LiteXModule):
3542
"""Memory-mapped SPI Flash controller.
@@ -124,6 +131,7 @@ def __init__(self, flash, clock_domain="sys", endianness="big", with_csr=True, w
124131
if with_write:
125132
write = Signal()
126133
self.data_write = Signal(32)
134+
program_cmd_width, program_addr_width, program_data_width, program_addr_bits = get_opcode_widths(flash.program_opcode)
127135
else:
128136
write = Constant(0)
129137

@@ -176,6 +184,9 @@ def __init__(self, flash, clock_domain="sys", endianness="big", with_csr=True, w
176184
NextState("PRE-BURST-CMD-WRITE"),
177185
),
178186
NextValue(write, 1)
187+
).Else(
188+
bus.ack.eq(1),
189+
NextValue(write, 0),
179190
)
180191
)
181192
)
@@ -193,6 +204,7 @@ def __init__(self, flash, clock_domain="sys", endianness="big", with_csr=True, w
193204
).Else(
194205
NextValue(byte_count, byte_count + 1),
195206
NextValue(write_mask, Cat(write_mask[1:len(bus.sel)], Signal(1))),
207+
NextValue(self.data_write, self.data_write >> 8),
196208
)
197209
)
198210

@@ -213,6 +225,8 @@ def __init__(self, flash, clock_domain="sys", endianness="big", with_csr=True, w
213225
fsm.act("BURST-CMD",
214226
If(write_enabled & write,
215227
source.data.eq(flash.program_opcode.code), # send command.
228+
source.width.eq(program_cmd_width),
229+
source.mask.eq(cmd_oe_mask[program_cmd_width]),
216230
)
217231
)
218232

@@ -238,6 +252,15 @@ def __init__(self, flash, clock_domain="sys", endianness="big", with_csr=True, w
238252
)
239253
)
240254

255+
if with_write:
256+
fsm.act("BURST-ADDR",
257+
If(write_enabled & write,
258+
source.width.eq(program_addr_width),
259+
source.mask.eq(addr_oe_mask[program_addr_width]),
260+
source.len.eq(program_addr_bits),
261+
)
262+
)
263+
241264
fsm.act("ADDR-RET",
242265
cs.eq(1),
243266
sink.ready.eq(1),
@@ -303,8 +326,8 @@ def __init__(self, flash, clock_domain="sys", endianness="big", with_csr=True, w
303326
fsm.act("WRITE",
304327
cs.eq(1),
305328
source.valid.eq(1),
306-
source.width.eq(flash.addr_width),
307-
source.mask.eq(addr_oe_mask[flash.bus_width]),
329+
source.width.eq(program_data_width),
330+
source.mask.eq(oe_mask[program_data_width]),
308331
source.data.eq(self.data_write),
309332
source.len.eq(8),
310333
If(source.ready,

0 commit comments

Comments
 (0)