Vivado的AXI时序

基本概念

简介

AXI4协议是AMBA协议(Advanced Microcontroller Bus Architecture)的一种,是由ARM和XILINX共同制定的最新一代用于SoC内IP 互联的规范。

AMBA协议家族树
在这里插入图片描述

AXI4协议包含三种AXI4接口,

  • AXI4(Memory-Mapped):基于地址映射的传输接口,允许突发长度可变的数据传输(最大突发长度为256),可用于实现高性能的数据传输;
  • AXI4-Lite:基于地址映射的轻量型传输接口,突发长度为1,可用于访问控制寄存器、连接低俗外设;
  • AXI4-Stream:基于数据流的传输接口,突发长度无限制,可用于高速数流的传输。

AXI4和AXI4-Lite接口包含5个通道,为读地址通道(AR)、写地址通道(AW)、读数据通道®、写数据通道(W)和写响应通道(B),如图 2、图 3所示。AXI4协议支持多重传输、读/写并发传输等传输方式,所支持的最大突发长度为256,AXI-Lite支持的最大突发长度为1。

读通道结构
在这里插入图片描述

写通道结构
在这里插入图片描述

信号接口定义

在这里插入图片描述

读/写传输

AXI4总线中的主设备和从设备通过VALID信号和READY信号双向握手机制实现数据传输,主设备通过VALID 信号表示是否存在有效数据或控制信号在通道上,从设备通过READY 信号表示是否可以接受通道上的数据,在读/写数据通道上都含有LAST 信号来表示当前传输数据是否为读/写突发传输操作中的最后一个。

读时序

当主设备向从设备发出读请求时,主设备发送突发传输操作的起始地址ARADDR和读地址有效信号ARVALID,同时发送控制信号确定传输的类型、数据长度、数据位宽等。从设备提供读地址准备信号 ARREADY表示接收读地址及其控制信号,根据收到的读地址及其控制信号,然后向主设备返回相应的读数据RDATA和读数据有效信号RVALID,主设备提供读准备信号RREADY表示是否准备接收读数据和响应信号。

AXI 总线的读突发传输时序
在这里插入图片描述
根据起始地址和控制信号,主设备从该次突发传输中读到 4个数据,当传输的为最后一个时,最户读数据RLAST为高电平,同时表示该次突发传输结束,可以准备下一次传输

AXI总线的交错读突发传输时序在这里插入图片描述

写时序

当主设备向从设备发出写请求时,主设备发送写突发传输操作的起始地址AWADDR 和写地址有效信号AWVALID,同时发送控制信号确定传输的类型、数据长度、数据位宽等。从设备提供写地址准备信号AWREADY 表示接收写地址及其控制信号,根据收到的写地址及其控制信号,同时主设备提供相应的写数据WDATA 和写数据有效信号WVALID,从设备提供写准备信号WREADY表示接收写数据,并返回响应信号给主设备,表示当前写数据传输的完成状态。

AXI总线的写突发传输时序在这里插入图片描述

突发长度、突发大小、突发类型、突发地址

在这里插入图片描述
在这里插入图片描述

握手过程及读/写操作的依赖关系

AXI 总线的5 个通道是相互独立的,但是都使用有效信号VALID 和准备信号READY 握手来实现数据与控制信号的传输。有效信号VALID 表示发送方传输的数据和控制信号有效,准备信号READY 表示接收方可以接收数据与控制信号,其中数据为读写地址、读写数据或者响应信号,只有当有效信号VALID 与对应的准备信号READY 都为高电平时,传输才能开始。

VALID在READY之前跳转的握手在这里插入图片描述

READY在VALID之前跳转的握手
在这里插入图片描述

VALID与READY同时跳转的握手在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

封装工具生成的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;

写时序
在这里插入图片描述
读时序
在这里插入图片描述

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

在这里插入图片描述
写时序
在这里插入图片描述
读时序
在这里插入图片描述

C代码2

写时序
在这里插入图片描述
读时序
在这里插入图片描述

C代码3

在这里插入图片描述
写时序
在这里插入图片描述
读时序
在这里插入图片描述

操控AXI BRAM

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

entity bram_op_wrapper is
port(
    clk          : in  std_logic;
    rst          : in  std_logic;

    user_wr_en   : in  std_logic;
    user_wr_len  : in  std_logic_vector( 7 downto 0);       --突发传输数据个数-1
    user_wr_addr : in  std_logic_vector(11 downto 0);
    user_wr_data : in  std_logic_vector(31 downto 0);

    user_rd_en   : in  std_logic;
    user_rd_len  : in  std_logic_vector( 7 downto 0);
    user_rd_addr : in  std_logic_vector(11 downto 0);
    user_rd_data : out std_logic_vector(31 downto 0);
    user_rd_vld  : out std_logic
);
end bram_op_wrapper;

architecture Behavioral of bram_op_wrapper is

--------------------------------------------------------------------------------
--                      类型定义
--------------------------------------------------------------------------------
    type aw_state_type is (AW_ST0,AW_ST1,AW_ST2,AW_ST3);
    type w_state_type  is (W_ST0,W_ST1,W_ST2);
    type ar_state_type is (AR_ST0,AR_ST1,AR_ST2,AR_ST3);
    type r_state_type  is (R_ST0,R_ST1,R_ST2);

--------------------------------------------------------------------------------
--                      component声明
--------------------------------------------------------------------------------
    component AXI_BRAM
        port (
            rsta_busy       : out std_logic;
            rstb_busy       : out std_logic;
            s_aclk          : in  std_logic;
            s_aresetn       : in  std_logic;
            s_axi_awid      : in  std_logic_vector(3 downto 0);
            s_axi_awaddr    : in  std_logic_vector(31 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_awvalid   : in  std_logic;
            s_axi_awready   : out std_logic;
            s_axi_wdata     : in  std_logic_vector(31 downto 0);
            s_axi_wstrb     : in  std_logic_vector(3 downto 0);
            s_axi_wlast     : in  std_logic;
            s_axi_wvalid    : in  std_logic;
            s_axi_wready    : out std_logic;
            s_axi_bid       : out std_logic_vector(3 downto 0);
            s_axi_bresp     : out std_logic_vector(1 downto 0);
            s_axi_bvalid    : out std_logic;
            s_axi_bready    : in  std_logic;
            s_axi_arid      : in  std_logic_vector(3 downto 0);
            s_axi_araddr    : in  std_logic_vector(31 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_arvalid   : in  std_logic;
            s_axi_arready   : out std_logic;
            s_axi_rid       : out std_logic_vector(3 downto 0);
            s_axi_rdata     : out std_logic_vector(31 downto 0);
            s_axi_rresp     : out std_logic_vector(1 downto 0);
            s_axi_rlast     : out std_logic;
            s_axi_rvalid    : out std_logic;
            s_axi_rready    : in  std_logic
        );
    end component;

    component FWFT_FIFO_W44_D512
        port (
            clk     : in  std_logic;
            srst    : in  std_logic;
            din     : in  std_logic_vector(43 downto 0);
            wr_en   : in  std_logic;
            rd_en   : in  std_logic;
            dout    : out std_logic_vector(43 downto 0);
            full    : out std_logic;
            empty   : out std_logic
        );
    end component;

--------------------------------------------------------------------------------
--                      信号声明
--------------------------------------------------------------------------------
    -- axi bram相关信号
    signal s_aresetn       : std_logic;
    signal s_axi_awid      : std_logic_vector(3 downto 0);
    signal s_axi_awaddr    : std_logic_vector(31 downto 0);
    signal s_axi_awlen     : std_logic_vector(7 downto 0);
    signal s_axi_awsize    : std_logic_vector(2 downto 0);
    signal s_axi_awburst   : std_logic_vector(1 downto 0);
    signal s_axi_awvalid   : std_logic;
    signal s_axi_awready   : std_logic;
    signal s_axi_wdata     : std_logic_vector(31 downto 0);
    signal s_axi_wstrb     : std_logic_vector(3 downto 0);
    signal s_axi_wlast     : std_logic;
    signal s_axi_wvalid    : std_logic;
    signal s_axi_wready    : std_logic;
    signal s_axi_bid       : std_logic_vector(3 downto 0);
    signal s_axi_bresp     : std_logic_vector(1 downto 0);
    signal s_axi_bvalid    : std_logic;
    signal s_axi_bready    : std_logic;
    signal s_axi_arid      : std_logic_vector(3 downto 0);
    signal s_axi_araddr    : std_logic_vector(31 downto 0);
    signal s_axi_arlen     : std_logic_vector(7 downto 0);
    signal s_axi_arsize    : std_logic_vector(2 downto 0);
    signal s_axi_arburst   : std_logic_vector(1 downto 0);
    signal s_axi_arvalid   : std_logic;
    signal s_axi_arready   : std_logic;
    signal s_axi_rid       : std_logic_vector(3 downto 0);
    signal s_axi_rdata     : std_logic_vector(31 downto 0);
    signal s_axi_rresp     : std_logic_vector(1 downto 0);
    signal s_axi_rlast     : std_logic;
    signal s_axi_rvalid    : std_logic;
    signal s_axi_rready    : std_logic;

    -- 写缓冲FIFO信号
    signal wr_fifo_din     : std_logic_vector(43 downto 0);
    signal wr_fifo_wr_en   : std_logic;
    signal wr_fifo_rd_en   : std_logic;
    signal wr_fifo_dout    : std_logic_vector(43 downto 0);
    signal wr_fifo_full    : std_logic;
    signal wr_fifo_empty   : std_logic;

    -- 读缓冲FIFO信号
    signal rd_fifo_din     : std_logic_vector(43 downto 0);
    signal rd_fifo_wr_en   : std_logic;
    signal rd_fifo_rd_en   : std_logic;
    signal rd_fifo_dout    : std_logic_vector(43 downto 0);
    signal rd_fifo_full    : std_logic;
    signal rd_fifo_empty   : std_logic;

    -- 复位信号
    signal rst_L1          : std_logic := '0';
    signal rst_cnt         : unsigned(7 downto 0) := (others=>'0');

    -- axi状态
    signal aw_state        : aw_state_type := AW_ST0;
    signal w_state         : w_state_type  := W_ST0;
    signal ar_state        : ar_state_type := AR_ST0;
    signal r_state         : r_state_type  := R_ST0;
                           
    signal wr_cnt          : unsigned(7 downto 0) := (others=>'0');
    
begin

    -----------------------------------------------------------------
    -- axi复位
    process(clk)
    begin
        if rising_edge(clk) then
            rst_L1 <= rst;
            if (rst_L1='0') and (rst='1') then
                rst_cnt <= (others=>'0');
            elsif (rst_cnt<20) then
                rst_cnt <= rst_cnt + 1;
            else
                rst_cnt <= rst_cnt;
            end if;

            if (rst_cnt<20) then
                s_aresetn <= '0';
            else
                s_aresetn <= '1';
            end if;
        end if;
    end process;

    -----------------------------------------------------------------
    -- 状态机
    process(clk)
    begin
        if rising_edge(clk) then
            case aw_state is
                when AW_ST0 =>
                    if (wr_fifo_empty='0') then                     -- FIFO中有数据,跳转状态
                        aw_state  <= AW_ST1;
                    else
                        aw_state  <= AW_ST0;
                    end if;
                when AW_ST1 =>
                    if (s_axi_awready='1') then
                        aw_state  <= AW_ST2;
                    else
                        aw_state  <= AW_ST1;
                    end if;
                when AW_ST2 =>
                    if (wr_cnt=unsigned(user_wr_len)) then
                        aw_state  <= AW_ST3;
                    else
                        aw_state  <= AW_ST2;
                    end if;
                when AW_ST3 =>
                    aw_state      <= AW_ST0;
                when others =>
                    aw_state      <= AW_ST0;
            end case;
        
            case w_state is
                when W_ST0 =>
                    wr_cnt            <= (others=>'0');
                    if (wr_fifo_empty='0') then                     -- FIFO中有数据,跳转状态
                        w_state       <= W_ST1;
                    else              
                        w_state       <= W_ST0;
                    end if;
                when W_ST1 =>
                    if (s_axi_wready='1') then
                        wr_cnt        <= wr_cnt + 1;
                    else
                        wr_cnt        <= wr_cnt;
                    end if;
                    if (wr_cnt=unsigned(user_wr_len)) then
                        w_state       <= W_ST2;
                    else
                        w_state       <= W_ST1;
                    end if;
                when W_ST2 =>
                    wr_cnt            <= (others=>'0');
                    w_state           <= W_ST0;
                when others =>
                    w_state           <= W_ST0;
            end case;
        end if;
    end process;
    
     -- 写地址通道
    s_axi_awid    <= "0000";
    s_axi_awsize  <= "010";
    s_axi_awburst <= "01";
    s_axi_awlen   <= user_wr_len;
    s_axi_awaddr  <=  std_logic_vector(to_unsigned(0,18)) & wr_fifo_dout(43 downto 32) & "00";    -- 设置突发写地址
    process(aw_state)
    begin
        case aw_state is
            when AW_ST0  =>
                s_axi_awvalid <= '0';
            when AW_ST1  =>
                s_axi_awvalid <= '1';
            when AW_ST2  =>
                s_axi_awvalid <= '0';
            when others  =>
                s_axi_awvalid <= '0';
        end case;
    end process;
    
    -- 写数据通道
    s_axi_wstrb   <= "1111";
    s_axi_wdata   <= wr_fifo_dout(31 downto 0);
    process(s_axi_wready,wr_fifo_empty,w_state,wr_cnt)
    begin
        case w_state is
            when W_ST0  =>
                wr_fifo_rd_en <= '0';
                s_axi_wlast   <= '0';
                s_axi_wvalid  <= '0';
            when W_ST1  =>
                 wr_fifo_rd_en <= s_axi_wready and (not wr_fifo_empty);
                 if (wr_cnt=unsigned(user_wr_len)) then
                    s_axi_wlast <= '1';
                 else
                    s_axi_wlast <= '0';
                 end if;
                 s_axi_wvalid <= '1';
            when W_ST2  =>
                wr_fifo_rd_en <= '0';
                s_axi_wlast   <= '0';
                s_axi_wvalid  <= '0';
            when others =>
                wr_fifo_rd_en <= '0';
                s_axi_wlast   <= '0';
                s_axi_wvalid  <= '0';
        end case;
    end process;

    -- 写响应通道
    process(s_axi_bresp,s_axi_bvalid)
    begin
        if (s_axi_bresp="00") and (s_axi_bvalid='1') then
            s_axi_bready <= '1';
        else
            s_axi_bready <= '0';
        end if;
    end process;

    -----------------------------------------------------------------
    -- 状态机
    process(clk)
    begin
        if rising_edge(clk) then
            case ar_state is
                when AR_ST0 =>
                    if (rd_fifo_empty='0') then                     -- FIFO中有数据,跳转状态
                        ar_state  <= AR_ST1;
                    else
                        ar_state  <= AR_ST0;
                    end if;
                when AR_ST1 =>
                    if (s_axi_arready='1') then
                        ar_state  <= AR_ST2;
                    else
                        ar_state  <= AR_ST1;
                    end if;
                when AR_ST2 =>
                    if (s_axi_rlast='1') then
                        ar_state  <= AR_ST3;
                    else
                        ar_state  <= AR_ST2;
                    end if;
                when AR_ST3 =>
                    ar_state      <= AR_ST0;
                when others =>
                    ar_state      <= AR_ST0;
            end case;
            
            case r_state is
                when R_ST0 =>
                     if (rd_fifo_empty='0') then                     -- FIFO中有数据,跳转状态
                         r_state <= R_ST1;
                     else
                         r_state <= R_ST0;
                     end if;
                when R_ST1 =>
                    if (s_axi_rlast='1') then
                        r_state  <= R_ST2;
                    else
                        r_state  <= R_ST1;
                    end if;
                when R_ST2 =>
                    r_state      <= R_ST0;
                when others =>
                    r_state      <= R_ST0;
            end case;
        end if;
    end process;
    
    -- 读地址通道
    s_axi_arid    <= (others=>'0');
    s_axi_arsize  <= "010";
    s_axi_arburst <= "01";
    s_axi_arlen   <= user_rd_len;
    s_axi_araddr  <= std_logic_vector(to_unsigned(0,18)) & rd_fifo_dout(43 downto 32) & "00";    -- 设置突发读地址
    process(ar_state)
    begin
        case ar_state is
            when AR_ST0 =>
                 s_axi_arvalid <= '0';
            when AR_ST1 =>
                 s_axi_arvalid <= '1';
            when AR_ST2 =>
                 s_axi_arvalid <= '0';
            when AR_ST3 =>
                 s_axi_arvalid <= '0';
            when others =>
                 s_axi_arvalid <= '0';
        end case;
    end process;
    
    -- 读数据通道
    process(r_state,s_axi_rlast,s_axi_rvalid,s_axi_rdata)
    begin
        case r_state is
            when R_ST0 =>
                 s_axi_rready  <= '0'; 
                 rd_fifo_rd_en <= '0'; 
                 user_rd_vld   <= '0';
                 user_rd_data  <= (others=>'0');
            when R_ST1 =>
                if (s_axi_rlast='1') then
                    rd_fifo_rd_en <= '1';
                else
                    rd_fifo_rd_en <= '0';
                end if;
                s_axi_rready  <= '1';
                user_rd_vld  <= s_axi_rvalid;
                user_rd_data <= s_axi_rdata;
            when R_ST2 =>
                s_axi_rready  <= '0';
                rd_fifo_rd_en <= '0';
            when others =>
                s_axi_rready  <= '0';
                rd_fifo_rd_en <= '0';
                user_rd_vld   <= '0';
                user_rd_data  <= (others=>'0');
        end case;
    end process;
    
    -----------------------------------------------------------------
    -- 例化axi bram
    Inst_AXI_BRAM : AXI_BRAM
    port map(
        rsta_busy       => open,
        rstb_busy       => open,
        s_aclk          => clk,
        s_aresetn       => s_aresetn,

        s_axi_awid      => s_axi_awid,
        s_axi_awaddr    => s_axi_awaddr,
        s_axi_awlen     => s_axi_awlen,
        s_axi_awsize    => s_axi_awsize,
        s_axi_awburst   => s_axi_awburst,
        s_axi_awvalid   => s_axi_awvalid,
        s_axi_awready   => s_axi_awready,

        s_axi_wdata     => s_axi_wdata,
        s_axi_wstrb     => s_axi_wstrb,
        s_axi_wlast     => s_axi_wlast,
        s_axi_wvalid    => s_axi_wvalid,
        s_axi_wready    => s_axi_wready,

        s_axi_bid       => s_axi_bid,
        s_axi_bresp     => s_axi_bresp,
        s_axi_bvalid    => s_axi_bvalid,
        s_axi_bready    => s_axi_bready,

        s_axi_arid      => s_axi_arid,
        s_axi_araddr    => s_axi_araddr,
        s_axi_arlen     => s_axi_arlen,
        s_axi_arsize    => s_axi_arsize,
        s_axi_arburst   => s_axi_arburst,
        s_axi_arvalid   => s_axi_arvalid,
        s_axi_arready   => s_axi_arready,

        s_axi_rid       => s_axi_rid,
        s_axi_rdata     => s_axi_rdata,
        s_axi_rresp     => s_axi_rresp,
        s_axi_rlast     => s_axi_rlast,
        s_axi_rvalid    => s_axi_rvalid,
        s_axi_rready    => s_axi_rready
    );

    -----------------------------------------------------------------
    -- 例化FIFO
    wr_fifo_wr_en <= user_wr_en;
    wr_fifo_din   <= user_wr_addr & user_wr_data;
    Inst_WR_FWFT_FIFO_W44_D512 : FWFT_FIFO_W44_D512
    port map(
        clk   => clk,
        srst  => rst,
        din   => wr_fifo_din,
        wr_en => wr_fifo_wr_en,
        rd_en => wr_fifo_rd_en,
        dout  => wr_fifo_dout,
        full  => wr_fifo_full,
        empty => wr_fifo_empty
    ); 

    rd_fifo_wr_en <= user_rd_en;
    rd_fifo_din   <= user_rd_addr & X"00000000";
    Inst_RD_FWFT_FIFO_W44_D512 : FWFT_FIFO_W44_D512
    port map(
        clk   => clk,
        srst  => rst,
        din   => rd_fifo_din,
        wr_en => rd_fifo_wr_en,
        rd_en => rd_fifo_rd_en,
        dout  => rd_fifo_dout,
        full  => rd_fifo_full,
        empty => rd_fifo_empty
    );

end Behavioral;

博文链接

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值