diff --git a/litex/build/xilinx/common.py b/litex/build/xilinx/common.py index 2de19bac7..f16e3454a 100644 --- a/litex/build/xilinx/common.py +++ b/litex/build/xilinx/common.py @@ -159,9 +159,9 @@ class XilinxDDRTristateImpl(Module): _o = Signal() _oe_n = Signal() _i = Signal() - self.specials += DDROutput(i1, i2, _o) - self.specials += DDROutput(~oe1, ~oe2, _oe_n) - self.specials += DDRInput(_i, o1, o2) + self.specials += DDROutput(i1, i2, _o, clk) + self.specials += DDROutput(~oe1, ~oe2, _oe_n, clk) + self.specials += DDRInput(_i, o1, o2, clk) self.specials += Instance("IOBUF", io_IO = io, o_O = _i, diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 3205628e8..82626f7d7 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1491,7 +1491,7 @@ class LiteXSoC(SoC): self.platform.add_false_path_constraints(self.crg.cd_sys.clk, eth_rx_clk, eth_tx_clk) # Add SPI Flash -------------------------------------------------------------------------------- - def add_spi_flash(self, name="spiflash", mode="4x", dummy_cycles=None, clk_freq=None, module=None, **kwargs): + def add_spi_flash(self, name="spiflash", mode="4x", dummy_cycles=None, clk_freq=None, module=None, init=None, clock_domain="sys", **kwargs): if module is None: # Use previous LiteX SPI Flash core with compat, will be deprecated at some point. from litex.compat.soc_add_spi_flash import add_spi_flash @@ -1499,7 +1499,6 @@ class LiteXSoC(SoC): # LiteSPI. else: # Imports. - from litespi.phy.generic import LiteSPIPHY from litespi import LiteSPI from litespi.opcodes import SpiNorFlashOpCodes @@ -1511,14 +1510,24 @@ class LiteXSoC(SoC): self.check_if_exists(name + "_phy") self.check_if_exists(name + "_mmap") spiflash_pads = self.platform.request(name if mode == "1x" else name + mode) - spiflash_phy = LiteSPIPHY(spiflash_pads, module, device=self.platform.device, default_divisor=int(self.sys_clk_freq/clk_freq)) - spiflash_core = LiteSPI(spiflash_phy, clk_freq=clk_freq, mmap_endianness=self.cpu.endianness, **kwargs) + if init is None: + from litespi.phy.generic import LiteSPIPHY + if not hasattr(spiflash_pads, "clk") or self.platform.device.startswith("LFE5U") or self.platform.device.startswith("LAE5U"): + spiflash_phy = LiteSPIPHY(spiflash_pads, module, clock_domain=clock_domain, device=self.platform.device, default_divisor=int(self.sys_clk_freq/clk_freq), legacy=True) + self.add_constant("SPIFLASH_LEGACY") + else: + spiflash_phy = LiteSPIPHY(spiflash_pads, module, clock_domain=clock_domain, device=self.platform.device, legacy=False) + else: + from litespi.phy.model import LiteSPIPHYModel + spiflash_phy = LiteSPIPHYModel(module, init=init, clock_domain=clock_domain) + spiflash_core = LiteSPI(spiflash_phy, clock_domain=clock_domain, mmap_endianness=self.cpu.endianness, **kwargs) setattr(self.submodules, name + "_phy", spiflash_phy) setattr(self.submodules, name + "_core", spiflash_core) 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) # Constants. + self.add_constant("SPIFLASH_FREQUENCY", clk_freq) self.add_constant("SPIFLASH_MODULE_NAME", module.name.upper()) self.add_constant("SPIFLASH_MODULE_TOTAL_SIZE", module.total_size) self.add_constant("SPIFLASH_MODULE_PAGE_SIZE", module.page_size) diff --git a/litex/soc/software/liblitespi/spiflash.c b/litex/soc/software/liblitespi/spiflash.c index 26ea525aa..e19179cf1 100644 --- a/litex/soc/software/liblitespi/spiflash.c +++ b/litex/soc/software/liblitespi/spiflash.c @@ -13,10 +13,9 @@ #include "spiflash.h" -#if defined(CSR_SPIFLASH_PHY_BASE) && defined(CSR_SPIFLASH_CORE_BASE) +#if defined(CSR_SPIFLASH_CORE_BASE) -//#define SPIFLASH_DEBUG -//#define SPIFLASH_MODULE_DUMMY_BITS 8 +#if defined(SPIFLASH_LEGACY) int spiflash_freq_init(void) { @@ -30,7 +29,7 @@ int spiflash_freq_init(void) /* Check if block is erased (filled with 0xFF) */ if(crc == CRC32_ERASED_FLASH) { - printf("First SPI Flash block erased, unable to perform freq test.\n\r"); + printf("Block of size %d, started on address 0x%lx is erased. Cannot proceed with SPI Flash frequency test.\n\r", SPI_FLASH_BLOCK_SIZE, SPIFLASH_BASE); return -1; } @@ -42,18 +41,41 @@ int spiflash_freq_init(void) #endif } lowest_div++; - printf("SPI Flash clk configured to %d MHz\n", (spiflash_core_sys_clk_freq_read()/(2*(1 + lowest_div)))/1000000); + printf("SPI Flash clk configured to %d MHz\n", (spiflash_frequency_read()/(2*(1 + lowest_div)))/1000000); spiflash_phy_clk_divisor_write(lowest_div); return 0; } +#else + +int spiflash_freq_init(void) +{ + unsigned int crc = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE); + unsigned int crc_test = crc; + +#if SPIFLASH_DEBUG + printf("Testing against CRC32: %08x\n\r", crc); +#endif + + /* Check if block is erased (filled with 0xFF) */ + if(crc == CRC32_ERASED_FLASH) { + printf("First SPI Flash block erased, unable to perform freq test.\n\r"); + return -1; + } + + printf("SPI Flash clk configured to %ld MHz\n", (unsigned long)(spiflash_frequency_read()/1e6)); + return 0; +} + +#endif // SPIFLASH_LEGACY + void spiflash_dummy_bits_setup(unsigned int dummy_bits) { - spiflash_phy_dummy_bits_write((uint32_t)dummy_bits); + spiflash_core_mmap_dummy_bits_write((uint32_t)dummy_bits); #if SPIFLASH_DEBUG - printf("Dummy bits set to: %d\n\r", spi_dummy_bits_read()); + printf("Dummy bits set to: %d\n\r", spiflash_core_mmap_dummy_bits_read()); #endif } @@ -111,8 +133,6 @@ void spiflash_init(void) #ifndef SPIFLASH_SKIP_FREQ_INIT /* Clk frequency auto-calibration. */ spiflash_freq_init(); -#else - printf("Warning: SPI Flash frequency auto-calibration skipped, using the default divisor of %d\n", spiflash_phy_clk_divisor_read()); #endif memspeed((unsigned int *) SPIFLASH_BASE, SPIFLASH_SIZE/16, 1, 0); diff --git a/litex/tools/litex_sim.py b/litex/tools/litex_sim.py index 8822ccd51..6a6815433 100755 --- a/litex/tools/litex_sim.py +++ b/litex/tools/litex_sim.py @@ -74,6 +74,19 @@ _io = [ Subsignal("sda_out", Pins(1)), Subsignal("sda_in", Pins(1)), ), + ("spiflash", 0, + Subsignal("cs_n", Pins(1)), + Subsignal("clk", Pins(1)), + Subsignal("mosi", Pins(1)), + Subsignal("miso", Pins(1)), + Subsignal("wp", Pins(1)), + Subsignal("hold", Pins(1)), + ), + ("spiflash4x", 0, + Subsignal("cs_n", Pins(1)), + Subsignal("clk", Pins(1)), + Subsignal("dq", Pins(4)), + ), ] # Platform ----------------------------------------------------------------------------------------- @@ -85,6 +98,9 @@ class Platform(SimPlatform): # Simulation SoC ----------------------------------------------------------------------------------- class SimSoC(SoCCore): + mem_map = { + "spiflash" : 0x80000000, + } def __init__(self, with_sdram = False, with_ethernet = False, @@ -99,6 +115,8 @@ class SimSoC(SoCCore): sdram_verbosity = 0, with_i2c = False, with_sdcard = False, + with_spi_flash = False, + flash_init = [], sim_debug = False, trace_reset_on = False, **kwargs): @@ -232,6 +250,15 @@ class SimSoC(SoCCore): if with_sdcard: self.add_sdcard("sdcard", use_emulator=True) + # SPI Flash -------------------------------------------------------------------------------- + if with_spi_flash: + from litespi.modules import S25FL128L + from litespi.opcodes import SpiNorFlashOpCodes as Codes + if flash_init is None: + platform.add_sources(os.path.abspath(os.path.dirname(__file__)), "../build/sim/verilog/iddr_verilog.v") + platform.add_sources(os.path.abspath(os.path.dirname(__file__)), "../build/sim/verilog/oddr_verilog.v") + self.add_spi_flash(mode="4x", module=S25FL128L(Codes.READ_1_1_4), with_master=True, init=flash_init) + # Simulation debugging ---------------------------------------------------------------------- if sim_debug: platform.add_debug(self, reset=1 if trace_reset_on else 0) @@ -295,6 +322,8 @@ def sim_args(parser): parser.add_argument("--with-analyzer", action="store_true", help="Enable Analyzer support") parser.add_argument("--with-i2c", action="store_true", help="Enable I2C support") parser.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support") + parser.add_argument("--with-spi-flash", action="store_true", help="Enable SPI Flash (MMAPed)") + parser.add_argument("--flash-init", default=None, help="Flash init file") parser.add_argument("--trace", action="store_true", help="Enable Tracing") parser.add_argument("--trace-fst", action="store_true", help="Enable FST tracing (default=VCD)") parser.add_argument("--trace-start", default="0", help="Time to start tracing (ps)") @@ -361,9 +390,11 @@ def main(): with_analyzer = args.with_analyzer, with_i2c = args.with_i2c, with_sdcard = args.with_sdcard, + with_spi_flash = args.with_spi_flash, sim_debug = args.sim_debug, trace_reset_on = trace_start > 0 or trace_end > 0, sdram_init = [] if args.sdram_init is None else get_mem_data(args.sdram_init, cpu.endianness), + flash_init = None if args.flash_init is None else get_mem_data(args.flash_init, "big"), **soc_kwargs) if args.ram_init is not None or args.sdram_init is not None: soc.add_constant("ROM_BOOT_ADDRESS", soc.mem_map["main_ram"])