Closed kamejoko80 closed 4 years ago
Hi,
here is some code i prototyped some time ago (but haven't tested it on hardware).
This is designed to be used with SPIMaster (https://github.com/enjoy-digital/litex/blob/master/litex/soc/cores/spi.py) and the idea is read data from Wishbone, write it to SPI and be able to control this DMA from the CPU:
from migen import *
from litex.soc.interconnect.csr import *
from litex.soc.interconnect import wishbone
SPI_START = (1<<0)
SPI_LENGTH = (1<<8)
SPI_DONE = (1<<0)
class Wishbone2SPIDMA(Module, AutoCSR):
def __init__(self):
# Wishbone
self.bus = bus = wishbone.Interface()
# Control
self.start = CSR()
self.done = CSRStatus()
# Read parameters: base and length of DMA
self.read_base = CSRStorage(32)
self.read_length = CSRStorage(32)
# SPI parameters: address of control/status/mosi registers
self.spi_control_reg_address = CSRStorage(32)
self.spi_status_reg_address = CSRStorage(32)
self.spi_mosi_reg_address = CSRStorage(32)
# # #
# Shorten CSR's names
start = self.start.re
done = self.done.status
read_base = self.read_base.storage[2:]
read_length = self.read_length.storage[2:]
spi_mosi_reg_address = self.spi_mosi_reg_address.storage
spi_control_reg_address = self.spi_control_reg_address.storage
spi_status_reg_address = self.spi_status_reg_address.storage
# internals
offset = Signal(32)
data = Signal(32)
# fsm
self.submodules.fsm = fsm = FSM()
fsm.act("IDLE",
If(start,
NextValue(offset, 0),
NextState("WISHBONE-READ-DATA")
).Else(
done.eq(1),
)
)
fsm.act("WISHBONE-READ-DATA",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.adr.eq(read_base + offset),
If(bus.ack,
NextValue(data, bus.dat_r),
NextState("SPI-WRITE-DATA")
)
)
fsm.act("SPI-WRITE-DATA",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_mosi_reg_address),
bus.dat_w.eq(data),
If(bus.ack,
NextState("SPI-WRITE-START")
)
)
fsm.act("SPI-WRITE-START",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_control_reg_address),
bus.dat_w.eq(SPI_START),
If(bus.ack,
NextState("SPI-WAIT-DONE")
)
)
fsm.act("SPI-WAIT-DONE",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.adr.eq(spi_status_reg_address),
If(bus.ack,
If(bus.dat_r & SPI_DONE,
NextState("INC-OFFSET")
)
)
)
fsm.act("INC-OFFSET",
If(offset >= read_length,
NextState("IDLE")
).Else(
NextValue(offset, offset + 1),
NextState("WISHBONE-READ-DATA")
)
)
if __name__ == '__main__':
dut = Wishbone2SPIDMA()
def dut_tb(dut):
yield dut.bus.ack.eq(1) # always ack
yield dut.bus.dat_r.eq(1) # always return 1
# configure DMA
yield dut.read_base.storage.eq(0x10000000)
yield dut.read_length.storage.eq(0x100)
yield dut.spi_mosi_reg_address.storage.eq(0x20000000)
yield dut.spi_control_reg_address.storage.eq(0x20000004)
yield dut.spi_status_reg_address.storage.eq(0x20000004)
yield
# start DMA
yield dut.start.re.eq(1)
yield
yield dut.start.re.eq(0)
yield
# wait DMA
while (yield dut.done.status) == 0:
yield
run_simulation(dut, dut_tb(dut), vcd_name="wb2spi_dma.vcd")
To integrate it in your design, in your SoC:
# SPI Master
self.submodules.spi = SPIMaster(pads, 32, sys_clk_freq, spi_clk_freq)
self.add_csr("spi")
#SPI DMA
self.submodules.spi_dma = Wishbone2SPIDMA()
self.add_csr("spi_dma")
self.bus.add_master(self.spi_dma.bus).
You will then need to write the CPU software to configure the address of the SPI Master registers of your design and program the DMA transfer.
Hi enjoy-digital,
Thanks for the reply.
I defined a function "add_spidma" in soc_linux.py
# SPI --------------------------------------------------------------------------------------
def add_spi(self, data_width, clk_freq):
spi_pads = self.platform.request("spi")
self.submodules.spi = SPIMaster(spi_pads, data_width, self.clk_freq, clk_freq)
self.add_csr("spi")
# SPI DMA ----------------------------------------------------------------------------------
def add_spidma(self):
self.submodules.spi_dma = Wishbone2SPIDMA()
self.add_csr("spi_dma")
self.bus.add_master(self.spi_dma.bus)
Then called it from make.py
if "spidma" in board.soc_capabilities:
soc.add_spidma()
Finally, I got the error:
INFO:SoCCSRHandler:spi CSR allocated at Location 7.
INFO:SoCCSRHandler:spi_dma CSR allocated at Location 8.
Traceback (most recent call last):
File "./make.py", line 463, in <module>
main()
File "./make.py", line 416, in main
soc.add_spidma()
File "/home/phuong/Workspace/FPGA/LITEX/linux-on-litex-vexriscv/soc_linux.py", line 133, in add_spidma
self.bus.add_master(self.spi_dma.bus)
File "/home/phuong/Workspace/FPGA/LITEX/linux-on-litex-vexriscv/litex/litex/soc/integration/soc.py", line 307, in add_master
master = self.add_adapter(name, master)
File "/home/phuong/Workspace/FPGA/LITEX/linux-on-litex-vexriscv/litex/litex/soc/integration/soc.py", line 286, in add_adapter
if interface.data_width != self.data_width:
AttributeError: 'NoneType' object has no attribute 'data_width'
Please correct me if I'm wrong. Thanks
Sorry, there was a typo in the integration code, it's: self.bus.add_master(master=self.spi_dma.bus)
and not self.bus.add_master(self.spi_dma.bus)
.
Hi enjoy-digital,
After correcting the typo, I could compile the gateware successfully, but the DMA doesn't work. To check the SPI, I've tried first with normal mode:
void spidma_test(void)
{
unsigned int ctrl;
/* SPI loopback config */
spi_loopback_write(1);
/* data to write */
spi_mosi_write(0xA5);
/* CS assert */
spi_cs_write(1);
/* SPI start, length = 32bits */
ctrl = (8 << 8) | (1 << 0);
spi_control_write(ctrl);
while(!spi_status_read());
/* CS de-assert */
spi_cs_write(0);
printf("MISO read %X\r\n", spi_miso_read());
}
Just added spidma_test into the bios command line for quick testing, then it worked properly, I could capture the waveform from the logic analyzer.
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2020 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Jun 22 2020 22:34:16
BIOS CRC passed (789a0fec)
Migen git sha1: 19d5eae
LiteX git sha1: 56e1528
--=============== SoC ==================--
CPU: VexRiscv @ 100MHz
ROM: 32KB
SRAM: 4KB
L2: 8KB
MAIN-RAM: 262144KB
--========== Initialization ============--
Initializing SDRAM...
SDRAM now under software control
Read leveling:
m0, b0: |00000000000000000000000000000000| delays: -
m0, b1: |00000000000000000000000000000000| delays: -
m0, b2: |00000000000000000000000000000000| delays: -
m0, b3: |00000000000000000000000000000000| delays: -
m0, b4: |00000000000000000000000000000000| delays: -
m0, b5: |00000000000000000000000000000000| delays: -
m0, b6: |00111111111111110000000000000000| delays: 09+-06
m0, b7: |00000000000000000000000000000000| delays: -
best: m0, b6 delays: 09+-06
m1, b0: |00000000000000000000000000000000| delays: -
m1, b1: |00000000000000000000000000000000| delays: -
m1, b2: |00000000000000000000000000000000| delays: -
m1, b3: |00000000000000000000000000000000| delays: -
m1, b4: |00000000000000000000000000000000| delays: -
m1, b5: |00000000000000000000000000000000| delays: -
m1, b6: |00011111111111100000000000000000| delays: 09+-06
m1, b7: |00000000000000000000000000000000| delays: -
best: m1, b6 delays: 09+-06
SDRAM now under hardware control
Memtest OK
Memspeed Writes: 262Mbps Reads: 327Mbps
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
Timeout
No boot medium found
--============= Console ================--
litex> spidma
MISO read A5
For DMA mode, I've tried with the following code:
void spidma_test(void)
{
unsigned int *buffer = (unsigned int *)MAIN_RAM_BASE;
/* initialize buffer */
buffer[0] = 0xA5A5A5A5;
buffer[1] = 0x12345678;
buffer[2] = 0x87654321;
buffer[3] = 0x11223344;
/* SPI loopback config */
spi_loopback_write(1);
/* config frame length = 1 byte */
spi_control_write(8 << 8);
/* initialize spi dma */
spi_dma_spi_control_reg_address_write(CSR_SPI_CONTROL_ADDR);
spi_dma_spi_status_reg_address_write(CSR_SPI_STATUS_ADDR);
spi_dma_spi_mosi_reg_address_write(CSR_SPI_MOSI_ADDR);
/* setup dma transfer */
spi_dma_read_base_write(MAIN_RAM_BASE);
spi_dma_read_length_write(16);
/* CS assert */
spi_cs_write(1);
/* start dma transfer */
spi_dma_start_write(1);
spi_dma_start_write(0);
/* wait for dma done */
while(!spi_dma_done_read());
/* CS de-assert */
spi_cs_write(0);
printf("DMA done! MISO read %X\r\n", spi_miso_read());
}
I got the result:
--============= Console ================--
litex> spidma
DMA done! MISO read 0
litex> mr 0x40000000 16
Memory dump:
0x40000000 a5 a5 a5 a5 78 56 34 12 21 43 65 87 44 33 22 11 ....xV4.!Ce.D3".
litex>
There is no pulse on the analyzer display, csn pin didn't change. There are somethings wrong here.
The way you are controlling the module seems fine, there are others typos in the Wishbone2SPIDMA code:
spi_mosi_reg_address = self.spi_mosi_reg_address.storage
spi_control_reg_address = self.spi_control_reg_address.storage
spi_status_reg_address = self.spi_status_reg_address.storage
should be:
spi_mosi_reg_address = self.spi_mosi_reg_address.storage[2:]
spi_control_reg_address = self.spi_control_reg_address.storage[2:]
spi_status_reg_address = self.spi_status_reg_address.storage[2:]
Hi enjoy-digital,
Thanks for your help.
After adding [2:] the result was not changed.
I noticed there is a function in the csr.h like:
static inline void spi_control_write(uint16_t v) {
csr_write_simple(v >> 8, 0xf0003800L);
csr_write_simple(v, 0xf0003804L);
}
It seems that my system is big-endian, then I've tried to modify the control register accessing in the dma.py:
fsm.act("SPI-WRITE-START",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_control_reg_address),
bus.dat_w.eq(SPI_START),
If(bus.ack,
NextState("SPI-WAIT-DONE")
)
)
Changed to:
fsm.act("SPI-WRITE-START",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_control_reg_address + 4),
bus.dat_w.eq(SPI_START),
If(bus.ack,
NextState("SPI-WAIT-DONE")
)
)
However, it still doesn't work. I have a question, does the code statement above can access the register by word, half-word, or byte? Does it allow unaligned access?
Thanks
@kamejoko80: sorry i just realized for this work you will need to set csr_data_width
to 32 in your SoC, otherwise you won't be able write the SPI control register with a single access as you noticed. (so change csr_data_width
to 32 and use the [2:] change i was suggesting).
Hi enjoy-digital,
Thanks for pointing out my mistake,
To make the DMA copy whole bytes in the buffer I've modified a little bit:
from migen import *
from litex.soc.interconnect.csr import *
from litex.soc.interconnect import wishbone
SPI_START = ((8<<8) | (1<<0))
SPI_LENGTH = (1<<8)
SPI_DONE = (1<<0)
class Wishbone2SPIDMA(Module, AutoCSR):
def __init__(self):
# Wishbone
self.bus = bus = wishbone.Interface()
# Control
self.start = CSR()
self.done = CSRStatus()
# Read parameters: base and length of DMA
self.read_base = CSRStorage(32)
self.read_length = CSRStorage(32)
# SPI parameters: address of control/status/mosi registers
self.spi_control_reg_address = CSRStorage(32)
self.spi_status_reg_address = CSRStorage(32)
self.spi_mosi_reg_address = CSRStorage(32)
# # #
# Shorten CSR's names
start = self.start.re
done = self.done.status
read_base = self.read_base.storage[2:]
read_length = self.read_length.storage
spi_mosi_reg_address = self.spi_mosi_reg_address.storage[2:]
spi_control_reg_address = self.spi_control_reg_address.storage[2:]
spi_status_reg_address = self.spi_status_reg_address.storage[2:]
# internals
word_offset = Signal(32)
byte_offset = Signal(3)
byte_count = Signal(32)
data = Signal(32)
# fsm
self.submodules.fsm = fsm = FSM()
fsm.act("IDLE",
If(start,
NextValue(word_offset, 0),
NextValue(byte_offset, 0),
NextValue(byte_count, 0),
NextState("WISHBONE-READ-DATA")
).Else(
done.eq(1),
)
)
fsm.act("WISHBONE-READ-DATA",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.adr.eq(read_base + word_offset),
If(bus.ack,
NextValue(data, bus.dat_r),
NextState("SPI-WRITE-DATA")
)
)
fsm.act("SPI-WRITE-DATA",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_mosi_reg_address),
bus.dat_w.eq(data),
If(bus.ack,
NextState("SPI-WRITE-START")
)
)
fsm.act("SPI-WRITE-START",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_control_reg_address),
bus.dat_w.eq(SPI_START),
If(bus.ack,
NextState("SPI-WAIT-DONE")
)
)
fsm.act("SPI-WAIT-DONE",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.adr.eq(spi_status_reg_address),
If(bus.ack,
If(bus.dat_r & SPI_DONE,
NextValue(byte_count, byte_count + 1),
NextValue(byte_offset, byte_offset + 1),
NextState("SHIFT-BYTE")
)
)
)
fsm.act("SHIFT-BYTE",
If(byte_count >= read_length,
NextState("IDLE")
).Elif(byte_offset >= 4,
NextValue(byte_offset, 0),
NextState("INC-WORD-OFFSET")
).Else(
NextValue(data, data >> 8),
NextState("SPI-WRITE-DATA")
)
)
fsm.act("INC-WORD-OFFSET",
NextValue(word_offset, word_offset + 1),
NextState("WISHBONE-READ-DATA")
)
Also changed the firmware:
unsigned int *buffer = (unsigned int *)MAIN_RAM_BASE;
/* initialize buffer */
buffer[0] = 0xA5A5A5A5;
buffer[1] = 0x12345678;
buffer[2] = 0x87654321;
buffer[3] = 0x11223344;
/* SPI loopback config */
spi_loopback_write(1);
/* config frame length = 1 byte */
//spi_control_write(8 << 8);
/* initialize spi dma */
spi_dma_spi_control_reg_address_write(CSR_SPI_CONTROL_ADDR);
spi_dma_spi_status_reg_address_write(CSR_SPI_STATUS_ADDR);
spi_dma_spi_mosi_reg_address_write(CSR_SPI_MOSI_ADDR);
/* setup dma transfer */
spi_dma_read_base_write(MAIN_RAM_BASE);
spi_dma_read_length_write(16);
/* CS assert */
spi_cs_write(1);
/* start dma transfer */
spi_dma_start_write(1);
spi_dma_start_write(0);
/* wait for dma done */
while(!spi_dma_done_read());
/* CS de-assert */
spi_cs_write(0);
printf("DMA done! MISO read %X\r\n", spi_miso_read());
By checking on the logic analyzer's display I saw the bytes are shifted out perfectly. Next step I'll try to modify the dma.py to support the DMA RX part.
Thank you,
Hi @kamejoko80,
great you got it working! In case you release your project, feel free to share it with us, it would make a good example and we could add a link to it to the wiki.
Hi enjoy-digital,
Yes, I will do.
Thank you very much.
Hi enjoy-digital,
I've added DMA RX part and consolidated the source code, but I could not write the MISO register's contain to the DMA RX RAM buffer:
#!/usr/bin/env python3
from migen import *
from litex.soc.interconnect.csr import *
from litex.soc.interconnect import wishbone
SPI_START = ((8<<8) | (1<<0))
SPI_DONE = (1<<0)
class Wishbone2SPIDMA(Module, AutoCSR):
def __init__(self):
# Wishbone
self.bus = bus = wishbone.Interface()
# Control
self.start = CSR()
self.done = CSRStatus()
# Read parameters: tx source address and length of DMA
self.tx_src_addr = CSRStorage(32) # DMA TX source address
self.rx_dst_addr = CSRStorage(32) # DMA RX destination address
self.tx_len = CSRStorage(32) # DMA TX size (bytes)
self.rx_ena = CSRStorage(32) # DMA RX enable
# SPI parameters: address of control/status/mosi registers
self.spi_control_reg_address = CSRStorage(32)
self.spi_status_reg_address = CSRStorage(32)
self.spi_mosi_reg_address = CSRStorage(32)
self.spi_miso_reg_address = CSRStorage(32)
# DMA debug
self.debug0 = CSRStorage(32)
self.debug1 = CSRStorage(32)
self.debug2 = CSRStorage(32)
self.debug3 = CSRStorage(32)
# # #
# Shorten CSR's names
start = self.start.re
done = self.done.status
tx_src_addr = self.tx_src_addr.storage[2:]
rx_dst_addr = self.rx_dst_addr.storage[2:]
tx_len = self.tx_len.storage
rx_ena = self.rx_ena
spi_mosi_reg_address = self.spi_mosi_reg_address.storage[2:]
spi_miso_reg_address = self.spi_miso_reg_address.storage[2:]
spi_control_reg_address = self.spi_control_reg_address.storage[2:]
spi_status_reg_address = self.spi_status_reg_address.storage[2:]
# internals
word_offset = Signal(32)
byte_offset = Signal(3)
byte_count = Signal(32)
tx_data = Signal(32)
rx_data = Signal(32)
miso_data = Signal(32)
# fsm
self.submodules.fsm = fsm = FSM()
fsm.act("IDLE",
If(start,
NextValue(word_offset, 0),
NextValue(byte_offset, 0),
NextValue(byte_count, 0),
NextValue(rx_data, 0),
NextState("WISHBONE-READ-TX-DMA-BUFF")
).Else(
done.eq(1),
)
)
fsm.act("WISHBONE-READ-TX-DMA-BUFF",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.adr.eq(tx_src_addr + word_offset),
If(bus.ack,
NextValue(tx_data, bus.dat_r),
NextState("WISHBONE-WRITE-MOSI-REG")
)
)
fsm.act("WISHBONE-WRITE-MOSI-REG",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_mosi_reg_address),
bus.dat_w.eq(tx_data),
If(bus.ack,
NextState("WISHBONE-WRITE-CONTROL-START")
)
)
fsm.act("WISHBONE-WRITE-CONTROL-START",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(spi_control_reg_address),
bus.dat_w.eq(SPI_START),
If(bus.ack,
NextState("SPI-WAIT-DONE")
)
)
fsm.act("SPI-WAIT-DONE",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.adr.eq(spi_status_reg_address),
If(bus.ack,
If(bus.dat_r & SPI_DONE,
If(rx_ena == 0,
NextValue(byte_count, byte_count + 1),
NextValue(byte_offset, byte_offset + 1),
NextState("SHIFT-BYTE")
).Else(
NextValue(byte_count, byte_count + 1),
NextValue(byte_offset, byte_offset + 1),
NextState("WISHBONE-READ-MISO-REG")
)
)
)
)
fsm.act("WISHBONE-READ-MISO-REG",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.adr.eq(spi_miso_reg_address),
If(bus.ack,
NextValue(miso_data, bus.dat_r),
NextState("SHIFT-BYTE")
)
)
fsm.act("WISHBONE-WRITE-RX-DMA-BUFF-LAST",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(rx_dst_addr + word_offset),
bus.dat_w.eq(rx_data),
If(bus.ack,
NextState("IDLE")
)
)
fsm.act("WISHBONE-WRITE-RX-DMA-BUFF",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(rx_dst_addr + word_offset),
bus.dat_w.eq(rx_data),
If(bus.ack,
NextValue(rx_data, 0),
NextState("INC-WORD-OFFSET")
)
)
fsm.act("SHIFT-BYTE",
If(byte_count >= tx_len,
If(rx_ena == 0,
NextState("IDLE")
).Else(
NextValue(rx_data, (rx_data << 8) | miso_data[0:8]),
NextState("WISHBONE-WRITE-RX-DMA-BUFF-LAST")
)
).Elif(byte_offset >= 4,
If(rx_ena == 0,
NextValue(byte_offset, 0),
NextState("INC-WORD-OFFSET")
).Else(
NextValue(byte_offset, 0),
NextValue(rx_data, (rx_data << 8) | miso_data[0:8]),
NextState("WISHBONE-WRITE-RX-DMA-BUFF")
)
).Else(
NextValue(rx_data, (rx_data << 8) | miso_data[0:8]),
NextValue(tx_data, tx_data >> 8),
NextState("WISHBONE-WRITE-MOSI-REG")
)
)
fsm.act("INC-WORD-OFFSET",
NextValue(word_offset, word_offset + 1),
NextState("WISHBONE-READ-TX-DMA-BUFF")
)
I'm stuck at the following code statement that attempts to copy a word from rx_data to the destination RAM buffer @ rx_dst_addr + word_offset.
fsm.act("WISHBONE-WRITE-RX-DMA-BUFF-LAST",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(rx_dst_addr + word_offset),
bus.dat_w.eq(rx_data),
If(bus.ack,
NextState("IDLE")
)
)
fsm.act("WISHBONE-WRITE-RX-DMA-BUFF",
bus.stb.eq(1),
bus.cyc.eq(1),
bus.we.eq(1),
bus.adr.eq(rx_dst_addr + word_offset),
bus.dat_w.eq(rx_data),
If(bus.ack,
NextValue(rx_data, 0),
NextState("INC-WORD-OFFSET")
)
)
Instead of copy to RAM, I've temporarily declared 4 CSRStorage and passed the address to the rx_dst_addr register then I saw the results are correct.
# DMA debug
self.debug0 = CSRStorage(32)
self.debug1 = CSRStorage(32)
self.debug2 = CSRStorage(32)
self.debug3 = CSRStorage(32)
/* setup dma transfer */
spi_dma_tx_src_addr_write(MAIN_RAM_BASE);
//spi_dma_rx_dst_addr_write(MAIN_RAM_BASE + 16); /* DMA RX buffer's address */
spi_dma_rx_dst_addr_write(CSR_SPI_DMA_DEBUG0_ADDR); /* Write the results to the CSRs */
spi_dma_tx_len_write(16);
spi_dma_rx_ena_write(1);
...
#if 0
printf("rx_buff[0] %X\r\n", rx_buff[0]);
printf("rx_buff[1] %X\r\n", rx_buff[1]);
printf("rx_buff[2] %X\r\n", rx_buff[2]);
printf("rx_buff[3] %X\r\n", rx_buff[3]);
#else
printf("rx_buff[0] %X\r\n", spi_dma_debug0_read());
printf("rx_buff[1] %X\r\n", spi_dma_debug1_read());
printf("rx_buff[2] %X\r\n", spi_dma_debug2_read());
printf("rx_buff[3] %X\r\n", spi_dma_debug3_read());
#endif
I don't know why the above code statement could copy the data to the CSRStorages but it couldn't in cases of RAM buffer?
Thanks for your help.
Hello,
Maybe I know how to resolve the problem, just adding bus.sel.eq(0b1111) in case of memory writing and it works properly now.
Hey @kamejoko80, have you managed to make this work but with SDIO?
Hello,
I'd like to connect FPGA with the Silabs WF200 Wifi controller. From the IC spec, it basically requires SPI or SDIO bus interface. First of all, I want to try with SPI because it is simple, but I don't know how configure SPI with DMA to increase the performance. Is there any reference design including gateware and firmware to build a Vexrisc-V system with SPI and DMA?
Thank you.