library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity led_control_s_axi is
generic (
C_S_AXI_DATA_WIDTH : integer := 32;
C_S_AXI_ADDR_WIDTH : integer := 4
);
port (
---------------------------------------------------
-- 用户端口
---------------------------------------------------
led_flash_en : out std_logic;
led_flash_time : out std_logic_vector(31 downto 0);
test : out std_logic_vector(127 downto 0);
---------------------------------------------------
-- Axi Slave Bus Interface
---------------------------------------------------
S_AXI_ACLK : in std_logic;
S_AXI_ARESETN : in std_logic;
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
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;
S_AXI_BRESP : out std_logic_vector(1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_RRESP : out std_logic_vector(1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic
);
end led_control_s_axi;
architecture arch_imp of led_control_s_axi is
-------------------------------------------------------------------------------
-- 常量声明
-------------------------------------------------------------------------------
-- local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
-- ADDR_LSB is used for addressing 32/64 bit registers/memories
-- ADDR_LSB = 2 for 32 bits (n downto 2)
-- ADDR_LSB = 3 for 64 bits (n downto 3)
constant ADDR_LSB : integer := (C_S_AXI_DATA_WIDTH/32)+ 1;
constant OPT_MEM_ADDR_BITS : integer := 1;
-------------------------------------------------------------------------------
-- 信号声明
-------------------------------------------------------------------------------
---- AXI4LITE signals
signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_awready : std_logic;
signal axi_wready : std_logic;
signal axi_bresp : std_logic_vector(1 downto 0);
signal axi_bvalid : std_logic;
signal axi_araddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_arready : std_logic;
signal axi_rdata : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal axi_rresp : std_logic_vector(1 downto 0);
signal axi_rvalid : std_logic;
---- Signals for user logic register space example
signal slv_reg0 : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg1 : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg2 : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg3 : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal slv_reg_rden : std_logic;
signal slv_reg_wren : std_logic;
signal reg_data_out : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal byte_index : integer;
signal aw_en : std_logic;
begin
-- I/O Connections assignments
S_AXI_AWREADY <= axi_awready;
S_AXI_WREADY <= axi_wready;
S_AXI_BRESP <= axi_bresp;
S_AXI_BVALID <= axi_bvalid;
S_AXI_ARREADY <= axi_arready;
S_AXI_RDATA <= axi_rdata;
S_AXI_RRESP <= axi_rresp;
S_AXI_RVALID <= axi_rvalid;
-------------------------------------------------------
-- Implement axi_awready generation
-- axi_awready is asserted for one S_AXI_ACLK clock cycle when both S_AXI_AWVALID and S_AXI_WVALID are asserted.axi_awready is de-asserted when reset is low.
-----------------------------------
-- Implement axi_awaddr latching
-- This process is used to latch the address when both S_AXI_AWVALID and S_AXI_WVALID are valid.
-------------------------------------------------------
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_awready <= '0';
aw_en <= '1';
axi_awaddr <= (others => '0');
else
if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then
-- slave is ready to accept write address when there is a valid write address and write data on the write address and data bus.
-- This design expects no outstanding transactions.
axi_awready <= '1';
aw_en <= '0';
axi_awaddr <= S_AXI_AWADDR;
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then
axi_awready <= '0';
aw_en <= '1';
else
axi_awready <= '0';
end if;
end if;
end if;
end process;
-- Implement axi_wready generation
-- axi_wready is asserted for one S_AXI_ACLK clock cycle when both S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is de-asserted when reset is low.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_wready <= '0';
else
if (axi_wready = '0' and S_AXI_WVALID = '1' and S_AXI_AWVALID = '1' and aw_en = '1') then
-- slave is ready to accept write data when there is a valid write address and write data on the write address and data bus.
-- This design expects no outstanding transactions.
axi_wready <= '1';
else
axi_wready <= '0';
end if;
end if;
end if;
end process;
-- Implement write response logic generation
-- The write response and response valid signals are asserted by the slave when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
-- This marks the acceptance of address and indicates the status of write transaction.
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_bvalid <= '0';
axi_bresp <= "00"; --need to work more on the responses
else
if (axi_awready = '1' and S_AXI_AWVALID = '1' and axi_wready = '1' and S_AXI_WVALID = '1' and axi_bvalid = '0' ) then
axi_bvalid <= '1';
axi_bresp <= "00";
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then --check if bready is asserted while bvalid is high)
axi_bvalid <= '0'; -- (there is a possibility that bready is always asserted high)
end if;
end if;
end if;
end process;
-- Implement axi_arready generation
-- axi_arready is asserted for one S_AXI_ACLK clock cycle when S_AXI_ARVALID is asserted. axi_awready is de-asserted when reset (active low) is asserted.
-- The read address is also latched when S_AXI_ARVALID is asserted. axi_araddr is reset to zero on reset assertion
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_arready <= '0';
axi_araddr <= (others => '1');
else
if (axi_arready = '0' and S_AXI_ARVALID = '1') then
axi_arready <= '1';
axi_araddr <= S_AXI_ARADDR;
else
axi_arready <= '0';
end if;
end if;
end if;
end process;
-- Implement axi_arvalid generation
-- axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
-- S_AXI_ARVALID and axi_arready are asserted. The slave registers
-- data are available on the axi_rdata bus at this instance. The
-- assertion of axi_rvalid marks the validity of read data on the
-- bus and axi_rresp indicates the status of read transaction.axi_rvalid
-- is deasserted on reset (active low). axi_rresp and axi_rdata are
-- cleared to zero on reset (active low).
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_rvalid <= '0';
axi_rresp <= "00";
else
if (axi_arready = '1' and S_AXI_ARVALID = '1' and axi_rvalid = '0') then
axi_rvalid <= '1';
axi_rresp <= "00"; -- 'OKAY' response
elsif (axi_rvalid = '1' and S_AXI_RREADY = '1') then
axi_rvalid <= '0';
end if;
end if;
end if;
end process;
-- Implement memory mapped register select and write logic generation
-- The write data is accepted and written to memory mapped registers when
-- axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
-- These registers are cleared when reset (active low) is applied.
-- Slave register write enable is asserted when valid address and data are available
-- and the slave is ready to accept the write address and write data.
slv_reg_wren <= axi_wready and S_AXI_WVALID and axi_awready and S_AXI_AWVALID ;
process (S_AXI_ACLK)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
slv_reg0 <= (others => '0');
slv_reg1 <= (others => '0');
slv_reg2 <= (others => '0');
slv_reg3 <= (others => '0');
else
loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
if (slv_reg_wren = '1') then
case loc_addr is
when b"00" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
slv_reg0(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"01" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
slv_reg1(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"10" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
slv_reg2(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"11" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
slv_reg3(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when others =>
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
slv_reg2 <= slv_reg2;
slv_reg3 <= slv_reg3;
end case;
end if;
end if;
end if;
end process;
-- Implement memory mapped register select and read logic generation
-- Slave register read enable is asserted when valid address is available
-- and the slave is ready to accept the read address.
slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid) ;
process (slv_reg0, slv_reg1, slv_reg2, slv_reg3, axi_araddr, S_AXI_ARESETN, slv_reg_rden)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
-- Address decoding for reading registers
loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
case loc_addr is
when b"00" =>
reg_data_out <= slv_reg0;
when b"01" =>
reg_data_out <= slv_reg1;
when b"10" =>
reg_data_out <= slv_reg2;
when b"11" =>
reg_data_out <= slv_reg3;
when others =>
reg_data_out <= (others => '0');
end case;
end process;
-- Output register or memory read data
process( S_AXI_ACLK ) is
begin
if (rising_edge (S_AXI_ACLK)) then
if ( S_AXI_ARESETN = '0' ) then
axi_rdata <= (others => '0');
else
if (slv_reg_rden = '1') then
axi_rdata <= reg_data_out;
end if;
end if;
end if;
end process;
-------------------------------------------------------
-- 用户逻辑
-------------------------------------------------------
led_flash_en <= slv_reg0(0);
led_flash_time <= slv_reg1;
-------------------------------------------------------
-- 观测信号
-------------------------------------------------------
test(3 downto 0) <= axi_awaddr;
test( 4) <= axi_awready;
test( 5) <= axi_wready;
test(7 downto 6) <= axi_bresp;
test( 8) <= axi_bvalid;
test(12 downto 9) <= axi_araddr;
test( 13) <= axi_arready;
test(45 downto 14) <= axi_rdata;
test(47 downto 46) <= axi_rresp;
test(48) <= axi_rvalid;
test(49) <= aw_en;
test(53 downto 50) <= S_AXI_AWADDR;
test(56 downto 54) <= S_AXI_AWPROT;
test(57) <= S_AXI_AWVALID;
test(89 downto 58) <= S_AXI_WDATA;
test(93 downto 90) <= S_AXI_WSTRB;
test( 94) <= S_AXI_WVALID;
test( 95) <= S_AXI_BREADY;
test(99 downto 96) <= S_AXI_ARADDR;
test(102 downto 100) <= S_AXI_ARPROT;
test( 103) <= S_AXI_ARVALID;
test( 104) <= S_AXI_RREADY;
test(127 downto 105) <= (others=>'0');
end arch_imp;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity full_test_S_AXI is
generic (
---------------------------------------------------
-- AXI参数
---------------------------------------------------
C_S_AXI_ID_WIDTH : integer := 1;
C_S_AXI_DATA_WIDTH : integer := 32;
C_S_AXI_ADDR_WIDTH : integer := 6;
C_S_AXI_AWUSER_WIDTH : integer := 1;
C_S_AXI_ARUSER_WIDTH : integer := 1;
C_S_AXI_WUSER_WIDTH : integer := 1;
C_S_AXI_RUSER_WIDTH : integer := 1;
C_S_AXI_BUSER_WIDTH : integer := 1
);
port (
---------------------------------------------------
-- 用户端口
---------------------------------------------------
test : out std_logic_vector(255 downto 0);
---------------------------------------------------
-- AXI FULL 端口
---------------------------------------------------
S_AXI_ACLK : in std_logic;
S_AXI_ARESETN : in std_logic;
S_AXI_AWID : in std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_AWLEN : in std_logic_vector(7 downto 0);
S_AXI_AWSIZE : in std_logic_vector(2 downto 0);
S_AXI_AWBURST : in std_logic_vector(1 downto 0);
S_AXI_AWLOCK : in std_logic;
S_AXI_AWCACHE : in std_logic_vector(3 downto 0);
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
S_AXI_AWQOS : in std_logic_vector(3 downto 0);
S_AXI_AWREGION : in std_logic_vector(3 downto 0);
S_AXI_AWUSER : in std_logic_vector(C_S_AXI_AWUSER_WIDTH-1 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
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_WLAST : in std_logic;
S_AXI_WUSER : in std_logic_vector(C_S_AXI_WUSER_WIDTH-1 downto 0);
S_AXI_WVALID : in std_logic;
S_AXI_WREADY : out std_logic;
S_AXI_BID : out std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_BRESP : out std_logic_vector(1 downto 0);
S_AXI_BUSER : out std_logic_vector(C_S_AXI_BUSER_WIDTH-1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
S_AXI_ARID : in std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_ARLEN : in std_logic_vector(7 downto 0);
S_AXI_ARSIZE : in std_logic_vector(2 downto 0);
S_AXI_ARBURST : in std_logic_vector(1 downto 0);
S_AXI_ARLOCK : in std_logic;
S_AXI_ARCACHE : in std_logic_vector(3 downto 0);
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
S_AXI_ARQOS : in std_logic_vector(3 downto 0);
S_AXI_ARREGION : in std_logic_vector(3 downto 0);
S_AXI_ARUSER : in std_logic_vector(C_S_AXI_ARUSER_WIDTH-1 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
S_AXI_RID : out std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_RRESP : out std_logic_vector(1 downto 0);
S_AXI_RLAST : out std_logic;
S_AXI_RUSER : out std_logic_vector(C_S_AXI_RUSER_WIDTH-1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic
);
end full_test_S_AXI;
architecture arch_imp of full_test_S_AXI is
-------------------------------------------------------------------------------
-- 常量声明
-------------------------------------------------------------------------------
constant ADDR_LSB : integer := (C_S_AXI_DATA_WIDTH/32)+ 1;
constant OPT_MEM_ADDR_BITS : integer := 3;
constant USER_NUM_MEM : integer := 1;
constant ALL_ZEROS : std_logic_vector (C_S_AXI_ADDR_WIDTH - 1 downto 0) := "000000";
-------------------------------------------------------------------------------
-- 信号声明
-------------------------------------------------------------------------------
---------------------------------------------------
-- AXI4 FULL signals
---------------------------------------------------
signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_awready : std_logic;
signal axi_wready : std_logic;
signal axi_bresp : std_logic_vector(1 downto 0);
signal axi_buser : std_logic_vector(C_S_AXI_BUSER_WIDTH-1 downto 0);
signal axi_bvalid : std_logic;
signal axi_araddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
signal axi_arready : std_logic;
signal axi_rdata : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal axi_rresp : std_logic_vector(1 downto 0);
signal axi_rlast : std_logic;
signal axi_ruser : std_logic_vector(C_S_AXI_RUSER_WIDTH-1 downto 0);
signal axi_rvalid : std_logic;
signal aw_wrap_en : std_logic; -- aw_wrap_en determines wrap boundary and enables wrapping
signal ar_wrap_en : std_logic; -- ar_wrap_en determines wrap boundary and enables wrapping
signal aw_wrap_size : integer;
signal ar_wrap_size : integer;
signal axi_awv_awr_flag : std_logic; -- The axi_awv_awr_flag flag marks the presence of write address valid
signal axi_arv_arr_flag : std_logic; --The axi_arv_arr_flag flag marks the presence of read address valid
signal axi_awlen_cntr : std_logic_vector(7 downto 0); -- The axi_awlen_cntr internal write address counter to keep track of beats in a burst transaction
signal axi_arlen_cntr : std_logic_vector(7 downto 0); --The axi_arlen_cntr internal read address counter to keep track of beats in a burst transaction
signal axi_arburst : std_logic_vector(2-1 downto 0);
signal axi_awburst : std_logic_vector(2-1 downto 0);
signal axi_arlen : std_logic_vector(8-1 downto 0);
signal axi_awlen : std_logic_vector(8-1 downto 0);
------------------------------------------------
---- Signals for user logic memory space example
--------------------------------------------------
type ram_type is array (2**OPT_MEM_ADDR_BITS-1 downto 0) of std_logic_vector (C_S_AXI_DATA_WIDTH-1 downto 0);
signal RAM : ram_type;
signal ram_data_in : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal ram_data_out : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
signal ram_wren,ram_rden : std_logic;
signal ram_address : std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
-- I/O Connections assignments
S_AXI_AWREADY <= axi_awready;
S_AXI_WREADY <= axi_wready;
S_AXI_BRESP <= axi_bresp;
S_AXI_BUSER <= axi_buser;
S_AXI_BVALID <= axi_bvalid;
S_AXI_ARREADY <= axi_arready;
S_AXI_RDATA <= axi_rdata;
S_AXI_RRESP <= axi_rresp;
S_AXI_RLAST <= axi_rlast;
S_AXI_RUSER <= axi_ruser;
S_AXI_RVALID <= axi_rvalid;
S_AXI_BID <= S_AXI_AWID;
S_AXI_RID <= S_AXI_ARID;
aw_wrap_size <= ((C_S_AXI_DATA_WIDTH)/8 * to_integer(unsigned(axi_awlen)));
ar_wrap_size <= ((C_S_AXI_DATA_WIDTH)/8 * to_integer(unsigned(axi_arlen)));
aw_wrap_en <= '1' when (((axi_awaddr AND std_logic_vector(to_unsigned(aw_wrap_size,C_S_AXI_ADDR_WIDTH))) XOR std_logic_vector(to_unsigned(aw_wrap_size,C_S_AXI_ADDR_WIDTH))) = ALL_ZEROS) else
'0';
ar_wrap_en <= '1' when (((axi_araddr AND std_logic_vector(to_unsigned(ar_wrap_size,C_S_AXI_ADDR_WIDTH))) XOR std_logic_vector(to_unsigned(ar_wrap_size,C_S_AXI_ADDR_WIDTH))) = ALL_ZEROS) else
'0';
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_awready <= '0';
axi_awv_awr_flag <= '0';
else
if (axi_awready = '0' and S_AXI_AWVALID = '1' and axi_awv_awr_flag = '0' and axi_arv_arr_flag = '0') then
-- slave is ready to accept an address and associated control signals
axi_awv_awr_flag <= '1'; -- used for generation of bresp() and bvalid
axi_awready <= '1';
elsif (S_AXI_WLAST = '1' and axi_wready = '1') then
-- preparing to accept next address after current write burst tx completion
axi_awv_awr_flag <= '0';
else
axi_awready <= '0';
end if;
end if;
end if;
end process;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_awaddr <= (others => '0');
axi_awburst <= (others => '0');
axi_awlen <= (others => '0');
axi_awlen_cntr <= (others => '0');
else
if (axi_awready = '0' and S_AXI_AWVALID = '1' and axi_awv_awr_flag = '0') then
-- address latching
axi_awaddr <= S_AXI_AWADDR(C_S_AXI_ADDR_WIDTH - 1 downto 0); ---- start address of transfer
axi_awlen_cntr <= (others => '0');
axi_awburst <= S_AXI_AWBURST;
axi_awlen <= S_AXI_AWLEN;
elsif((axi_awlen_cntr <= axi_awlen) and axi_wready = '1' and S_AXI_WVALID = '1') then
axi_awlen_cntr <= std_logic_vector(unsigned(axi_awlen_cntr) + 1);
case (axi_awburst) is
when "00" => -- fixed burst
-- The write address for all the beats in the transaction are fixed
axi_awaddr <= axi_awaddr; ----for awsize = 4 bytes (010)
when "01" => --incremental burst
-- The write address for all the beats in the transaction are increments by awsize
axi_awaddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB) <= std_logic_vector (unsigned(axi_awaddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB)) + 1);--awaddr aligned to 4 byte boundary
axi_awaddr(ADDR_LSB-1 downto 0) <= (others => '0'); ----for awsize = 4 bytes (010)
when "10" => --Wrapping burst
-- The write address wraps when the address reaches wrap boundary
if (aw_wrap_en = '1') then
axi_awaddr <= std_logic_vector (unsigned(axi_awaddr) - (to_unsigned(aw_wrap_size,C_S_AXI_ADDR_WIDTH)));
else
axi_awaddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB) <= std_logic_vector (unsigned(axi_awaddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB)) + 1);--awaddr aligned to 4 byte boundary
axi_awaddr(ADDR_LSB-1 downto 0) <= (others => '0'); ----for awsize = 4 bytes (010)
end if;
when others => --reserved (incremental burst for example)
axi_awaddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB) <= std_logic_vector (unsigned(axi_awaddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB)) + 1);--for awsize = 4 bytes (010)
axi_awaddr(ADDR_LSB-1 downto 0) <= (others => '0');
end case;
end if;
end if;
end if;
end process;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_wready <= '0';
else
if (axi_wready = '0' and S_AXI_WVALID = '1' and axi_awv_awr_flag = '1') then
axi_wready <= '1';
-- elsif (axi_awv_awr_flag = '0') then
elsif (S_AXI_WLAST = '1' and axi_wready = '1') then
axi_wready <= '0';
end if;
end if;
end if;
end process;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_bvalid <= '0';
axi_bresp <= "00"; --need to work more on the responses
axi_buser <= (others => '0');
else
if (axi_awv_awr_flag = '1' and axi_wready = '1' and S_AXI_WVALID = '1' and axi_bvalid = '0' and S_AXI_WLAST = '1' ) then
axi_bvalid <= '1';
axi_bresp <= "00";
elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then
--check if bready is asserted while bvalid is high)
axi_bvalid <= '0';
end if;
end if;
end if;
end process;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_arready <= '0';
axi_arv_arr_flag <= '0';
else
if (axi_arready = '0' and S_AXI_ARVALID = '1' and axi_awv_awr_flag = '0' and axi_arv_arr_flag = '0') then
axi_arready <= '1';
axi_arv_arr_flag <= '1';
elsif (axi_rvalid = '1' and S_AXI_RREADY = '1' and (axi_arlen_cntr = axi_arlen)) then
-- preparing to accept next address after current read completion
axi_arv_arr_flag <= '0';
else
axi_arready <= '0';
end if;
end if;
end if;
end process;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_araddr <= (others => '0');
axi_arburst <= (others => '0');
axi_arlen <= (others => '0');
axi_arlen_cntr <= (others => '0');
axi_rlast <= '0';
axi_ruser <= (others => '0');
else
if (axi_arready = '0' and S_AXI_ARVALID = '1' and axi_arv_arr_flag = '0') then
-- address latching
axi_araddr <= S_AXI_ARADDR(C_S_AXI_ADDR_WIDTH - 1 downto 0); ---- start address of transfer
axi_arlen_cntr <= (others => '0');
axi_rlast <= '0';
axi_arburst <= S_AXI_ARBURST;
axi_arlen <= S_AXI_ARLEN;
elsif((axi_arlen_cntr <= axi_arlen) and axi_rvalid = '1' and S_AXI_RREADY = '1') then
axi_arlen_cntr <= std_logic_vector (unsigned(axi_arlen_cntr) + 1);
axi_rlast <= '0';
case (axi_arburst) is
when "00" => -- fixed burst
-- The read address for all the beats in the transaction are fixed
axi_araddr <= axi_araddr; ----for arsize = 4 bytes (010)
when "01" => --incremental burst
-- The read address for all the beats in the transaction are increments by awsize
axi_araddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB) <= std_logic_vector (unsigned(axi_araddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB)) + 1); --araddr aligned to 4 byte boundary
axi_araddr(ADDR_LSB-1 downto 0) <= (others => '0'); ----for awsize = 4 bytes (010)
when "10" => --Wrapping burst
-- The read address wraps when the address reaches wrap boundary
if (ar_wrap_en = '1') then
axi_araddr <= std_logic_vector (unsigned(axi_araddr) - (to_unsigned(ar_wrap_size,C_S_AXI_ADDR_WIDTH)));
else
axi_araddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB) <= std_logic_vector (unsigned(axi_araddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB)) + 1); --araddr aligned to 4 byte boundary
axi_araddr(ADDR_LSB-1 downto 0) <= (others => '0'); ----for awsize = 4 bytes (010)
end if;
when others => --reserved (incremental burst for example)
axi_araddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB) <= std_logic_vector (unsigned(axi_araddr(C_S_AXI_ADDR_WIDTH - 1 downto ADDR_LSB)) + 1);--for arsize = 4 bytes (010)
axi_araddr(ADDR_LSB-1 downto 0) <= (others => '0');
end case;
elsif((axi_arlen_cntr = axi_arlen) and axi_rlast = '0' and axi_arv_arr_flag = '1') then
axi_rlast <= '1';
elsif (S_AXI_RREADY = '1') then
axi_rlast <= '0';
end if;
end if;
end if;
end process;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
axi_rvalid <= '0';
axi_rresp <= "00";
else
if (axi_arv_arr_flag = '1' and axi_rvalid = '0') then
axi_rvalid <= '1';
axi_rresp <= "00"; -- 'OKAY' response
elsif (axi_rvalid = '1' and S_AXI_RREADY = '1') then
axi_rvalid <= '0';
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------
-- 用户逻辑
---------------------------------------------------------------------------
ram_wren <= axi_wready and S_AXI_WVALID ;
ram_rden <= axi_arv_arr_flag ;
ram_address <= axi_araddr(ADDR_LSB+OPT_MEM_ADDR_BITS downto ADDR_LSB) when axi_arv_arr_flag = '1' else
axi_awaddr(ADDR_LSB+OPT_MEM_ADDR_BITS downto ADDR_LSB) when axi_awv_awr_flag = '1' else
(others => '0');
ram_data_in <= S_AXI_WDATA;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if ram_wren = '1' then
RAM(to_integer(unsigned(ram_address))) <= ram_data_in;
end if;
ram_data_out <= RAM(to_integer(unsigned(ram_address)));
end if;
end process;
process(ram_data_out, axi_rvalid) is
begin
if (axi_rvalid = '1') then
axi_rdata <= ram_data_out;
else
axi_rdata <= (others => '0');
end if;
end process;
---------------------------------------------------------------------------
-- 观测信号
---------------------------------------------------------------------------
test( 0) <= S_AXI_ACLK;
test( 1) <= S_AXI_ARESETN;
test( 2) <= S_AXI_AWID(0);
test( 8 downto 3) <= S_AXI_AWADDR;
test( 9) <= '0';
test( 17 downto 10) <= S_AXI_AWLEN;
test( 20 downto 18) <= S_AXI_AWSIZE;
test( 22 downto 21) <= S_AXI_AWBURST;
test( 23) <= S_AXI_AWLOCK;
test( 27 downto 24) <= S_AXI_AWCACHE;
test( 30 downto 28) <= S_AXI_AWPROT;
test( 34 downto 31) <= S_AXI_AWQOS;
test( 38 downto 35) <= S_AXI_AWREGION;
test( 39) <= S_AXI_AWVALID;
test( 71 downto 40) <= S_AXI_WDATA;
test( 75 downto 72) <= S_AXI_WSTRB;
test( 76) <= S_AXI_WLAST;
test( 77) <= S_AXI_WVALID;
test( 78) <= S_AXI_BREADY;
test( 79) <= S_AXI_ARID(0);
test( 85 downto 80) <= S_AXI_ARADDR;
test( 86) <= '0';
test( 94 downto 87) <= S_AXI_ARLEN;
test( 97 downto 95) <= S_AXI_ARSIZE;
test( 99 downto 98) <= S_AXI_ARBURST;
test( 100) <= S_AXI_ARLOCK;
test(104 downto 101) <= S_AXI_ARCACHE;
test(107 downto 105) <= S_AXI_ARPROT;
test(111 downto 108) <= S_AXI_ARQOS;
test(115 downto 112) <= S_AXI_ARREGION;
test( 116) <= S_AXI_ARVALID;
test( 117) <= S_AXI_RREADY;
test( 118) <= axi_awready;
test( 119) <= axi_wready;
test( 120) <= axi_bresp(0);
test( 121) <= axi_bvalid;
test( 122) <= axi_arready;
test(154 downto 123) <= axi_rdata;
test(156 downto 155) <= axi_rresp;
test( 157) <= axi_rlast;
test( 158) <= axi_rvalid;
test( 159) <= S_AXI_AWID(0);
test( 160) <= S_AXI_ARID(0);
test(255 downto 161) <= (others=>'0');
end arch_imp;
注意memcpy的使用对读写时序的影响
ZYNQ+Vivado2015.2系列(七)软硬件联合Debug观察AXI总线读、写时各信号的时序
AXI4 & AXI4-stream 相关笔记
AXI协议中的模棱两可的含义的解释
【JokerのZYNQ7020】AXI4_FULL。