Reputation: 1910
In my VHDL, I have a toplevel interface of an APB slave, and an AXI master port, then I mark these interfaces as Xilinx Interfaces so that Vivado will know how to group them together in the Block Designer GUI of vivado. Here's the code:
library ieee;
use ieee.std_logic_1164.all;
entity rtl_top is
port(
-- Clocks
axi_aclk :in std_logic;
axi_arst_n :in std_logic;
-- Peripheral Servant Port: from ZYNQ Master Port
-- (Connect to ZYNQ M_AXI_GPO -> axi-interconnect -> axi-apb-bridge)
s_apb_gp0_paddr :in std_logic_vector(31 downto 0);
s_apb_gp0_psel :in std_logic;
s_apb_gp0_penable :in std_logic;
s_apb_gp0_pwrite :in std_logic;
s_apb_gp0_pwdata :in std_logic_vector(31 downto 0);
s_apb_gp0_pready :out std_logic;
s_apb_gp0_prdata :out std_logic_vector(31 downto 0);
s_apb_gp0_pslverr :out std_logic;
--Peripheral DMA port: to ZYNQ Servant Port S_AXI_GP0
-- (actually, don't connect it, its just a placeholder)
m_axi_gp0_araddr :out std_logic_vector(31 downto 0);
m_axi_gp0_arburst :out std_logic_vector(1 downto 0);
m_axi_gp0_arcache :out std_logic_vector(3 downto 0);
m_axi_gp0_arid :out std_logic_vector(5 downto 0);
m_axi_gp0_arlen :out std_logic_vector(3 downto 0);
m_axi_gp0_arlock :out std_logic_vector(1 downto 0);
m_axi_gp0_arprot :out std_logic_vector(2 downto 0);
m_axi_gp0_arqos :out std_logic_vector(3 downto 0);
m_axi_gp0_arready :in std_logic;
m_axi_gp0_arsize :out std_logic_vector(2 downto 0);
m_axi_gp0_arvalid :out std_logic;
m_axi_gp0_awaddr :out std_logic_vector(31 downto 0);
m_axi_gp0_awburst :out std_logic_vector(1 downto 0);
m_axi_gp0_awid :out std_logic_vector(5 downto 0);
m_axi_gp0_awprot :out std_logic_vector(2 downto 0);
m_axi_gp0_awqos :out std_logic_vector(3 downto 0);
m_axi_gp0_awready :in std_logic;
m_axi_gp0_awvalid :out std_logic;
m_axi_gp0_bid :in std_logic_vector(5 downto 0);
m_axi_gp0_bready :out std_logic;
m_axi_gp0_bresp :in std_logic_vector(1 downto 0);
m_axi_gp0_bvalid :in std_logic;
m_axi_gp0_rdata :in std_logic_vector(31 downto 0);
m_axi_gp0_rid :in std_logic_vector(5 downto 0);
m_axi_gp0_rlast :in std_logic;
m_axi_gp0_rready :out std_logic;
m_axi_gp0_rresp :in std_logic_vector(1 downto 0);
m_axi_gp0_rvalid :in std_logic;
m_axi_gp0_wdata :out std_logic_vector(31 downto 0);
m_axi_gp0_wid :out std_logic_vector(5 downto 0);
m_axi_gp0_wlast :out std_logic;
m_axi_gp0_wready :in std_logic;
m_axi_gp0_wstrb :out std_logic_vector(3 downto 0);
m_axi_gp0_wvalid :out std_logic
);
ATTRIBUTE X_INTERFACE_INFO :STRING;
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_paddr :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PADDR";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_psel :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PSEL";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_penable :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PENABLE";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pwrite :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PWRITE";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pwdata :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PWDATA";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pready :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PREADY";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_prdata :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PRDATA";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pslverr :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PSLVERR";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_araddr :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARADDR";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arburst :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARBURST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arcache :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARCACHE";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arlen :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARLEN";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arlock :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARLOCK";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arprot :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARPROT";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arqos :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARQOS";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arready :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARREADY";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arsize :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARSIZE";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_arvalid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 ARVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_awaddr :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 AWADDR";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_awburst :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 AWBURST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_awid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 AWID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_awprot :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 AWPROT";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_awqos :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 AWQOS";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_awready :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 AWREADY";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_awvalid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 AWVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_bid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 BID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_bready :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 BREADY";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_bresp :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 BRESP";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_bvalid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 BVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_rdata :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 RDATA";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_rid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 RID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_rlast :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 RLAST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_rready :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 RREADY";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_rresp :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 RRESP";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_rvalid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 RVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_wdata :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 WDATA";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_wid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 WID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_wlast :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 WLAST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_wready :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 WREADY";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_wstrb :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 WSTRB";
ATTRIBUTE X_INTERFACE_INFO of m_axi_gp0_wvalid :SIGNAL is "xilinx.com:interface:aximm:1.0 M_AXI_GP0 WVALID";
end entity;
architecture rtl of rtl_top is
begin
--ZYNQ API Slave Port Placeholder
s_apb_gp0_pready <= '0';
s_apb_gp0_prdata <= (others => '0');
s_apb_gp0_pslverr <= '0';
--ZYNQ Axi MASTER Port Placeholder
m_axi_gp0_araddr <= (others => '0');
m_axi_gp0_arburst <= (others => '0');
m_axi_gp0_arcache <= (others => '0');
m_axi_gp0_arid <= (others => '0');
m_axi_gp0_arlen <= (others => '0');
m_axi_gp0_arlock <= (others => '0');
m_axi_gp0_arprot <= (others => '0');
m_axi_gp0_arqos <= (others => '0');
m_axi_gp0_arsize <= (others => '0');
m_axi_gp0_awaddr <= (others => '0');
m_axi_gp0_awburst <= (others => '0');
m_axi_gp0_awid <= (others => '0');
m_axi_gp0_awprot <= (others => '0');
m_axi_gp0_awqos <= (others => '0');
m_axi_gp0_wdata <= (others => '0');
m_axi_gp0_wid <= (others => '0');
m_axi_gp0_wstrb <= (others => '0');
m_axi_gp0_arvalid <= '0';
m_axi_gp0_awvalid <= '0';
m_axi_gp0_bready <= '0';
m_axi_gp0_rready <= '0';
m_axi_gp0_wlast <= '0';
m_axi_gp0_wvalid <= '0';
end architecture;
My question is: why does vivado only recognize one of the Intefaces when I add it to the Block Design GUI? see Picture:
Upvotes: 2
Views: 2353
Reputation: 269
You should get a plethora of warnings in Vivado when trying to place your RTL module:
WARNING: [IP_Flow 19-529] Port Map 'PADDR': Port named 'rtl_top' does not exist.
WARNING: [IP_Flow 19-571] Bus Interface 'S_APB_GP0': Physical port "rtl_top" of a port map does not exist
WARNING: [IP_Flow 19-1965] Bus Interface 'S_APB_GP0': A port map to the required logical port "PSEL" of the bus abstraction "xilinx.com:interface:apb_rtl:1.0" is missing.
Moving the attribute specification into the architecture
section (leaving the attribute declaration inside the entity
declaration) yields better results:
Obtained with:
library ieee;
use ieee.std_logic_1164.all;
entity rtl_top is
port(
-- Clocks
axi_aclk :in std_logic;
axi_arst_n :in std_logic;
-- Peripheral Servant Port: from ZYNQ Master Port
-- (Connect to ZYNQ M_AXI_GPO -> axi-interconnect -> axi-apb-bridge)
s_apb_gp0_paddr :in std_logic_vector(31 downto 0);
s_apb_gp0_psel :in std_logic;
s_apb_gp0_penable :in std_logic;
s_apb_gp0_pwrite :in std_logic;
s_apb_gp0_pwdata :in std_logic_vector(31 downto 0);
s_apb_gp0_pready :out std_logic;
s_apb_gp0_prdata :out std_logic_vector(31 downto 0);
s_apb_gp0_pslverr :out std_logic;
--Peripheral DMA port: to ZYNQ Servant Port S_AXI_GP0
-- (actually, don't connect it, its just a placeholder)
m_axi_gp0_araddr :out std_logic_vector(31 downto 0);
m_axi_gp0_arburst :out std_logic_vector(1 downto 0);
m_axi_gp0_arcache :out std_logic_vector(3 downto 0);
m_axi_gp0_arid :out std_logic_vector(5 downto 0);
m_axi_gp0_arlen :out std_logic_vector(3 downto 0);
m_axi_gp0_arlock :out std_logic_vector(1 downto 0);
m_axi_gp0_arprot :out std_logic_vector(2 downto 0);
m_axi_gp0_arqos :out std_logic_vector(3 downto 0);
m_axi_gp0_arready :in std_logic;
m_axi_gp0_arsize :out std_logic_vector(2 downto 0);
m_axi_gp0_arvalid :out std_logic;
m_axi_gp0_awaddr :out std_logic_vector(31 downto 0);
m_axi_gp0_awburst :out std_logic_vector(1 downto 0);
m_axi_gp0_awid :out std_logic_vector(5 downto 0);
m_axi_gp0_awprot :out std_logic_vector(2 downto 0);
m_axi_gp0_awqos :out std_logic_vector(3 downto 0);
m_axi_gp0_awready :in std_logic;
m_axi_gp0_awvalid :out std_logic;
m_axi_gp0_bid :in std_logic_vector(5 downto 0);
m_axi_gp0_bready :out std_logic;
m_axi_gp0_bresp :in std_logic_vector(1 downto 0);
m_axi_gp0_bvalid :in std_logic;
m_axi_gp0_rdata :in std_logic_vector(31 downto 0);
m_axi_gp0_rid :in std_logic_vector(5 downto 0);
m_axi_gp0_rlast :in std_logic;
m_axi_gp0_rready :out std_logic;
m_axi_gp0_rresp :in std_logic_vector(1 downto 0);
m_axi_gp0_rvalid :in std_logic;
m_axi_gp0_wdata :out std_logic_vector(31 downto 0);
m_axi_gp0_wid :out std_logic_vector(5 downto 0);
m_axi_gp0_wlast :out std_logic;
m_axi_gp0_wready :in std_logic;
m_axi_gp0_wstrb :out std_logic_vector(3 downto 0);
m_axi_gp0_wvalid :out std_logic
);
ATTRIBUTE X_INTERFACE_INFO :STRING;
end entity;
architecture rtl of rtl_top is
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_paddr :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PADDR";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_psel :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PSEL";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_penable :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PENABLE";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pwrite :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PWRITE";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pwdata :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PWDATA";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pready :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PREADY";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_prdata :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PRDATA";
ATTRIBUTE X_INTERFACE_INFO of s_apb_gp0_pslverr :SIGNAL is "xilinx.com:interface:apb:1.0 S_APB_GP0 PSLVERR";
begin
--ZYNQ API Slave Port Placeholder
s_apb_gp0_pready <= '0';
s_apb_gp0_prdata <= (others => '0');
s_apb_gp0_pslverr <= '0';
--ZYNQ Axi MASTER Port Placeholder
m_axi_gp0_araddr <= (others => '0');
m_axi_gp0_arburst <= (others => '0');
m_axi_gp0_arcache <= (others => '0');
m_axi_gp0_arid <= (others => '0');
m_axi_gp0_arlen <= (others => '0');
m_axi_gp0_arlock <= (others => '0');
m_axi_gp0_arprot <= (others => '0');
m_axi_gp0_arqos <= (others => '0');
m_axi_gp0_arsize <= (others => '0');
m_axi_gp0_awaddr <= (others => '0');
m_axi_gp0_awburst <= (others => '0');
m_axi_gp0_awid <= (others => '0');
m_axi_gp0_awprot <= (others => '0');
m_axi_gp0_awqos <= (others => '0');
m_axi_gp0_wdata <= (others => '0');
m_axi_gp0_wid <= (others => '0');
m_axi_gp0_wstrb <= (others => '0');
m_axi_gp0_arvalid <= '0';
m_axi_gp0_awvalid <= '0';
m_axi_gp0_bready <= '0';
m_axi_gp0_rready <= '0';
m_axi_gp0_wlast <= '0';
m_axi_gp0_wvalid <= '0';
end architecture;
That's right, I didn't even need to include the interface info for the AXI interface to get a nice pretty port. (I would still keep it, just curious how Vivado can cope with no interface info for AXI.) I'd guess Vivado recognizes AXI interfaces by name alone, since Xilinx loves AXI so much now.
What puzzles me is that keeping the attribute specification in the architecture
section seems to violate the VHDL spec, as pointed out in the Answer to your last attribute Question. user1155120 was right though, it looks like Vivado adheres to the wrong behavior.
Upvotes: 2