From 0c91bb7b96400bc60d5845494bc399b9cdf2a1b4 Mon Sep 17 00:00:00 2001 From: Pawel Sagan Date: Wed, 1 Sep 2021 10:19:12 +0200 Subject: [PATCH 1/5] litex_sim: adding spi-flash option to simulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Sagan --- litex/tools/litex_sim.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/litex/tools/litex_sim.py b/litex/tools/litex_sim.py index b1ab167c5..b08b77efc 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,7 @@ class SimSoC(SoCCore): sdram_verbosity = 0, with_i2c = False, with_sdcard = False, + with_spi_flash = False, sim_debug = False, trace_reset_on = False, **kwargs): @@ -232,6 +249,14 @@ 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 + 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) + # Simulation debugging ---------------------------------------------------------------------- if sim_debug: platform.add_debug(self, reset=1 if trace_reset_on else 0) @@ -295,6 +320,7 @@ 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("--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)") @@ -354,6 +380,7 @@ 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), From 837de615e6bd4ae3105472f3ee6c1feca02a78f2 Mon Sep 17 00:00:00 2001 From: Pawel Sagan Date: Tue, 31 Aug 2021 16:39:34 +0200 Subject: [PATCH 2/5] =?UTF-8?q?liblitespi:=20adjusting=20code=20to=20oddr/?= =?UTF-8?q?iddr=20litespi=20implementation=20Changing=20litespi=20register?= =?UTF-8?q?s=20configuration=20to=20be=20compatible=20with=20a=20new=20imp?= =?UTF-8?q?lementation.=20Signed-off-by:=20Pawe=C5=82=20Sagan=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- litex/soc/integration/soc.py | 13 +++++++++---- litex/soc/software/liblitespi/spiflash.c | 23 ++++------------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 3205628e8..a73e21be1 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,20 @@ 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 + spiflash_phy = LiteSPIPHY(spiflash_pads, module, clock_domain=clock_domain, device=self.platform.device,) + 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..80ea8f752 100644 --- a/litex/soc/software/liblitespi/spiflash.c +++ b/litex/soc/software/liblitespi/spiflash.c @@ -13,14 +13,13 @@ #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 int spiflash_freq_init(void) { - unsigned int lowest_div = spiflash_phy_clk_divisor_read(); unsigned int crc = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE); unsigned int crc_test = crc; @@ -34,26 +33,14 @@ int spiflash_freq_init(void) return -1; } - while((crc == crc_test) && (lowest_div-- > 0)) { - spiflash_phy_clk_divisor_write((uint32_t)lowest_div); - crc_test = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE); -#if SPIFLASH_DEBUG - printf("[DIV: %d] %08x\n\r", lowest_div, crc_test); -#endif - } - lowest_div++; - printf("SPI Flash clk configured to %d MHz\n", (spiflash_core_sys_clk_freq_read()/(2*(1 + lowest_div)))/1000000); - - spiflash_phy_clk_divisor_write(lowest_div); - + printf("SPI Flash clk configured to %ld MHz\n", (unsigned long)(spiflash_frequency_read()/1e6)); return 0; } - 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 +98,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); From 25e0153dd5556233a3d8fa854f5da6b840b1b5d3 Mon Sep 17 00:00:00 2001 From: Piotr Binkowski Date: Fri, 27 Aug 2021 16:38:43 +0200 Subject: [PATCH 3/5] litex_sim: use flash model in simulation --- litex/tools/litex_sim.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/litex/tools/litex_sim.py b/litex/tools/litex_sim.py index b08b77efc..0568e211f 100755 --- a/litex/tools/litex_sim.py +++ b/litex/tools/litex_sim.py @@ -116,6 +116,7 @@ class SimSoC(SoCCore): with_i2c = False, with_sdcard = False, with_spi_flash = False, + flash_init = [], sim_debug = False, trace_reset_on = False, **kwargs): @@ -253,9 +254,10 @@ class SimSoC(SoCCore): if with_spi_flash: from litespi.modules import S25FL128L from litespi.opcodes import SpiNorFlashOpCodes as Codes - 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) + 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: @@ -321,6 +323,7 @@ def sim_args(parser): 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)") @@ -384,6 +387,7 @@ def main(): 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"]) From 3cf612666383522dce1fd3a9fccdbe281baec82a Mon Sep 17 00:00:00 2001 From: Pawel Sagan Date: Wed, 1 Sep 2021 16:54:53 +0200 Subject: [PATCH 4/5] litex: adding explicit clk signal to ODDR/IDDR models in DDRTristate --- litex/build/xilinx/common.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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, From ad0fcc22e602891ec5eeae67ecc94a8fc170fa2c Mon Sep 17 00:00:00 2001 From: Pawel Sagan Date: Thu, 2 Sep 2021 17:38:17 +0200 Subject: [PATCH 5/5] litex: adding legacy mode for litespi Inside the litex add_spi_flash function we are detecting the devices that can't be used with more efficient DDR version of litespi phy core and we are choosing whether to instantiate the legacy or DDR core --- litex/soc/integration/soc.py | 6 +++- litex/soc/software/liblitespi/spiflash.c | 39 ++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index a73e21be1..82626f7d7 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1512,7 +1512,11 @@ class LiteXSoC(SoC): spiflash_pads = self.platform.request(name if mode == "1x" else name + mode) if init is None: from litespi.phy.generic import LiteSPIPHY - spiflash_phy = LiteSPIPHY(spiflash_pads, module, clock_domain=clock_domain, device=self.platform.device,) + 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) diff --git a/litex/soc/software/liblitespi/spiflash.c b/litex/soc/software/liblitespi/spiflash.c index 80ea8f752..e19179cf1 100644 --- a/litex/soc/software/liblitespi/spiflash.c +++ b/litex/soc/software/liblitespi/spiflash.c @@ -15,8 +15,40 @@ #if defined(CSR_SPIFLASH_CORE_BASE) -//#define SPIFLASH_DEBUG -//#define SPIFLASH_MODULE_DUMMY_BITS 8 +#if defined(SPIFLASH_LEGACY) + +int spiflash_freq_init(void) +{ + unsigned int lowest_div = spiflash_phy_clk_divisor_read(); + 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("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; + } + + while((crc == crc_test) && (lowest_div-- > 0)) { + spiflash_phy_clk_divisor_write((uint32_t)lowest_div); + crc_test = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE); +#if SPIFLASH_DEBUG + printf("[DIV: %d] %08x\n\r", lowest_div, crc_test); +#endif + } + lowest_div++; + 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) { @@ -36,6 +68,9 @@ int spiflash_freq_init(void) 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_core_mmap_dummy_bits_write((uint32_t)dummy_bits);