External Memory-Mapped Components
An important feature of XML2VHDL is the ability to link external memory-mapped components into the shared generated memory-mapped architecture as a device using the XML register descriptions.
An example use-case is integrating the Xilinx System Management Wizard IP (refer to Links). This is a useful component, as it provides temperature and voltage monitoring of the FPGA.
<?xml version="1.0" encoding="ISO-8859-1"?>
<node id="sys_mon" hw_ignore="yes">
<!-- System Management Wizard Local Register Grouping -->
<node id="srr" address="0x0" mask="0xFFFFFFFF" permission="rw" hw_rst="no" description="Software Reset Register"/>
<node id="sr" address="0x4" mask="0xFFFFFFFF" permission="rw" hw_rst="no" description="Status Register"/>
<node id="aosr" address="0x8" mask="0xFFFFFFFF" permission="rw" hw_rst="no" description="Alarm Output Status Register"/>
<node id="convstr" address="0xc" mask="0xFFFFFFFF" permission="rw" hw_rst="no" description="CONVST Register. Bit[0] = ADC convert start register. Bit[17:2] = Wait cycle for temperature update"/>
...
...
<node id="seq_reg7" address="0xd3c" mask="0xFFFFFFFF" permission="rw" hw_rst="no" description="SYSMON Sequence Register 7 (ADC channel acquisition time)"/>
</node>
The XML Register Map description in the code above describes registers within the Xilinx System Management Wizard IP. This file needs to be manually created, with the names and descriptions obtained from the Xilinx IP Product Guide (PG185). Mapping all the registers of this IP into a XML2VHDL description allows any associated monitoring and control software to reference these locations and child bit-fields in a consistent manner. This ensures their underlying meaning can be derived by name, instead of the end-suer having to cross-reference address locations and decode bit-field values from registers manually.
Attention
It should be noted that this XML Register Map top-level node uses the
attribute hw_ignore="yes". This this will disable the generation of
VHDL output files for the current description. These are NOT
required as the Xilinx IP already provides an AXI4-Lite
interface to connect to the Logic-side of the generated XML2VHDL output.
Linking to an Interconnect
The next step is to link the generated XML output to a parent Interconnect
(in the example, the id="sys_mon" of the IC_XML_NODENAME Interconnect),
as shown below. IC_XML_NODENAME can also be used to link any other external
memory-mapped components.
Tip
It is recommended to connect external memory-mapped components via an Interconnect positioned at the end-user host design top-level in order to simplify connectivity throughout the design.
<?xml version="1.0" encoding="ISO-8859-1"?>
<node id="IC_XML_NODENAME" address="0x0" hw_type="ic">
...
...
<node id="sys_mon" address="0x80000" link="sys_mon_output.xml"/>
...
...
</node>
Connecting to Logic-side
The final step is to instantiate and connect the System Management IP to the end-user host design. This needs to be done using a custom VHDL wrapper file, used to expand the AXI4-Lite interface VHDL Recordings types and to connect them to the corresponding signals presented by the AXI4-Lite interface on the Xilinx IP. A non-functional example VHDL wrapper template is shown below.
-- -----------------------------------------------------------------------------
-- Non-functional example template
-- -----------------------------------------------------------------------------
entity external_mmap_if_wrapper is
port(
axi4lite_aclk : in std_logic;
axi4lite_areset_n : in std_logic;
axi4lite_mosi : in t_axi4lite_mosi;
axi4lite_miso : out t_axi4lite_miso
);
end entity external_mmap_if_wrapper;
architecture wrapper of external_mmap_if_wrapper is
component external_mmap_with_ax4lite is
port(
axi4lite_aclk : in std_logic;
axi4lite_areset_n : in std_logic;
gpo_0 : out std_logic_vector(7 downto 0);
axi4lite_s0_araddr : in std_logic_vector(8 downto 0);
axi4lite_s0_arready : out std_logic;
axi4lite_s0_arvalid : in std_logic;
axi4lite_s0_awaddr : in std_logic_vector(8 downto 0);
axi4lite_s0_awready : out std_logic;
axi4lite_s0_awvalid : in std_logic;
axi4lite_s0_bready : in std_logic;
axi4lite_s0_bresp : out std_logic_vector(1 downto 0);
axi4lite_s0_bvalid : out std_logic;
axi4lite_s0_rdata : out std_logic_vector(31 downto 0);
axi4lite_s0_rready : in std_logic;
axi4lite_s0_rresp : out std_logic_vector(1 downto 0);
axi4lite_s0_rvalid : out std_logic;
axi4lite_s0_wdata : in std_logic_vector(31 downto 0);
axi4lite_s0_wready : out std_logic;
axi4lite_s0_wstrb : in std_logic_vector(3 downto 0);
axi4lite_s0_wvalid : in std_logic
);
end component external_mmap_with_ax4lite;
-- Internal signals: -------------------------------------------------------
signal axi4lite_s0_araddr : std_logic_vector(8 downto 0);
signal axi4lite_s0_arready : std_logic;
signal axi4lite_s0_arvalid : std_logic;
signal axi4lite_s0_awaddr : std_logic_vector(8 downto 0);
signal axi4lite_s0_awready : std_logic;
signal axi4lite_s0_awvalid : std_logic;
signal axi4lite_s0_bready : std_logic;
signal axi4lite_s0_bresp : std_logic_vector(1 downto 0);
signal axi4lite_s0_bvalid : std_logic;
signal axi4lite_s0_rdata : std_logic_vector(31 downto 0);
signal axi4lite_s0_rready : std_logic;
signal axi4lite_s0_rresp : std_logic_vector(1 downto 0);
signal axi4lite_s0_rvalid : std_logic;
signal axi4lite_s0_wdata : std_logic_vector(31 downto 0);
signal axi4lite_s0_wready : std_logic;
signal axi4lite_s0_wstrb : std_logic_vector(3 downto 0);
signal axi4lite_s0_wvalid : std_logic;
--
signal axi4lite_mosi_int : t_axi4lite_mosi;
signal axi4lite_miso_int : t_axi4lite_miso;
begin
-- Mapping of signals to MISO/MOSI Records: --------------------------------
axi4lite_s0_awaddr(8 downto 0) <= axi4lite_mosi.awaddr(8 downto 0);
axi4lite_s0_awvalid <= axi4lite_mosi.awvalid;
axi4lite_miso.awready <= axi4lite_s0_awready;
--
axi4lite_s0_wdata(31 downto 0) <= axi4lite_mosi.wdata;
axi4lite_s0_wstrb(3 downto 0) <= axi4lite_mosi.wstrb;
axi4lite_s0_wvalid <= axi4lite_mosi.wvalid;
axi4lite_miso.wready <= axi4lite_s0_wready;
--
axi4lite_miso.bresp <= axi4lite_s0_bresp(1 downto 0);
axi4lite_miso.bvalid <= axi4lite_s0_bvalid;
axi4lite_s0_bready <= axi4lite_mosi.bready;
--
axi4lite_s0_araddr(8 downto 0) <= axi4lite_mosi.araddr(8 downto 0);
axi4lite_s0_arvalid <= axi4lite_mosi.arvalid;
axi4lite_miso.arready <= axi4lite_s0_arready;
--
axi4lite_miso.rdata <= axi4lite_s0_rdata(31 downto 0);
axi4lite_miso.rresp <= axi4lite_s0_rresp(1 downto 0);
axi4lite_miso.rvalid <= axi4lite_s0_rvalid;
axi4lite_s0_rready <= axi4lite_mosi.rready;
external_mmap_with_ax4lite_inst : component external_mmap_with_ax4lite
port map(
axi4lite_aclk => axi4lite_aclk,
axi4lite_areset_n => axi4lite_areset_n,
axi4lite_s0_araddr(8 downto 0) => axi4lite_s0_araddr(8 downto 0),
axi4lite_s0_arready => axi4lite_s0_arready,
axi4lite_s0_arvalid => axi4lite_s0_arvalid,
axi4lite_s0_awaddr(8 downto 0) => axi4lite_s0_awaddr(8 downto 0),
axi4lite_s0_awready => axi4lite_s0_awready,
axi4lite_s0_awvalid => axi4lite_s0_awvalid,
axi4lite_s0_bready => axi4lite_s0_bready,
axi4lite_s0_bresp(1 downto 0) => axi4lite_s0_bresp(1 downto 0),
axi4lite_s0_bvalid => axi4lite_s0_bvalid,
axi4lite_s0_rdata(31 downto 0) => axi4lite_s0_rdata(31 downto 0),
axi4lite_s0_rready => axi4lite_s0_rready,
axi4lite_s0_rresp(1 downto 0) => axi4lite_s0_rresp(1 downto 0),
axi4lite_s0_rvalid => axi4lite_s0_rvalid,
axi4lite_s0_wdata(31 downto 0) => axi4lite_s0_wdata(31 downto 0),
axi4lite_s0_wready => axi4lite_s0_wready,
axi4lite_s0_wstrb(3 downto 0) => axi4lite_s0_wstrb(3 downto 0),
axi4lite_s0_wvalid => axi4lite_s0_wvalid
);
end architecture wrapper;
The example VHDL below demonstrates the final instantiation of the external memory-mapped component with the XML2VHDL generated VHDL Interconnect which is used to decode the absolute addresses of the target address-space.
--***********************************************************************
-- AXI4LITE INTERCONNECT
--***********************************************************************
axi4lite_IC_XML_NODENAME_ic_inst: entity XML_LINK_LIB.axi4lite_IC_XML_NODENAME_ic
port map(
axi4lite_aclk => c2c_mm_clk,
axi4lite_aresetn => c2c_mm_rstn_sync,
axi4lite_mosi => axi4lite_io_mosi,
axi4lite_mosi_arr => axi4lite_mosi_arr,
axi4lite_miso_arr => axi4lite_miso_arr,
axi4lite_miso => axi4lite_io_miso
);
--***********************************************************************
-- SYSTEM MONITOR
--***********************************************************************
sys_mon_gen : if g_sys_mon_inst = true generate
sys_mon_top_inst : entity sys_mon_lib.sys_mon_top
generic map (
g_vaux_width => vauxp'length
)
port map (
axi4lite_aclk => c2c_mm_clk,
axi4lite_aresetn => c2c_mm_rstn_sync,
axi4lite_mosi => axi4lite_mosi_arr(axi4lite_mmap_get_id(XML_LINKED_LIB.axi4lite_IC_XML_NODENAME_mmap_pkg.id_sys_mon)),
axi4lite_miso => axi4lite_miso_arr(axi4lite_mmap_get_id(XML_LINKED_LIB.axi4lite_IC_XML_NODENAME_mmap_pkg.id_sys_mon)),
vp => vp,
vn => vn,
vauxp => vauxp,
vauxn => vauxn
);
end generate sys_mon_gen;