From 01ce8ab0d1fb33e9700f754409dd6d7ccb3d61e0 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Fri, 8 Dec 2023 11:57:35 +0100 Subject: [PATCH 1/4] soc/interconnect/axi/axi_lite:axi_lite_to_simple: avoid multiple read access --- litex/soc/interconnect/axi/axi_lite.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/litex/soc/interconnect/axi/axi_lite.py b/litex/soc/interconnect/axi/axi_lite.py index 6c7ad3db9..37d7f6c5e 100644 --- a/litex/soc/interconnect/axi/axi_lite.py +++ b/litex/soc/interconnect/axi/axi_lite.py @@ -132,11 +132,12 @@ class AXILiteInterface: def axi_lite_to_simple(axi_lite, port_adr, port_dat_r, port_dat_w=None, port_we=None): """Connection of AXILite to simple bus with 1-cycle latency, such as CSR bus or Memory port""" - bus_data_width = axi_lite.data_width - adr_shift = log2_int(bus_data_width//8) - do_read = Signal() - do_write = Signal() - last_was_read = Signal() + bus_data_width = axi_lite.data_width + adr_shift = log2_int(bus_data_width//8) + do_read = Signal() + do_write = Signal() + last_was_read = Signal() + port_dat_r_latched = Signal(axi_lite.data_width) comb = [] if port_dat_w is not None: @@ -169,14 +170,17 @@ def axi_lite_to_simple(axi_lite, port_adr, port_dat_r, port_dat_w=None, port_we= ) ).Elif(do_read, port_adr.eq(axi_lite.ar.addr[adr_shift:]), - NextState("SEND-READ-RESPONSE"), + NextState("LATCH-READ-RESPONSE"), ) ) + fsm.act("LATCH-READ-RESPONSE", + NextValue(port_dat_r_latched, port_dat_r), + NextState("SEND-READ-RESPONSE") + ), fsm.act("SEND-READ-RESPONSE", NextValue(last_was_read, 1), # As long as we have correct address port.dat_r will be valid. - port_adr.eq(axi_lite.ar.addr[adr_shift:]), - axi_lite.r.data.eq(port_dat_r), + axi_lite.r.data.eq(port_dat_r_latched), axi_lite.r.resp.eq(RESP_OKAY), axi_lite.r.valid.eq(1), If(axi_lite.r.ready, From 13987659a908852aba36ba33120723e8f3244a28 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Fri, 8 Dec 2023 11:59:33 +0100 Subject: [PATCH 2/4] soc/interconnect/axi/axi_lite: AXILiteInterconnectShared, AXILiteCrossbar: propagate master bus address width to Interface --- litex/soc/interconnect/axi/axi_lite.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/litex/soc/interconnect/axi/axi_lite.py b/litex/soc/interconnect/axi/axi_lite.py index 37d7f6c5e..64d514d91 100644 --- a/litex/soc/interconnect/axi/axi_lite.py +++ b/litex/soc/interconnect/axi/axi_lite.py @@ -132,11 +132,12 @@ class AXILiteInterface: def axi_lite_to_simple(axi_lite, port_adr, port_dat_r, port_dat_w=None, port_we=None): """Connection of AXILite to simple bus with 1-cycle latency, such as CSR bus or Memory port""" - bus_data_width = axi_lite.data_width - adr_shift = log2_int(bus_data_width//8) - do_read = Signal() - do_write = Signal() - last_was_read = Signal() + bus_data_width = axi_lite.data_width + adr_shift = log2_int(bus_data_width//8) + do_read = Signal() + do_write = Signal() + last_was_read = Signal() + port_dat_r_latched = Signal(axi_lite.data_width) comb = [] @@ -777,7 +778,8 @@ class AXILiteInterconnectShared(LiteXModule): """AXI Lite shared interconnect""" def __init__(self, masters, slaves, register=False, timeout_cycles=1e6): data_width = get_check_parameters(ports=masters + [s for _, s in slaves]) - shared = AXILiteInterface(data_width=data_width) + adr_width = max([m.address_width for m in masters]) + shared = AXILiteInterface(data_width=data_width, address_width=adr_width) self.arbiter = AXILiteArbiter(masters, shared) self.decoder = AXILiteDecoder(shared, slaves) if timeout_cycles is not None: @@ -790,8 +792,9 @@ class AXILiteCrossbar(LiteXModule): """ def __init__(self, masters, slaves, register=False, timeout_cycles=1e6): data_width = get_check_parameters(ports=masters + [s for _, s in slaves]) + adr_width = max([m.address_width for m in masters]) matches, busses = zip(*slaves) - access_m_s = [[AXILiteInterface(data_width=data_width) for j in slaves] for i in masters] # a[master][slave] + access_m_s = [[AXILiteInterface(data_width=data_width, address_width=adr_width) for j in slaves] for i in masters] # a[master][slave] access_s_m = list(zip(*access_m_s)) # a[slave][master] # Decode each master into its access row. for slaves, master in zip(access_m_s, masters): From 1a8fd2e808cba1a0790b9ae28c4812c74fa2caf7 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Fri, 8 Dec 2023 12:00:50 +0100 Subject: [PATCH 3/4] soc/interconnect/axi/axi_full: AXIInterconnectShared, AXICrossbar: propagate master bus address width to Interface --- litex/soc/interconnect/axi/axi_full.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/litex/soc/interconnect/axi/axi_full.py b/litex/soc/interconnect/axi/axi_full.py index 83410819a..dd7303878 100644 --- a/litex/soc/interconnect/axi/axi_full.py +++ b/litex/soc/interconnect/axi/axi_full.py @@ -613,7 +613,8 @@ class AXIInterconnectShared(LiteXModule): """AXI shared interconnect""" def __init__(self, masters, slaves, register=False, timeout_cycles=1e6): data_width = get_check_parameters(ports=masters + [s for _, s in slaves]) - shared = AXIInterface(data_width=data_width) + adr_width = max([m.address_width for m in masters]) + shared = AXIInterface(data_width=data_width, address_width=adr_width) self.arbiter = AXIArbiter(masters, shared) self.decoder = AXIDecoder(shared, slaves) if timeout_cycles is not None: @@ -626,8 +627,9 @@ class AXICrossbar(LiteXModule): """ def __init__(self, masters, slaves, register=False, timeout_cycles=1e6): data_width = get_check_parameters(ports=masters + [s for _, s in slaves]) + adr_width = max([m.address_width for m in masters]) matches, busses = zip(*slaves) - access_m_s = [[AXIInterface(data_width=data_width) for j in slaves] for i in masters] # a[master][slave] + access_m_s = [[AXIInterface(data_width=data_width, address_width=adr_width) for j in slaves] for i in masters] # a[master][slave] access_s_m = list(zip(*access_m_s)) # a[slave][master] # Decode each master into its access row. for slaves, master in zip(access_m_s, masters): From 2134c0d0b027934a99e135af93ac8ee48a2f0e5b Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Fri, 8 Dec 2023 12:02:45 +0100 Subject: [PATCH 4/4] soc/integration/soc: when adding a CSR Bridge bus_bridge must keep bus.address_width instead of the default value --- litex/soc/integration/soc.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index eedcc82b2..bede4562d 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1039,9 +1039,17 @@ class SoC(LiteXModule, SoCCoreCompat): "axi-lite": axi.AXILite2CSR, "axi" : axi.AXILite2CSR, # Note: CSR is a slow bus so using AXI-Lite is fine. }[self.bus.standard] + bus_bridge_cls = { + "wishbone": wishbone.Interface, + "axi-lite": axi.AXILiteInterface, + "axi" : axi.AXILiteInterface, + }[self.bus.standard] csr_bridge_name = f"{name}_bridge" self.check_if_exists(csr_bridge_name) csr_bridge = csr_bridge_cls( + bus_bridge_cls( + address_width = self.bus.address_width, + data_width = self.bus.data_width), bus_csr = csr_bus.Interface( address_width = self.csr.address_width, data_width = self.csr.data_width),