VIVADO自动生成的AXI IP时序

文章目录

  • 读/写操作的依赖关系
    • 写操作
    • 读操作
  • 封装工具生成的IP
    • AXI lite
      • VHDL代码
    • AXI full
      • VHDL代码
      • C代码1
      • C代码2
      • C代码3
  • 博文链接

读/写操作的依赖关系

写操作

VIVADO自动生成的AXI IP时序_第1张图片
VIVADO自动生成的AXI IP时序_第2张图片

读操作

VIVADO自动生成的AXI IP时序_第3张图片
VIVADO自动生成的AXI IP时序_第4张图片

封装工具生成的IP

AXI lite

VHDL代码

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;

写时序
VIVADO自动生成的AXI IP时序_第5张图片
读时序
VIVADO自动生成的AXI IP时序_第6张图片

AXI full

VHDL代码

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的使用对读写时序的影响

C代码1

VIVADO自动生成的AXI IP时序_第7张图片
写时序
VIVADO自动生成的AXI IP时序_第8张图片
读时序
VIVADO自动生成的AXI IP时序_第9张图片

C代码2

写时序
VIVADO自动生成的AXI IP时序_第10张图片
读时序
VIVADO自动生成的AXI IP时序_第11张图片

C代码3

VIVADO自动生成的AXI IP时序_第12张图片
写时序
VIVADO自动生成的AXI IP时序_第13张图片
读时序
VIVADO自动生成的AXI IP时序_第14张图片

博文链接

ZYNQ+Vivado2015.2系列(七)软硬件联合Debug观察AXI总线读、写时各信号的时序
AXI4 & AXI4-stream 相关笔记
AXI协议中的模棱两可的含义的解释
【JokerのZYNQ7020】AXI4_FULL。

你可能感兴趣的:(FPGA)