diff --git a/CHANGES.md b/CHANGES.md
index b537e2812..f672c3d10 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,33 @@
-[> Changes since 2023.08
+[> Changes since 2023.12
------------------------
+ [> Fixed
+ --------
+ - integration/soc : Fixed typo in cpu mem_bus axi-via-wb downconvert
+ - interconnect/ahb/AHB2Wishbone : Fixed size check that was too restrictive.
+ - liteeth/phy/gw5rgmii : Fixed Clk assignments.
+ - build/efinix/programmer : Updated for compatibility with latest Efinity versions.
+ - litespi/software: : Fixed SPI Flash Clk Divider computation when with L2 Cache.
+ - litepcie/us(p)pciephy : Fixed x8 / 256-bit wide case.
+
+ [> Added
+ --------
+ - build/openfpgaloader : Added kwargs support to flash for specific/less common cases.
+ - cpu/gowin_emcu : Improved/Cleaned-up.
+ - interconnect/ahb : Added data_width/address_width parameters.
+ - interconnect/ahb : Added proper byte/sel support to AHB2Wishbone.
+ - cpu/gowin_ae350 : Added initial support.
+ - cpu/naxriscv : Updated arch definition and added rvc configuration parameters.
+ - cpu/vexriscv_smp : Added csr/clint/plic base address configuration parameters.
+ - liteeth/phy : Added 7-Series/Ultrascale(+) 2500BaseX PHYs.
+ - litespi/sdrphy: : Allowed flash parameter to be None.
+ - litespi/integration : Improved integration and simplifications.
+ - export/builder : Add import/merge of Sub-SoCs .json files.
+
+ [> Changed
+ ----------
+
+[> 2023.12, released on December 25th 2023
+------------------------------------------
[> Fixed
--------
- liteeth/arp : Fixed response on table update.
@@ -30,16 +58,20 @@
- litepcie : Simplify/Cleanup Ultrascale(+) integration and allow .xci generation from .tcl.
- litepcie : Initial 64-bit DMA suppport.
- bios : Added bios_format / --bios-format to allow enabling float/double printf.
- - soc/cores/clock : Added proper clock feedback support on Efinix TRIONPLL.
+ - soc/cores/clock : Added proper clock feedback support on Efinix TRIONPLL/TITANIUMPLL.
- liteiclink/phy : Added Efinix support/examples on Trion/Titanium.
- liteiclink/serwb : Reused Etherbone from LiteEth to avoid code duplication.
- interconnect : Added 64-bit support to Wishbone/AXI-Lite/AXI.
- jtag : Fixed firmware upload over JTAG-UART.
- jtag : Improved speed (~X16) on JTABone/JTAGUART on all supported devices (Xilinx, Altera, Efinix, etc...)
+ - litesata/phy : Added GTHE4 support on Ultrascale+.
+ - litex_boards : Added Machdyne's Mozart with the Sechzig ML1 module support.
+ - liteiclink : Added clk_ratio of 1:2, 1:4 on Efinix/SerWB to make clocking more flexible.
[> Changed
----------
- - build/osfpga: Removed initial support (would need feedbacks/updates).
+ - build/osfpga : Removed initial support (would need feedbacks/updates).
+ - python3 : Updated minimum python3 version to 3.7 (To allow more than 255 arguments in functions).
[> 2023.08, released on September 14th 2023
-------------------------------------------
diff --git a/README.md b/README.md
index 721021380..becbbe4de 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
```
- Copyright 2012-2023 / Enjoy-Digital & LiteX developers
+ Copyright 2012-2024 / Enjoy-Digital & LiteX developers
```
[![](https://github.com/enjoy-digital/litex/workflows/ci/badge.svg)](https://github.com/enjoy-digital/litex/actions)
![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)
diff --git a/litex/build/efinix/efinity.py b/litex/build/efinix/efinity.py
index 04f6df610..2e0b79963 100644
--- a/litex/build/efinix/efinity.py
+++ b/litex/build/efinix/efinity.py
@@ -361,8 +361,19 @@ class EfinityToolchain(GenericToolchain):
"--io_weak_pullup", "on",
"--enable_roms", "on",
"--mode", self.platform.spi_mode,
- "--width", "1",
+ "--width", self.platform.spi_width,
"--enable_crc_check", "on"
], common.colors)
if r != 0:
raise OSError("Error occurred during efx_pgm execution.")
+
+ # BINARY
+ os.environ['EFXPGM_HOME'] = self.efinity_path + "/pgm"
+ r = tools.subprocess_call_filtered([self.efinity_path + "/bin/python3",
+ self.efinity_path + "/pgm/bin/efx_pgm/export_bitstream.py",
+ "hex_to_bin",
+ f"{self._build_name}.hex",
+ f"{self._build_name}.bin"
+ ], common.colors)
+ if r != 0:
+ raise OSError("Error occurred during export_bitstream execution.")
diff --git a/litex/build/efinix/ifacewriter.py b/litex/build/efinix/ifacewriter.py
index be480cb26..5ec2a3b88 100644
--- a/litex/build/efinix/ifacewriter.py
+++ b/litex/build/efinix/ifacewriter.py
@@ -281,15 +281,9 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
if block["version"] == "V3":
cmd += 'design.gen_pll_ref_clock("{}", pll_res="{}", refclk_src="EXTERNAL", refclk_name="{}", ext_refclk_no="{}", ext_refclk_type="LVDS_RX")\n\n' \
.format(name, block["resource"], block["input_clock_pad"], block["clock_no"])
- cmd += 'design.set_property("{}","FEEDBACK_MODE","CORE","PLL")\n\n'.format(name)
else:
cmd += 'design.set_property("{}","EXT_CLK","EXT_CLK{}","PLL")\n'.format(name, block["clock_no"])
- if block["feedback"] != -1:
- cmd += 'design.set_property("{}","FEEDBACK_MODE","{}","PLL")\n'.format(name, "CORE" if block["feedback"] == 0 else "LOCAL")
- cmd += 'design.set_property("{}","FEEDBACK_CLK","CLK{}","PLL")\n'.format(name, block["feedback"])
- else:
- cmd += 'design.set_property("{}","FEEDBACK_MODE","INTERNAL","PLL")\n'.format(name)
cmd += 'design.assign_resource("{}","{}","PLL")\n'.format(name, block["resource"])
@@ -329,7 +323,14 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
else:
cmd += 'design.set_property("{}","CLKOUT{}_PHASE_SETTING","{}","PLL")\n'.format(name, i, clock[2] // 45)
- if block["feedback"] == -1:
+ # Titanium has always a feedback (local: CLK0, CORE: any output)
+ if block["version"] == "V3":
+ feedback_clk = block["feedback"]
+ cmd += 'design.set_property("{}", "FEEDBACK_MODE", "{}", "PLL")\n'.format(name, "LOCAL" if feedback_clk < 1 else "CORE")
+ cmd += 'design.set_property("{}", "FEEDBACK_CLK", "CLK{}", "PLL")\n'.format(name, 0 if feedback_clk < 1 else feedback_clk)
+
+ # auto_calc_pll_clock is always working with Titanium and only working when feedback is unused for Trion
+ if block["feedback"] == -1 or block["version"] == "V3":
cmd += "target_freq = {\n"
for i, clock in enumerate(block["clk_out"]):
cmd += ' "CLKOUT{}_FREQ": "{}",\n'.format(i, clock[1] / 1e6)
@@ -338,6 +339,9 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
cmd += ' "CLKOUT{}_DYNPHASE_EN": "1",\n'.format(i)
cmd += "}\n"
+ if block["version"] == "V1_V2":
+ cmd += 'design.set_property("{}","FEEDBACK_MODE","INTERNAL","PLL")\n'.format(name)
+
cmd += 'calc_result = design.auto_calc_pll_clock("{}", target_freq)\n'.format(name)
cmd += 'for c in calc_result:\n'
cmd += ' print(c)\n'
@@ -349,6 +353,8 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
cmd += 'design.set_property("{}","CLKOUT{}_PHASE","{}","PLL")\n'.format(name, i, clock[2])
#cmd += 'design.set_property("{}","CLKOUT{}_FREQ","{}","PLL")\n'.format(name, i, clock[2])
cmd += 'design.set_property("{}","CLKOUT{}_DIV","{}","PLL")\n'.format(name, i, block[f"CLKOUT{i}_DIV"])
+ cmd += 'design.set_property("{}","FEEDBACK_MODE","{}","PLL")\n'.format(name, "LOCAL" if block["feedback"] == 0 else "CORE")
+ cmd += 'design.set_property("{}","FEEDBACK_CLK","CLK{}","PLL")\n'.format(name, block["feedback"])
if "extra" in block:
cmd += block["extra"]
@@ -358,17 +364,19 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
cmd += 'print("#### {} ####")\n'.format(name)
cmd += 'clksrc_info = design.trace_ref_clock("{}", block_type="PLL")\n'.format(name)
cmd += 'pprint.pprint(clksrc_info)\n'
- cmd += 'clock_source_prop = ["REFCLK_SOURCE", "CORE_CLK_PIN", "EXT_CLK", "REFCLK_FREQ", "RESOURCE"]\n'
+ cmd += 'clock_source_prop = ["REFCLK_SOURCE", "CORE_CLK_PIN", "EXT_CLK", "REFCLK_FREQ", "RESOURCE", "FEEDBACK_MODE", "FEEDBACK_CLK"]\n'
for i, clock in enumerate(block["clk_out"]):
cmd += 'clock_source_prop += ["CLKOUT{}_FREQ", "CLKOUT{}_PHASE", "CLKOUT{}_EN"]\n'.format(i, i, i)
cmd += 'prop_map = design.get_property("{}", clock_source_prop, block_type="PLL")\n'.format(name)
cmd += 'pprint.pprint(prop_map)\n'
- for i, clock in enumerate(block["clk_out"]):
- cmd += '\nfreq = float(prop_map["CLKOUT{}_FREQ"])\n'.format(i)
- cmd += 'if freq != {}:\n'.format(clock[1]/1e6)
- cmd += ' print("ERROR: CLKOUT{} configured for {}MHz is {{}}MHz".format(freq))\n'.format(i, clock[1]/1e6)
- cmd += ' exit("PLL ERROR")\n'
+ # Efinix python API is buggy for Trion devices when a feedback is defined...
+ if block["version"] == "V3" or (block["version"] == "V1_V2" and block["feedback"] == -1):
+ for i, clock in enumerate(block["clk_out"]):
+ cmd += '\nfreq = float(prop_map["CLKOUT{}_FREQ"])\n'.format(i)
+ cmd += 'if freq != {}:\n'.format(clock[1]/1e6)
+ cmd += ' print("ERROR: CLKOUT{} configured for {}MHz is {{}}MHz".format(freq))\n'.format(i, clock[1]/1e6)
+ cmd += ' exit("PLL ERROR")\n'
cmd += "\n#---------- END PLL {} ---------\n\n".format(name)
return cmd
diff --git a/litex/build/efinix/platform.py b/litex/build/efinix/platform.py
index 1dc76fb90..52d1fc4cc 100644
--- a/litex/build/efinix/platform.py
+++ b/litex/build/efinix/platform.py
@@ -23,13 +23,14 @@ class EfinixPlatform(GenericPlatform):
_supported_toolchains = ["efinity"]
- def __init__(self, *args, iobank_info=None, toolchain="efinity", spi_mode="active", **kwargs):
+ def __init__(self, *args, iobank_info=None, toolchain="efinity", spi_mode="active", spi_width="1", **kwargs):
GenericPlatform.__init__(self, *args, **kwargs)
self.timing_model = self.device[-2:]
self.device = self.device[:-2]
self.iobank_info = iobank_info
self.spi_mode = spi_mode
+ self.spi_width = spi_width
if self.device[:2] == "Ti":
self.family = "Titanium"
else:
diff --git a/litex/build/efinix/programmer.py b/litex/build/efinix/programmer.py
index 1b91863b4..1c42a0c9f 100644
--- a/litex/build/efinix/programmer.py
+++ b/litex/build/efinix/programmer.py
@@ -28,7 +28,8 @@ class EfinixProgrammer(GenericProgrammer):
os.environ["EFINITY_HOME"] = self.efinity_path
def load_bitstream(self, bitstream_file, cable_suffix=""):
- os.environ['EFXPGM_HOME'] = self.efinity_path + '/pgm'
+ os.environ['EFXPGM_HOME'] = self.efinity_path + "/pgm"
+ os.environ["EFXDBG_HOME"] = self.efinity_path + "/debugger"
if (subprocess.call([self.efinity_path + '/bin/python3', self.efinity_path +
'/pgm/bin/efx_pgm/ftdi_program.py', bitstream_file,
"-m", "jtag"], env=os.environ.copy()) != 0):
diff --git a/litex/build/gowin/common.py b/litex/build/gowin/common.py
index fd554e946..1869385af 100644
--- a/litex/build/gowin/common.py
+++ b/litex/build/gowin/common.py
@@ -7,6 +7,8 @@
from migen.fhdl.module import Module
from migen.genlib.resetsync import AsyncResetSynchronizer
+from litex.gen import *
+
from litex.build.io import *
# Gowin AsyncResetSynchronizer ---------------------------------------------------------------------
@@ -58,7 +60,9 @@ class GowinDDROutputImpl(Module):
i_CLK = clk,
i_D0 = i1,
i_D1 = i2,
+ i_TX = 0,
o_Q0 = o,
+ o_Q1 = Open(),
)
class GowinDDROutput:
diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py
index 8ee97cecf..7129db38e 100644
--- a/litex/build/gowin/gowin.py
+++ b/litex/build/gowin/gowin.py
@@ -26,6 +26,7 @@ class GowinToolchain(GenericToolchain):
def __init__(self):
super().__init__()
self.options = {}
+ self.additional_cst_commands = []
def finalize(self):
if self.platform.verilog_include_paths:
@@ -108,6 +109,8 @@ class GowinToolchain(GenericToolchain):
if self.named_pc:
cst.extend(self.named_pc)
+ cst.extend(self.additional_cst_commands)
+
tools.write_to_file(f"{self._build_name}.cst", "\n".join(cst))
return (f"{self._build_name}.cst", "CST")
diff --git a/litex/build/gowin/platform.py b/litex/build/gowin/platform.py
index 2e8a75f44..f21d11ee7 100644
--- a/litex/build/gowin/platform.py
+++ b/litex/build/gowin/platform.py
@@ -43,3 +43,6 @@ class GowinPlatform(GenericPlatform):
def build(self, *args, **kwargs):
return self.toolchain.build(self, *args, **kwargs)
+
+ def add_false_path_constraint(self, from_, to):
+ pass
diff --git a/litex/build/openfpgaloader.py b/litex/build/openfpgaloader.py
index c6f38ae38..8b41d3093 100644
--- a/litex/build/openfpgaloader.py
+++ b/litex/build/openfpgaloader.py
@@ -13,31 +13,66 @@ class OpenFPGALoader(GenericProgrammer):
needs_bitreverse = False
def __init__(self, board="", cable="", freq=0, fpga_part="", index_chain=None):
+ # openFPGALoader base command.
self.cmd = ["openFPGALoader"]
+
+ # Specify FPGA board.
if board:
self.cmd += ["--board", board]
+
+ # Specify FPGA part/device.
if fpga_part:
self.cmd += ["--fpga-part", fpga_part]
+
+ # Specify programmation cable.
if cable:
self.cmd += ["--cable", cable]
+
+ # Specify programmation frequency.
if freq:
self.cmd += ["--freq", str(int(float(freq)))]
+
+ # Specify index in the JTAG chain.
if index_chain is not None:
self.cmd += ["--index-chain", str(int(index_chain))]
def load_bitstream(self, bitstream_file):
+ # Load base command.
cmd = self.cmd + ["--bitstream", bitstream_file]
+
+ # Execute command.
self.call(cmd)
- def flash(self, address, data_file, external=False, unprotect_flash=False, verify=False):
+ def flash(self, address, data_file, external=False, unprotect_flash=False, verify=False, **kwargs):
+ # Flash base command.
cmd = self.cmd + ["--write-flash", "--bitstream", data_file]
+
+ # Flash Internal/External selection.
if external:
cmd += ["--external-flash"]
+
+ # Flash Offset.
if address:
cmd += ["--offset"]
cmd += [str(address)]
+
+ # Flash Unprotect.
if unprotect_flash:
cmd += ["--unprotect-flash"]
+
+ # Flash Verify.
if verify:
cmd += ["--verify"]
- self.call(cmd)
+
+ # Handle kwargs for specific, less common cases.
+ for key, value in kwargs.items():
+ cmd.append(f"--{key.replace('_', '-')}")
+ if value is not None:
+ cmd.append(str(value))
+
+ # Execute Command.
+ try:
+ self.call(cmd)
+ except OSError as e:
+ print(' '.join(cmd))
+ raise
diff --git a/litex/soc/cores/clock/efinix.py b/litex/soc/cores/clock/efinix.py
index ba803c741..63cca6839 100644
--- a/litex/soc/cores/clock/efinix.py
+++ b/litex/soc/cores/clock/efinix.py
@@ -88,7 +88,7 @@ class EFINIXPLL(LiteXModule):
self.logger.info("Clock source: {}, using EXT_CLK{}".format(block["input_clock"], clock_no))
self.platform.get_pll_resource(pll_res)
else:
- block["input_clock"] = "INTERNAL"
+ block["input_clock"] = "INTERNAL" if self.type == "TITANIUMPLL" else "CORE"
block["resource"] = self.platform.get_free_pll_resource()
block["input_signal"] = name
self.logger.info("Clock source: {}".format(block["input_clock"]))
@@ -240,23 +240,24 @@ class EFINIXPLL(LiteXModule):
# no solution found for this clk: params are uncompatibles
if found == False:
break
- if len(cx_list) == 2:
- params_list.append([n, m, o, c, cx_list[0], cx_list[1]])
+ if len(cx_list) == n_out:
+ params_list.append([n, m, o, c, cx_list])
vco_max_freq = 0
o_div_max = 0
params_list2 = []
for p in params_list:
- (n, m, o, c, c0, c1) = p
+ (n, m, o, c, cx_list) = p
fpfd_tmp = clk_in_freq / n
fvco_tmp = fpfd_tmp * m * o * c
- if o > o_div_max:
- o_div_max = o
# Interface designer always select high VCO freq
if fvco_tmp > vco_max_freq:
vco_max_freq = fvco_tmp
params_list2.clear()
+ o_div_max = 0
fpll_tmp = fvco_tmp / o
if fvco_tmp == vco_max_freq:
+ if o > o_div_max:
+ o_div_max = o
params_list2.append({
"fvco" : fvco_tmp,
"fpll" : fpll_tmp,
@@ -265,8 +266,7 @@ class EFINIXPLL(LiteXModule):
"N" : n,
"O" : o,
"Cfbk" : c,
- "c0" : c0,
- "c1" : c1,
+ **{f"c{n}" : cx_list[n] for n in range(n_out)},
})
# Again: Interface Designer prefers high O divider.
diff --git a/litex/soc/cores/cpu/cortex_m3/core.py b/litex/soc/cores/cpu/cortex_m3/core.py
index b2a852afc..c1f88908a 100644
--- a/litex/soc/cores/cpu/cortex_m3/core.py
+++ b/litex/soc/cores/cpu/cortex_m3/core.py
@@ -5,8 +5,6 @@
# Copyright (c) 2022 Florent Kermarrec
# SPDX-License-Identifier: BSD-2-Clause
-import os
-
from migen import *
from litex.gen import *
diff --git a/litex/soc/cores/cpu/gowin_ae350/__init__.py b/litex/soc/cores/cpu/gowin_ae350/__init__.py
new file mode 100644
index 000000000..55596975c
--- /dev/null
+++ b/litex/soc/cores/cpu/gowin_ae350/__init__.py
@@ -0,0 +1 @@
+from litex.soc.cores.cpu.gowin_ae350.core import GowinAE350
diff --git a/litex/soc/cores/cpu/gowin_ae350/boot-helper.S b/litex/soc/cores/cpu/gowin_ae350/boot-helper.S
new file mode 100644
index 000000000..e8bd5c760
--- /dev/null
+++ b/litex/soc/cores/cpu/gowin_ae350/boot-helper.S
@@ -0,0 +1,4 @@
+ .section .text, "ax", @progbits
+ .global boot_helper
+boot_helper:
+ jr x13
diff --git a/litex/soc/cores/cpu/gowin_ae350/core.py b/litex/soc/cores/cpu/gowin_ae350/core.py
new file mode 100644
index 000000000..6d7a8271e
--- /dev/null
+++ b/litex/soc/cores/cpu/gowin_ae350/core.py
@@ -0,0 +1,308 @@
+#
+# This file is part of LiteX.
+#
+# Copyright (c) 2024 Gwenhael Goavec-Merou
+# Copyright (c) 2024 Florent Kermarrec
+# SPDX-License-Identifier: BSD-2-Clause
+
+import os
+
+from migen import *
+
+from litex.gen import *
+
+from litex.soc.interconnect import wishbone, ahb
+from litex.soc.interconnect.csr import *
+from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32
+
+# Gowin AE350 Constants ----------------------------------------------------------------------------
+
+APB_CE_APB = (1 << 0)
+APB_CE_UART1 = (1 << 1)
+APB_CE_UART2 = (1 << 2)
+APB_CE_SPI = (1 << 3)
+APB_CE_GPIO = (1 << 4)
+APB_CE_PIT = (1 << 5)
+APB_CE_I2C = (1 << 6)
+APB_CE_WDT = (1 << 7)
+
+# Gowin AE350 --------------------------------------------------------------------------------------
+
+class GowinAE350(CPU):
+ variants = ["standard"]
+ category = "hardcore"
+ family = "riscv"
+ name = "gowin_ae350"
+ human_name = "Gowin AE350"
+ data_width = 32
+ endianness = "little"
+ reset_address = 0x8000_0000
+ gcc_triple = CPU_GCC_TRIPLE_RISCV32
+ linker_output_format = "elf32-littleriscv"
+ nop = "nop"
+ io_regions = {
+ # Origin, Length.
+ 0xe800_0000: 0x6000_0000
+ }
+
+ @property
+ def mem_map(self):
+ return {
+ "rom" : 0x80000000,
+ "sram" : 0x00000000,
+ "peripherals" : 0xf0000000,
+ "csr" : 0xe8000000,
+ }
+
+ # GCC Flags.
+ @property
+ def gcc_flags(self):
+ flags = f" -mabi=ilp32 -march=rv32imafdc"
+ flags += f" -D__AE350__"
+ return flags
+
+ def __init__(self, platform, variant, *args, **kwargs):
+ self.platform = platform
+ self.reset = Signal()
+ self.ibus = ibus = wishbone.Interface(data_width=32, address_width=32, addressing="byte")
+ self.dbus = dbus = wishbone.Interface(data_width=64, address_width=32, addressing="word")
+ self.pbus = pbus = wishbone.Interface(data_width=32, address_width=32, addressing="byte")
+ self.periph_buses = [ibus, dbus, pbus] # Peripheral buses (Connected to main SoC's bus).
+ self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
+
+
+ # AHBLite Buses.
+ # --------------
+ self.ahb_rom = ahb_rom = ahb.AHBInterface(data_width=32, address_width=32)
+ self.ahb_ram = ahb_ram = ahb.AHBInterface(data_width=64, address_width=32)
+ self.ahb_exts = ahb_exts = ahb.AHBInterface(data_width=32, address_width=32)
+ self.comb += [
+ # Set AHBLite ROM static signals.
+ ahb_rom.sel.eq(1),
+ ahb_rom.size.eq(0b010),
+ ahb_rom.burst.eq(0),
+ # Set AHBLite RAM static signals.
+ ahb_ram.sel.eq(1),
+ ]
+
+ # CPU Instance.
+ # -------------
+ self.cpu_params = dict(
+ # Clk/Rst.
+ i_CORE_CLK = ClockSignal("cpu"),
+ i_DDR_CLK = ClockSignal("sys"),
+ i_AHB_CLK = ClockSignal("sys"),
+ i_APB_CLK = ClockSignal("sys"),
+ i_POR_N = 1,
+ i_HW_RSTN = ~(ResetSignal("sys") | self.reset),
+ o_PRESETN = Open(),
+ o_HRESETN = Open(),
+ o_DDR_RSTN = Open(),
+
+ # Features/Peripherals Enable.
+ i_CORE_CE = 1,
+ i_AXI_CE = 1,
+ i_DDR_CE = 1,
+ i_AHB_CE = 1,
+ i_APB_CE = Constant(APB_CE_APB, 8),
+ i_APB2AHB_CE = 1,
+
+ # WFI.
+ o_CORE0_WFI_MODE = Open(),
+ i_WAKEUP_IN = 0,
+
+ # RTC.
+ i_RTC_CLK = ClockSignal("sys"),
+ o_RTC_WAKEUP = Open(),
+
+ # Interrupts.
+ i_GP_INT = Constant(0, 16),
+
+ # DMA.
+ i_DMA_REQ = Constant(0, 8),
+ o_DMA_ACK = Open(8),
+
+ # AHBLite ROM interface.
+ i_ROM_HRDATA = ahb_rom.rdata,
+ i_ROM_HREADY = ahb_rom.readyout,
+ i_ROM_HRESP = ahb_rom.resp,
+ o_ROM_HADDR = ahb_rom.addr,
+ o_ROM_HTRANS = ahb_rom.trans,
+ o_ROM_HWRITE = ahb_rom.write,
+
+ # APBLite Fabric interface (Slave).
+ o_APB_PADDR = Open(32),
+ o_APB_PENABLE = Open(),
+ i_APB_PRDATA = Constant(0, 32),
+ i_APB_PREADY = 0,
+ o_APB_PSEL = Open(),
+ o_APB_PWDATA = Open(32),
+ o_APB_PWRITE = Open(),
+ i_APB_PSLVERR = 0,
+ o_APB_PPROT = Open(3),
+ o_APB_PSTRB = Open(4),
+
+ # AHBLite Peripheral interface (Master).
+ i_EXTS_HRDATA = ahb_exts.rdata,
+ i_EXTS_HREADYIN = ahb_exts.readyout,
+ i_EXTS_HRESP = ahb_exts.resp,
+ o_EXTS_HADDR = ahb_exts.addr,
+ o_EXTS_HBURST = ahb_exts.burst,
+ o_EXTS_HPROT = ahb_exts.prot,
+ o_EXTS_HSEL = ahb_exts.sel,
+ o_EXTS_HSIZE = ahb_exts.size,
+ o_EXTS_HTRANS = ahb_exts.trans,
+ o_EXTS_HWDATA = ahb_exts.wdata,
+ o_EXTS_HWRITE = ahb_exts.write,
+
+ # AHBLite Peripheral interface (Slave).
+ i_EXTM_HADDR = Constant(0, 32),
+ i_EXTM_HBURST = Constant(0, 3),
+ i_EXTM_HPROT = Constant(0, 4),
+ o_EXTM_HRDATA = Open(64),
+ i_EXTM_HREADY = 0,
+ o_EXTM_HREADYOUT = Open(),
+ o_EXTM_HRESP = Open(),
+ i_EXTM_HSEL = 0,
+ i_EXTM_HSIZE = Constant(0, 3),
+ i_EXTM_HTRANS = Constant(0, 2),
+ i_EXTM_HWDATA = Constant(0, 64),
+ i_EXTM_HWRITE = 0,
+
+ # AHBLite RAM interface (Slave).
+ i_DDR_HRDATA = ahb_ram.rdata,
+ i_DDR_HREADY = ahb_ram.readyout,
+ i_DDR_HRESP = ahb_ram.resp,
+ o_DDR_HADDR = ahb_ram.addr,
+ o_DDR_HBURST = ahb_ram.burst,
+ o_DDR_HPROT = ahb_ram.prot,
+ o_DDR_HSIZE = ahb_ram.size,
+ o_DDR_HTRANS = ahb_ram.trans,
+ o_DDR_HWDATA = ahb_ram.wdata,
+ o_DDR_HWRITE = ahb_ram.write,
+
+ # GPIOs.
+ i_GPIO_IN = Constant(0, 32),
+ o_GPIO_OUT = Open(32),
+ o_GPIO_OE = Open(32),
+
+ # SCAN.
+ i_SCAN_EN = 0,
+ i_SCAN_TEST = 0,
+ i_SCAN_IN = Constant(0xfffff, 20),
+ o_SCAN_OUT = Open(20),
+
+ # Integrated JTAG.
+ i_INTEG_TCK = 1,
+ i_INTEG_TDI = 1,
+ i_INTEG_TMS = 1,
+ i_INTEG_TRST = 1,
+ o_INTEG_TDO = Open(),
+
+ # SRAM (FIXME : Cleanup).
+ i_PGEN_CHAIN_I = 1,
+ o_PRDYN_CHAIN_O = Open(),
+ i_EMA = Constant(0b011, 3),
+ i_EMAW = Constant(0b01, 2),
+ i_EMAS = 0,
+ i_RET1N = 1,
+ i_RET2N = 1,
+
+ # SPI.
+ i_SPI2_HOLDN_IN = 0,
+ i_SPI2_WPN_IN = 0,
+ i_SPI2_CLK_IN = 0,
+ i_SPI2_CSN_IN = 0,
+ i_SPI2_MISO_IN = 0,
+ i_SPI2_MOSI_IN = 0,
+ o_SPI2_HOLDN_OUT = Open(),
+ o_SPI2_HOLDN_OE = Open(),
+ o_SPI2_WPN_OUT = Open(),
+ o_SPI2_WPN_OE = Open(),
+ o_SPI2_CLK_OUT = Open(),
+ o_SPI2_CLK_OE = Open(),
+ o_SPI2_CSN_OUT = Open(),
+ o_SPI2_CSN_OE = Open(),
+ o_SPI2_MISO_OUT = Open(),
+ o_SPI2_MISO_OE = Open(),
+ o_SPI2_MOSI_OUT = Open(),
+ o_SPI2_MOSI_OE = Open(),
+
+ # I2C.
+ i_I2C_SCL_IN = 0,
+ i_I2C_SDA_IN = 0,
+ o_I2C_SCL = Open(),
+ o_I2C_SDA = Open(),
+
+ # PIT/PWM.
+ o_CH0_PWM = Open(),
+ o_CH0_PWMOE = Open(),
+ o_CH1_PWM = Open(),
+ o_CH1_PWMOE = Open(),
+ o_CH2_PWM = Open(),
+ o_CH2_PWMOE = Open(),
+ o_CH3_PWM = Open(),
+ o_CH3_PWMOE = Open(),
+
+ # UART1.
+ o_UART1_TXD = Open(),
+ o_UART1_RTSN = Open(),
+ i_UART1_RXD = 0,
+ i_UART1_CTSN = 0,
+ i_UART1_DSRN = 0,
+ i_UART1_DCDN = 0,
+ i_UART1_RIN = 0,
+ o_UART1_DTRN = Open(),
+ o_UART1_OUT1N = Open(),
+ o_UART1_OUT2N = Open(),
+
+ # UART2.
+ o_UART2_TXD = Open(),
+ o_UART2_RTSN = Open(),
+ i_UART2_RXD = 0,
+ i_UART2_CTSN = 1,
+ i_UART2_DCDN = 1,
+ i_UART2_DSRN = 1,
+ i_UART2_RIN = 1,
+ o_UART2_DTRN = Open(),
+ o_UART2_OUT1N = Open(),
+ o_UART2_OUT2N = Open(),
+
+ # JTAG.
+ i_DBG_TCK = 1,
+ i_TMS_IN = 1,
+ i_TRST_IN = 1,
+ i_TDI_IN = 0,
+ o_TDO_OUT = Open(),
+ o_TDO_OE = Open(),
+
+ # Test.
+ i_TEST_CLK = 0,
+ i_TEST_MODE = 0,
+ i_TEST_RSTN = 1,
+ )
+
+ # AHBLite ROM Interface.
+ # ----------------------
+ self.submodules += ahb.AHB2Wishbone(ahb_rom, self.ibus)
+
+ # AHBLite RAM Interface.
+ # ----------------------
+ self.submodules += ahb.AHB2Wishbone(ahb_ram, self.dbus)
+
+ # AHBLite Peripheral Interface.
+ # -----------------------------
+ self.submodules += ahb.AHB2Wishbone(ahb_exts, self.pbus)
+
+ def connect_jtag(self, pads):
+ self.cpu_params.update(
+ i_DBG_TCK = pads.tck,
+ i_TMS_IN = pads.tms,
+ i_TRST_IN = pads.trst,
+ i_TDI_IN = pads.tdi,
+ o_TDO_OUT = pads.tdo,
+ o_TDO_OE = Open(),
+ )
+
+ def do_finalize(self):
+ self.specials += Instance("AE350_SOC", **self.cpu_params)
diff --git a/litex/soc/cores/cpu/gowin_ae350/crt0.S b/litex/soc/cores/cpu/gowin_ae350/crt0.S
new file mode 100644
index 000000000..13bfc48e9
--- /dev/null
+++ b/litex/soc/cores/cpu/gowin_ae350/crt0.S
@@ -0,0 +1,75 @@
+#define MIE_MEIE 0x800
+
+ .global _start
+_start:
+ j reset_vector
+
+reset_vector:
+ la sp, _fstack
+ la t0, trap_vector
+ csrw mtvec, t0
+
+ // initialize .data
+ la t0, _fdata
+ la t1, _edata
+ la t2, _fdata_rom
+1: beq t0, t1, 2f
+ lw t3, 0(t2)
+ sw t3, 0(t0)
+ addi t0, t0, 4
+ addi t2, t2, 4
+ j 1b
+2:
+
+ // initialize .bss
+ la t0, _fbss
+ la t1, _ebss
+1: beq t0, t1, 3f
+ sw zero, 0(t0)
+ addi t0, t0, 4
+ j 1b
+3:
+ // enable external interrupts
+ li t0, MIE_MEIE
+ csrs mie, t0
+
+ call main
+1: j 1b
+
+trap_vector:
+ addi sp, sp, -16*4
+ sw ra, 0*4(sp)
+ sw t0, 1*4(sp)
+ sw t1, 2*4(sp)
+ sw t2, 3*4(sp)
+ sw a0, 4*4(sp)
+ sw a1, 5*4(sp)
+ sw a2, 6*4(sp)
+ sw a3, 7*4(sp)
+ sw a4, 8*4(sp)
+ sw a5, 9*4(sp)
+ sw a6, 10*4(sp)
+ sw a7, 11*4(sp)
+ sw t3, 12*4(sp)
+ sw t4, 13*4(sp)
+ sw t5, 14*4(sp)
+ sw t6, 15*4(sp)
+ call isr
+ lw ra, 0*4(sp)
+ lw t0, 1*4(sp)
+ lw t1, 2*4(sp)
+ lw t2, 3*4(sp)
+ lw a0, 4*4(sp)
+ lw a1, 5*4(sp)
+ lw a2, 6*4(sp)
+ lw a3, 7*4(sp)
+ lw a4, 8*4(sp)
+ lw a5, 9*4(sp)
+ lw a6, 10*4(sp)
+ lw a7, 11*4(sp)
+ lw t3, 12*4(sp)
+ lw t4, 13*4(sp)
+ lw t5, 14*4(sp)
+ lw t6, 15*4(sp)
+ addi sp, sp, 16*4
+ mret
diff --git a/litex/soc/cores/cpu/gowin_ae350/irq.h b/litex/soc/cores/cpu/gowin_ae350/irq.h
new file mode 100644
index 000000000..7374cf506
--- /dev/null
+++ b/litex/soc/cores/cpu/gowin_ae350/irq.h
@@ -0,0 +1,4 @@
+#ifndef __IRQ_H
+#define __IRQ_H
+
+#endif /* __IRQ_H */
diff --git a/litex/soc/cores/cpu/gowin_ae350/system.h b/litex/soc/cores/cpu/gowin_ae350/system.h
new file mode 100644
index 000000000..c27fc4da8
--- /dev/null
+++ b/litex/soc/cores/cpu/gowin_ae350/system.h
@@ -0,0 +1,19 @@
+#ifndef __SYSTEM_H
+#define __SYSTEM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__attribute__((unused)) static void flush_cpu_icache(void){}; /* FIXME */
+__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME */
+void flush_l2_cache(void);
+
+void busy_wait(unsigned int ms);
+void busy_wait_us(unsigned int us);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SYSTEM_H */
diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py
index c8551b21c..d9ba87858 100644
--- a/litex/soc/cores/cpu/gowin_emcu/core.py
+++ b/litex/soc/cores/cpu/gowin_emcu/core.py
@@ -2,52 +2,18 @@
# This file is part of LiteX.
#
# Copyright (c) 2021 Ilia Sergachev
+# Copyright (c) 2024 Florent Kermarrec
# SPDX-License-Identifier: BSD-2-Clause
from migen import *
from litex.gen import *
-from litex.soc.interconnect import wishbone, ahb
from litex.soc.cores.cpu import CPU
+from litex.soc.interconnect import wishbone
+from litex.soc.interconnect import ahb
-# AHB Flash ----------------------------------------------------------------------------------------
-
-class AHBFlash(LiteXModule):
- def __init__(self, bus):
- addr = Signal(13)
- read = Signal()
- self.comb += bus.resp.eq(0)
-
- self.fsm = fsm = FSM()
- fsm.act("IDLE",
- bus.readyout.eq(1),
- If(bus.sel & bus.trans[1],
- NextValue(addr, bus.addr[2:]),
- NextState("READ"),
- )
- )
- fsm.act("READ",
- read.eq(1),
- NextState("WAIT"),
- )
- fsm.act("WAIT",
- NextState("IDLE")
- )
- self.specials += Instance("FLASH256K",
- o_DOUT = bus.rdata,
- i_DIN = Signal(32),
- i_XADR = addr[6:],
- i_YADR = addr[:6],
- i_XE = ~ResetSignal("sys"),
- i_YE = ~ResetSignal("sys"),
- i_SE = read,
- i_PROG = 0,
- i_ERASE = 0,
- i_NVSTR = 0
- )
-
-# Gowin EMCU ---------------------------------------------------------------------------------------
+# Gowin EMCU (Enhanced MCU / Cortex M3) ------------------------------------------------------------
class GowinEMCU(CPU):
variants = ["standard"]
@@ -57,69 +23,155 @@ class GowinEMCU(CPU):
human_name = "Gowin EMCU"
data_width = 32
endianness = "little"
+ reset_address = 0x0000_0000
gcc_triple = "arm-none-eabi"
- gcc_flags = "-mcpu=cortex-m3 -mthumb"
linker_output_format = "elf32-littlearm"
nop = "nop"
io_regions = {
# Origin, Length.
- 0x4000_0000: 0x2000_0000,
- 0xA000_0000: 0x6000_0000
+ 0x4000_0000 : 0x2000_0000,
+ 0xa000_0000 : 0x6000_0000,
}
+ # Memory Mapping.
@property
def mem_map(self):
return {
- "rom" : 0x0000_0000,
- "sram" : 0x2000_0000,
- "peripherals" : 0x4000_0000,
- "csr" : 0xa000_0000,
+ "rom" : 0x0000_0000,
+ "sram" : 0x2000_0000,
+ "main_ram" : 0x1000_0000,
+ "csr" : 0xa000_0000,
}
- def __init__(self, platform, variant, *args, **kwargs):
- super().__init__(*args, **kwargs)
+ # GCC Flags.
+ @property
+ def gcc_flags(self):
+ flags = f" -march=armv7-m -mthumb"
+ flags += f" -D__CortexM3__"
+ flags += f" -DUART_POLLING"
+ return flags
- self.reset = Signal()
- self.bus_reset = Signal()
- bus_reset_n = Signal()
- self.comb += self.bus_reset.eq(~bus_reset_n)
- self.interrupt = Signal(5)
- self.reset_address = self.mem_map["rom"] + 0
+ def __init__(self, platform, variant="standard"):
+ self.platform = platform
+ self.reset = Signal()
+ self.pbus = wishbone.Interface(data_width=32, address_width=32, addressing="byte")
+ self.periph_buses = [self.pbus]
+ self.memory_buses = []
- self.gpio_in = Signal(16)
- self.gpio_out = Signal(16)
- self.gpio_out_en = Signal(16)
+ # CPU Instance.
+ # -------------
- self.cpu_params = dict()
- self.cpu_params.update(
+ bus_reset_n = Signal()
+ ahb_flash = ahb.AHBInterface(data_width=32, address_width=32)
+ ahb_targexp0 = ahb.AHBInterface(data_width=32, address_width=32)
+
+ self.cpu_params = dict(
+ # Clk/Rst.
+ i_FCLK = ClockSignal("sys"),
+ i_PORESETN = ~ (ResetSignal("sys") | self.reset),
+ i_SYSRESETN = ~ (ResetSignal("sys") | self.reset),
i_MTXREMAP = Signal(4, reset=0b1111),
o_MTXHRESETN = bus_reset_n,
+ # RTC.
+ i_RTCSRCCLK = 0b0, # RTC Clk In.
+
+ # GPIOs.
+ i_IOEXPINPUTI = 0x0000, # GPIO Input (16-bit).
+ o_IOEXPOUTPUTO = Open(16), # GPIO Output (16-bit).
+ o_IOEXPOUTPUTENO = Open(16), # GPIO Output Enable (16-bit).
+
+ # UART0.
+ i_UART0RXDI = 0b0,
+ o_UART0TXDO = Open(),
+ o_UART0BAUDTICK = Open(),
+
+ # UART1.
+ i_UART1RXDI = 0b0,
+ o_UART1TXDO = Open(),
+ o_UART1BAUDTICK = Open(),
+
+ # Interrupts.
+ i_GPINT = 0,
+ o_INTMONITOR = Open(),
+
+ # Flash.
i_FLASHERR = Signal(),
i_FLASHINT = Signal(),
- i_FCLK = ClockSignal("sys"),
- i_PORESETN = ~self.reset,
- i_SYSRESETN = ~self.reset,
- i_RTCSRCCLK = Signal(), # TODO - RTC clk in
+ # Debug/JTAG.
+ o_DAPTDO = Open(),
+ o_DAPJTAGNSW = Open(),
+ o_DAPNTDOEN = Open(),
+ i_DAPSWDITMS = 0,
+ i_DAPTDI = 0,
+ i_DAPNTRST = 0,
+ i_DAPSWCLKTCK = 0,
- i_IOEXPINPUTI = self.gpio_in,
- o_IOEXPOUTPUTO = self.gpio_out,
- o_IOEXPOUTPUTENO = self.gpio_out_en,
+ # TARGFLASH0 / AHBLite Master.
+ o_TARGFLASH0HSEL = ahb_flash.sel,
+ o_TARGFLASH0HADDR = ahb_flash.addr,
+ o_TARGFLASH0HTRANS = ahb_flash.trans,
+ o_TARGFLASH0HSIZE = ahb_flash.size,
+ o_TARGFLASH0HBURST = ahb_flash.burst,
+ o_TARGFLASH0HREADYMUX = Open(),
+ i_TARGFLASH0HRDATA = ahb_flash.rdata,
+ i_TARGFLASH0HRUSER = 0b000,
+ i_TARGFLASH0HRESP = ahb_flash.resp,
+ i_TARGFLASH0EXRESP = 0b0,
+ i_TARGFLASH0HREADYOUT = ahb_flash.readyout,
- i_GPINT = self.interrupt,
- o_INTMONITOR = Signal(),
+ # TARGEXP0 / AHBLite Master.
+ o_TARGEXP0HSEL = ahb_targexp0.sel,
+ o_TARGEXP0HADDR = ahb_targexp0.addr,
+ o_TARGEXP0HTRANS = ahb_targexp0.trans,
+ o_TARGEXP0HWRITE = ahb_targexp0.write,
+ o_TARGEXP0HSIZE = ahb_targexp0.size,
+ o_TARGEXP0HBURST = ahb_targexp0.burst,
+ o_TARGEXP0HPROT = ahb_targexp0.prot,
+ o_TARGEXP0MEMATTR = Open(2),
+ o_TARGEXP0EXREQ = Open(),
+ o_TARGEXP0HMASTER = Open(4),
+ o_TARGEXP0HWDATA = ahb_targexp0.wdata,
+ o_TARGEXP0HMASTLOCK = ahb_targexp0.mastlock,
+ o_TARGEXP0HREADYMUX = Open(),
+ o_TARGEXP0HAUSER = Open(),
+ o_TARGEXP0HWUSER = Open(4),
+ i_TARGEXP0HRDATA = ahb_targexp0.rdata,
+ i_TARGEXP0HREADYOUT = ahb_targexp0.readyout,
+ i_TARGEXP0HRESP = ahb_targexp0.resp,
+ i_TARGEXP0EXRESP = 0b0,
+ i_TARGEXP0HRUSER = 0b000,
+
+ # INITEXP0 / AHBLite Slave.
+ o_INITEXP0HRDATA = Open(32),
+ o_INITEXP0HREADY = Open(),
+ o_INITEXP0HRESP = Open(),
+ o_INITEXP0EXRESP = Open(),
+ o_INITEXP0HRUSER = Open(3),
+ i_INITEXP0HSEL = 0b0,
+ i_INITEXP0HADDR = 0x00000000,
+ i_INITEXP0HTRANS = 0b00,
+ i_INITEXP0HWRITE = 0b0,
+ i_INITEXP0HSIZE = 0b000,
+ i_INITEXP0HBURST = 0b000,
+ i_INITEXP0HPROT = 0b0000,
+ i_INITEXP0MEMATTR = 0b00,
+ i_INITEXP0EXREQ = 0b0,
+ i_INITEXP0HMASTER = 0b0000,
+ i_INITEXP0HWDATA = 0x00000000,
+ i_INITEXP0HMASTLOCK = 0b0,
+ i_INITEXP0HAUSER = 0b0,
+ i_INITEXP0HWUSER = 0b0000,
)
- # 32b CPU SRAM split between 8 SRAMs x 4 bit each
-
- sram_dw = 32
- single_sram_dw = 4
- n_srams = sram_dw // single_sram_dw
+ # SRAM (32-bit RAM split between 4 SRAMs x 8-bit each).
+ # -----------------------------------------------------
+ # CPU SRAM Interface.
sram0_addr = Signal(13)
- sram0_rdata = Signal(sram_dw)
- sram0_wdata = Signal(sram_dw)
+ sram0_rdata = Signal(32)
+ sram0_wdata = Signal(32)
sram0_cs = Signal()
sram0_wren = Signal(4)
self.cpu_params.update(
@@ -130,61 +182,75 @@ class GowinEMCU(CPU):
o_SRAM0CS = sram0_cs,
)
- for i in range(n_srams):
+ # SRAMS Instances.
+ for i in range(4):
self.specials += Instance("SDPB",
p_READ_MODE = 0,
- p_BIT_WIDTH_0 = single_sram_dw,
- p_BIT_WIDTH_1 = single_sram_dw,
+ p_BIT_WIDTH_0 = 8,
+ p_BIT_WIDTH_1 = 8,
p_RESET_MODE = "SYNC",
- p_BLK_SEL_0 = 0b111,
- p_BLK_SEL_1 = 0b111,
- o_DO = Cat(sram0_rdata[i * single_sram_dw: (i + 1) * single_sram_dw], Signal(sram_dw - single_sram_dw)),
- i_DI = Cat(sram0_wdata[i * single_sram_dw: (i + 1) * single_sram_dw], Signal(sram_dw - single_sram_dw)),
- i_ADA = Cat(Signal(2), sram0_addr[:-1]),
- i_ADB = Cat(Signal(2), sram0_addr[:-1]),
- i_CEA = sram0_wren[i // 2],
- i_CEB = ~sram0_wren[i // 2],
- i_CLKA = ClockSignal(),
- i_CLKB = ClockSignal(),
- i_RESETA = 0,
- i_RESETB = self.bus_reset,
+ p_BLK_SEL_0 = Constant(0, 3),
+ p_BLK_SEL_1 = Constant(0, 3),
+ i_BLKSELA = 0b000,
+ i_BLKSELB = 0b000,
+ o_DO = sram0_rdata[8*i:8*(i + 1)],
+ i_DI = sram0_wdata[8*i:8*(i + 1)],
+ i_ADA = Cat(Signal(3), sram0_addr),
+ i_ADB = Cat(Signal(3), sram0_addr),
+ i_CEA = sram0_cs & sram0_wren[i],
+ i_CEB = sram0_cs,
+ i_CLKA = ClockSignal("sys"),
+ i_CLKB = ClockSignal("sys"),
+ i_RESETA = ~bus_reset_n,
+ i_RESETB = ~bus_reset_n,
i_OCE = 1,
- i_BLKSELA = Cat(sram0_cs, sram0_cs, sram0_cs),
- i_BLKSELB = Cat(sram0_cs, sram0_cs, sram0_cs),
)
- # Boot Flash memory connected via AHB
+ # Flash (Boot Flash memory connected via AHB).
+ # --------------------------------------------
+
+ class AHBFlash(LiteXModule):
+ def __init__(self, bus):
+ addr = Signal(13)
+ read = Signal()
+ self.comb += bus.resp.eq(0)
+
+ self.fsm = fsm = FSM()
+ fsm.act("IDLE",
+ bus.readyout.eq(1),
+ If(bus.sel & bus.trans[1],
+ NextValue(addr, bus.addr[2:]),
+ NextState("READ"),
+ )
+ )
+ fsm.act("READ",
+ read.eq(1),
+ NextState("WAIT"),
+ )
+ fsm.act("WAIT",
+ NextState("IDLE")
+ )
+ self.specials += Instance("FLASH256K",
+ o_DOUT = bus.rdata,
+ i_DIN = Signal(32),
+ i_XADR = addr[6:],
+ i_YADR = addr[:6],
+ i_XE = ~ResetSignal("sys"),
+ i_YE = ~ResetSignal("sys"),
+ i_SE = read,
+ i_PROG = 0,
+ i_ERASE = 0,
+ i_NVSTR = 0
+ )
- ahb_flash = ahb.Interface()
- for s, _ in ahb_flash.master_signals:
- if s in ["wdata", "write", "mastlock", "prot"]:
- continue
- self.cpu_params[f"o_TARGFLASH0H{s.upper()}"] = getattr(ahb_flash, s)
- for s, _ in ahb_flash.slave_signals:
- self.cpu_params[f"i_TARGFLASH0H{s.upper()}"] = getattr(ahb_flash, s)
flash = ResetInserter()(AHBFlash(ahb_flash))
- self.comb += flash.reset.eq(self.bus_reset)
+ self.comb += flash.reset.eq(~bus_reset_n)
self.submodules += flash
- # Extension AHB -> Wishbone CSR via bridge
-
- self.pbus = wishbone.Interface(data_width=32, adr_width=30, addressing="word")
- self.periph_buses = [self.pbus]
- ahb_targexp0 = ahb.Interface()
- for s, _ in ahb_targexp0.master_signals:
- self.cpu_params[f"o_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s)
- for s, _ in ahb_targexp0.slave_signals:
- self.cpu_params[f"i_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s)
+ # Peripheral Bus (AHB -> Wishbone).
+ # ---------------------------------
self.submodules += ahb.AHB2Wishbone(ahb_targexp0, self.pbus)
- def connect_uart(self, pads, n=0):
- assert n in (0, 1), "this CPU has 2 built-in UARTs, 0 and 1"
- self.cpu_params.update({
- f"i_UART{n}RXDI": pads.rx,
- f"o_UART{n}TXDO": pads.tx,
- f"o_UART{n}BAUDTICK": Signal()
- })
-
def connect_jtag(self, pads):
self.cpu_params.update(
i_DAPSWDITMS = pads.tms,
diff --git a/litex/soc/cores/cpu/gowin_emcu/crt0.c b/litex/soc/cores/cpu/gowin_emcu/crt0.c
index bea687093..54415dad1 100644
--- a/litex/soc/cores/cpu/gowin_emcu/crt0.c
+++ b/litex/soc/cores/cpu/gowin_emcu/crt0.c
@@ -8,6 +8,10 @@ void _start(void);
void default_handler(void);
void _start(void) {
+ __asm__(
+ "mov r0, %0\n"
+ "mov sp, r0\n" : : "r" (&_fstack)
+ );
uint32_t *y = &_fdata_rom;
for (uint32_t *x = &_fdata; x < &_edata; x ++)
*x = *y ++;
@@ -15,33 +19,77 @@ void _start(void) {
for (uint32_t *x = &_fbss; x < &_ebss; x ++)
*x = 0;
- UART0->ctrl = 0b11; // set rx and tx enable bits
- UART0->baud_div = CONFIG_CLOCK_FREQUENCY / 115200; // FIXME
-
__asm__("bl main");
while(1);
}
+
void default_handler(void) {
while(1);
}
-
const void* isr_vector[] __attribute__((__used__)) __attribute__((section(".isr_vector"))) = {
&_fstack,
- _start,
+ _start, // reset
+ default_handler, // nmi
+ default_handler, // hard fault
+ default_handler, // mem manage
+ default_handler, // bus fault
+ default_handler, // usage fault
+ (void *) 0x55, // reserved
+ 0, // reserved
+ 0, // reserved
+ 0, // reserved
+ default_handler, // svc
+ default_handler, // debug mon
+ 0, // reserved
+ default_handler, // pend sv
+ default_handler, // systick
+ // external
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
+ default_handler,
default_handler,
default_handler,
default_handler,
default_handler,
default_handler,
- 0,
- 0,
- 0,
- 0,
default_handler,
default_handler,
- 0,
default_handler,
- default_handler
};
+
+__asm__ (
+"__gnu_thumb1_case_uhi:\n"
+"push {r0, r1}\n"
+"mov r1, lr\n"
+"lsrs r1, r1, #1\n"
+"lsls r0, r0, #1\n"
+"lsls r1, r1, #1\n"
+"ldrh r1, [r1, r0]\n"
+"lsls r1, r1, #1\n"
+"add lr, lr, r1\n"
+"pop {r0, r1}\n"
+"bx lr\n"
+);
diff --git a/litex/soc/cores/cpu/gowin_emcu/system.h b/litex/soc/cores/cpu/gowin_emcu/system.h
index 2fc3a77d1..262446a62 100644
--- a/litex/soc/cores/cpu/gowin_emcu/system.h
+++ b/litex/soc/cores/cpu/gowin_emcu/system.h
@@ -5,66 +5,13 @@
extern "C" {
#endif
-__attribute__((unused)) static void flush_cpu_icache(void){};
-__attribute__((unused)) static void flush_cpu_dcache(void){};
+__attribute__((unused)) static void flush_cpu_icache(void){}; /* No instruction cache */
+__attribute__((unused)) static void flush_cpu_dcache(void){}; /* No instruction cache */
void flush_l2_cache(void);
void busy_wait(unsigned int ms);
void busy_wait_us(unsigned int us);
-#include
-
-// FIXME
-#define CSR_UART_BASE
-#define UART_POLLING
-
-struct EMCU_UART
-{
- volatile uint32_t data;
- volatile uint32_t state;
- volatile uint32_t ctrl;
- volatile uint32_t int_ctrl;
- volatile uint32_t baud_div;
-};
-
-#define PERIPHERALS_BASE 0x40000000
-#define UART0 ((struct EMCU_UART *) (PERIPHERALS_BASE + 0x4000))
-
-static inline char uart_txfull_read(void);
-static inline char uart_rxempty_read(void);
-static inline void uart_ev_enable_write(char c);
-static inline void uart_rxtx_write(char c);
-static inline char uart_rxtx_read(void);
-static inline void uart_ev_pending_write(char);
-static inline char uart_ev_pending_read(void);
-
-static inline char uart_txfull_read(void) {
- return UART0->state & 0b01;
-}
-
-static inline char uart_rxempty_read(void) {
- return !(UART0->state & 0b10);
-}
-
-static inline void uart_ev_enable_write(char c) {
- // FIXME
-}
-
-static inline void uart_rxtx_write(char c) {
- UART0->data = (uint32_t) c;
-}
-
-static inline char uart_rxtx_read(void)
-{
- return (char)(UART0->data);
-}
-
-static inline void uart_ev_pending_write(char x) {}
-static inline char uart_ev_pending_read(void) {
- return 0;
-}
-
-
#ifdef __cplusplus
}
#endif
diff --git a/litex/soc/cores/cpu/naxriscv/core.py b/litex/soc/cores/cpu/naxriscv/core.py
index 294974b2e..a052dc6b2 100755
--- a/litex/soc/cores/cpu/naxriscv/core.py
+++ b/litex/soc/cores/cpu/naxriscv/core.py
@@ -69,7 +69,7 @@ class NaxRiscv(CPU):
# Arch.
@staticmethod
def get_arch():
- arch = f"rv{NaxRiscv.xlen}ima"
+ arch = f"rv{NaxRiscv.xlen}i2p0_ma"
if NaxRiscv.with_fpu:
arch += "fd"
if NaxRiscv.with_rvc:
@@ -115,6 +115,7 @@ class NaxRiscv(CPU):
cpu_group.add_argument("--update-repo", default="recommended", choices=["latest","wipe+latest","recommended","wipe+recommended","no"], help="Specify how the NaxRiscv & SpinalHDL repo should be updated (latest: update to HEAD, recommended: Update to known compatible version, no: Don't update, wipe+*: Do clean&reset before checkout)")
cpu_group.add_argument("--no-netlist-cache", action="store_true", help="Always (re-)build the netlist.")
cpu_group.add_argument("--with-fpu", action="store_true", help="Enable the F32/F64 FPU.")
+ cpu_group.add_argument("--with-rvc", action="store_true", help="Enable the Compress ISA extension.")
cpu_group.add_argument("--l2-bytes", default=128*1024, help="NaxRiscv L2 bytes, default 128 KB.")
cpu_group.add_argument("--l2-ways", default=8, help="NaxRiscv L2 ways, default 8.")
@@ -127,6 +128,7 @@ class NaxRiscv(CPU):
NaxRiscv.update_repo = args.update_repo
NaxRiscv.no_netlist_cache = args.no_netlist_cache
NaxRiscv.with_fpu = args.with_fpu
+ NaxRiscv.with_rvc = args.with_rvc
if args.scala_file:
NaxRiscv.scala_files = args.scala_file
if args.scala_args:
@@ -302,10 +304,12 @@ class NaxRiscv(CPU):
), shell=True)
# Use specific SHA1 (Optional).
print(f"Updating {name} Git repository...")
+ cwd = os.getcwd()
os.chdir(os.path.join(dir))
wipe_cmd = "&& git clean --force -d -x && git reset --hard" if "wipe" in NaxRiscv.update_repo else ""
checkout_cmd = f"&& git checkout {hash}" if hash is not None else ""
subprocess.check_call(f"cd {dir} {wipe_cmd} && git checkout {branch} && git submodule init && git pull --recurse-submodules {checkout_cmd}", shell=True)
+ os.chdir(cwd)
# Netlist Generation.
@staticmethod
@@ -342,6 +346,8 @@ class NaxRiscv(CPU):
gen_args.append(f"--scala-file={file}")
if(NaxRiscv.with_fpu):
gen_args.append(f"--scala-args=rvf=true,rvd=true")
+ if(NaxRiscv.with_rvc):
+ gen_args.append(f"--scala-args=rvc=true")
cmd = f"""cd {ndir} && sbt "runMain naxriscv.platform.litex.NaxGen {" ".join(gen_args)}\""""
print("NaxRiscv generation command :")
diff --git a/litex/soc/cores/cpu/vexriscv_smp/core.py b/litex/soc/cores/cpu/vexriscv_smp/core.py
index 6760a4b6d..776d07de1 100755
--- a/litex/soc/cores/cpu/vexriscv_smp/core.py
+++ b/litex/soc/cores/cpu/vexriscv_smp/core.py
@@ -58,32 +58,38 @@ class VexRiscvSMP(CPU):
jtag_tap = False
dtlb_size = 4
itlb_size = 4
+ csr_base = 0xf000_0000
+ clint_base = 0xf001_0000
+ plic_base = 0xf0c0_0000
# Command line configuration arguments.
@staticmethod
def args_fill(parser):
cpu_group = parser.add_argument_group(title="CPU options")
- cpu_group.add_argument("--cpu-count", default=1, help="Number of CPU(s) in the cluster.", type=int)
- cpu_group.add_argument("--with-coherent-dma", action="store_true", help="Enable Coherent DMA Slave interface.")
- cpu_group.add_argument("--without-coherent-dma", action="store_true", help="Disable Coherent DMA Slave interface.")
- cpu_group.add_argument("--dcache-width", default=None, help="L1 data cache bus width.")
- cpu_group.add_argument("--icache-width", default=None, help="L1 instruction cache bus width.")
- cpu_group.add_argument("--dcache-size", default=None, help="L1 data cache size in byte per CPU.")
- cpu_group.add_argument("--dcache-ways", default=None, help="L1 data cache ways per CPU.")
- cpu_group.add_argument("--icache-size", default=None, help="L1 instruction cache size in byte per CPU.")
- cpu_group.add_argument("--icache-ways", default=None, help="L1 instruction cache ways per CPU")
- cpu_group.add_argument("--aes-instruction", default=None, help="Enable AES instruction acceleration.")
- cpu_group.add_argument("--without-out-of-order-decoder", action="store_true", help="Reduce area at cost of peripheral access speed")
- cpu_group.add_argument("--with-wishbone-memory", action="store_true", help="Disable native LiteDRAM interface")
- cpu_group.add_argument("--with-privileged-debug", action="store_true", help="Enable official RISC-V debug spec")
- cpu_group.add_argument("--hardware-breakpoints", default=1, help="Number of hardware breapoints", type=int)
- cpu_group.add_argument("--wishbone-force-32b", action="store_true", help="Force the wishbone bus to be 32 bits")
- cpu_group.add_argument("--with-fpu", action="store_true", help="Enable the F32/F64 FPU")
- cpu_group.add_argument("--cpu-per-fpu", default="4", help="Maximal ratio between CPU count and FPU count. Will instanciate as many FPU as necessary.")
- cpu_group.add_argument("--with-rvc", action="store_true", help="Enable RISC-V compressed instruction support")
- cpu_group.add_argument("--dtlb-size", default=4, help="Data TLB size.")
- cpu_group.add_argument("--itlb-size", default=4, help="Instruction TLB size.")
- cpu_group.add_argument("--expose-time", action="store_true", help="Add CLINT time output.")
+ cpu_group.add_argument("--cpu-count", default=1, help="Number of CPU(s) in the cluster.", type=int)
+ cpu_group.add_argument("--with-coherent-dma", action="store_true", help="Enable Coherent DMA Slave interface.")
+ cpu_group.add_argument("--without-coherent-dma", action="store_true", help="Disable Coherent DMA Slave interface.")
+ cpu_group.add_argument("--dcache-width", default=None, help="L1 data cache bus width.")
+ cpu_group.add_argument("--icache-width", default=None, help="L1 instruction cache bus width.")
+ cpu_group.add_argument("--dcache-size", default=None, help="L1 data cache size in byte per CPU.")
+ cpu_group.add_argument("--dcache-ways", default=None, help="L1 data cache ways per CPU.")
+ cpu_group.add_argument("--icache-size", default=None, help="L1 instruction cache size in byte per CPU.")
+ cpu_group.add_argument("--icache-ways", default=None, help="L1 instruction cache ways per CPU")
+ cpu_group.add_argument("--aes-instruction", default=None, help="Enable AES instruction acceleration.")
+ cpu_group.add_argument("--without-out-of-order-decoder", action="store_true", help="Reduce area at cost of peripheral access speed")
+ cpu_group.add_argument("--with-wishbone-memory", action="store_true", help="Disable native LiteDRAM interface")
+ cpu_group.add_argument("--with-privileged-debug", action="store_true", help="Enable official RISC-V debug spec")
+ cpu_group.add_argument("--hardware-breakpoints", default=1, help="Number of hardware breapoints", type=int)
+ cpu_group.add_argument("--wishbone-force-32b", action="store_true", help="Force the wishbone bus to be 32 bits")
+ cpu_group.add_argument("--with-fpu", action="store_true", help="Enable the F32/F64 FPU")
+ cpu_group.add_argument("--cpu-per-fpu", default="4", help="Maximal ratio between CPU count and FPU count. Will instanciate as many FPU as necessary.")
+ cpu_group.add_argument("--with-rvc", action="store_true", help="Enable RISC-V compressed instruction support")
+ cpu_group.add_argument("--dtlb-size", default=4, help="Data TLB size.")
+ cpu_group.add_argument("--itlb-size", default=4, help="Instruction TLB size.")
+ cpu_group.add_argument("--expose-time", action="store_true", help="Add CLINT time output.")
+ cpu_group.add_argument("--csr-base", default="0xf0000000", help="CSR base address.")
+ cpu_group.add_argument("--clint-base", default="0xf0010000", help="CLINT base address.")
+ cpu_group.add_argument("--plic-base", default="0xf0c00000", help="PLIC base address.")
cpu_group.add_argument("--jtag-tap", action="store_true", help="Add the jtag tap instead of jtag instruction interface")
@staticmethod
@@ -120,8 +126,11 @@ class VexRiscvSMP(CPU):
VexRiscvSMP.cpu_per_fpu = args.cpu_per_fpu
if(args.with_rvc):
VexRiscvSMP.with_rvc = True
- if(args.dtlb_size): VexRiscvSMP.dtlb_size = int(args.dtlb_size)
- if(args.itlb_size): VexRiscvSMP.itlb_size = int(args.itlb_size)
+ if(args.dtlb_size): VexRiscvSMP.dtlb_size = int(args.dtlb_size)
+ if(args.itlb_size): VexRiscvSMP.itlb_size = int(args.itlb_size)
+ if(args.csr_base): VexRiscvSMP.csr_base = int(args.csr_base, 16)
+ if(args.clint_base): VexRiscvSMP.clint_base = int(args.clint_base, 16)
+ if(args.plic_base): VexRiscvSMP.plic_base = int(args.plic_base, 16)
if(args.jtag_tap): VexRiscvSMP.jtag_tap = int(args.jtag_tap)
# ABI.
@@ -149,9 +158,9 @@ class VexRiscvSMP(CPU):
"rom": 0x0000_0000,
"sram": 0x1000_0000,
"main_ram": 0x4000_0000,
- "csr": 0xf000_0000,
- "clint": 0xf001_0000,
- "plic": 0xf0c0_0000,
+ "csr": VexRiscvSMP.csr_base,
+ "clint": VexRiscvSMP.clint_base,
+ "plic": VexRiscvSMP.plic_base,
}
# GCC Flags.
diff --git a/litex/soc/cores/spi/spi_master.py b/litex/soc/cores/spi/spi_master.py
index 377cb4782..a7d42f9b7 100644
--- a/litex/soc/cores/spi/spi_master.py
+++ b/litex/soc/cores/spi/spi_master.py
@@ -1,7 +1,7 @@
#
# This file is part of LiteX.
#
-# Copyright (c) 2019-2020 Florent Kermarrec
+# Copyright (c) 2019-2024 Florent Kermarrec
# SPDX-License-Identifier: BSD-2-Clause
import math
@@ -18,8 +18,26 @@ from litex.soc.interconnect.csr import *
class SPIMaster(LiteXModule):
"""4-wire SPI Master
- Provides a simple and minimal hardware SPI Master with CPOL=0, CPHA=0 and build time
- configurable data_width and frequency.
+ Implements a 4-wire SPI Master with CPOL=0 and CPHA=0, tailored for FPGA designs. It allows
+ configurable data_width and SPI clock frequency at build time. Supports Raw and Aligned modes
+ for data transfer and software-controlled Chip Select (CS) for extended SPI operations.
+
+ Parameters:
+ pads (Record) : Interface pads for SPI signals. If None, a default layout is used.
+ data_width (int) : Maximum Data width of SPI transactions.
+ sys_clk_freq (int) : System clock frequency in Hz.
+ spi_clk_freq (int) : Desired SPI clock frequency in Hz.
+ with_csr (bool, optional) : Enables CSR interface if True.
+ mode (str, optional) : 'raw' for as-is data transfer or 'aligned' for transaction length-based alignment.
+
+ Modes:
+ Raw : MOSI data is aligned to the core's data-width. Optimal for data-width matching SPI transactions.
+ Aligned : MOSI data is aligned based on the transaction's length. Suitable for variable-length SPI transactions.
+
+ CS Control:
+ Software-controlled CS is available for scenarios requiring precise control over CS assertion, like
+ SPI Flash page programming or when hardware CS lines are insufficient. It allows manual CS management,
+ enabling complex transaction sequences and extended device communication.
"""
pads_layout = [("clk", 1), ("cs_n", 1), ("mosi", 1), ("miso", 1)]
def __init__(self, pads, data_width, sys_clk_freq, spi_clk_freq, with_csr=True, mode="raw"):
diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py
index 5e0595ac7..955c29293 100644
--- a/litex/soc/integration/builder.py
+++ b/litex/soc/integration/builder.py
@@ -2,7 +2,7 @@
# This file is part of LiteX.
#
# This file is Copyright (c) 2015 Sebastien Bourdeauducq
-# This file is Copyright (c) 2015-2021 Florent Kermarrec
+# This file is Copyright (c) 2015-2024 Florent Kermarrec
# This file is Copyright (c) 2018-2019 Antmicro
# This file is Copyright (c) 2018 Sergiusz Bazanski
# This file is Copyright (c) 2016-2017 Tim 'mithro' Ansell
@@ -127,6 +127,9 @@ class Builder:
self.add_software_package(name)
self.add_software_library(name)
+ # JSONs.
+ self.jsons = []
+
def add_software_package(self, name, src_dir=None):
if src_dir is None:
src_dir = os.path.join(soc_directory, "software", name)
@@ -135,6 +138,30 @@ class Builder:
def add_software_library(self, name):
self.software_libraries.append(name)
+ def add_json(self, filename, name="", origin=0):
+ self.jsons.append((filename, name, origin))
+
+ def _get_json_mem_regions(self):
+ mem_regions = {}
+ for filename, name, origin in self.jsons:
+ _, _, _mem_regions = export.load_csr_json(filename, name, origin)
+ mem_regions.update(_mem_regions)
+ return mem_regions
+
+ def _get_json_constants(self):
+ constants = {}
+ for filename, name, origin in self.jsons:
+ _, _constants, _ = export.load_csr_json(filename, name, origin)
+ constants.update(_constants)
+ return constants
+
+ def _get_json_csr_regions(self):
+ csr_regions = {}
+ for filename, name, origin in self.jsons:
+ _csr_regions, _, _ = export.load_csr_json(filename, name, origin)
+ csr_regions.update(_csr_regions)
+ return csr_regions
+
def _get_variables_contents(self):
# Helper.
variables_contents = []
@@ -147,7 +174,7 @@ class Builder:
raise e
# Define packages and libraries.
- define("PACKAGES", " ".join(name for name, src_dir in self.software_packages))
+ define("PACKAGES", " ".join(name for name, src_dir in self.software_packages))
define("PACKAGE_DIRS", " ".join(src_dir for name, src_dir in self.software_packages))
define("LIBS", " ".join(self.software_libraries))
@@ -180,6 +207,11 @@ class Builder:
_create_dir(self.include_dir)
_create_dir(self.generated_dir)
+ # Integrate JSON files.
+ self.soc.mem_regions.update(self._get_json_mem_regions())
+ self.soc.constants.update( self._get_json_constants())
+ self.soc.csr_regions.update(self._get_json_csr_regions())
+
# Generate BIOS files when the SoC uses it.
if with_bios:
# Generate Variables to variables.mak.
diff --git a/litex/soc/integration/export.py b/litex/soc/integration/export.py
index 3a00b88f7..487a36041 100644
--- a/litex/soc/integration/export.py
+++ b/litex/soc/integration/export.py
@@ -2,7 +2,7 @@
# This file is part of LiteX.
#
# This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq
-# This file is Copyright (c) 2014-2019 Florent Kermarrec
+# This file is Copyright (c) 2014-2024 Florent Kermarrec
# This file is Copyright (c) 2018 Dolu1990
# This file is Copyright (c) 2019 Gabriel L. Somlo
# This file is Copyright (c) 2018 Jean-François Nguyen
@@ -29,6 +29,7 @@ from sysconfig import get_platform
from migen import *
from litex.soc.interconnect.csr import CSRStatus
+from litex.soc.integration.soc import SoCRegion
from litex.build.tools import generated_banner
@@ -149,7 +150,7 @@ def get_mem_header(regions):
for name, region in regions.items():
r += f"#ifndef {name.upper()}_BASE\n"
r += f"#define {name.upper()}_BASE 0x{region.origin:08x}L\n"
- r += f"#define {name.upper()}_SIZE 0x{region.length:08x}\n"
+ r += f"#define {name.upper()}_SIZE 0x{region.size:08x}\n"
r += "#endif\n\n"
r += "#ifndef MEM_REGIONS\n"
@@ -370,7 +371,7 @@ def get_i2c_header(i2c_init_values):
r += "\n#endif\n"
return r
-# JSON Export --------------------------------------------------------------------------------------
+# JSON Export / Import ----------------------------------------------------------------------------
def get_csr_json(csr_regions={}, constants={}, mem_regions={}):
alignment = constants.get("CONFIG_CSR_ALIGNMENT", 32)
@@ -382,6 +383,7 @@ def get_csr_json(csr_regions={}, constants={}, mem_regions={}):
"memories": {},
}
+ # Get CSR Regions.
for name, region in csr_regions.items():
d["csr_bases"][name] = region.origin
region_origin = region.origin
@@ -398,18 +400,64 @@ def get_csr_json(csr_regions={}, constants={}, mem_regions={}):
}
region_origin += alignment//8*_size
+ # Get Constants.
for name, value in constants.items():
d["constants"][name.lower()] = value.lower() if isinstance(value, str) else value
+ # Get Mem Regions.
for name, region in mem_regions.items():
d["memories"][name.lower()] = {
"base": region.origin,
- "size": region.length,
+ "size": region.size,
"type": region.type,
}
+ # Return JSON Dump.
return json.dumps(d, indent=4)
+class MockCSR:
+ def __init__(self, name, size, type):
+ self.name = name
+ self.size = size
+ self.type = type
+
+class MockCSRRegion:
+ def __init__(self, origin, obj):
+ self.origin = origin
+ self.obj = obj
+ self.busword = 32
+
+def load_csr_json(filename, origin=0, name=""):
+ if len(name):
+ name += "_"
+ # Read File.
+ with open(filename, 'r') as json_file:
+ config_data = json.load(json_file)
+
+ # Load CSR Regions.
+ csr_regions = {}
+ for region_name, addr in config_data.get("csr_bases", {}).items():
+ csrs = []
+ for csr_name, info in config_data.get("csr_registers", {}).items():
+ region_prefix, _, csr_suffix = csr_name.rpartition("_")
+ if region_prefix.startswith(region_name):
+ if region_prefix == region_name:
+ final_name = csr_suffix
+ else:
+ final_name = f"{region_prefix[len(region_name) + 1:]}_{csr_suffix}"
+ csrs.append(MockCSR(final_name, info["size"], info["type"]))
+ csr_regions[name + region_name] = MockCSRRegion(origin + addr, csrs)
+
+ # Load Constants.
+ constants = {(name + const_name).upper(): value for const_name, value in config_data.get("constants", {}).items()}
+
+ # Load Memory Regions.
+ mem_regions = {}
+ for mem_name, info in config_data.get("memories", {}).items():
+ mem_regions[name + mem_name.lower()] = SoCRegion(origin + info["base"], info["size"], info["type"])
+
+ # Return CSR Regions, Constants, Mem Regions.
+ return csr_regions, constants, mem_regions
# CSV Export --------------------------------------------------------------------------------------
diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py
index 17fe98f79..c5c43aa7f 100644
--- a/litex/soc/integration/soc.py
+++ b/litex/soc/integration/soc.py
@@ -8,6 +8,7 @@
import os
import sys
+import math
import time
import logging
import argparse
@@ -40,6 +41,18 @@ def build_time(with_time=True):
fmt = "%Y-%m-%d %H:%M:%S" if with_time else "%Y-%m-%d"
return datetime.datetime.fromtimestamp(time.time()).strftime(fmt)
+def add_ip_address_constants(soc, name, ip_address):
+ _ip_address = ip_address.split(".")
+ assert len(_ip_address) == 4
+ for n in range(4):
+ assert int(_ip_address[n]) < 256
+ soc.add_constant(f"{name}{n+1}", int(_ip_address[n]))
+
+def add_mac_address_constants(soc, name, mac_address):
+ assert mac_address < 2**48
+ for n in range(6):
+ soc.add_constant(f"{name}{n+1}", (mac_address >> ((5 - n) * 8)) & 0xff)
+
# SoCError -----------------------------------------------------------------------------------------
class SoCError(Exception):
@@ -68,6 +81,7 @@ class SoCRegion:
self.mode = mode
self.cached = cached
self.linker = linker
+ self.type = ""
def decoder(self, bus):
origin = self.origin
@@ -649,9 +663,9 @@ class SoCLocHandler(LiteXModule):
class SoCCSRHandler(SoCLocHandler):
supported_data_width = [8, 32]
- supported_address_width = [14+i for i in range(4)]
+ supported_address_width = [14, 15, 16, 17, 18]
supported_alignment = [32]
- supported_paging = [0x800*2**i for i in range(4)]
+ supported_paging = [0x400, 0x800, 0x1000, 0x2000, 0x4000]
supported_ordering = ["big", "little"]
# Creation -------------------------------------------------------------------------------------
@@ -1246,7 +1260,7 @@ class SoC(LiteXModule, SoCCoreCompat):
if hasattr(self, "ctrl") and self.bus.timeout is not None:
if hasattr(self.ctrl, "bus_error") and hasattr(self.bus._interconnect, "timeout"):
self.comb += self.ctrl.bus_error.eq(self.bus._interconnect.timeout.error)
- self.add_config("BUS_STANDARD", self.bus.standard.upper())
+ self.add_config("BUS_STANDARD", self.bus.standard)
self.add_config("BUS_DATA_WIDTH", self.bus.data_width)
self.add_config("BUS_ADDRESS_WIDTH", self.bus.address_width)
self.add_config("BUS_BURSTING", int(self.bus.bursting))
@@ -1651,9 +1665,9 @@ class LiteXSoC(SoC):
else:
mem_wb = wishbone.Interface(
data_width = self.cpu.mem_axi.data_width,
- adr_width = 32-log2_int(mem_bus.data_width//8,
+ adr_width = 32-log2_int(mem_bus.data_width//8),
addressing = "word",
- ))
+ )
mem_a2w = axi.AXI2Wishbone(
axi = mem_bus,
wishbone = mem_wb,
@@ -1726,7 +1740,9 @@ class LiteXSoC(SoC):
nrxslots = 2, rxslots_read_only = True,
ntxslots = 2, txslots_write_only = False,
with_timestamp = False,
- with_timing_constraints = True):
+ with_timing_constraints = True,
+ local_ip = None,
+ remote_ip = None):
# Imports
from liteeth.mac import LiteEthMAC
from liteeth.phy.model import LiteEthPHYModel
@@ -1764,8 +1780,15 @@ class LiteXSoC(SoC):
# Dynamic IP (if enabled).
if dynamic_ip:
+ assert local_ip is None
self.add_constant("ETH_DYNAMIC_IP")
+ # Local/Remote IP Configuration (optional).
+ if local_ip:
+ add_ip_address_constants(self, "LOCALIP", local_ip)
+ if remote_ip:
+ add_ip_address_constants(self, "REMOTEIP", remote_ip)
+
# Software Debug
if software_debug:
self.add_constant("ETH_UDP_TX_DEBUG")
@@ -1792,7 +1815,11 @@ class LiteXSoC(SoC):
buffer_depth = 16,
with_ip_broadcast = True,
with_timing_constraints = True,
- with_ethmac = False):
+ with_ethmac = False,
+ ethmac_address = 0x10e2d5000001,
+ ethmac_local_ip = "192.168.1.51",
+ ethmac_remote_ip = "192.168.1.100"):
+
# Imports
from liteeth.core import LiteEthUDPIPCore
from liteeth.frontend.etherbone import LiteEthEtherbone
@@ -1819,7 +1846,8 @@ class LiteXSoC(SoC):
ethcore = ClockDomainsRenamer({
"eth_tx": phy_cd + "_tx",
"eth_rx": phy_cd + "_rx",
- "sys": phy_cd + "_rx"})(ethcore)
+ "sys" : {True: "sys", False: phy_cd + "_rx"}[with_ethmac],
+ })(ethcore)
self.add_module(name=f"ethcore_{name}", module=ethcore)
etherbone_cd = "sys"
@@ -1850,6 +1878,9 @@ class LiteXSoC(SoC):
# Ethernet MAC (CPU).
if with_ethmac:
+ assert mac_address != ethmac_address
+ assert ip_address != ethmac_local_ip
+
self.check_if_exists("ethmac")
ethcore.autocsr_exclude = {"mac"}
# Software Interface.
@@ -1863,8 +1894,12 @@ class LiteXSoC(SoC):
self.add_constant("ETH_PHY_NO_RESET") # Disable reset from BIOS to avoid disabling Hardware Interface.
+ add_ip_address_constants(self, "LOCALIP", ethmac_local_ip)
+ add_ip_address_constants(self, "REMOTEIP", ethmac_remote_ip)
+ add_mac_address_constants(self, "MACADDR", ethmac_address)
+
# Add SPI Flash --------------------------------------------------------------------------------
- def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=None, module=None, phy=None, rate="1:1", software_debug=False, **kwargs):
+ def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=20e6, module=None, phy=None, rate="1:1", software_debug=False, **kwargs):
# Imports.
from litespi import LiteSPI
from litespi.phy.generic import LiteSPIPHY
@@ -1872,14 +1907,15 @@ class LiteXSoC(SoC):
# Checks/Parameters.
assert mode in ["1x", "4x"]
- if clk_freq is None: clk_freq = self.sys_clk_freq
+ default_divisor = math.ceil(self.sys_clk_freq/(2*clk_freq)) - 1
+ clk_freq = int(self.sys_clk_freq/(2*(default_divisor + 1)))
# PHY.
spiflash_phy = phy
if spiflash_phy is None:
self.check_if_exists(f"{name}_phy")
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), rate=rate)
+ spiflash_phy = LiteSPIPHY(spiflash_pads, module, device=self.platform.device, default_divisor=default_divisor, rate=rate)
self.add_module(name=f"{name}_phy", module=spiflash_phy)
# Core.
@@ -1890,14 +1926,14 @@ class LiteXSoC(SoC):
self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region)
# Constants.
- self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq)
- self.add_constant(f"{name}_MODULE_NAME", module.name.upper())
+ 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 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 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")
diff --git a/litex/soc/interconnect/ahb.py b/litex/soc/interconnect/ahb.py
index a39d3d2e2..178eeb346 100644
--- a/litex/soc/interconnect/ahb.py
+++ b/litex/soc/interconnect/ahb.py
@@ -15,38 +15,37 @@ from litex.gen import *
# Helpers ------------------------------------------------------------------------------------------
-class TransferType(IntEnum):
+class AHBTransferType(IntEnum):
"""Defines types of AHB transfers."""
IDLE = 0
BUSY = 1
NONSEQUENTIAL = 2
SEQUENTIAL = 3
-# AHB Interface ------------------------------------------------------------------------------------
+# AHB Definition -----------------------------------------------------------------------------------
-class Interface(Record):
- """Sets up the AHB interface signals for master and slave."""
- adr_width = 32
- data_width = 32
- addressing = "byte"
- master_signals = [
- ("addr", adr_width),
- ("burst", 3),
- ("mastlock", 1),
- ("prot", 4),
- ("size", 3),
- ("trans", 2),
- ("wdata", data_width),
- ("write", 1),
- ("sel", 1),
- ]
- slave_signals = [
- ("rdata", data_width),
- ("readyout", 1),
- ("resp", 1),
- ]
- def __init__(self):
- Record.__init__(self, set_layout_parameters(self.master_signals + self.slave_signals))
+def ahb_description(data_width, address_width):
+ return [
+ ("addr", address_width, DIR_M_TO_S),
+ ("burst", 3, DIR_M_TO_S),
+ ("mastlock", 1, DIR_M_TO_S),
+ ("prot", 4, DIR_M_TO_S),
+ ("size", 3, DIR_M_TO_S),
+ ("trans", 2, DIR_M_TO_S),
+ ("wdata", data_width, DIR_M_TO_S),
+ ("write", 1, DIR_M_TO_S),
+ ("sel", 1, DIR_M_TO_S),
+ ("rdata", data_width, DIR_S_TO_M),
+ ("readyout", 1, DIR_S_TO_M),
+ ("resp", 1, DIR_S_TO_M),
+]
+
+class AHBInterface(Record):
+ def __init__(self, data_width=32, address_width=32):
+ Record.__init__(self, ahb_description(data_width, address_width))
+ self.data_width = data_width
+ self.address_width = address_width
+ self.addressing = "byte"
# AHB to Wishbone ---------------------------------------------------------------------------------
@@ -62,32 +61,83 @@ class AHB2Wishbone(LiteXModule):
"word" : log2_int(ahb.data_width//8),
"byte" : 0
}[wishbone.addressing]
- assert ahb.data_width == wishbone.data_width
- assert ahb.adr_width == wishbone.adr_width + wishbone_adr_shift
+ assert ahb.data_width in [32, 64]
+ assert ahb.data_width == wishbone.data_width
+ assert ahb.address_width == wishbone.adr_width + wishbone_adr_shift
+
+ def wishbone_sel_decoder(ahb_size, ahb_addr):
+ if ahb.data_width == 64:
+ wishbone_sel = Signal(8)
+ self.comb += Case(ahb_size, {
+ # 8-bit access.
+ 0b00 : Case(ahb_addr[0:3], {
+ 0b000 : wishbone_sel.eq(0b0000_0001),
+ 0b001 : wishbone_sel.eq(0b0000_0010),
+ 0b010 : wishbone_sel.eq(0b0000_0100),
+ 0b011 : wishbone_sel.eq(0b0000_1000),
+ 0b100 : wishbone_sel.eq(0b0001_0000),
+ 0b101 : wishbone_sel.eq(0b0010_0000),
+ 0b110 : wishbone_sel.eq(0b0100_0000),
+ 0b111 : wishbone_sel.eq(0b1000_0000),
+ }),
+ # 16-bit access.
+ 0b01 : Case(ahb_addr[1:3], {
+ 0b00 : wishbone_sel.eq(0b0000_0011),
+ 0b01 : wishbone_sel.eq(0b0000_1100),
+ 0b10 : wishbone_sel.eq(0b0011_0000),
+ 0b11 : wishbone_sel.eq(0b1100_0000),
+ }),
+ # 32-bit access.
+ 0b10 : Case(ahb_addr[2:3], {
+ 0b0 : wishbone_sel.eq(0b0000_1111),
+ 0b1 : wishbone_sel.eq(0b1111_0000),
+ }),
+ # 64-bit access.
+ 0b11 : wishbone_sel.eq(0b1111_1111),
+ })
+ return wishbone_sel
+ if ahb.data_width == 32:
+ wishbone_sel = Signal(4)
+ self.comb += Case(ahb_size, {
+ # 8-bit access.
+ 0b00 : Case(ahb_addr[0:2], {
+ 0b00 : wishbone_sel.eq(0b0001),
+ 0b01 : wishbone_sel.eq(0b0010),
+ 0b10 : wishbone_sel.eq(0b0100),
+ 0b11 : wishbone_sel.eq(0b1000),
+ }),
+ # 16-bit access.
+ 0b01 : Case(ahb_addr[1:2], {
+ 0b0 : wishbone_sel.eq(0b0011),
+ 0b1 : wishbone_sel.eq(0b1100),
+ }),
+ # 32-bit access.
+ 0b10 : wishbone_sel.eq(0b1111),
+ # 64-bit access (Should not happen but do a full 32-bit access).
+ 0b11 : wishbone_sel.eq(0b1111),
+ })
+ return wishbone_sel
# FSM.
self.fsm = fsm = FSM()
- fsm.act("IDLE",
+ fsm.act("ADDRESS-PHASE",
ahb.readyout.eq(1),
If(ahb.sel &
- (ahb.size == wishbone_adr_shift) &
- (ahb.trans == TransferType.NONSEQUENTIAL),
- NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]),
- NextValue(wishbone.dat_w, ahb.wdata),
- NextValue(wishbone.we, ahb.write),
- NextValue(wishbone.sel, 2**len(wishbone.sel) - 1),
- NextState("ACT"),
+ (ahb.size <= log2_int(ahb.data_width//8)) &
+ (ahb.trans == AHBTransferType.NONSEQUENTIAL),
+ NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]),
+ NextValue(wishbone.we, ahb.write),
+ NextValue(wishbone.sel, wishbone_sel_decoder(ahb.size, ahb.addr)),
+ NextState("DATA-PHASE"),
)
)
- fsm.act("ACT",
+ fsm.act("DATA-PHASE",
wishbone.stb.eq(1),
wishbone.cyc.eq(1),
+ wishbone.dat_w.eq(ahb.wdata),
+ ahb.resp.eq(wishbone.err),
If(wishbone.ack,
- If(~wishbone.we,
- NextValue(ahb.rdata, wishbone.dat_r)
- ),
- NextState("IDLE")
+ NextValue(ahb.rdata, wishbone.dat_r),
+ NextState("ADDRESS-PHASE")
)
)
-
- self.comb += ahb.resp.eq(wishbone.err)
diff --git a/litex/soc/software/bios/boot.c b/litex/soc/software/bios/boot.c
index 34079b69d..7c62409e4 100755
--- a/litex/soc/software/bios/boot.c
+++ b/litex/soc/software/bios/boot.c
@@ -304,7 +304,11 @@ int serialboot(void)
#define TFTP_SERVER_PORT 69
#endif
+#ifdef MACADDR1
+static unsigned char macadr[6] = {MACADDR1, MACADDR2, MACADDR3, MACADDR4, MACADDR5, MACADDR6};
+#else
static unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
+#endif
#ifdef LOCALIP1
static unsigned int local_ip[4] = {LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4};
diff --git a/litex/soc/software/bios/cmds/cmd_bios.c b/litex/soc/software/bios/cmds/cmd_bios.c
index 2006dd540..5acf67140 100644
--- a/litex/soc/software/bios/cmds/cmd_bios.c
+++ b/litex/soc/software/bios/cmds/cmd_bios.c
@@ -115,6 +115,8 @@ static void crc_handler(int nb_params, char **params)
return;
}
+ flush_cpu_dcache();
+ flush_l2_cache();
printf("CRC32: %08x", crc32((unsigned char *)addr, length));
}
diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c
index 69fbd22af..67ca3d590 100644
--- a/litex/soc/software/bios/main.c
+++ b/litex/soc/software/bios/main.c
@@ -110,7 +110,7 @@ __attribute__((__used__)) int main(int i, char **c)
printf("\e[1m /____/_/\\__/\\__/_/|_|\e[0m\n");
printf("\e[1m Build your hardware, easily!\e[0m\n");
printf("\n");
- printf(" (c) Copyright 2012-2023 Enjoy-Digital\n");
+ printf(" (c) Copyright 2012-2024 Enjoy-Digital\n");
printf(" (c) Copyright 2007-2015 M-Labs\n");
printf("\n");
#ifndef CONFIG_BIOS_NO_BUILD_TIME
@@ -125,7 +125,11 @@ __attribute__((__used__)) int main(int i, char **c)
printf("--=============== \e[1mSoC\e[0m ==================--\n");
printf("\e[1mCPU\e[0m:\t\t%s @ %dMHz\n",
CONFIG_CPU_HUMAN_NAME,
+#ifdef CONFIG_CPU_CLK_FREQ
+ CONFIG_CPU_CLK_FREQ/1000000);
+#else
CONFIG_CLOCK_FREQUENCY/1000000);
+#endif
printf("\e[1mBUS\e[0m:\t\t%s %d-bit @ %dGiB\n",
CONFIG_BUS_STANDARD,
CONFIG_BUS_DATA_WIDTH,
diff --git a/litex/soc/software/liblitespi/spiflash.c b/litex/soc/software/liblitespi/spiflash.c
index 410c43948..53bb936ef 100644
--- a/litex/soc/software/liblitespi/spiflash.c
+++ b/litex/soc/software/liblitespi/spiflash.c
@@ -1,6 +1,7 @@
// This file is Copyright (c) 2020 Antmicro
// License: BSD
+#include
#include
#include
#include
@@ -25,6 +26,8 @@ int spiflash_freq_init(void)
unsigned int lowest_div, crc, crc_test;
lowest_div = spiflash_phy_clk_divisor_read();
+ flush_cpu_dcache();
+ flush_l2_cache();
crc = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE);
crc_test = crc;
@@ -40,19 +43,21 @@ int spiflash_freq_init(void)
while((crc == crc_test) && (lowest_div-- > 0)) {
spiflash_phy_clk_divisor_write((uint32_t)lowest_div);
+ flush_cpu_dcache();
+ flush_l2_cache();
crc_test = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE);
#ifdef 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_PHY_FREQUENCY/(2*(1 + lowest_div)))/1000000);
+ printf("SPI Flash clk configured to %d MHz\n", CONFIG_CLOCK_FREQUENCY/(2*(1+lowest_div)*1000000));
spiflash_phy_clk_divisor_write(lowest_div);
#else
- printf("SPI Flash clk configured to %ld MHz\n", (unsigned long)(SPIFLASH_PHY_FREQUENCY/1e6));
+ printf("SPI Flash clk configured to %ld MHz\n", SPIFLASH_PHY_FREQUENCY/1000000);
#endif
@@ -63,7 +68,7 @@ void spiflash_dummy_bits_setup(unsigned int dummy_bits)
{
spiflash_core_mmap_dummy_bits_write((uint32_t)dummy_bits);
#ifdef SPIFLASH_DEBUG
- printf("Dummy bits set to: %d\n\r", spiflash_core_mmap_dummy_bits_read());
+ printf("Dummy bits set to: %" PRIx32 "\n\r", spiflash_core_mmap_dummy_bits_read());
#endif
}
@@ -107,7 +112,7 @@ static uint32_t transfer_byte(uint8_t b)
return spiflash_core_master_rxtx_read();
}
-static void transfer_cmd(uint8_t *bs, uint8_t *resp, int len)
+static void transfer_cmd(volatile uint8_t *bs, volatile uint8_t *resp, int len)
{
spiflash_core_master_phyconfig_len_write(8);
spiflash_core_master_phyconfig_width_write(1);
@@ -170,7 +175,7 @@ static void page_program(uint32_t addr, uint8_t *data, int len)
w_buf[1] = addr>>16;
w_buf[2] = addr>>8;
w_buf[3] = addr>>0;
- memcpy(w_buf+4, data, len);
+ memcpy((void *)w_buf+4, (void *)data, len);
transfer_cmd(w_buf, r_buf, len+4);
}
diff --git a/setup.py b/setup.py
index 08af7085f..a52575a62 100755
--- a/setup.py
+++ b/setup.py
@@ -4,30 +4,30 @@ from setuptools import setup
from setuptools import find_packages
-with open("README.md", "r") as fp:
+with open("README.md", "r", encoding="utf-8") as fp:
long_description = fp.read()
setup(
- name="litex",
- version="2023.08",
- description="Python SoC/Core builder for building FPGA based systems.",
- long_description=long_description,
- long_description_content_type="text/markdown",
- author="Florent Kermarrec",
- author_email="florent@enjoy-digital.fr",
- url="http://enjoy-digital.fr",
- download_url="https://github.com/enjoy-digital/litex",
- test_suite="test",
- license="BSD",
- python_requires="~=3.6",
- install_requires=[
+ name = "litex",
+ version = "2023.12",
+ description = "Python SoC/Core builder for building FPGA based systems.",
+ long_description = long_description,
+ long_description_content_type = "text/markdown",
+ author = "Florent Kermarrec",
+ author_email = "florent@enjoy-digital.fr",
+ url = "http://enjoy-digital.fr",
+ download_url = "https://github.com/enjoy-digital/litex",
+ test_suite = "test",
+ license = "BSD",
+ python_requires = "~=3.7",
+ install_requires = [
"migen",
"packaging",
"pyserial",
"requests",
],
- extras_require={
+ extras_require = {
"develop": [
"meson"
"pexpect"
@@ -35,14 +35,14 @@ setup(
"requests"
]
},
- packages=find_packages(exclude=("test*", "sim*", "doc*")),
- include_package_data=True,
- package_data={
+ packages = find_packages(exclude=("test*", "sim*", "doc*")),
+ include_package_data = True,
+ package_data = {
'litex.soc.doc': ['static/*']
},
- platforms=["Any"],
- keywords="HDL ASIC FPGA hardware design",
- classifiers=[
+ platforms = ["Any"],
+ keywords = "HDL ASIC FPGA hardware design",
+ classifiers = [
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
"Environment :: Console",
"Development Status :: 3 - Alpha",
@@ -51,7 +51,7 @@ setup(
"Operating System :: OS Independent",
"Programming Language :: Python",
],
- entry_points={
+ entry_points = {
"console_scripts": [
# Terminal/Server/Client.
"litex_term = litex.tools.litex_term:main",