Merge pull request #2028 from VOGL-electronic/spi_ram_add
soc: add add_spi_ram function
This commit is contained in:
commit
6623a5b691
|
@ -27,12 +27,13 @@ class OpenOCD(GenericProgrammer):
|
||||||
])
|
])
|
||||||
self.call(["openocd", "-f", config, "-c", script])
|
self.call(["openocd", "-f", config, "-c", script])
|
||||||
|
|
||||||
def flash(self, address, data, set_qe=False):
|
def flash(self, address, data, set_qe=False, init_commands=[]):
|
||||||
config = self.find_config()
|
config = self.find_config()
|
||||||
flash_proxy = self.find_flash_proxy()
|
flash_proxy = self.find_flash_proxy()
|
||||||
script = "; ".join([
|
script = "; ".join([
|
||||||
"init",
|
"init",
|
||||||
"jtagspi_init 0 {{{}}}".format(flash_proxy),
|
"jtagspi_init 0 {{{}}}".format(flash_proxy)
|
||||||
|
] + init_commands + [
|
||||||
"jtagspi set_qe 0 1" if set_qe else "",
|
"jtagspi set_qe 0 1" if set_qe else "",
|
||||||
"jtagspi_program {{{}}} 0x{:x}".format(data, address),
|
"jtagspi_program {{{}}} 0x{:x}".format(data, address),
|
||||||
"fpga_program",
|
"fpga_program",
|
||||||
|
|
|
@ -2092,6 +2092,72 @@ class LiteXSoC(SoC):
|
||||||
self.add_module(name=f"{name}_core", module=spiflash_core)
|
self.add_module(name=f"{name}_core", module=spiflash_core)
|
||||||
spiflash_region = SoCRegion(origin=self.mem_map.get(name, None), size=module.total_size)
|
spiflash_region = SoCRegion(origin=self.mem_map.get(name, None), size=module.total_size)
|
||||||
self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region)
|
self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region)
|
||||||
|
self.comb += spiflash_core.mmap.offset.eq(self.bus.regions.get(name, None).origin)
|
||||||
|
|
||||||
|
# Constants.
|
||||||
|
self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq)
|
||||||
|
self.add_constant(f"{name}_MODULE_NAME", module.name)
|
||||||
|
self.add_constant(f"{name}_MODULE_TOTAL_SIZE", module.total_size)
|
||||||
|
self.add_constant(f"{name}_MODULE_PAGE_SIZE", module.page_size)
|
||||||
|
if mode in [ "4x" ]:
|
||||||
|
if SpiNorFlashOpCodes.READ_1_1_4 in module.supported_opcodes:
|
||||||
|
self.add_constant(f"{name}_MODULE_QUAD_CAPABLE")
|
||||||
|
if SpiNorFlashOpCodes.READ_4_4_4 in module.supported_opcodes:
|
||||||
|
self.add_constant(f"{name}_MODULE_QPI_CAPABLE")
|
||||||
|
if software_debug:
|
||||||
|
self.add_constant(f"{name}_DEBUG")
|
||||||
|
|
||||||
|
# Add SPI RAM --------------------------------------------------------------------------------
|
||||||
|
def add_spi_ram(self, name="spiram", mode="4x", clk_freq=20e6, module=None, phy=None, rate="1:1", software_debug=False,
|
||||||
|
l2_cache_size = 8192,
|
||||||
|
l2_cache_reverse = False,
|
||||||
|
l2_cache_full_memory_we = True,
|
||||||
|
**kwargs):
|
||||||
|
# Imports.
|
||||||
|
from litespi import LiteSPI
|
||||||
|
from litespi.phy.generic import LiteSPIPHY
|
||||||
|
from litespi.opcodes import SpiNorFlashOpCodes
|
||||||
|
|
||||||
|
# Checks/Parameters.
|
||||||
|
assert mode in ["1x", "4x"]
|
||||||
|
default_divisor = math.ceil(self.sys_clk_freq/(2*clk_freq)) - 1
|
||||||
|
clk_freq = int(self.sys_clk_freq/(2*(default_divisor + 1)))
|
||||||
|
|
||||||
|
# PHY.
|
||||||
|
spiram_phy = phy
|
||||||
|
if spiram_phy is None:
|
||||||
|
self.check_if_exists(f"{name}_phy")
|
||||||
|
spiram_pads = self.platform.request(name if mode == "1x" else name + mode)
|
||||||
|
spiram_phy = LiteSPIPHY(spiram_pads, module, device=self.platform.device, default_divisor=default_divisor, rate=rate)
|
||||||
|
self.add_module(name=f"{name}_phy", module=spiram_phy)
|
||||||
|
|
||||||
|
# Core.
|
||||||
|
self.check_if_exists(f"{name}_mmap")
|
||||||
|
spiram_core = LiteSPI(spiram_phy, mmap_endianness=self.cpu.endianness, with_mmap_write=True, **kwargs)
|
||||||
|
self.add_module(name=f"{name}_core", module=spiram_core)
|
||||||
|
spiram_region = SoCRegion(origin=self.mem_map.get(name, None), size=module.total_size)
|
||||||
|
|
||||||
|
# Create Wishbone Slave.
|
||||||
|
wb_spiram = wishbone.Interface(data_width=32, address_width=32, addressing="word")
|
||||||
|
self.bus.add_slave(name=name, slave=wb_spiram, region=spiram_region)
|
||||||
|
self.comb += spiram_core.mmap.offset.eq(self.bus.regions.get(name, None).origin)
|
||||||
|
|
||||||
|
# L2 Cache
|
||||||
|
if l2_cache_size != 0:
|
||||||
|
# Insert L2 cache inbetween Wishbone bus and LiteSPI
|
||||||
|
l2_cache_size = max(l2_cache_size, int(2*32/8)) # Use minimal size if lower
|
||||||
|
l2_cache_size = 2**int(log2(l2_cache_size)) # Round to nearest power of 2
|
||||||
|
l2_cache = wishbone.Cache(
|
||||||
|
cachesize = l2_cache_size//4,
|
||||||
|
master = wb_spiram,
|
||||||
|
slave = spiram_core.bus,
|
||||||
|
reverse = l2_cache_reverse)
|
||||||
|
if l2_cache_full_memory_we:
|
||||||
|
l2_cache = FullMemoryWE()(l2_cache)
|
||||||
|
self.l2_cache = l2_cache
|
||||||
|
self.add_config("L2_SIZE", l2_cache_size)
|
||||||
|
else:
|
||||||
|
self.submodules += wishbone.Converter(wb_spiram, spiram_core.bus)
|
||||||
|
|
||||||
# Constants.
|
# Constants.
|
||||||
self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq)
|
self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq)
|
||||||
|
|
|
@ -18,18 +18,24 @@ extern unsigned int _ftext, _edata_rom;
|
||||||
#define NUMBER_OF_BYTES_ON_A_LINE 16
|
#define NUMBER_OF_BYTES_ON_A_LINE 16
|
||||||
void dump_bytes(unsigned int *ptr, int count, unsigned long addr)
|
void dump_bytes(unsigned int *ptr, int count, unsigned long addr)
|
||||||
{
|
{
|
||||||
char *data = (char *)ptr;
|
uint32_t *dptr = (uint32_t *)ptr;
|
||||||
|
char data[NUMBER_OF_BYTES_ON_A_LINE];
|
||||||
int line_bytes = 0, i = 0;
|
int line_bytes = 0, i = 0;
|
||||||
|
|
||||||
|
|
||||||
fputs("Memory dump:", stdout);
|
fputs("Memory dump:", stdout);
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
line_bytes =
|
line_bytes =
|
||||||
(count > NUMBER_OF_BYTES_ON_A_LINE)?
|
(count > NUMBER_OF_BYTES_ON_A_LINE)?
|
||||||
NUMBER_OF_BYTES_ON_A_LINE : count;
|
NUMBER_OF_BYTES_ON_A_LINE : count;
|
||||||
|
for (i = 0; i < line_bytes; i+=4){
|
||||||
|
*((uint32_t*)&data[i]) = *(dptr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
printf("\n0x%08lx ", addr);
|
printf("\n0x%08lx ", addr);
|
||||||
for (i = 0; i < line_bytes; i++)
|
for (i = 0; i < line_bytes; i++)
|
||||||
printf("%02x ", *(unsigned char *)(data+i));
|
printf("%02x ", (unsigned char)data[i]);
|
||||||
|
|
||||||
for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++)
|
for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++)
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
@ -37,16 +43,15 @@ void dump_bytes(unsigned int *ptr, int count, unsigned long addr)
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
|
||||||
for (i = 0; i<line_bytes; i++) {
|
for (i = 0; i<line_bytes; i++) {
|
||||||
if ((*(data+i) < 0x20) || (*(data+i) > 0x7e))
|
if ((data[i] < 0x20) || (data[i] > 0x7e))
|
||||||
printf(".");
|
printf(".");
|
||||||
else
|
else
|
||||||
printf("%c", *(data+i));
|
printf("%c", data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++)
|
for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++)
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
|
||||||
data += (char)line_bytes;
|
|
||||||
count -= line_bytes;
|
count -= line_bytes;
|
||||||
addr += line_bytes;
|
addr += line_bytes;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue