Как и обещал, выкладываю свои шаблоны.
Мастер пишет по фиксированному адресу 4 фиксированных слова, потом их читает и отправляет во внешний порт. Проверка на ошибки шины не производится, поэтому виснет при неправильном адресе!
CODE
-------------------------------------------------------------------------------
--
-- AXI4-Lite Master
-- Simplified IP-core that performs 32-byte write to fixed address and reads it back
-- Does not perform error check on write and read!!!
--
-- VHDL-Standard: VHDL'93
----------------------------------------------------------------------------
--
-- Structure:
-- axi_lite_master
--
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
--library unisim;
--use unisim.vcomponents.all;
entity AXI4_master_lite is
generic(
C_M_AXI_ADDR_WIDTH : integer := 32;
C_M_AXI_DATA_WIDTH : integer := 32
);
port(
STATUS: out std_logic_vector(31 downto 0); -- output for debug purposes
-- System Signals
M_AXI_ACLK : in std_logic;
M_AXI_ARESETN : in std_logic;
-- Master Interface Write Address
M_AXI_AWADDR : out std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
M_AXI_AWPROT : out std_logic_vector(3-1 downto 0);
M_AXI_AWVALID : out std_logic;
M_AXI_AWREADY : in std_logic;
-- Master Interface Write Data
M_AXI_WDATA : out std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
M_AXI_WSTRB : out std_logic_vector(C_M_AXI_DATA_WIDTH/8-1 downto 0);
M_AXI_WVALID : out std_logic;
M_AXI_WREADY : in std_logic;
-- Master Interface Write Response
M_AXI_BRESP : in std_logic_vector(2-1 downto 0);
M_AXI_BVALID : in std_logic;
M_AXI_BREADY : out std_logic;
-- Master Interface Read Address
M_AXI_ARADDR : out std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
M_AXI_ARPROT : out std_logic_vector(3-1 downto 0);
M_AXI_ARVALID : out std_logic;
M_AXI_ARREADY : in std_logic;
-- Master Interface Read Data
M_AXI_RDATA : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
M_AXI_RRESP : in std_logic_vector(2-1 downto 0);
M_AXI_RVALID : in std_logic;
M_AXI_RREADY : out std_logic
);
end AXI4_master_lite;
-------------------------------------------------------------------------------
-- Architecture
-------------------------------------------------------------------------------
architecture implementation of AXI4_master_lite is
signal testreg: std_logic_vector (C_M_AXI_DATA_WIDTH-1 downto 0);
signal counter, ctrread: integer range 0 to 32;
type state_type is (ST_IDLE, ST_WRITE,ST_DWRITE,ST_DACK, ST_ACK,ST_BREADY);
signal state, next_state : state_type;
type Rstate_type is (ST_IDLE, ST_RADDR,ST_RDATA);
signal Rstate:Rstate_type;
signal start_read:std_logic;
begin
M_AXI_AWPROT<=(others=>'0');
M_AXI_ARPROT<=(others=>'0');
WRITE_SM: process (M_AXI_ACLK) is
begin
if M_AXI_ARESETN='0' then
testreg<=x"A5A5A5A5";
M_AXI_AWVALID<='0';
M_AXI_WVALID<='0';
M_AXI_BREADY<='0';
counter<=0;
state<=ST_IDLE;
start_read<='0';
STATUS(15 downto 0)<=(others=>'0');
else
if M_AXI_ACLK'event and M_AXI_ACLK='1' then
case state is
when ST_IDLE =>
M_AXI_AWVALID<='0';
M_AXI_WVALID<='0';
M_AXI_BREADY<='0';
if counter<31 then
state<=ST_WRITE;
STATUS(15 downto 0)<=x"0001";
else
state<=state;
start_read<='1'; -- after writes we initiate reading
end if;
when ST_WRITE =>
M_AXI_AWADDR(31 downto 8)<=x"A800F0";
M_AXI_AWADDR(7 downto 0)<=std_logic_vector(to_unsigned(counter,8));
M_AXI_WDATA<=testreg;
M_AXI_WSTRB<="1111";
M_AXI_AWVALID<='1';
M_AXI_WDATA<=testreg;
M_AXI_WSTRB<="1111";
M_AXI_WVALID<='1';
state<=ST_ACK;
STATUS(15 downto 0)<=x"0002";
when ST_ACK =>
if M_AXI_AWREADY='1' then
M_AXI_AWVALID<='0';
counter<=counter+4;
state<=ST_DACK;
STATUS(15 downto 0)<=x"0003";
else
next_state<=state;
end if;
when ST_DWRITE =>
M_AXI_WDATA<=testreg;
M_AXI_WSTRB<="1111";
M_AXI_WVALID<='1';
state<=ST_DACK;
STATUS(15 downto 0)<=x"0004";
when ST_DACK =>
if M_AXI_WREADY='1' then
M_AXI_WVALID<='0';
M_AXI_BREADY<='1';
state<=ST_BREADY;
STATUS(15 downto 0)<=x"0005";
else
state<=state;
end if;
when ST_BREADY =>
if M_AXI_BVALID='1' then
M_AXI_BREADY<='0';
state<=ST_IDLE;
STATUS(15 downto 0)<=x"0006";
else
state<=state;
end if;
end case;
end if;
end if;
end process;
READ_SM: process(M_AXI_ACLK) is
begin
if M_AXI_ARESETN='0' then
M_AXI_ARVALID<='0';
M_AXI_RREADY<='0';
Rstate<=ST_IDLE;
ctrread<=0;
STATUS(31 downto 16)<=(others=>'0');
else
if M_AXI_ACLK'event and M_AXI_ACLK='1' then
case Rstate is
when ST_IDLE =>
if start_read='1' and ctrread<31 then
Rstate<=ST_RADDR;
M_AXI_ARVALID<='1';
M_AXI_ARADDR(31 downto 8)<=x"A800F0";
M_AXI_ARADDR(7 downto 0)<=std_logic_vector(to_unsigned(ctrread,8));
end if;
when ST_RADDR =>
M_AXI_ARVALID<='0';
M_AXI_RREADY<='1';
if M_AXI_RVALID='1' then
ctrread<=ctrread+4;
STATUS(31 downto 16)<=M_AXI_RDATA(15 downto 0);
Rstate<=ST_RDATA;
end if;
when ST_RDATA =>
M_AXI_RREADY<='0';
Rstate<=ST_IDLE;
end case;
end if;
end if;
end process;
end implementation;
Слейв это 2 регистра, ошибок не возвращает (всегда можно прочитать). Проверка на валидность адреса тоже рудиментарная.
CODE
-------------------------------------------------------------------------------
--
-- AXI4-Lite Slave
--
-- VHDL-Standard: VHDL'93
----------------------------------------------------------------------------
--
-- Structure:
-- axi_lite_slave
--
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
--library unisim;
--use unisim.vcomponents.all;
entity axi_paer_router is
generic(
C_M_AXI_ADDR_WIDTH : integer := 32;
C_M_AXI_DATA_WIDTH : integer := 32;
C_S_AXI_ADDR_WIDTH : integer := 32;
C_S_AXI_DATA_WIDTH : integer := 32;
C_S_AXI_MIN_SIZE : std_logic_vector := X"000001FF";
C_USE_WSTRB : integer := 0;
C_DPHASE_TIMEOUT : integer := 8;
C_BASEADDR : std_logic_vector := X"00000000";
C_HIGHADDR : std_logic_vector := X"00000010";
C_FAMILY : string := "spartan6";
C_NUM_REG : integer := 1;
C_NUM_MEM : integer := 1;
C_SLV_AWIDTH : integer := 32;
C_SLV_DWIDTH : integer := 32
);
port(
-- System Signals
M_AXI_ACLK : in std_logic; -- это еще остались от мастер-слейва, поэтому не переименовал
M_AXI_ARESETN : in std_logic; -- это еще остались от мастер-слейва, поэтому не переименовал
-- Slave Interface Write Address Ports
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_AWPROT : in std_logic_vector(3-1 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
-- Slave Interface Write Data Ports
S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_WSTRB : in std_logic_vector(C_S_AXI_DATA_WIDTH/8-1 downto 0);
S_AXI_WVALID : in std_logic;
S_AXI_WREADY : out std_logic;
-- Slave Interface Write Response Ports
S_AXI_BRESP : out std_logic_vector(2-1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
-- Slave Interface Read Address Ports
S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_ARPROT : in std_logic_vector(3-1 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
-- Slave Interface Read Data Ports
S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_RRESP : out std_logic_vector(2-1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic
);
end axi_paer_router;
-------------------------------------------------------------------------------
-- Architecture
-------------------------------------------------------------------------------
architecture implementation of axi_paer_router is
signal conf_reg: std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); -- вот и память слейва, 2 регистра
signal addr_reg: std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
type Rstate_type is (ST_IDLE, ST_READ);
signal R_state : Rstate_type;
type Wstate_type is (ST_IDLE,ST_WRITE, ST_CONFIRM);
signal W_state : Wstate_type;
begin
---------------------------------------------------------
WRITE_PROC: process(M_AXI_ACLK) is
begin
if M_AXI_ARESETN='0' then
conf_reg<=(others=>'0');
addr_reg<=(others=>'0');
else
if M_AXI_ACLK'event and M_AXI_ACLK='1' then
case W_state is
when ST_IDLE=>
S_AXI_BVALID<='0';
if S_AXI_AWVALID='1' then
S_AXI_AWREADY<='1';
W_state<=ST_WRITE;
end if;
when ST_WRITE=>
S_AXI_AWREADY<='0';
if S_AXI_WVALID='1' then
S_AXI_WREADY<='1';
if S_AXI_AWADDR(2)='0' then -- every 4th byte (either XXXXXXX0 or XXXXXXX4)
conf_reg<=S_AXI_WDATA;
else
addr_reg<=S_AXI_WDATA; -- вот такая примитивная адресация - все адреса мапированы в 2 рег
end if;
W_state<=ST_CONFIRM;
end if;
when ST_CONFIRM=>
S_AXI_BRESP<="00";
S_AXI_WREADY<='0';
S_AXI_BVALID<='1';
if S_AXI_BREADY='1' then
W_state<=ST_IDLE;
end if;
end case;
end if;
end if;
end process;
---------------------------------------------------------
READ_PROC: process (M_AXI_ACLK) is
begin
if M_AXI_ARESETN='0' then
R_state<=ST_IDLE;
else
if M_AXI_ACLK'event and M_AXI_ACLK='1' then
S_AXI_ARREADY<='0';
S_AXI_RVALID<='0';
S_AXI_RRESP<="00";
case R_state is
when ST_IDLE=>
if S_AXI_ARVALID='1' then
S_AXI_ARREADY<='1';
R_state<=ST_READ;
else R_state<=R_state;
end if;
when ST_READ =>
S_AXI_ARREADY<='0';
S_AXI_RVALID<='1';
S_AXI_RRESP<="00";
if S_AXI_ARADDR(2)='0' then -- every 4th byte (either XXXXXXX0 or XXXXXXX4)
S_AXI_RDATA<=conf_reg;
else
S_AXI_RDATA<=addr_reg;
end if;
if S_AXI_RREADY ='1' then
R_state<=ST_IDLE;
else R_state<=R_state;
end if;
end case;
end if;
end if;
end process;
end implementation;
Если кто-то не хочет использовать Xilinx IPIF, может воспользоваться вышеприведенными шаблонами для собственных корок. Лицензия WTFPL

. Обе корки протестированы в железе, собирались на xc6slx45 с микроблейзом в ИСЕ 14.2.
Помогла документация:
http://www.xilinx.com/support/documentatio..._ipif_ds765.pdfhttp://www.xilinx.com/support/documentatio...master_lite.pdfhttp://home.mit.bme.hu/~feher/MSC_RA/ARM/A...otocol_spec.pdfПо возможности постараюсь помочь, если у кого-то будут вопросы. На самом деле шина значительно проще чем кажется - глаза боятся, а руки делают.