export axi4 lite cpuif
This commit is contained in:
@@ -5,7 +5,7 @@ from peakrdl.config import schema
|
|||||||
from peakrdl.plugins.entry_points import get_entry_points
|
from peakrdl.plugins.entry_points import get_entry_points
|
||||||
from peakrdl.plugins.exporter import ExporterSubcommandPlugin
|
from peakrdl.plugins.exporter import ExporterSubcommandPlugin
|
||||||
|
|
||||||
from .cpuif import BaseCpuif, apb3, apb4
|
from .cpuif import BaseCpuif, apb3, apb4, axi4lite
|
||||||
from .exporter import BusDecoderExporter
|
from .exporter import BusDecoderExporter
|
||||||
from .udps import ALL_UDPS
|
from .udps import ALL_UDPS
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ def get_cpuifs(config: list[tuple[str, Any]]) -> dict[str, type[BaseCpuif]]:
|
|||||||
"apb3-flat": apb3.APB3CpuifFlat,
|
"apb3-flat": apb3.APB3CpuifFlat,
|
||||||
"apb4": apb4.APB4Cpuif,
|
"apb4": apb4.APB4Cpuif,
|
||||||
"apb4-flat": apb4.APB4CpuifFlat,
|
"apb4-flat": apb4.APB4CpuifFlat,
|
||||||
# "axi4-lite": axi4lite.AXI4Lite_Cpuif,
|
"axi4-lite": axi4lite.AXI4LiteCpuif,
|
||||||
# "axi4-lite-flat": axi4lite.AXI4Lite_Cpuif_flattened,
|
"axi4-lite-flat": axi4lite.AXI4LiteCpuifFlat,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load any cpuifs specified via entry points
|
# Load any cpuifs specified via entry points
|
||||||
|
|||||||
4
src/peakrdl_busdecoder/cpuif/axi4lite/__init__.py
Normal file
4
src/peakrdl_busdecoder/cpuif/axi4lite/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .axi4_lite_cpuif import AXI4LiteCpuif
|
||||||
|
from .axi4_lite_cpuif_flat import AXI4LiteCpuifFlat
|
||||||
|
|
||||||
|
__all__ = ["AXI4LiteCpuif", "AXI4LiteCpuifFlat"]
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
from typing import overload
|
||||||
|
|
||||||
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
|
from ...utils import get_indexed_path
|
||||||
|
from ..base_cpuif import BaseCpuif
|
||||||
|
|
||||||
|
|
||||||
|
class AXI4LiteCpuifFlat(BaseCpuif):
|
||||||
|
template_path = "axi4lite_tmpl.sv"
|
||||||
|
is_interface = True
|
||||||
|
|
||||||
|
def _port_declaration(self, child: AddressableNode) -> str:
|
||||||
|
base = f"axi4lite_intf.master m_axil_{child.inst_name}"
|
||||||
|
|
||||||
|
# When unrolled, current_idx is set - append it to the name
|
||||||
|
if child.current_idx is not None:
|
||||||
|
base = f"{base}_{'_'.join(map(str, child.current_idx))}"
|
||||||
|
|
||||||
|
# Only add array dimensions if this should be treated as an array
|
||||||
|
if self.check_is_array(child):
|
||||||
|
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
|
||||||
|
|
||||||
|
return base
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_declaration(self) -> str:
|
||||||
|
"""Returns the port declaration for the AXI4-Lite interface."""
|
||||||
|
slave_ports: list[str] = ["axi4lite_intf.slave s_axil"]
|
||||||
|
master_ports: list[str] = list(map(self._port_declaration, self.addressable_children))
|
||||||
|
|
||||||
|
return ",\n".join(slave_ports + master_ports)
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def signal(self, signal: str, node: None = None, indexer: None = None) -> str: ...
|
||||||
|
@overload
|
||||||
|
def signal(self, signal: str, node: AddressableNode, indexer: str) -> str: ...
|
||||||
|
def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str:
|
||||||
|
if node is None or indexer is None:
|
||||||
|
# Node is none, so this is a slave signal
|
||||||
|
return f"s_axil.{signal}"
|
||||||
|
|
||||||
|
# Master signal
|
||||||
|
return f"m_axil_{get_indexed_path(node.parent, node, indexer, skip_kw_filter=True)}.{signal}"
|
||||||
|
|
||||||
|
def fanout(self, node: AddressableNode) -> str:
|
||||||
|
fanout: dict[str, str] = {}
|
||||||
|
|
||||||
|
wr_sel = f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
|
||||||
|
rd_sel = f"cpuif_rd_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
|
||||||
|
|
||||||
|
# Write address channel
|
||||||
|
fanout[self.signal("AWVALID", node, "gi")] = wr_sel
|
||||||
|
fanout[self.signal("AWADDR", node, "gi")] = self.signal("AWADDR")
|
||||||
|
fanout[self.signal("AWPROT", node, "gi")] = self.signal("AWPROT")
|
||||||
|
|
||||||
|
# Write data channel
|
||||||
|
fanout[self.signal("WVALID", node, "gi")] = wr_sel
|
||||||
|
fanout[self.signal("WDATA", node, "gi")] = "cpuif_wr_data"
|
||||||
|
fanout[self.signal("WSTRB", node, "gi")] = "cpuif_wr_byte_en"
|
||||||
|
|
||||||
|
# Write response channel (master -> slave)
|
||||||
|
fanout[self.signal("BREADY", node, "gi")] = self.signal("BREADY")
|
||||||
|
|
||||||
|
# Read address channel
|
||||||
|
fanout[self.signal("ARVALID", node, "gi")] = rd_sel
|
||||||
|
fanout[self.signal("ARADDR", node, "gi")] = self.signal("ARADDR")
|
||||||
|
fanout[self.signal("ARPROT", node, "gi")] = self.signal("ARPROT")
|
||||||
|
|
||||||
|
# Read data channel (master -> slave)
|
||||||
|
fanout[self.signal("RREADY", node, "gi")] = self.signal("RREADY")
|
||||||
|
|
||||||
|
return "\n".join(f"assign {lhs} = {rhs};" for lhs, rhs in fanout.items())
|
||||||
|
|
||||||
|
def fanin(self, node: AddressableNode | None = None) -> str:
|
||||||
|
fanin: dict[str, str] = {}
|
||||||
|
if node is None:
|
||||||
|
fanin["cpuif_rd_ack"] = "'0"
|
||||||
|
fanin["cpuif_rd_err"] = "'0"
|
||||||
|
else:
|
||||||
|
# Read side: ack comes from RVALID; err if RRESP[1] is set (SLVERR/DECERR)
|
||||||
|
fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i")
|
||||||
|
fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]"
|
||||||
|
|
||||||
|
return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items())
|
||||||
|
|
||||||
|
def readback(self, node: AddressableNode | None = None) -> str:
|
||||||
|
fanin: dict[str, str] = {}
|
||||||
|
if node is None:
|
||||||
|
fanin["cpuif_rd_data"] = "'0"
|
||||||
|
else:
|
||||||
|
fanin["cpuif_rd_data"] = self.signal("RDATA", node, "i")
|
||||||
|
|
||||||
|
return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items())
|
||||||
Reference in New Issue
Block a user