From ca63db4040e9a53a6c0982ad88cf7c98ca85f29b Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 5 Mar 2019 12:26:10 +0100 Subject: [PATCH 01/52] bios/sdram: use burstdet detection for ECP5DDRPHY init --- litex/soc/software/bios/sdram.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index 401b73ffb..4ffb108ee 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -210,13 +210,14 @@ void sdrwr(char *startaddr) #if defined (USDDRPHY) #define ERR_DDRPHY_DELAY 512 +#define ERR_DDRPHY_BITSLIP DFII_NPHASES*2 #elif defined (ECP5DDRPHY) #define ERR_DDRPHY_DELAY 8 +#define ERR_DDRPHY_BITSLIP 1 #else #define ERR_DDRPHY_DELAY 32 -#endif - #define ERR_DDRPHY_BITSLIP DFII_NPHASES*2 +#endif #define NBMODULES DFII_PIX_DATA_SIZE*DFII_NPHASES/8 @@ -461,6 +462,9 @@ static int read_level_scan(int module, int bitslip) int show = 1; #ifdef USDDRPHY show = (j%16 == 0); +#endif +#ifdef ECP5DDRPHY + ddrphy_burstdet_clr_write(1); #endif command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); cdelay(15); @@ -471,6 +475,10 @@ static int read_level_scan(int module, int bitslip) if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1]) working = 0; } +#ifdef ECP5DDRPHY + if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1) + working = 0; +#endif if (show) printf("%d", working); score += working; @@ -526,6 +534,9 @@ static void read_level(int module) delay = 0; read_delay_rst(module); while(1) { +#ifdef ECP5DDRPHY + ddrphy_burstdet_clr_write(1); +#endif command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); cdelay(15); working = 1; @@ -535,6 +546,10 @@ static void read_level(int module) if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1]) working = 0; } +#ifdef ECP5DDRPHY + if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1) + working = 0; +#endif if(working) break; delay++; @@ -557,6 +572,9 @@ static void read_level(int module) /* Find largest working delay */ while(1) { +#ifdef ECP5DDRPHY + ddrphy_burstdet_clr_write(1); +#endif command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); cdelay(15); working = 1; @@ -566,6 +584,10 @@ static void read_level(int module) if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1]) working = 0; } +#ifdef ECP5DDRPHY + if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1) + working = 0; +#endif if(!working) break; delay++; From 7de1fe519a86b258ad2f3a7bc4584f1302c3ee1f Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 5 Mar 2019 13:23:38 +0100 Subject: [PATCH 02/52] targets/versa_ecp5: update ECP5DDRPHY on BaseSoC, add EthernetSoC --- litex/boards/targets/versa_ecp5.py | 52 ++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/litex/boards/targets/versa_ecp5.py b/litex/boards/targets/versa_ecp5.py index e670499eb..f82e42e80 100755 --- a/litex/boards/targets/versa_ecp5.py +++ b/litex/boards/targets/versa_ecp5.py @@ -13,7 +13,10 @@ from litex.soc.integration.soc_sdram import * from litex.soc.integration.builder import * from litedram.modules import MT41K64M16 -from litedram.phy import ECP5DDRPHY, ECP5DDRPHYInit +from litedram.phy import ECP5DDRPHY + +from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII +from liteeth.core.mac import LiteEthMAC # CRG ---------------------------------------------------------------------------------------------- @@ -70,7 +73,7 @@ class BaseSoC(SoCSDRAM): csr_map.update(SoCSDRAM.csr_map) def __init__(self, toolchain="diamond", **kwargs): platform = versa_ecp5.Platform(toolchain=toolchain) - sys_clk_freq = int(50e6) + sys_clk_freq = int(75e6) SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq, integrated_rom_size=0x8000, **kwargs) @@ -84,24 +87,61 @@ class BaseSoC(SoCSDRAM): platform.request("ddram"), sys_clk_freq=sys_clk_freq) self.add_constant("ECP5DDRPHY", None) - ddrphy_init = ECP5DDRPHYInit(self.crg, self.ddrphy) - self.submodules += ddrphy_init + self.comb += crg.stop.eq(self.ddrphy.init.stop) sdram_module = MT41K64M16(sys_clk_freq, "1:2") self.register_sdram(self.ddrphy, sdram_module.geom_settings, sdram_module.timing_settings) +# EthernetSoC -------------------------------------------------------------------------------------- + +class EthernetSoC(BaseSoC): + csr_map = { + "ethphy": 18, + "ethmac": 19 + } + csr_map.update(BaseSoC.csr_map) + + interrupt_map = { + "ethmac": 3, + } + interrupt_map.update(BaseSoC.interrupt_map) + + mem_map = { + "ethmac": 0x30000000, # (shadow @0xb0000000) + } + mem_map.update(BaseSoC.mem_map) + + def __init__(self, toolchain="diamond", **kwargs): + BaseSoC.__init__(self, toolchain=toolchain, **kwargs) + + self.submodules.ethphy = LiteEthPHYRGMII( + self.platform.request("eth_clocks"), + self.platform.request("eth")) + self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, + interface="wishbone", endianness=self.cpu.endianness) + self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus) + self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000) + + self.ethphy.crg.cd_eth_rx.clk.attr.add("keep") + self.ethphy.crg.cd_eth_tx.clk.attr.add("keep") + self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk, 1e9/125e6) + self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk, 1e9/125e6) + # Build -------------------------------------------------------------------------------------------- def main(): - parser = argparse.ArgumentParser(description="LiteX SoC on ECP5") + parser = argparse.ArgumentParser(description="LiteX SoC on Versa ECP5") parser.add_argument("--gateware-toolchain", dest="toolchain", default="diamond", help='gateware toolchain to use, diamond (default) or trellis') builder_args(parser) soc_sdram_args(parser) + parser.add_argument("--with-ethernet", action="store_true", + help="enable Ethernet support") args = parser.parse_args() - soc = BaseSoC(toolchain=args.toolchain, **soc_sdram_argdict(args)) + cls = EthernetSoC if args.with_ethernet else BaseSoC + soc = cls(args.toolchain, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) builder.build() From 317dba831492474cde30b26a4324b3b684debcda Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 5 Mar 2019 18:01:03 +0100 Subject: [PATCH 03/52] software/bios/sdram: use specific ERR_DDRPHY_BITSLIP/NMODULES computation In the future, the PHYs should generated these constants. --- litex/soc/software/bios/sdram.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index 4ffb108ee..409a7b812 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -210,17 +210,18 @@ void sdrwr(char *startaddr) #if defined (USDDRPHY) #define ERR_DDRPHY_DELAY 512 -#define ERR_DDRPHY_BITSLIP DFII_NPHASES*2 +#define ERR_DDRPHY_BITSLIP 8 +#define NBMODULES DFII_PIX_DATA_SIZE/2 #elif defined (ECP5DDRPHY) #define ERR_DDRPHY_DELAY 8 #define ERR_DDRPHY_BITSLIP 1 +#define NBMODULES DFII_PIX_DATA_SIZE/4 #else #define ERR_DDRPHY_DELAY 32 -#define ERR_DDRPHY_BITSLIP DFII_NPHASES*2 +#define ERR_DDRPHY_BITSLIP 8 +#define NBMODULES DFII_PIX_DATA_SIZE/2 #endif -#define NBMODULES DFII_PIX_DATA_SIZE*DFII_NPHASES/8 - #ifdef CSR_DDRPHY_WLEVEL_EN_ADDR void sdrwlon(void) From b014c7194be669d8c471c11074e775b0d6e6d471 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Wed, 6 Mar 2019 12:59:49 -0500 Subject: [PATCH 04/52] build/lattice/trellis: also generate bitstream in svf format Before being able to program the board (e.g., with openocd), one would have to convert the bitstream file to .svf using a python script included with the source trellis distribution. However,the trellis 'ecppack' utility can also generate .svf bitstream files directly. --- litex/build/lattice/trellis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/build/lattice/trellis.py b/litex/build/lattice/trellis.py index f4c7c05cf..63a8d75d4 100644 --- a/litex/build/lattice/trellis.py +++ b/litex/build/lattice/trellis.py @@ -143,7 +143,7 @@ class LatticeTrellisToolchain: self.build_template = [ "yosys -q -l {build_name}.rpt {build_name}.ys", "nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config --{architecture} --package {package} --freq {freq_constraint}", - "ecppack {build_name}.config {build_name}.bit" + "ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit" ] self.freq_constraints = dict() From aed2e9b4b57e7af39fa4c736fc293c2bb63762b6 Mon Sep 17 00:00:00 2001 From: chmousset Date: Thu, 7 Mar 2019 09:40:58 +0100 Subject: [PATCH 05/52] [fix] utils was not installed from pip --- litex/utils/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 litex/utils/__init__.py diff --git a/litex/utils/__init__.py b/litex/utils/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/litex/utils/__init__.py @@ -0,0 +1 @@ + From 411bca790a6a263d994d724f8f366ce5d98e75cc Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 13 Mar 2019 10:42:10 +0100 Subject: [PATCH 06/52] utils/litex_sim: increase default integrated_main_ram_size to 256MB, automatically boot on main_ram when ram_init is specified --- litex/utils/litex_sim.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/litex/utils/litex_sim.py b/litex/utils/litex_sim.py index 4e6eb88dc..868dbb197 100755 --- a/litex/utils/litex_sim.py +++ b/litex/utils/litex_sim.py @@ -218,11 +218,11 @@ def main(): if args.rom_init: soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init) if not args.with_sdram: - soc_kwargs["integrated_main_ram_size"] = 0x10000 + soc_kwargs["integrated_main_ram_size"] = 0x1000000 # 256 MB if args.ram_init is not None: soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init) - soc_kwargs["integrated_main_ram_size"] = max(len(soc_kwargs["integrated_main_ram_init"]), 0x10000) else: + assert args.ram_init is None soc_kwargs["integrated_main_ram_size"] = 0x0 if args.with_ethernet: sim_config.add_module("ethernet", "eth", args={"interface": "tap0", "ip": "192.168.1.100"}) @@ -235,6 +235,8 @@ def main(): with_etherbone=args.with_etherbone, with_analyzer=args.with_analyzer, **soc_kwargs) + if args.ram_init is not None: + soc.add_constant("ROM_BOOT_ADDRESS", 0x40000000) builder_kwargs["csr_csv"] = "csr.csv" builder = Builder(soc, **builder_kwargs) vns = builder.build(run=False, threads=args.threads, sim_config=sim_config, trace=args.trace) From a549f0941be25cd7b329e492081c1d84cd9d3583 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 13 Mar 2019 10:56:09 +0100 Subject: [PATCH 07/52] utils/litex_sim: handle cpu_endianness for rom-init/ram-init --- litex/utils/litex_sim.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/litex/utils/litex_sim.py b/litex/utils/litex_sim.py index 868dbb197..3a485a97c 100755 --- a/litex/utils/litex_sim.py +++ b/litex/utils/litex_sim.py @@ -215,12 +215,18 @@ def main(): sim_config = SimConfig(default_clk="sys_clk") sim_config.add_module("serial2console", "serial") + + cpu_endianness = "big" + if "cpu_type" in soc_kwargs: + if soc_kwargs["cpu_type"] in ["picorv32", "vexriscv"]: + cpu_endianness = "little" + if args.rom_init: - soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init) + soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init, cpu_endianness) if not args.with_sdram: soc_kwargs["integrated_main_ram_size"] = 0x1000000 # 256 MB if args.ram_init is not None: - soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init) + soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init, cpu_endianness) else: assert args.ram_init is None soc_kwargs["integrated_main_ram_size"] = 0x0 From b04a756abb03cce48a1be84878c02c5a5bbe8b70 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 15 Mar 2019 17:49:39 +0100 Subject: [PATCH 08/52] vexriscv/core: fix min variant --- litex/soc/cores/cpu/vexriscv/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py index 1edcc3f7b..3700bf44c 100644 --- a/litex/soc/cores/cpu/vexriscv/core.py +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -155,8 +155,8 @@ class VexRiscv(Module, AutoCSR): "std_debug": "VexRiscv_Debug.v", "lite": "VexRiscv_Lite.v", "lite_debug": "VexRiscv_LiteDebug.v", - "min": "VexRiscv_Lite.v", - "min_debug": "VexRiscv_LiteDebug.v", + "min": "VexRiscv_Min.v", + "min_debug": "VexRiscv_MinDebug.v", } cpu_filename = verilog_variants[variant] vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog") From 7b88980d06d2526123965b86257ea4eb4ef86915 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 15 Mar 2019 18:16:25 +0100 Subject: [PATCH 09/52] vexriscv: allow user to use an external variant --- litex/soc/cores/cpu/vexriscv/core.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py index 3700bf44c..5a1afedcb 100644 --- a/litex/soc/cores/cpu/vexriscv/core.py +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -18,6 +18,9 @@ class VexRiscv(Module, AutoCSR): variant = "std_debug" if variant == "debug" else variant variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug") assert variant in variants, "Unsupported variant %s" % variant + self.platform = platform + self.variant = variant + self.external_variant = None self.reset = Signal() self.ibus = ibus = wishbone.Interface() self.dbus = dbus = wishbone.Interface() @@ -59,9 +62,6 @@ class VexRiscv(Module, AutoCSR): if "debug" in variant: self.add_debug() - # add verilog sources - self.add_sources(platform, variant) - def add_debug(self): debug_reset = Signal() @@ -162,5 +162,11 @@ class VexRiscv(Module, AutoCSR): vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog") platform.add_source(os.path.join(vdir, cpu_filename)) + def use_external_variant(self, variant_filename): + self.external_variant = True + self.platform.add_source(variant_filename) + def do_finalize(self): + if not self.external_variant: + self.add_sources(self.platform, self.variant) self.specials += Instance("VexRiscv", **self.cpu_params) From 7bc13ba841d129039d702beb623078138c2db023 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 16 Mar 2019 09:33:16 +0100 Subject: [PATCH 10/52] build/microsemi/libero_soc: add linux build script support --- litex/build/microsemi/libero_soc.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/litex/build/microsemi/libero_soc.py b/litex/build/microsemi/libero_soc.py index 4327f6239..a82ac5862 100644 --- a/litex/build/microsemi/libero_soc.py +++ b/litex/build/microsemi/libero_soc.py @@ -23,6 +23,8 @@ def _format_io_constraint(c): elif isinstance(c, IOStandard): return "-io_std {} ".format(c.name) elif isinstance(c, Misc): + return "-RES_PULL {} ".format(c.misc) + else: raise NotImplementedError @@ -183,7 +185,10 @@ def _build_script(build_name, device, toolchain_path, ver=None): copy_stmt = "copy" fail_stmt = " || exit /b" else: - raise NotImplementedError + script_ext = ".sh" + build_script_contents = "# Autogenerated by Migen\n\n" + copy_stmt = "cp" + fail_stmt = " || exit 1" build_script_file = "build_" + build_name + script_ext tools.write_to_file(build_script_file, build_script_contents, From 3f386dad7dd3342498041cfe7c1ab68605cb35d4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 16 Mar 2019 21:23:36 +0100 Subject: [PATCH 11/52] soc_core/get_mem_data: add json support example of json file: { "vmlinux.bin": "0x00000000", "vmlinux.dtb": "0x01000000", "initramdisk.gz": "0x01002000" } --- litex/soc/integration/soc_core.py | 47 ++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index ed9c02af0..b8897d00b 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -1,5 +1,7 @@ +import os import struct import inspect +import json from operator import itemgetter from migen import * @@ -36,24 +38,43 @@ def mem_decoder(address, start=26, end=29): def get_mem_data(filename, endianness="big", mem_size=None): - data = [] - with open(filename, "rb") as mem_file: - while True: - w = mem_file.read(4) - if not w: - break - if endianness == "little": - data.append(struct.unpack("I", w)[0]) - data_size = len(data)*4 + # create memory regions + _, ext = os.path.splitext(filename) + if ext == ".json": + f = open(filename, "r") + regions = json.load(f) + f.close() + else: + regions = {filename: "0x00000000"} + + # determine data_size + data_size = 0 + for filename, base in regions.items(): + data_size = max(int(base, 16) + os.path.getsize(filename), data_size) assert data_size > 0 if mem_size is not None: assert data_size < mem_size, ( "file is too big: {}/{} bytes".format( - data_size, mem_size)) - return data + data_size, mem_size)) + # fill data + data = [0]*(data_size//4) + for filename, base in regions.items(): + with open(filename, "rb") as f: + i = 0 + while True: + w = f.read(4) + if not w: + break + if len(w) != 4: + for i in range(len(w), 4): + w += b'\x00' + if endianness == "little": + data[i] = struct.unpack("I", w)[0] + i += 1 + return data class ReadOnlyDict(dict): def __readonly__(self, *args, **kwargs): From fd7ed6c1ec24ffbdbebb465bc8cc4713b6d40181 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 16 Mar 2019 21:25:02 +0100 Subject: [PATCH 12/52] utils/litex_sim: fix main_ram_size --- litex/utils/litex_sim.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/utils/litex_sim.py b/litex/utils/litex_sim.py index 3a485a97c..808bd8b9b 100755 --- a/litex/utils/litex_sim.py +++ b/litex/utils/litex_sim.py @@ -224,7 +224,7 @@ def main(): if args.rom_init: soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init, cpu_endianness) if not args.with_sdram: - soc_kwargs["integrated_main_ram_size"] = 0x1000000 # 256 MB + soc_kwargs["integrated_main_ram_size"] = 0x10000000 # 256 MB if args.ram_init is not None: soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init, cpu_endianness) else: From 57e1ccd5f8e96889965d235f59b16cca752c770b Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 22 Mar 2019 16:06:52 +0000 Subject: [PATCH 13/52] build/xilinx: Update Yosys write_edif parameters --- litex/build/xilinx/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/build/xilinx/common.py b/litex/build/xilinx/common.py index da22e6358..36da5b66e 100644 --- a/litex/build/xilinx/common.py +++ b/litex/build/xilinx/common.py @@ -265,7 +265,7 @@ setattr -set keep 1 a:async_reg=true synth_xilinx -top top -write_edif -attrprop {build_name}.edif +write_edif -pvector bra -attrprop {build_name}.edif """.format(build_name=build_name) ys_name = build_name + ".ys" From 552b0243b398502d6140715139c1739227851b0f Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 27 Mar 2019 21:15:14 +0100 Subject: [PATCH 14/52] soc/interconnect/axi: remove dead code (thanks gsomlo) --- litex/soc/interconnect/axi.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/litex/soc/interconnect/axi.py b/litex/soc/interconnect/axi.py index 7d0792cee..a110c36d2 100644 --- a/litex/soc/interconnect/axi.py +++ b/litex/soc/interconnect/axi.py @@ -78,8 +78,6 @@ class AXI2Wishbone(Module): NextState("DO-WRITE") ) ) - axi_ar_addr = Signal(32) - self.comb += axi_ar_addr.eq(axi.ar.addr - base_address) fsm.act("DO-READ", wishbone.stb.eq(1), wishbone.cyc.eq(1), From 449632e43012bee423c23e634cedf7e3f4ce8696 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Wed, 27 Mar 2019 16:38:25 -0400 Subject: [PATCH 15/52] soc/interconnect/axi: data/address length cleanup Instead of hard-coding data and address width to 32, assert that the AXI and Wishbone interfaces have *matching* address and data widths. --- litex/soc/interconnect/axi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/litex/soc/interconnect/axi.py b/litex/soc/interconnect/axi.py index a110c36d2..17d431e64 100644 --- a/litex/soc/interconnect/axi.py +++ b/litex/soc/interconnect/axi.py @@ -60,12 +60,12 @@ class AXIInterface(Record): class AXI2Wishbone(Module): def __init__(self, axi, wishbone, base_address): - assert axi.data_width == 32 - assert axi.address_width == 32 + assert axi.data_width == len(wishbone.dat_r) + assert axi.address_width == len(wishbone.adr) + 2 _data = Signal(axi.data_width) - _read_addr = Signal(32) - _write_addr = Signal(32) + _read_addr = Signal(axi.address_width) + _write_addr = Signal(axi.address_width) self.comb += _read_addr.eq(axi.ar.addr - base_address) self.comb += _write_addr.eq(axi.aw.addr - base_address) From 66dffb7071d661be40ac19ef786b22145b44a27b Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 29 Mar 2019 00:51:16 +0100 Subject: [PATCH 16/52] software/bios: improve readibility, add soc informations --- litex/soc/software/bios/main.c | 43 +++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 89a3b9cce..7ec5d7785 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -302,8 +302,7 @@ static void wcsr(char *csr, char *value) static void help(void) { - puts("LiteX SoC BIOS"); - puts("Available commands:"); + puts("LiteX BIOS, available commands:"); puts("mr - read address space"); puts("mw - write address space"); puts("mc - copy address space"); @@ -433,10 +432,10 @@ static void crcbios(void) length = (unsigned int)&_edata - offset_bios; actual_crc = crc32((unsigned char *)offset_bios, length); if(expected_crc == actual_crc) - printf("BIOS CRC passed (%08x)\n", actual_crc); + printf(" BIOS CRC passed (%08x)\n", actual_crc); else { - printf("BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc); - printf("The system will continue, but expect problems.\n"); + printf(" BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc); + printf(" The system will continue, but expect problems.\n"); } } @@ -509,12 +508,22 @@ int main(int i, char **c) irq_setmask(0); irq_setie(1); uart_init(); + printf("\n"); printf("\e[1m __ _ __ _ __\e[0m\n"); printf("\e[1m / / (_) /____ | |/_/\e[0m\n"); printf("\e[1m / /__/ / __/ -_)> <\e[0m\n"); printf("\e[1m /____/_/\\__/\\__/_/|_|\e[0m\n"); - printf("\e[1m SoC BIOS / CPU: "); + printf("\n"); + printf(" (c) Copyright 2012-2019 Enjoy-Digital\n"); + printf(" (c) Copyright 2012-2015 M-Labs Ltd\n"); + printf("\n"); + printf(" BIOS built on "__DATE__" "__TIME__"\n"); + crcbios(); + printf("\n"); + + printf("--============ \e[1mSoC info\e[0m ================--\n"); + printf("\e[1mCPU: \e[0m"); #ifdef __lm32__ printf("LM32"); #elif __or1k__ @@ -528,13 +537,14 @@ int main(int i, char **c) #else printf("Unknown"); #endif - printf(" / %3dMHz\e[0m\n", SYSTEM_CLOCK_FREQUENCY/1000000); + printf("\n"); + printf("\e[1mFrequency\e[0m: %dMHz\n", SYSTEM_CLOCK_FREQUENCY/1000000); + printf("\e[1mROM\e[0m: %dKB\n", ROM_SIZE/1024); + printf("\e[1mSRAM\e[0m: %dKB\n", SRAM_SIZE/1024); + printf("\e[1mMAIN-RAM\e[0m: %dKB\n", MAIN_RAM_SIZE/1024); + printf("\n"); - puts( - "(c) Copyright 2012-2018 Enjoy-Digital\n" - "(c) Copyright 2007-2018 M-Labs Limited\n" - "Built "__DATE__" "__TIME__"\n"); - crcbios(); + printf("--========= \e[1mPeripherals init\e[0m ===========--\n"); #ifdef CSR_ETHMAC_BASE eth_init(); #endif @@ -547,11 +557,16 @@ int main(int i, char **c) sdr_ok = 1; #endif #endif + if (sdr_ok !=1) + printf("Memory initialization failed\n"); + printf("\n"); + + printf("--========== \e[1mBoot sequence\e[0m =============--\n"); if(sdr_ok) boot_sequence(); - else - printf("Memory initialization failed\n"); + printf("\n"); + printf("--============= \e[1mConsole\e[0m ================--\n"); while(1) { putsnonl("\e[1mBIOS>\e[0m "); readstr(buffer, 64); From f4369c8fb2207721de4aa2b5d8957aab6bb5e946 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 29 Mar 2019 19:40:24 +0100 Subject: [PATCH 17/52] bios/main: remove csr functions (not used and only supported by lm32), improve help presentation --- litex/soc/software/bios/main.c | 124 +-------------------------------- 1 file changed, 3 insertions(+), 121 deletions(-) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 7ec5d7785..5560444ea 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -186,118 +186,6 @@ static void ident(void) printf("Ident: %s\n", buffer); } -#ifdef __lm32__ -enum { - CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA, - CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3, - CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3, -}; - -/* processor registers */ -static int parse_csr(const char *csr) -{ - if(!strcmp(csr, "ie")) return CSR_IE; - if(!strcmp(csr, "im")) return CSR_IM; - if(!strcmp(csr, "ip")) return CSR_IP; - if(!strcmp(csr, "icc")) return CSR_ICC; - if(!strcmp(csr, "dcc")) return CSR_DCC; - if(!strcmp(csr, "cc")) return CSR_CC; - if(!strcmp(csr, "cfg")) return CSR_CFG; - if(!strcmp(csr, "eba")) return CSR_EBA; - if(!strcmp(csr, "dc")) return CSR_DC; - if(!strcmp(csr, "deba")) return CSR_DEBA; - if(!strcmp(csr, "jtx")) return CSR_JTX; - if(!strcmp(csr, "jrx")) return CSR_JRX; - if(!strcmp(csr, "bp0")) return CSR_BP0; - if(!strcmp(csr, "bp1")) return CSR_BP1; - if(!strcmp(csr, "bp2")) return CSR_BP2; - if(!strcmp(csr, "bp3")) return CSR_BP3; - if(!strcmp(csr, "wp0")) return CSR_WP0; - if(!strcmp(csr, "wp1")) return CSR_WP1; - if(!strcmp(csr, "wp2")) return CSR_WP2; - if(!strcmp(csr, "wp3")) return CSR_WP3; - - return 0; -} - -static void rcsr(char *csr) -{ - unsigned int csr2; - register unsigned int value; - - if(*csr == 0) { - printf("rcsr \n"); - return; - } - - csr2 = parse_csr(csr); - if(csr2 == 0) { - printf("incorrect csr\n"); - return; - } - - switch(csr2) { - case CSR_IE: asm volatile ("rcsr %0,ie":"=r"(value)); break; - case CSR_IM: asm volatile ("rcsr %0,im":"=r"(value)); break; - case CSR_IP: asm volatile ("rcsr %0,ip":"=r"(value)); break; - case CSR_CC: asm volatile ("rcsr %0,cc":"=r"(value)); break; - case CSR_CFG: asm volatile ("rcsr %0,cfg":"=r"(value)); break; - case CSR_EBA: asm volatile ("rcsr %0,eba":"=r"(value)); break; - case CSR_DEBA: asm volatile ("rcsr %0,deba":"=r"(value)); break; - case CSR_JTX: asm volatile ("rcsr %0,jtx":"=r"(value)); break; - case CSR_JRX: asm volatile ("rcsr %0,jrx":"=r"(value)); break; - default: printf("csr write only\n"); return; - } - - printf("%08x\n", value); -} - -static void wcsr(char *csr, char *value) -{ - char *c; - unsigned int csr2; - register unsigned int value2; - - if((*csr == 0) || (*value == 0)) { - printf("wcsr
\n"); - return; - } - - csr2 = parse_csr(csr); - if(csr2 == 0) { - printf("incorrect csr\n"); - return; - } - value2 = strtoul(value, &c, 0); - if(*c != 0) { - printf("incorrect value\n"); - return; - } - - switch(csr2) { - case CSR_IE: asm volatile ("wcsr ie,%0"::"r"(value2)); break; - case CSR_IM: asm volatile ("wcsr im,%0"::"r"(value2)); break; - case CSR_ICC: asm volatile ("wcsr icc,%0"::"r"(value2)); break; - case CSR_DCC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break; - case CSR_EBA: asm volatile ("wcsr eba,%0"::"r"(value2)); break; - case CSR_DC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break; - case CSR_DEBA: asm volatile ("wcsr deba,%0"::"r"(value2)); break; - case CSR_JTX: asm volatile ("wcsr jtx,%0"::"r"(value2)); break; - case CSR_JRX: asm volatile ("wcsr jrx,%0"::"r"(value2)); break; - case CSR_BP0: asm volatile ("wcsr bp0,%0"::"r"(value2)); break; - case CSR_BP1: asm volatile ("wcsr bp1,%0"::"r"(value2)); break; - case CSR_BP2: asm volatile ("wcsr bp2,%0"::"r"(value2)); break; - case CSR_BP3: asm volatile ("wcsr bp3,%0"::"r"(value2)); break; - case CSR_WP0: asm volatile ("wcsr wp0,%0"::"r"(value2)); break; - case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break; - case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break; - case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break; - default: printf("csr read only\n"); return; - } -} - -#endif /* __lm32__ */ - /* Init + command line */ static void help(void) @@ -306,12 +194,10 @@ static void help(void) puts("mr - read address space"); puts("mw - write address space"); puts("mc - copy address space"); + puts(""); puts("crc - compute CRC32 of a part of the address space"); puts("ident - display identifier"); -#ifdef __lm32__ - puts("rcsr - read processor CSR"); - puts("wcsr - write processor CSR"); -#endif + puts(""); #ifdef CSR_CTRL_BASE puts("reboot - reset processor"); #endif @@ -325,6 +211,7 @@ static void help(void) #ifdef ROM_BOOT_ADDRESS puts("romboot - boot from embedded rom"); #endif + puts(""); #ifdef CSR_SDRAM_BASE puts("memtest - run a memory test"); #endif @@ -384,11 +271,6 @@ static void do_command(char *c) else if(strcmp(token, "help") == 0) help(); -#ifdef __lm32__ - else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c)); - else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c)); -#endif - #ifdef CSR_SDRAM_BASE else if(strcmp(token, "sdrrow") == 0) sdrrow(get_token(&c)); else if(strcmp(token, "sdrsw") == 0) sdrsw(); From b92b89ab927650235e907733b2b81e7bf3a72564 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 30 Mar 2019 10:19:00 +0100 Subject: [PATCH 18/52] bios/main: print boot sequence only if sdr_ok --- litex/soc/software/bios/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 5560444ea..71b03a3e7 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -443,10 +443,10 @@ int main(int i, char **c) printf("Memory initialization failed\n"); printf("\n"); - printf("--========== \e[1mBoot sequence\e[0m =============--\n"); if(sdr_ok) + printf("--========== \e[1mBoot sequence\e[0m =============--\n"); boot_sequence(); - printf("\n"); + printf("\n"); printf("--============= \e[1mConsole\e[0m ================--\n"); while(1) { From 6599f7bb50da4690d9a97395ae859bf01038e235 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 30 Mar 2019 10:56:17 +0100 Subject: [PATCH 19/52] bios/main: move sdrinit --- litex/soc/software/bios/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 71b03a3e7..6f68be622 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -280,6 +280,7 @@ static void do_command(char *c) else if(strcmp(token, "sdrrderr") == 0) sdrrderr(get_token(&c)); else if(strcmp(token, "sdrwr") == 0) sdrwr(get_token(&c)); #ifdef CSR_DDRPHY_BASE + else if(strcmp(token, "sdrinit") == 0) sdrinit(); #ifdef CSR_DDRPHY_WLEVEL_EN_ADDR else if(strcmp(token, "sdrwlon") == 0) sdrwlon(); else if(strcmp(token, "sdrwloff") == 0) sdrwloff(); @@ -287,7 +288,6 @@ static void do_command(char *c) else if(strcmp(token, "sdrlevel") == 0) sdrlevel(); #endif else if(strcmp(token, "memtest") == 0) memtest(); - else if(strcmp(token, "sdrinit") == 0) sdrinit(); #endif else if(strcmp(token, "") != 0) From dd214d2d2199d625e20804eff16a63f7a5ef9a15 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 30 Mar 2019 11:49:39 +0100 Subject: [PATCH 20/52] bios/main: align SoC info, show CPU speed on CPU line, show L2 --- litex/soc/software/bios/main.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 6f68be622..18215fef0 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -405,7 +405,7 @@ int main(int i, char **c) printf("\n"); printf("--============ \e[1mSoC info\e[0m ================--\n"); - printf("\e[1mCPU: \e[0m"); + printf("\e[1mCPU\e[0m: "); #ifdef __lm32__ printf("LM32"); #elif __or1k__ @@ -419,11 +419,13 @@ int main(int i, char **c) #else printf("Unknown"); #endif - printf("\n"); - printf("\e[1mFrequency\e[0m: %dMHz\n", SYSTEM_CLOCK_FREQUENCY/1000000); - printf("\e[1mROM\e[0m: %dKB\n", ROM_SIZE/1024); - printf("\e[1mSRAM\e[0m: %dKB\n", SRAM_SIZE/1024); - printf("\e[1mMAIN-RAM\e[0m: %dKB\n", MAIN_RAM_SIZE/1024); + printf(" @ %dMHz\n", SYSTEM_CLOCK_FREQUENCY/1000000); + printf("\e[1mROM\e[0m: %dKB\n", ROM_SIZE/1024); + printf("\e[1mSRAM\e[0m: %dKB\n", SRAM_SIZE/1024); +#ifdef L2_SIZE + printf("\e[1mL2\e[0m: %dKB\n", L2_SIZE/1024); +#endif + printf("\e[1mMAIN-RAM\e[0m: %dKB\n", MAIN_RAM_SIZE/1024); printf("\n"); printf("--========= \e[1mPeripherals init\e[0m ===========--\n"); @@ -443,10 +445,11 @@ int main(int i, char **c) printf("Memory initialization failed\n"); printf("\n"); - if(sdr_ok) + if(sdr_ok) { printf("--========== \e[1mBoot sequence\e[0m =============--\n"); boot_sequence(); printf("\n"); + } printf("--============= \e[1mConsole\e[0m ================--\n"); while(1) { From f452d3e96f6aa19776e6f4aaf31e13df36935bf6 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 30 Mar 2019 12:27:06 +0100 Subject: [PATCH 21/52] README: bump copyright year --- LICENSE | 6 +++--- README | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index fc78898b6..4ec4486d5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,14 +1,14 @@ -Unless otherwise noted, LiteX is copyright (C) 2012-2018 Florent Kermarrec. +Unless otherwise noted, LiteX is copyright (C) 2012-2019 Florent Kermarrec. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. + list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED diff --git a/README b/README index 388858ca6..ee4d46c7e 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ Migen inside Build your hardware, easily! - Copyright 2012-2018 / EnjoyDigital + Copyright 2012-2019 / EnjoyDigital [> Intro -------- From 1f0b3f81245b80d2a45a623884d95339ef4c9ae1 Mon Sep 17 00:00:00 2001 From: Caleb Jamison Date: Sun, 31 Mar 2019 10:33:39 -0500 Subject: [PATCH 22/52] Add ifdef check for MAIN_RAM_SIZE --- litex/soc/software/bios/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 18215fef0..ba75f38c9 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -425,7 +425,9 @@ int main(int i, char **c) #ifdef L2_SIZE printf("\e[1mL2\e[0m: %dKB\n", L2_SIZE/1024); #endif +#ifdef MAIN_RAM_SIZE printf("\e[1mMAIN-RAM\e[0m: %dKB\n", MAIN_RAM_SIZE/1024); +#endif printf("\n"); printf("--========= \e[1mPeripherals init\e[0m ===========--\n"); From b15fd9d83456c0258dbc11c5a926b528d6007724 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 1 Apr 2019 10:23:05 +0200 Subject: [PATCH 23/52] interconnect/axi: add missing axi signals --- litex/soc/interconnect/axi.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/litex/soc/interconnect/axi.py b/litex/soc/interconnect/axi.py index 17d431e64..4692cbfdc 100644 --- a/litex/soc/interconnect/axi.py +++ b/litex/soc/interconnect/axi.py @@ -20,26 +20,31 @@ def ax_description(address_width, id_width): ("burst", 2), # Burst type ("len", 8), # Number of data (-1) transfers (up to 256) ("size", 4), # Number of bytes (-1) of each data transfer (up to 1024 bits) + ("lock", 2), + ("prot", 3), + ("cache", 4), + ("qos", 4), ("id", id_width) ] -def w_description(data_width): +def w_description(data_width, id_width): return [ ("data", data_width), - ("strb", data_width//8) + ("strb", data_width//8), + ("id", id_width) ] def b_description(id_width): return [ ("resp", 2), - ("id", id_width) + ("id", id_width) ] def r_description(data_width, id_width): return [ ("resp", 2), ("data", data_width), - ("id", id_width) + ("id", id_width) ] @@ -51,7 +56,7 @@ class AXIInterface(Record): self.clock_domain = clock_domain self.aw = stream.Endpoint(ax_description(address_width, id_width)) - self.w = stream.Endpoint(w_description(data_width)) + self.w = stream.Endpoint(w_description(data_width, id_width)) self.b = stream.Endpoint(b_description(id_width)) self.ar = stream.Endpoint(ax_description(address_width, id_width)) self.r = stream.Endpoint(r_description(data_width, id_width)) From 7375856bec17a67fec2a521273d393c6285bdcbe Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 1 Apr 2019 10:31:33 +0200 Subject: [PATCH 24/52] integration/soc_zynq: connect axi signals that were missing --- litex/soc/integration/soc_zynq.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/litex/soc/integration/soc_zynq.py b/litex/soc/integration/soc_zynq.py index 955402c39..473e2b4d3 100644 --- a/litex/soc/integration/soc_zynq.py +++ b/litex/soc/integration/soc_zynq.py @@ -57,10 +57,10 @@ class SoCZynq(SoCCore): # fabric clk o_FCLK_CLK0=ClockSignal("sys"), - # axi clk + # axi gp0 clk i_M_AXI_GP0_ACLK=ClockSignal("sys"), - # axi aw + # axi gp0 aw o_M_AXI_GP0_AWVALID=axi_gp0.aw.valid, i_M_AXI_GP0_AWREADY=axi_gp0.aw.ready, o_M_AXI_GP0_AWADDR=axi_gp0.aw.addr, @@ -68,12 +68,12 @@ class SoCZynq(SoCCore): o_M_AXI_GP0_AWLEN=axi_gp0.aw.len, o_M_AXI_GP0_AWSIZE=axi_gp0.aw.size, o_M_AXI_GP0_AWID=axi_gp0.aw.id, - #o_M_AXI_GP0_AWLOCK =, - #o_M_AXI_GP0_AWPROT =, - #o_M_AXI_GP0_AWCACHE =, - #o_M_AXI_GP0_AWQOS =, + o_M_AXI_GP0_AWLOCK=axi_gp0.aw.lock, + o_M_AXI_GP0_AWPROT=axi_gp0.aw.prot, + o_M_AXI_GP0_AWCACHE=axi_gp0.aw.cache, + o_M_AXI_GP0_AWQOS=axi_gp0.aw.qos, - # axi w + # axi gp0 w o_M_AXI_GP0_WVALID=axi_gp0.w.valid, o_M_AXI_GP0_WLAST=axi_gp0.w.last, i_M_AXI_GP0_WREADY=axi_gp0.w.ready, @@ -81,26 +81,26 @@ class SoCZynq(SoCCore): o_M_AXI_GP0_WDATA=axi_gp0.w.data, o_M_AXI_GP0_WSTRB=axi_gp0.w.strb, - # axi b + # axi gp0 b i_M_AXI_GP0_BVALID=axi_gp0.b.valid, o_M_AXI_GP0_BREADY=axi_gp0.b.ready, i_M_AXI_GP0_BID=axi_gp0.b.id, i_M_AXI_GP0_BRESP=axi_gp0.b.resp, - # axi ar + # axi gp0 ar o_M_AXI_GP0_ARVALID=axi_gp0.ar.valid, i_M_AXI_GP0_ARREADY=axi_gp0.ar.ready, o_M_AXI_GP0_ARADDR=axi_gp0.ar.addr, o_M_AXI_GP0_ARBURST=axi_gp0.ar.burst, o_M_AXI_GP0_ARLEN=axi_gp0.ar.len, o_M_AXI_GP0_ARID=axi_gp0.ar.id, - #o_M_AXI_GP0_ARLOCK=, - #o_M_AXI_GP0_ARSIZE=, - #o_M_AXI_GP0_ARPROT=, - #o_M_AXI_GP0_ARCACHE=, - #o_M_AXI_GP0_ARQOS=, + o_M_AXI_GP0_ARLOCK=axi_gp0.ar.lock, + o_M_AXI_GP0_ARSIZE=axi_gp0.ar.size, + o_M_AXI_GP0_ARPROT=axi_gp0.ar.prot, + o_M_AXI_GP0_ARCACHE=axi_gp0.ar.cache, + o_M_AXI_GP0_ARQOS=axi_gp0.ar.qos, - # axi r + # axi gp0 r i_M_AXI_GP0_RVALID=axi_gp0.r.valid, o_M_AXI_GP0_RREADY=axi_gp0.r.ready, i_M_AXI_GP0_RLAST=axi_gp0.r.last, From 38d404c3cb60b7cb9d794d180c6b8f8265d4a482 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 1 Apr 2019 10:50:04 +0200 Subject: [PATCH 25/52] integration/soc_zynq: use add methods to add optional peripherals --- litex/soc/integration/soc_zynq.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/litex/soc/integration/soc_zynq.py b/litex/soc/integration/soc_zynq.py index 473e2b4d3..a040f11c1 100644 --- a/litex/soc/integration/soc_zynq.py +++ b/litex/soc/integration/soc_zynq.py @@ -12,12 +12,12 @@ from litex.soc.interconnect import axi class SoCZynq(SoCCore): SoCCore.mem_map["csr"] = 0x00000000 def __init__(self, platform, clk_freq, ps7_name, **kwargs): + self.ps7_name = ps7_name SoCCore.__init__(self, platform, clk_freq, cpu_type=None, shadow_base=0x00000000, **kwargs) - # PS7 -------------------------------------------------------------------------------------- - self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12) + # PS7 (Minimal) ---------------------------------------------------------------------------- ps7_ddram_pads = platform.request("ps7_ddram") - self.specials += Instance(ps7_name, + self.ps7_params = dict( # clk/rst io_PS_CLK=platform.request("ps7_clk"), io_PS_PORB=platform.request("ps7_porb"), @@ -59,7 +59,12 @@ class SoCZynq(SoCCore): # axi gp0 clk i_M_AXI_GP0_ACLK=ClockSignal("sys"), + ) + platform.add_ip(os.path.join("ip", ps7_name + ".xci")) + def add_gp0(self): + self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12) + self.ps7_params.update( # axi gp0 aw o_M_AXI_GP0_AWVALID=axi_gp0.aw.valid, i_M_AXI_GP0_AWREADY=axi_gp0.aw.ready, @@ -108,13 +113,15 @@ class SoCZynq(SoCCore): i_M_AXI_GP0_RRESP=axi_gp0.r.resp, i_M_AXI_GP0_RDATA=axi_gp0.r.data, ) - platform.add_ip(os.path.join("ip", ps7_name + ".xci")) - # AXI to Wishbone -------------------------------------------------------------------------- - self.wb_gp0 = wb_gp0 = wishbone.Interface() - axi2wishbone = axi.AXI2Wishbone(axi_gp0, wb_gp0, base_address=0x43c00000) + def add_axi_to_wishbone(self, axi_port, base_address=0x43c00000): + wb = wishbone.Interface() + axi2wishbone = axi.AXI2Wishbone(axi_port, wb, base_address) self.submodules += axi2wishbone - self.add_wb_master(wb_gp0) + self.add_wb_master(wb) + + def do_finalize(self): + self.specials += Instance(self.ps7_name, **self.ps7_params) def generate_software_header(self, filename): csr_header = get_csr_header(self.get_csr_regions(), From 794c3c58601f4ab886bbdcd4522b7e27943a31b2 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 1 Apr 2019 11:07:30 +0200 Subject: [PATCH 26/52] integration/soc_zynq: add add_hp0 method --- litex/soc/integration/soc_zynq.py | 80 ++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/litex/soc/integration/soc_zynq.py b/litex/soc/integration/soc_zynq.py index a040f11c1..dc53227af 100644 --- a/litex/soc/integration/soc_zynq.py +++ b/litex/soc/integration/soc_zynq.py @@ -8,6 +8,19 @@ from litex.soc.integration.cpu_interface import get_csr_header from litex.soc.interconnect import wishbone from litex.soc.interconnect import axi +# Record layouts ----------------------------------------------------------------------------------- + +def axi_fifo_ctrl_layout(): + return [ + ("racount", 3, DIR_M_TO_S), + ("rcount", 8, DIR_M_TO_S), + ("rdissuecapen", 1, DIR_S_TO_M), + ("wacount", 6, DIR_M_TO_S), + ("wcount", 8, DIR_M_TO_S), + ("wrissuecapen", 1, DIR_S_TO_M), + ] + +# SoC Zync ----------------------------------------------------------------------------------------- class SoCZynq(SoCCore): SoCCore.mem_map["csr"] = 0x00000000 @@ -62,6 +75,8 @@ class SoCZynq(SoCCore): ) platform.add_ip(os.path.join("ip", ps7_name + ".xci")) + # GP0 ------------------------------------------------------------------------------------------ + def add_gp0(self): self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12) self.ps7_params.update( @@ -82,7 +97,7 @@ class SoCZynq(SoCCore): o_M_AXI_GP0_WVALID=axi_gp0.w.valid, o_M_AXI_GP0_WLAST=axi_gp0.w.last, i_M_AXI_GP0_WREADY=axi_gp0.w.ready, - #o_M_AXI_GP0_WID=, + o_M_AXI_GP0_WID=axi_gp0.w.id, o_M_AXI_GP0_WDATA=axi_gp0.w.data, o_M_AXI_GP0_WSTRB=axi_gp0.w.strb, @@ -114,6 +129,69 @@ class SoCZynq(SoCCore): i_M_AXI_GP0_RDATA=axi_gp0.r.data, ) + # HP0 ------------------------------------------------------------------------------------------ + + def add_hp0(self): + self.axi_hp0 = axi_hp0 = axi.AXIInterface(data_width=64, address_width=32, id_width=6) + self.axi_hp0_fifo_ctrl = axi_hp0_fifo_ctrl = Record(axi_fifo_ctrl_layout()) + self.ps7_params.update( + # axi hp0 aw + i_M_AXI_HP0_AWVALID=axi_hp0.aw.valid, + o_M_AXI_HP0_AWREADY=axi_hp0.aw.ready, + i_M_AXI_HP0_AWADDR=axi_hp0.aw.addr, + i_M_AXI_HP0_AWBURST=axi_hp0.aw.burst, + i_M_AXI_HP0_AWLEN=axi_hp0.aw.len, + i_M_AXI_HP0_AWSIZE=axi_hp0.aw.size, + i_M_AXI_HP0_AWID=axi_hp0.aw.id, + i_M_AXI_HP0_AWLOCK=axi_hp0.aw.lock, + i_M_AXI_HP0_AWPROT=axi_hp0.aw.prot, + i_M_AXI_HP0_AWCACHE=axi_hp0.aw.cache, + i_M_AXI_HP0_AWQOS=axi_hp0.aw.qos, + + # axi hp0 w + i_M_AXI_HP0_WVALID=axi_hp0.w.valid, + i_M_AXI_HP0_WLAST=axi_hp0.w.last, + o_M_AXI_HP0_WREADY=axi_hp0.w.ready, + i_M_AXI_HP0_WID=axi_hp0.w.id, + i_M_AXI_HP0_WDATA=axi_hp0.w.data, + i_M_AXI_HP0_WSTRB=axi_hp0.w.strb, + + # axi hp0 b + o_M_AXI_HP0_BVALID=axi_hp0.b.valid, + i_M_AXI_HP0_BREADY=axi_hp0.b.ready, + o_M_AXI_HP0_BID=axi_hp0.b.id, + o_M_AXI_HP0_BRESP=axi_hp0.b.resp, + + # axi hp0 ar + i_M_AXI_HP0_ARVALID=axi_hp0.ar.valid, + o_M_AXI_HP0_ARREADY=axi_hp0.ar.ready, + i_M_AXI_HP0_ARADDR=axi_hp0.ar.addr, + i_M_AXI_HP0_ARBURST=axi_hp0.ar.burst, + i_M_AXI_HP0_ARLEN=axi_hp0.ar.len, + i_M_AXI_HP0_ARID=axi_hp0.ar.id, + i_M_AXI_HP0_ARLOCK=axi_hp0.ar.lock, + i_M_AXI_HP0_ARSIZE=axi_hp0.ar.size, + i_M_AXI_HP0_ARPROT=axi_hp0.ar.prot, + i_M_AXI_HP0_ARCACHE=axi_hp0.ar.cache, + i_M_AXI_HP0_ARQOS=axi_hp0.ar.qos, + + # axi hp0 r + o_M_AXI_HP0_RVALID=axi_hp0.r.valid, + i_M_AXI_HP0_RREADY=axi_hp0.r.ready, + o_M_AXI_HP0_RLAST=axi_hp0.r.last, + o_M_AXI_HP0_RID=axi_hp0.r.id, + o_M_AXI_HP0_RRESP=axi_hp0.r.resp, + o_M_AXI_HP0_RDATA=axi_hp0.r.data, + + # axi hp0 fifo ctrl + i_S_AXI_HP0_FIFO_CTRL_0_RACOUNT=axi_hp0_fifo_ctrl.racount, + i_S_AXI_HP0_FIFO_CTRL_0_RCOUNT=axi_hp0_fifo_ctrl.rcount, + o_S_AXI_HP0_FIFO_CTRL_0_RDISSUECAPEN=axi_hp0_fifo_ctrl.rdissuecapen, + i_S_AXI_HP0_FIFO_CTRL_0_WACOUNT=axi_hp0_fifo_ctrl.wacount, + i_S_AXI_HP0_FIFO_CTRL_0_WCOUNT=axi_hp0_fifo_ctrl.wcount, + o_S_AXI_HP0_FIFO_CTRL_0_WRISSUECAPEN=axi_hp0_fifo_ctrl.wrissuecapen + ) + def add_axi_to_wishbone(self, axi_port, base_address=0x43c00000): wb = wishbone.Interface() axi2wishbone = axi.AXI2Wishbone(axi_port, wb, base_address) From 866fa34493fe04ad82c107bd5fcdf4eec171ecef Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 1 Apr 2019 14:44:37 +0200 Subject: [PATCH 27/52] integration/soc_zynq: fix missing SoCCore.do_finalize Signed-off-by: Florent Kermarrec --- litex/soc/integration/soc_zynq.py | 1 + 1 file changed, 1 insertion(+) diff --git a/litex/soc/integration/soc_zynq.py b/litex/soc/integration/soc_zynq.py index dc53227af..c6b0a5661 100644 --- a/litex/soc/integration/soc_zynq.py +++ b/litex/soc/integration/soc_zynq.py @@ -199,6 +199,7 @@ class SoCZynq(SoCCore): self.add_wb_master(wb) def do_finalize(self): + SoCCore.do_finalize(self) self.specials += Instance(self.ps7_name, **self.ps7_params) def generate_software_header(self, filename): From 8558065fcacd39e7182804430fa5c420f4978b6b Mon Sep 17 00:00:00 2001 From: vytautasb Date: Mon, 8 Apr 2019 13:28:25 +0300 Subject: [PATCH 28/52] litex/build/altera/common: added reset synchronizer --- litex/build/altera/common.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/litex/build/altera/common.py b/litex/build/altera/common.py index fafb49837..5d5739100 100644 --- a/litex/build/altera/common.py +++ b/litex/build/altera/common.py @@ -1,6 +1,9 @@ from migen.fhdl.module import Module from migen.fhdl.specials import Instance from migen.genlib.io import DifferentialInput, DifferentialOutput +from migen.genlib.resetsync import AsyncResetSynchronizer + +from migen.fhdl.structure import * class AlteraDifferentialInputImpl(Module): @@ -32,8 +35,29 @@ class AlteraDifferentialOutput: def lower(dr): return AlteraDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n) +class AlteraAsyncResetSynchronizerImpl(Module): + def __init__(self, cd, async_reset): + if not hasattr(async_reset, "attr"): + i, async_reset = async_reset, Signal() + self.comb += async_reset.eq(i) + rst_meta = Signal() + self.specials += [ + Instance("DFF", i_d=0, i_clk=cd.clk, i_clrn=1, + i_prn=async_reset, o_q=rst_meta, + attr={"async_reg", "ars_ff1"}), + Instance("DFF", i_d=rst_meta, i_clk=cd.clk, i_clrn=1, + i_prn=async_reset, o_q=cd.rst, + attr={"async_reg", "ars_ff2"}) + ] + +class AlteraAsyncResetSynchronizer: + @staticmethod + def lower(dr): + return AlteraAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) + altera_special_overrides = { DifferentialInput: AlteraDifferentialInput, - DifferentialOutput: AlteraDifferentialOutput + DifferentialOutput: AlteraDifferentialOutput, + AsyncResetSynchronizer: AlteraAsyncResetSynchronizer } From 04939990ac5b4e29d47309318152bb8e6dc5e5c5 Mon Sep 17 00:00:00 2001 From: vytautasb Date: Mon, 8 Apr 2019 13:34:59 +0300 Subject: [PATCH 29/52] litex/build/altera/quartus: changes to make top level assigment in .qsf file with build name --- litex/build/altera/quartus.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/litex/build/altera/quartus.py b/litex/build/altera/quartus.py index 1ebc08da6..6d36ce63c 100644 --- a/litex/build/altera/quartus.py +++ b/litex/build/altera/quartus.py @@ -50,7 +50,7 @@ def _format_qsf(signame, pin, others, resname): return '\n'.join(fmt_c) -def _build_qsf(named_sc, named_pc): +def _build_qsf(named_sc, named_pc, build_name): lines = [] for sig, pins, others, resname in named_sc: if len(pins) > 1: @@ -64,7 +64,8 @@ def _build_qsf(named_sc, named_pc): lines.append("") lines.append("\n\n".join(named_pc)) - lines.append("set_global_assignment -name top_level_entity top") + # Set top level name to "build_name" in .qsf file instead always use "top" name + lines.append("set_global_assignment -name top_level_entity " + build_name) return "\n".join(lines) @@ -86,7 +87,7 @@ def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name): lines.append("set_global_assignment -name SEARCH_PATH {}".format( path.replace("\\", "/"))) - lines.append(_build_qsf(named_sc, named_pc)) + lines.append(_build_qsf(named_sc, named_pc, build_name)) lines.append("set_global_assignment -name DEVICE {}".format(device)) tools.write_to_file("{}.qsf".format(build_name), "\n".join(lines)) From f8dcdb70d27352f801e63d3b95871ddc287582af Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 10 Apr 2019 16:16:47 +0200 Subject: [PATCH 30/52] software/libnet: add #ifdef on eth_init --- litex/soc/software/bios/main.c | 2 +- litex/soc/software/libnet/microudp.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index ba75f38c9..26ca39838 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -431,7 +431,7 @@ int main(int i, char **c) printf("\n"); printf("--========= \e[1mPeripherals init\e[0m ===========--\n"); -#ifdef CSR_ETHMAC_BASE +#ifdef CSR_ETHPHY_CRG_RESET_ADDR eth_init(); #endif #ifdef CSR_SDRAM_BASE diff --git a/litex/soc/software/libnet/microudp.c b/litex/soc/software/libnet/microudp.c index 38e16588b..1850a274a 100644 --- a/litex/soc/software/libnet/microudp.c +++ b/litex/soc/software/libnet/microudp.c @@ -461,6 +461,7 @@ static void busy_wait(unsigned int ds) while(timer0_value_read()) timer0_update_value_write(1); } +#ifdef CSR_ETHPHY_CRG_RESET_ADDR void eth_init(void) { ethphy_crg_reset_write(0); @@ -471,6 +472,7 @@ void eth_init(void) ethphy_crg_reset_write(0); busy_wait(2); } +#endif #ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR void eth_mode(void) From 792245f1964d2d374a4bd820f3d53060c299b06b Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 10 Apr 2019 16:36:49 +0200 Subject: [PATCH 31/52] boards/targets/kcu105: add Ethernet (with 1Gbps SFP adapter) --- litex/boards/targets/kcu105.py | 51 +++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/litex/boards/targets/kcu105.py b/litex/boards/targets/kcu105.py index f496e53e0..502af29ee 100755 --- a/litex/boards/targets/kcu105.py +++ b/litex/boards/targets/kcu105.py @@ -14,6 +14,9 @@ from litex.soc.integration.builder import * from litedram.modules import EDY4016A from litedram.phy import usddrphy +from liteeth.phy.ku_1000basex import KU_1000BASEX +from liteeth.core.mac import LiteEthMAC + # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): @@ -92,15 +95,61 @@ class BaseSoC(SoCSDRAM): sdram_module.geom_settings, sdram_module.timing_settings) + +# EthernetSoC ------------------------------------------------------------------------------------------ + +class EthernetSoC(BaseSoC): + csr_map = { + "ethphy": 18, + "ethmac": 19 + } + csr_map.update(BaseSoC.csr_map) + + interrupt_map = { + "ethmac": 3, + } + interrupt_map.update(BaseSoC.interrupt_map) + + mem_map = { + "ethmac": 0x30000000, # (shadow @0xb0000000) + } + mem_map.update(BaseSoC.mem_map) + + def __init__(self, **kwargs): + BaseSoC.__init__(self, **kwargs) + + self.comb += self.platform.request("sfp_tx_disable_n", 0).eq(1) + self.submodules.ethphy = KU_1000BASEX(self.crg.cd_clk200.clk, + self.platform.request("sfp", 0), sys_clk_freq=self.clk_freq) + self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, + interface="wishbone", endianness=self.cpu.endianness) + self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus) + self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000) + + self.crg.cd_sys.clk.attr.add("keep") + self.ethphy.cd_eth_rx.clk.attr.add("keep") + self.ethphy.cd_eth_tx.clk.attr.add("keep") + self.platform.add_period_constraint(self.ethphy.cd_eth_rx.clk, 1e9/125e6) + self.platform.add_period_constraint(self.ethphy.cd_eth_tx.clk, 1e9/125e6) + self.platform.add_false_path_constraints( + self.crg.cd_sys.clk, + self.ethphy.cd_eth_rx.clk, + self.ethphy.cd_eth_tx.clk) + + self.platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks REQP-1753]") + # Build -------------------------------------------------------------------------------------------- def main(): parser = argparse.ArgumentParser(description="LiteX SoC on KCU105") builder_args(parser) soc_sdram_args(parser) + parser.add_argument("--with-ethernet", action="store_true", + help="enable Ethernet support") args = parser.parse_args() - soc = BaseSoC(**soc_sdram_argdict(args)) + cls = EthernetSoC if args.with_ethernet else BaseSoC + soc = cls(**soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) builder.build() From 7e53bff39dafb7f2ea7d3acb4e94290ecd388645 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 10 Apr 2019 18:04:48 +0200 Subject: [PATCH 32/52] litex_setup: add litesata --- litex_setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/litex_setup.py b/litex_setup.py index 0275a0bd3..614af61af 100755 --- a/litex_setup.py +++ b/litex_setup.py @@ -15,6 +15,7 @@ repos = [ ("liteusb", ("http://github.com/enjoy-digital/", False, True)), ("litedram", ("http://github.com/enjoy-digital/", False, True)), ("litepcie", ("http://github.com/enjoy-digital/", False, True)), + ("litesata", ("http://github.com/enjoy-digital/", False, True)), ("litesdcard", ("http://github.com/enjoy-digital/", False, True)), ("liteiclink", ("http://github.com/enjoy-digital/", False, True)), ("litevideo", ("http://github.com/enjoy-digital/", False, True)), From c7ac96761c46b15fff3a46f7c79c98be8f4c49a6 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 11 Apr 2019 22:26:58 +0200 Subject: [PATCH 33/52] bios/sdram: add __attribute__((unused)) on cdelay --- litex/soc/software/bios/sdram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index 409a7b812..ebd53130e 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -17,7 +17,7 @@ #define MAIN_RAM_BASE SRAM_BASE #endif -static void cdelay(int i) +__attribute__((unused)) static void cdelay(int i) { while(i > 0) { #if defined (__lm32__) From 1569e2e0cf70a5febe3d1c7875ebb9ceddcd2a4c Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 12 Apr 2019 17:08:29 +0200 Subject: [PATCH 34/52] software/libnet: remove use of ethmac_mem.h --- litex/soc/software/include/hw/ethmac_mem.h | 11 ----------- litex/soc/software/libnet/microudp.c | 11 ++++++----- 2 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 litex/soc/software/include/hw/ethmac_mem.h diff --git a/litex/soc/software/include/hw/ethmac_mem.h b/litex/soc/software/include/hw/ethmac_mem.h deleted file mode 100644 index 03c7b96d0..000000000 --- a/litex/soc/software/include/hw/ethmac_mem.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __HW_ETHMAC_MEM_H -#define __HW_ETHMAC_MEM_H - -#include - -#define ETHMAC_RX0_BASE ETHMAC_BASE -#define ETHMAC_RX1_BASE (ETHMAC_BASE+0x0800) -#define ETHMAC_TX0_BASE (ETHMAC_BASE+0x1000) -#define ETHMAC_TX1_BASE (ETHMAC_BASE+0x1800) - -#endif diff --git a/litex/soc/software/libnet/microudp.c b/litex/soc/software/libnet/microudp.c index 1850a274a..90b73a7e1 100644 --- a/litex/soc/software/libnet/microudp.c +++ b/litex/soc/software/libnet/microudp.c @@ -1,4 +1,6 @@ #include +#include + #ifdef CSR_ETHMAC_BASE #include @@ -6,7 +8,6 @@ #include #include #include -#include #include @@ -415,10 +416,10 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip) ethmac_sram_reader_ev_pending_write(ETHMAC_EV_SRAM_READER); ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER); - rxbuffer0 = (ethernet_buffer *)ETHMAC_RX0_BASE; - rxbuffer1 = (ethernet_buffer *)ETHMAC_RX1_BASE; - txbuffer0 = (ethernet_buffer *)ETHMAC_TX0_BASE; - txbuffer1 = (ethernet_buffer *)ETHMAC_TX1_BASE; + rxbuffer0 = (ethernet_buffer *)(ETHMAC_BASE + 0*ETHMAC_SLOT_SIZE); + rxbuffer1 = (ethernet_buffer *)(ETHMAC_BASE + 1*ETHMAC_SLOT_SIZE); + txbuffer0 = (ethernet_buffer *)(ETHMAC_BASE + 2*ETHMAC_SLOT_SIZE); + txbuffer1 = (ethernet_buffer *)(ETHMAC_BASE + 3*ETHMAC_SLOT_SIZE); rxslot = 0; txslot = 0; From fdeff7f64fc9280a347be9e8a6fcfac9d173e0c4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 12 Apr 2019 17:09:50 +0200 Subject: [PATCH 35/52] software/libnet/microudp: set raw frame size to ETHMAC_SLOT_SIZE --- litex/soc/software/libnet/microudp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/software/libnet/microudp.c b/litex/soc/software/libnet/microudp.c index 90b73a7e1..be23d7336 100644 --- a/litex/soc/software/libnet/microudp.c +++ b/litex/soc/software/libnet/microudp.c @@ -111,7 +111,7 @@ struct ethernet_frame { typedef union { struct ethernet_frame frame; - unsigned char raw[1532]; + unsigned char raw[ETHMAC_SLOT_SIZE]; } ethernet_buffer; From 92a79c6dc187fcb82baa39f126d063fddcc10e02 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 12 Apr 2019 17:14:07 +0200 Subject: [PATCH 36/52] software/libnet/microudp: simplify rxbuffer managment --- litex/soc/software/libnet/microudp.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/litex/soc/software/libnet/microudp.c b/litex/soc/software/libnet/microudp.c index be23d7336..9c1202127 100644 --- a/litex/soc/software/libnet/microudp.c +++ b/litex/soc/software/libnet/microudp.c @@ -114,12 +114,8 @@ typedef union { unsigned char raw[ETHMAC_SLOT_SIZE]; } ethernet_buffer; - -static unsigned int rxslot; static unsigned int rxlen; static ethernet_buffer *rxbuffer; -static ethernet_buffer *rxbuffer0; -static ethernet_buffer *rxbuffer1; static unsigned int txslot; static unsigned int txlen; static ethernet_buffer *txbuffer; @@ -416,15 +412,11 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip) ethmac_sram_reader_ev_pending_write(ETHMAC_EV_SRAM_READER); ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER); - rxbuffer0 = (ethernet_buffer *)(ETHMAC_BASE + 0*ETHMAC_SLOT_SIZE); - rxbuffer1 = (ethernet_buffer *)(ETHMAC_BASE + 1*ETHMAC_SLOT_SIZE); txbuffer0 = (ethernet_buffer *)(ETHMAC_BASE + 2*ETHMAC_SLOT_SIZE); txbuffer1 = (ethernet_buffer *)(ETHMAC_BASE + 3*ETHMAC_SLOT_SIZE); - rxslot = 0; txslot = 0; - rxbuffer = rxbuffer0; txbuffer = txbuffer0; for(i=0;i<6;i++) @@ -435,18 +427,17 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip) for(i=0;i<6;i++) cached_mac[i] = 0; + rxbuffer = (ethernet_buffer *)ETHMAC_BASE; rx_callback = (udp_callback)0; } void microudp_service(void) { + unsigned int rxslot; if(ethmac_sram_writer_ev_pending_read() & ETHMAC_EV_SRAM_WRITER) { rxslot = ethmac_sram_writer_slot_read(); + rxbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * rxslot); rxlen = ethmac_sram_writer_length_read(); - if (rxslot) - rxbuffer = rxbuffer1; - else - rxbuffer = rxbuffer0; process_frame(); ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER); } From 3441eb05cb9c4d9b027cfdca5a61b0f0c8884ec7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 12 Apr 2019 17:15:09 +0200 Subject: [PATCH 37/52] software/libnet/microudp: cleanup eth_init --- litex/soc/software/libnet/microudp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/litex/soc/software/libnet/microudp.c b/litex/soc/software/libnet/microudp.c index 9c1202127..50107b932 100644 --- a/litex/soc/software/libnet/microudp.c +++ b/litex/soc/software/libnet/microudp.c @@ -453,18 +453,15 @@ static void busy_wait(unsigned int ds) while(timer0_value_read()) timer0_update_value_write(1); } -#ifdef CSR_ETHPHY_CRG_RESET_ADDR void eth_init(void) { - ethphy_crg_reset_write(0); - busy_wait(2); - /* that pesky ethernet PHY needs two resets at times... */ +#ifdef CSR_ETHPHY_CRG_RESET_ADDR ethphy_crg_reset_write(1); busy_wait(2); ethphy_crg_reset_write(0); busy_wait(2); -} #endif +} #ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR void eth_mode(void) From 13a76ec7fbc943be5141892bc8b2630269d25a96 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 12 Apr 2019 18:10:44 +0200 Subject: [PATCH 38/52] software/libnet/microudp: simplify txbuffer managment --- litex/soc/software/libnet/microudp.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/litex/soc/software/libnet/microudp.c b/litex/soc/software/libnet/microudp.c index 50107b932..69aa901db 100644 --- a/litex/soc/software/libnet/microudp.c +++ b/litex/soc/software/libnet/microudp.c @@ -116,15 +116,12 @@ typedef union { static unsigned int rxlen; static ethernet_buffer *rxbuffer; -static unsigned int txslot; static unsigned int txlen; static ethernet_buffer *txbuffer; -static ethernet_buffer *txbuffer0; -static ethernet_buffer *txbuffer1; static void send_packet(void) { - + unsigned int txslot; #ifndef HW_PREAMBLE_CRC unsigned int crc; crc = crc32(&txbuffer->raw[8], txlen-8); @@ -144,15 +141,13 @@ static void send_packet(void) printf("\n"); #endif - ethmac_sram_reader_slot_write(txslot); ethmac_sram_reader_length_write(txlen); - while(!(ethmac_sram_reader_ready_read())); ethmac_sram_reader_start_write(1); - txslot = (txslot+1)%2; - if (txslot) - txbuffer = txbuffer1; - else - txbuffer = txbuffer0; + while(!(ethmac_sram_reader_ready_read())); + txslot = ethmac_sram_reader_slot_read(); + txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * (ETHMAC_RX_SLOTS + txslot)); + txslot = (txslot+1)%ETHMAC_TX_SLOTS; + ethmac_sram_reader_slot_write(txslot); } static unsigned char my_mac[6]; @@ -412,13 +407,6 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip) ethmac_sram_reader_ev_pending_write(ETHMAC_EV_SRAM_READER); ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER); - txbuffer0 = (ethernet_buffer *)(ETHMAC_BASE + 2*ETHMAC_SLOT_SIZE); - txbuffer1 = (ethernet_buffer *)(ETHMAC_BASE + 3*ETHMAC_SLOT_SIZE); - - txslot = 0; - - txbuffer = txbuffer0; - for(i=0;i<6;i++) my_mac[i] = macaddr[i]; my_ip = ip; @@ -427,6 +415,10 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip) for(i=0;i<6;i++) cached_mac[i] = 0; + ethmac_sram_reader_slot_write(0); + txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * ETHMAC_RX_SLOTS); + + rxbuffer = (ethernet_buffer *)ETHMAC_BASE; rx_callback = (udp_callback)0; } From 76bc57851bce3a49425e73f8047b7c3f5e8ea891 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 14 Apr 2019 08:56:51 +0200 Subject: [PATCH 39/52] litex_server: refactor parameters and to allow setting bind address In some cases, it can be useful to bind to "0.0.0.0" instead of "localhost". While adding bind address support, parameters passing has also been refactored to ease adding parameters in the future. --- litex/utils/litex_server.py | 84 +++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/litex/utils/litex_server.py b/litex/utils/litex_server.py index 8bb2f86f5..c89261b63 100755 --- a/litex/utils/litex_server.py +++ b/litex/utils/litex_server.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +import argparse + import sys import socket import time @@ -10,8 +12,9 @@ from litex.soc.tools.remote.etherbone import EtherboneIPC class RemoteServer(EtherboneIPC): - def __init__(self, comm, port=1234): + def __init__(self, comm, bind, port=1234): self.comm = comm + self.bind = bind self.port = port self.lock = False @@ -21,7 +24,7 @@ class RemoteServer(EtherboneIPC): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) for i in range(32): try: - self.socket.bind(("localhost", self.port + i)) + self.socket.bind((bind, self.port + i)) break except: pass @@ -95,46 +98,57 @@ class RemoteServer(EtherboneIPC): def main(): print("LiteX remote server") - if len(sys.argv) < 2 or len(sys.argv) > 4: - print("usages:") - print("litex_server uart [port] [baudrate]") - print("litex_server udp [server] [server_port]") - print("litex_server pcie [bar]") - sys.exit() - comm = sys.argv[1] - if comm == "uart": + parser = argparse.ArgumentParser() + # Common arguments + parser.add_argument("--bind", default="localhost", + help="Host binding address") + + # UART arguments + parser.add_argument("--uart", action="store_true", + help="Select UART interface") + parser.add_argument("--uart-port", default="", + help="Set UART port") + parser.add_argument("--uart-baudrate", default=115200, + help="Set UART baudrate") + + # UDP arguments + parser.add_argument("--udp", action="store_true", + help="Select UDP interface") + parser.add_argument("--udp-ip", default="192.168.1.50", + help="Set UDP remote IP address") + parser.add_argument("--udp-port", default=1234, + help="Set UDP remote port") + + # PCIe arguments + parser.add_argument("--pcie", action="store_true", + help="Select PCIe interface") + parser.add_argument("--pcie-bar", default="", + help="Set PCIe BAR") + args = parser.parse_args() + + + if args.uart: from litex.soc.tools.remote import CommUART - uart_port = None - uart_baudrate = 115200 - if len(sys.argv) > 2: - uart_port = sys.argv[2] - if len(sys.argv) > 3: - uart_baudrate = int(float(sys.argv[3])) + uart_port = args.uart_port + uart_baudrate = int(float(args.uart_baudrate)) print("[CommUART] port: {} / baudrate: {} / ".format(uart_port, uart_baudrate), end="") comm = CommUART(uart_port, uart_baudrate) - elif comm == "udp": + elif args.udp: from litex.soc.tools.remote import CommUDP - server = "192.168.1.50" - server_port = 1234 - if len(sys.argv) > 2: - server = sys.argv[2] - if len(sys.argv) > 3: - server_port = int(sys.argv[3]) - print("[CommUDP] server: {} / port: {} / ".format(server, server_port), end="") - comm = CommUDP(server, server_port) - elif comm == "pcie": + udp_ip = args.udp_ip + udp_port = int(args.udp_port) + print("[CommUDP] ip: {} / port: {} / ".format(udp_ip, udp_port), end="") + comm = CommUDP(udp_ip, udp_port) + elif args.pcie: from litex.soc.tools.remote import CommPCIe - bar = "" - if len(sys.argv) > 2: - bar = sys.argv[2] - if len(sys.argv) > 3: - bar_size = int(sys.argv[3]) - print("[CommPCIe] bar: {} / ".format(bar), end="") - comm = CommPCIe(bar) + pcie_bar = args.pcie_bar + print("[CommPCIe] bar: {} / ".format(args.pcie_bar), end="") + comm = CommPCIe(args.pcie_bar) else: - raise NotImplementedError + parser.print_help() + exit() - server = RemoteServer(comm) + server = RemoteServer(comm, args.bind) server.open() server.start(4) try: From db11aec9610d176481e095d9a143918f9d7c8aa6 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 14 Apr 2019 12:11:37 +0200 Subject: [PATCH 40/52] litex_server: allow setting bind port, remove auto-incrementing on bind_port --- litex/utils/litex_server.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/litex/utils/litex_server.py b/litex/utils/litex_server.py index c89261b63..ba14d01d7 100755 --- a/litex/utils/litex_server.py +++ b/litex/utils/litex_server.py @@ -12,23 +12,18 @@ from litex.soc.tools.remote.etherbone import EtherboneIPC class RemoteServer(EtherboneIPC): - def __init__(self, comm, bind, port=1234): + def __init__(self, comm, bind_ip, bind_port=1234): self.comm = comm - self.bind = bind - self.port = port + self.bind_ip = bind_ip + self.bind_port = bind_port self.lock = False def open(self): if hasattr(self, "socket"): return self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - for i in range(32): - try: - self.socket.bind((bind, self.port + i)) - break - except: - pass - print("tcp port: {:d}".format(self.port + i)) + self.socket.bind((self.bind_ip, self.bind_port)) + print("tcp port: {:d}".format(self.bind_port)) self.socket.listen(1) self.comm.open() @@ -100,8 +95,10 @@ def main(): print("LiteX remote server") parser = argparse.ArgumentParser() # Common arguments - parser.add_argument("--bind", default="localhost", - help="Host binding address") + parser.add_argument("--bind-ip", default="localhost", + help="Host bind address") + parser.add_argument("--bind-port", default=1234, + help="Host bind port") # UART arguments parser.add_argument("--uart", action="store_true", @@ -148,7 +145,7 @@ def main(): parser.print_help() exit() - server = RemoteServer(comm, args.bind) + server = RemoteServer(comm, args.bind_ip, int(args.bind_port)) server.open() server.start(4) try: From be99083e2b64fc82d4398b9a16c29b10565742ae Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 14 Apr 2019 14:00:35 +0200 Subject: [PATCH 41/52] litex_server: add message and exit when mandarory arguments are missing. --- litex/utils/litex_server.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/litex/utils/litex_server.py b/litex/utils/litex_server.py index ba14d01d7..b5dcb8f3a 100755 --- a/litex/utils/litex_server.py +++ b/litex/utils/litex_server.py @@ -103,7 +103,7 @@ def main(): # UART arguments parser.add_argument("--uart", action="store_true", help="Select UART interface") - parser.add_argument("--uart-port", default="", + parser.add_argument("--uart-port", default=None, help="Set UART port") parser.add_argument("--uart-baudrate", default=115200, help="Set UART baudrate") @@ -119,13 +119,16 @@ def main(): # PCIe arguments parser.add_argument("--pcie", action="store_true", help="Select PCIe interface") - parser.add_argument("--pcie-bar", default="", + parser.add_argument("--pcie-bar", default=None, help="Set PCIe BAR") args = parser.parse_args() if args.uart: from litex.soc.tools.remote import CommUART + if args.uart_port is None: + print("Need to specify --uart-port, exiting.") + exit() uart_port = args.uart_port uart_baudrate = int(float(args.uart_baudrate)) print("[CommUART] port: {} / baudrate: {} / ".format(uart_port, uart_baudrate), end="") @@ -139,6 +142,9 @@ def main(): elif args.pcie: from litex.soc.tools.remote import CommPCIe pcie_bar = args.pcie_bar + if args.pcie_bar is None: + print("Need to speficy --pcie-bar, exiting.") + exit() print("[CommPCIe] bar: {} / ".format(args.pcie_bar), end="") comm = CommPCIe(args.pcie_bar) else: From a2bc4bb777dc19a4f6e9b67605834c0bc5904a3e Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 15 Apr 2019 08:23:27 +0200 Subject: [PATCH 42/52] litex_server: set socket.SO_REUSEPORT to avoid waiting 60s in case of unclean termination --- litex/utils/litex_server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/litex/utils/litex_server.py b/litex/utils/litex_server.py index b5dcb8f3a..f8c6b116e 100755 --- a/litex/utils/litex_server.py +++ b/litex/utils/litex_server.py @@ -22,6 +22,7 @@ class RemoteServer(EtherboneIPC): if hasattr(self, "socket"): return self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) self.socket.bind((self.bind_ip, self.bind_port)) print("tcp port: {:d}".format(self.bind_port)) self.socket.listen(1) From 538ca59ab6094608d9e84fef3988a590b78367d9 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 15 Apr 2019 10:51:17 +0200 Subject: [PATCH 43/52] build/xilinx/vivado: round period constraints to lowest picosecond Vivado will do the opposite if we don't do it, with this change we ensure the applied period constraints will always be >= to the requested constraint. --- litex/build/xilinx/vivado.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index 54bbfe85e..b9750bba5 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -4,6 +4,7 @@ import os import subprocess import sys +import math from migen.fhdl.structure import _Fragment @@ -250,6 +251,7 @@ class XilinxVivadoToolchain: def add_period_constraint(self, platform, clk, period): if clk in self.clocks: raise ValueError("A period constraint already exists") + period = math.floor(period*1e3)/1e3 # round to lowest picosecond self.clocks[clk] = period def add_false_path_constraint(self, platform, from_, to): From f986974d608bae6f5e6fe09c260d8c93729c817c Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 15 Apr 2019 10:57:00 +0200 Subject: [PATCH 44/52] soc/cores/clock: improve presentation --- litex/soc/cores/clock.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/litex/soc/cores/clock.py b/litex/soc/cores/clock.py index 785d971cd..e50dd1a08 100644 --- a/litex/soc/cores/clock.py +++ b/litex/soc/cores/clock.py @@ -1,9 +1,4 @@ -""" -Clock Abstraction Modules - - -Made in Paris-CDG while waiting a delayed Air-France KLM flight... -""" +"""Clock Abstraction Modules""" from migen import * from migen.genlib.io import DifferentialInput @@ -15,7 +10,7 @@ from litex.soc.interconnect.csr import * def period_ns(freq): return 1e9/freq -# Xilinx / 7-Series +# Xilinx / 7-Series -------------------------------------------------------------------------------- class S7Clocking(Module, AutoCSR): clkfbout_mult_frange = (2, 64+1) @@ -204,7 +199,7 @@ class S7IDELAYCTRL(Module): ) self.specials += Instance("IDELAYCTRL", i_REFCLK=cd.clk, i_RST=ic_reset) -# Xilinx / Ultrascale +# Xilinx / Ultrascale ------------------------------------------------------------------------------ # TODO: # - use Ultrascale primitives instead of 7-Series' ones. (Vivado recognize and convert them). @@ -404,7 +399,7 @@ class USIDELAYCTRL(Module): i_REFCLK=cd.clk, i_RST=ic_reset) -# Lattice / ECP5 +# Lattice / ECP5 ----------------------------------------------------------------------------------- # TODO: # - add proper phase support. From c252972bef8524ca167917270c78f1bbb9582aca Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 15 Apr 2019 11:36:42 +0200 Subject: [PATCH 45/52] soc/cores/clock: add divclk_divide/vco_margin support on S7/Ultrascale --- litex/soc/cores/clock.py | 112 +++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/litex/soc/cores/clock.py b/litex/soc/cores/clock.py index e50dd1a08..962d69cba 100644 --- a/litex/soc/cores/clock.py +++ b/litex/soc/cores/clock.py @@ -16,7 +16,8 @@ class S7Clocking(Module, AutoCSR): clkfbout_mult_frange = (2, 64+1) clkout_divide_range = (1, 128+1) - def __init__(self): + def __init__(self, vco_margin=0): + self.vco_margin = vco_margin self.reset = Signal() self.locked = Signal() self.clkin_freq = None @@ -57,30 +58,32 @@ class S7Clocking(Module, AutoCSR): def compute_config(self): config = {} - config["divclk_divide"] = 1 - for clkfbout_mult in range(*self.clkfbout_mult_frange): - all_valid = True - vco_freq = self.clkin_freq*clkfbout_mult - (vco_freq_min, vco_freq_max) = self.vco_freq_range - if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max: - for n, (clk, f, p, m) in sorted(self.clkouts.items()): - valid = False - for d in range(*self.clkout_divide_range): - clk_freq = vco_freq/d - if abs(clk_freq - f) < f*m: - config["clkout{}_freq".format(n)] = clk_freq - config["clkout{}_divide".format(n)] = d - config["clkout{}_phase".format(n)] = p - valid = True - break - if not valid: - all_valid = False - else: - all_valid = False - if all_valid: - config["vco"] = vco_freq - config["clkfbout_mult"] = clkfbout_mult - return config + for divclk_divide in range(*self.divclk_divide_range): + config["divclk_divide"] = divclk_divide + for clkfbout_mult in range(*self.clkfbout_mult_frange): + all_valid = True + vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide + (vco_freq_min, vco_freq_max) = self.vco_freq_range + if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and + vco_freq <= vco_freq_max*(1 - self.vco_margin)): + for n, (clk, f, p, m) in sorted(self.clkouts.items()): + valid = False + for d in range(*self.clkout_divide_range): + clk_freq = vco_freq/d + if abs(clk_freq - f) < f*m: + config["clkout{}_freq".format(n)] = clk_freq + config["clkout{}_divide".format(n)] = d + config["clkout{}_phase".format(n)] = p + valid = True + break + if not valid: + all_valid = False + else: + all_valid = False + if all_valid: + config["vco"] = vco_freq + config["clkfbout_mult"] = clkfbout_mult + return config raise ValueError("No PLL config found") def expose_drp(self): @@ -122,6 +125,7 @@ class S7PLL(S7Clocking): def __init__(self, speedgrade=-1): S7Clocking.__init__(self) + self.divclk_divide_range = (1, 56+1) self.vco_freq_range = { -1: (800e6, 2133e6), -2: (800e6, 1866e6), @@ -152,6 +156,7 @@ class S7MMCM(S7Clocking): def __init__(self, speedgrade=-1): S7Clocking.__init__(self) + self.divclk_divide_range = (1, 106+1) self.clkin_freq_range = { -1: (10e6, 800e6), -2: (10e6, 933e6), @@ -208,7 +213,8 @@ class USClocking(Module, AutoCSR): clkfbout_mult_frange = (2, 64+1) clkout_divide_range = (1, 128+1) - def __init__(self): + def __init__(self, vco_margin=0): + self.vco_margin = vco_margin self.reset = Signal() self.locked = Signal() self.clkin_freq = None @@ -249,30 +255,32 @@ class USClocking(Module, AutoCSR): def compute_config(self): config = {} - config["divclk_divide"] = 1 - for clkfbout_mult in range(*self.clkfbout_mult_frange): - all_valid = True - vco_freq = self.clkin_freq*clkfbout_mult - (vco_freq_min, vco_freq_max) = self.vco_freq_range - if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max: - for n, (clk, f, p, m) in sorted(self.clkouts.items()): - valid = False - for d in range(*self.clkout_divide_range): - clk_freq = vco_freq/d - if abs(clk_freq - f) < f*m: - config["clkout{}_freq".format(n)] = clk_freq - config["clkout{}_divide".format(n)] = d - config["clkout{}_phase".format(n)] = p - valid = True - break - if not valid: - all_valid = False - else: - all_valid = False - if all_valid: - config["vco"] = vco_freq - config["clkfbout_mult"] = clkfbout_mult - return config + for divclk_divide in range(*self.divclk_divide_range): + config["divclk_divide"] = divclk_divide + for clkfbout_mult in range(*self.clkfbout_mult_frange): + all_valid = True + vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide + (vco_freq_min, vco_freq_max) = self.vco_freq_range + if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and + vco_freq <= vco_freq_max*(1 - self.vco_margin)): + for n, (clk, f, p, m) in sorted(self.clkouts.items()): + valid = False + for d in range(*self.clkout_divide_range): + clk_freq = vco_freq/d + if abs(clk_freq - f) < f*m: + config["clkout{}_freq".format(n)] = clk_freq + config["clkout{}_divide".format(n)] = d + config["clkout{}_phase".format(n)] = p + valid = True + break + if not valid: + all_valid = False + else: + all_valid = False + if all_valid: + config["vco"] = vco_freq + config["clkfbout_mult"] = clkfbout_mult + return config raise ValueError("No PLL config found") def expose_drp(self): @@ -313,12 +321,12 @@ class USPLL(USClocking): def __init__(self, speedgrade=-1): USClocking.__init__(self) + self.divclk_divide_range = (1, 56+1) self.clkin_freq_range = { -1: (70e6, 800e6), -2: (70e6, 933e6), -3: (70e6, 1066e6), }[speedgrade] - self.vco_freq_range = { -1: (600e6, 1200e6), -2: (600e6, 1335e6), @@ -349,12 +357,12 @@ class USMMCM(USClocking): def __init__(self, speedgrade=-1): USClocking.__init__(self) + self.divclk_divide_range = (1, 106+1) self.clkin_freq_range = { -1: (10e6, 800e6), -2: (10e6, 933e6), -3: (10e6, 1066e6), }[speedgrade] - self.vco_freq_range = { -1: (600e6, 1200e6), -2: (600e6, 1440e6), From 1275e2f150552c5b257368c7a00078c120cf2918 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 15 Apr 2019 16:48:47 +0200 Subject: [PATCH 46/52] build/xilinx/vivado: set quiet property on MultiReg/AsyncResetSynchronizer constraints MultiReg/AsyncResetSynchronizer are not necessarily present in all design, set quiet property to avoid generating false warnings. --- litex/build/xilinx/vivado.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index b9750bba5..81af2b0c1 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -197,23 +197,23 @@ class XilinxVivadoToolchain: # The asynchronous input to a MultiReg is a false path platform.add_platform_command( "set_false_path -quiet " - "-to [get_nets -filter {{mr_ff == TRUE}}]" + "-to [get_nets -quiet -filter {{mr_ff == TRUE}}]" ) # The asychronous reset input to the AsyncResetSynchronizer is a false # path platform.add_platform_command( "set_false_path -quiet " - "-to [get_pins -filter {{REF_PIN_NAME == PRE}} " - "-of [get_cells -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]" + "-to [get_pins -quiet -filter {{REF_PIN_NAME == PRE}} " + "-of [get_cells -quiet -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]" ) # clock_period-2ns to resolve metastability on the wire between the # AsyncResetSynchronizer FFs platform.add_platform_command( "set_max_delay 2 -quiet " - "-from [get_pins -filter {{REF_PIN_NAME == Q}} " - "-of [get_cells -filter {{ars_ff1 == TRUE}}]] " - "-to [get_pins -filter {{REF_PIN_NAME == D}} " - "-of [get_cells -filter {{ars_ff2 == TRUE}}]]" + "-from [get_pins -quiet -filter {{REF_PIN_NAME == Q}} " + "-of [get_cells -quiet -filter {{ars_ff1 == TRUE}}]] " + "-to [get_pins -quiet -filter {{REF_PIN_NAME == D}} " + "-of [get_cells -quiet -filter {{ars_ff2 == TRUE}}]]" ) def build(self, platform, fragment, build_dir="build", build_name="top", From 017147c623c77fbb7be5615b8435f03cc5bdddd7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 16 Apr 2019 16:57:23 +0200 Subject: [PATCH 47/52] build/altera: switch to sdc constraints, add add_false_path_constraints method --- litex/build/altera/platform.py | 7 ++++++ litex/build/altera/quartus.py | 43 ++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/litex/build/altera/platform.py b/litex/build/altera/platform.py index bccab35d2..332f60d73 100644 --- a/litex/build/altera/platform.py +++ b/litex/build/altera/platform.py @@ -25,3 +25,10 @@ class AlteraPlatform(GenericPlatform): if hasattr(clk, "p"): clk = clk.p self.toolchain.add_period_constraint(self, clk, period) + + def add_false_path_constraint(self, from_, to): + if hasattr(from_, "p"): + from_ = from_.p + if hasattr(to, "p"): + to = to.p + self.toolchain.add_false_path_constraint(self, from_, to) diff --git a/litex/build/altera/quartus.py b/litex/build/altera/quartus.py index 6d36ce63c..2aa025567 100644 --- a/litex/build/altera/quartus.py +++ b/litex/build/altera/quartus.py @@ -1,8 +1,9 @@ -# This file is Copyright (c) 2013 Florent Kermarrec +# This file is Copyright (c) 2013-2019 Florent Kermarrec # License: BSD import os import subprocess +import math from migen.fhdl.structure import _Fragment @@ -69,6 +70,22 @@ def _build_qsf(named_sc, named_pc, build_name): return "\n".join(lines) +def _build_sdc(clocks, false_paths, vns, build_name): + lines = [] + for clk, period in sorted(clocks.items(), key=lambda x: x[0].duid): + lines.append( + "create_clock -name {clk} -period ".format(clk=vns.get_name(clk)) + str(period) + + " [get_ports {{{clk}}}]".format(clk=vns.get_name(clk))) + for from_, to in sorted(false_paths, + key=lambda x: (x[0].duid, x[1].duid)): + lines.append( + "set_false_path " + "-from [get_clocks {{{from_}}}] " + "-to [get_clocks {{{to}}}]".format( + from_=vns.get_name(from_), to=vns.get_name(to))) + tools.write_to_file("{}.sdc".format(build_name), "\n".join(lines)) + + def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name): lines = [] for filename, language, library in sources: @@ -82,6 +99,7 @@ def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name): lang=language.upper(), path=filename.replace("\\", "/"), lib=library)) + lines.append("set_global_assignment -name SDC_FILE {}.sdc".format(build_name)) for path in vincpaths: lines.append("set_global_assignment -name SEARCH_PATH {}".format( @@ -117,6 +135,10 @@ fi class AlteraQuartusToolchain: + def __init__(self): + self.clocks = dict() + self.false_paths = set() + def build(self, platform, fragment, build_dir="build", build_name="top", toolchain_path=None, run=True, **kwargs): if toolchain_path is None: @@ -140,6 +162,8 @@ class AlteraQuartusToolchain: named_sc, named_pc, build_name) + + _build_sdc(self.clocks, self.false_paths, v_output.ns, build_name) if run: _run_quartus(build_name, toolchain_path) @@ -148,12 +172,11 @@ class AlteraQuartusToolchain: return v_output.ns def add_period_constraint(self, platform, clk, period): - # TODO: handle differential clk - platform.add_platform_command( - "set_global_assignment -name duty_cycle 50 -section_id {clk}", - clk=clk) - platform.add_platform_command( - "set_global_assignment -name fmax_requirement \"{freq} MHz\" " - "-section_id {clk}".format(freq=(1. / period) * 1000, - clk="{clk}"), - clk=clk) + if clk in self.clocks: + raise ValueError("A period constraint already exists") + period = math.floor(period*1e3)/1e3 # round to lowest picosecond + self.clocks[clk] = period + + def add_false_path_constraint(self, platform, from_, to): + if (to, from_) not in self.false_paths: + self.false_paths.add((from_, to)) From 40de01bcb0a9bf5992602e8fc50e338fc2c07dff Mon Sep 17 00:00:00 2001 From: Joanna Brozek Date: Fri, 12 Apr 2019 17:23:23 +0200 Subject: [PATCH 48/52] vexriscv: Add full and full_debug CPU variant --- litex/soc/cores/cpu/vexriscv/core.py | 4 +++- litex/soc/cores/cpu/vexriscv/verilog | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py index 5a1afedcb..c4c0df658 100644 --- a/litex/soc/cores/cpu/vexriscv/core.py +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -16,7 +16,7 @@ class VexRiscv(Module, AutoCSR): def __init__(self, platform, cpu_reset_address, variant=None): variant = "std" if variant is None else variant variant = "std_debug" if variant == "debug" else variant - variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug") + variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug", "full", "full_debug") assert variant in variants, "Unsupported variant %s" % variant self.platform = platform self.variant = variant @@ -157,6 +157,8 @@ class VexRiscv(Module, AutoCSR): "lite_debug": "VexRiscv_LiteDebug.v", "min": "VexRiscv_Min.v", "min_debug": "VexRiscv_MinDebug.v", + "full": "VexRiscv_Full.v", + "full_debug": "VexRiscv_FullDebug.v", } cpu_filename = verilog_variants[variant] vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog") diff --git a/litex/soc/cores/cpu/vexriscv/verilog b/litex/soc/cores/cpu/vexriscv/verilog index d7bbc2c16..ebe406465 160000 --- a/litex/soc/cores/cpu/vexriscv/verilog +++ b/litex/soc/cores/cpu/vexriscv/verilog @@ -1 +1 @@ -Subproject commit d7bbc2c167f1a0886c446d3c305d0ed4388570be +Subproject commit ebe4064653bc143bf92a0ccdd1099173620fcbf5 From e1683078ece9914c4619879a5fdef46300ac64a4 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Wed, 17 Apr 2019 10:39:35 -0400 Subject: [PATCH 49/52] build/sim/core: Initialize Verilator commandArgs Required when DUT is using plusargs. Prevents Verilator simulation from crashing with "Verilog called $test$plusargs or $value$plusargs without testbench C first calling Verilated::commandArgs(argc,argv)". --- litex/build/sim/core/sim.c | 3 ++- litex/build/sim/core/veril.cpp | 5 +++++ litex/build/sim/core/veril.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/litex/build/sim/core/sim.c b/litex/build/sim/core/sim.c index 32124ee19..3f7ad6489 100644 --- a/litex/build/sim/core/sim.c +++ b/litex/build/sim/core/sim.c @@ -203,7 +203,7 @@ static void cb(int sock, short which, void *arg) } } -int main() +int main(int argc, char *argv[]) { void *vdut=NULL; struct timeval tv; @@ -224,6 +224,7 @@ int main() goto out; } + litex_sim_init_cmdargs(argc, argv); if(RC_OK != (ret = litex_sim_initialize_all(&vdut, base))) { goto out; diff --git a/litex/build/sim/core/veril.cpp b/litex/build/sim/core/veril.cpp index ef43fb1df..6821e2078 100644 --- a/litex/build/sim/core/veril.cpp +++ b/litex/build/sim/core/veril.cpp @@ -17,6 +17,11 @@ extern "C" void litex_sim_eval(void *vdut) dut->eval(); } +extern "C" void litex_sim_init_cmdargs(int argc, char *argv[]) +{ + Verilated::commandArgs(argc, argv); +} + extern "C" void litex_sim_init_tracer(void *vdut) { Vdut *dut = (Vdut*)vdut; diff --git a/litex/build/sim/core/veril.h b/litex/build/sim/core/veril.h index 35326ade6..b8c5f1651 100644 --- a/litex/build/sim/core/veril.h +++ b/litex/build/sim/core/veril.h @@ -4,6 +4,7 @@ #define __VERIL_H_ #ifdef __cplusplus +extern "C" void litex_sim_init_cmdargs(int argc, char *argv[]); extern "C" void litex_sim_eval(void *vdut); extern "C" void litex_sim_init_tracer(void *vdut); extern "C" void litex_sim_tracer_dump(); From a92e90b215326cb2c5d2761fde641df14a6a5d7a Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 18 Apr 2019 18:42:29 +0200 Subject: [PATCH 50/52] soc/interconnect: add avalon with converters to/from native streams --- litex/soc/interconnect/avalon.py | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 litex/soc/interconnect/avalon.py diff --git a/litex/soc/interconnect/avalon.py b/litex/soc/interconnect/avalon.py new file mode 100644 index 000000000..edc2f6f10 --- /dev/null +++ b/litex/soc/interconnect/avalon.py @@ -0,0 +1,38 @@ +from migen import * + +from litex.soc.interconnect import stream + +# AvalonST to/from Native -------------------------------------------------------------------------- + +class Native2AvalonST(Module): + def __init__(self, layout, latency=2): + self.sink = sink = stream.Endpoint(layout) + self.source = source = stream.Endpoint(layout) + + # # # + + _from = sink + for n in range(latency): + _to = stream.Endpoint(layout) + self.sync += _from.connect(_to, omit={"ready"}) + if n == 0: + self.sync += _to.valid.eq(sink.valid & source.ready) + _from = _to + self.comb += _to.connect(source, omit={"ready"}) + self.comb += sink.ready.eq(source.ready) + + +class AvalonST2Native(Module): + def __init__(self, layout, latency=2): + self.sink = sink = stream.Endpoint(layout) + self.source = source = stream.Endpoint(layout) + + # # # + + buf = stream.SyncFIFO(layout, max(latency, 4)) + self.submodules += buf + self.comb += [ + sink.connect(buf.sink, omit={"ready"}), + sink.ready.eq(source.ready), + buf.source.connect(source) + ] From a78ca2de927f1b6955aad19530210970417d71b4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 19 Apr 2019 09:18:25 +0200 Subject: [PATCH 51/52] build/xilinx/vivado: only set library for vhdl files (not supported for verilog/system-verilog) --- litex/build/xilinx/vivado.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index 81af2b0c1..09a19411c 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -1,4 +1,4 @@ -# This file is Copyright (c) 2014 Florent Kermarrec +# This file is Copyright (c) 2014-2019 Florent Kermarrec # License: BSD import os @@ -118,8 +118,9 @@ class XilinxVivadoToolchain: for filename, language, library in sources: filename_tcl = "{" + filename + "}" tcl.append("add_files " + filename_tcl) - tcl.append("set_property library {} [get_files {}]" - .format(library, filename_tcl)) + if language == "vhdl": + tcl.append("set_property library {} [get_files {}]" + .format(library, filename_tcl)) for filename in edifs: filename_tcl = "{" + filename + "}" tcl.append("read_edif " + filename_tcl) From fa9560869446c68c57e2ce867f3692735fa3ebc4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 19 Apr 2019 10:21:56 +0200 Subject: [PATCH 52/52] soc/integration/soc_zynq: fix HP0 connections --- litex/soc/integration/soc_zynq.py | 88 +++++++++++++++---------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/litex/soc/integration/soc_zynq.py b/litex/soc/integration/soc_zynq.py index c6b0a5661..86d2d7b1a 100644 --- a/litex/soc/integration/soc_zynq.py +++ b/litex/soc/integration/soc_zynq.py @@ -136,60 +136,60 @@ class SoCZynq(SoCCore): self.axi_hp0_fifo_ctrl = axi_hp0_fifo_ctrl = Record(axi_fifo_ctrl_layout()) self.ps7_params.update( # axi hp0 aw - i_M_AXI_HP0_AWVALID=axi_hp0.aw.valid, - o_M_AXI_HP0_AWREADY=axi_hp0.aw.ready, - i_M_AXI_HP0_AWADDR=axi_hp0.aw.addr, - i_M_AXI_HP0_AWBURST=axi_hp0.aw.burst, - i_M_AXI_HP0_AWLEN=axi_hp0.aw.len, - i_M_AXI_HP0_AWSIZE=axi_hp0.aw.size, - i_M_AXI_HP0_AWID=axi_hp0.aw.id, - i_M_AXI_HP0_AWLOCK=axi_hp0.aw.lock, - i_M_AXI_HP0_AWPROT=axi_hp0.aw.prot, - i_M_AXI_HP0_AWCACHE=axi_hp0.aw.cache, - i_M_AXI_HP0_AWQOS=axi_hp0.aw.qos, + i_S_AXI_HP0_AWVALID=axi_hp0.aw.valid, + o_S_AXI_HP0_AWREADY=axi_hp0.aw.ready, + i_S_AXI_HP0_AWADDR=axi_hp0.aw.addr, + i_S_AXI_HP0_AWBURST=axi_hp0.aw.burst, + i_S_AXI_HP0_AWLEN=axi_hp0.aw.len, + i_S_AXI_HP0_AWSIZE=axi_hp0.aw.size, + i_S_AXI_HP0_AWID=axi_hp0.aw.id, + i_S_AXI_HP0_AWLOCK=axi_hp0.aw.lock, + i_S_AXI_HP0_AWPROT=axi_hp0.aw.prot, + i_S_AXI_HP0_AWCACHE=axi_hp0.aw.cache, + i_S_AXI_HP0_AWQOS=axi_hp0.aw.qos, # axi hp0 w - i_M_AXI_HP0_WVALID=axi_hp0.w.valid, - i_M_AXI_HP0_WLAST=axi_hp0.w.last, - o_M_AXI_HP0_WREADY=axi_hp0.w.ready, - i_M_AXI_HP0_WID=axi_hp0.w.id, - i_M_AXI_HP0_WDATA=axi_hp0.w.data, - i_M_AXI_HP0_WSTRB=axi_hp0.w.strb, + i_S_AXI_HP0_WVALID=axi_hp0.w.valid, + i_S_AXI_HP0_WLAST=axi_hp0.w.last, + o_S_AXI_HP0_WREADY=axi_hp0.w.ready, + i_S_AXI_HP0_WID=axi_hp0.w.id, + i_S_AXI_HP0_WDATA=axi_hp0.w.data, + i_S_AXI_HP0_WSTRB=axi_hp0.w.strb, # axi hp0 b - o_M_AXI_HP0_BVALID=axi_hp0.b.valid, - i_M_AXI_HP0_BREADY=axi_hp0.b.ready, - o_M_AXI_HP0_BID=axi_hp0.b.id, - o_M_AXI_HP0_BRESP=axi_hp0.b.resp, + o_S_AXI_HP0_BVALID=axi_hp0.b.valid, + i_S_AXI_HP0_BREADY=axi_hp0.b.ready, + o_S_AXI_HP0_BID=axi_hp0.b.id, + o_S_AXI_HP0_BRESP=axi_hp0.b.resp, # axi hp0 ar - i_M_AXI_HP0_ARVALID=axi_hp0.ar.valid, - o_M_AXI_HP0_ARREADY=axi_hp0.ar.ready, - i_M_AXI_HP0_ARADDR=axi_hp0.ar.addr, - i_M_AXI_HP0_ARBURST=axi_hp0.ar.burst, - i_M_AXI_HP0_ARLEN=axi_hp0.ar.len, - i_M_AXI_HP0_ARID=axi_hp0.ar.id, - i_M_AXI_HP0_ARLOCK=axi_hp0.ar.lock, - i_M_AXI_HP0_ARSIZE=axi_hp0.ar.size, - i_M_AXI_HP0_ARPROT=axi_hp0.ar.prot, - i_M_AXI_HP0_ARCACHE=axi_hp0.ar.cache, - i_M_AXI_HP0_ARQOS=axi_hp0.ar.qos, + i_S_AXI_HP0_ARVALID=axi_hp0.ar.valid, + o_S_AXI_HP0_ARREADY=axi_hp0.ar.ready, + i_S_AXI_HP0_ARADDR=axi_hp0.ar.addr, + i_S_AXI_HP0_ARBURST=axi_hp0.ar.burst, + i_S_AXI_HP0_ARLEN=axi_hp0.ar.len, + i_S_AXI_HP0_ARID=axi_hp0.ar.id, + i_S_AXI_HP0_ARLOCK=axi_hp0.ar.lock, + i_S_AXI_HP0_ARSIZE=axi_hp0.ar.size, + i_S_AXI_HP0_ARPROT=axi_hp0.ar.prot, + i_S_AXI_HP0_ARCACHE=axi_hp0.ar.cache, + i_S_AXI_HP0_ARQOS=axi_hp0.ar.qos, # axi hp0 r - o_M_AXI_HP0_RVALID=axi_hp0.r.valid, - i_M_AXI_HP0_RREADY=axi_hp0.r.ready, - o_M_AXI_HP0_RLAST=axi_hp0.r.last, - o_M_AXI_HP0_RID=axi_hp0.r.id, - o_M_AXI_HP0_RRESP=axi_hp0.r.resp, - o_M_AXI_HP0_RDATA=axi_hp0.r.data, + o_S_AXI_HP0_RVALID=axi_hp0.r.valid, + i_S_AXI_HP0_RREADY=axi_hp0.r.ready, + o_S_AXI_HP0_RLAST=axi_hp0.r.last, + o_S_AXI_HP0_RID=axi_hp0.r.id, + o_S_AXI_HP0_RRESP=axi_hp0.r.resp, + o_S_AXI_HP0_RDATA=axi_hp0.r.data, # axi hp0 fifo ctrl - i_S_AXI_HP0_FIFO_CTRL_0_RACOUNT=axi_hp0_fifo_ctrl.racount, - i_S_AXI_HP0_FIFO_CTRL_0_RCOUNT=axi_hp0_fifo_ctrl.rcount, - o_S_AXI_HP0_FIFO_CTRL_0_RDISSUECAPEN=axi_hp0_fifo_ctrl.rdissuecapen, - i_S_AXI_HP0_FIFO_CTRL_0_WACOUNT=axi_hp0_fifo_ctrl.wacount, - i_S_AXI_HP0_FIFO_CTRL_0_WCOUNT=axi_hp0_fifo_ctrl.wcount, - o_S_AXI_HP0_FIFO_CTRL_0_WRISSUECAPEN=axi_hp0_fifo_ctrl.wrissuecapen + o_S_AXI_HP0_RACOUNT=axi_hp0_fifo_ctrl.racount, + o_S_AXI_HP0_RCOUNT=axi_hp0_fifo_ctrl.rcount, + i_S_AXI_HP0_RDISSUECAP1_EN=axi_hp0_fifo_ctrl.rdissuecapen, + o_S_AXI_HP0_WACOUNT=axi_hp0_fifo_ctrl.wacount, + o_S_AXI_HP0_WCOUNT=axi_hp0_fifo_ctrl.wcount, + i_S_AXI_HP0_WRISSUECAP1_EN=axi_hp0_fifo_ctrl.wrissuecapen ) def add_axi_to_wishbone(self, axi_port, base_address=0x43c00000):