写在前面

打包2个AXI4-Full接口的IP(一主一从),来对其提供的仿真和原始代码学习一番。限于篇幅,将分2篇文章写完,本文写AXI4-Full接口。AXI4-Full接口的源码基本与AXI4-Lite接口的源码一致,不过多了突发传输控制的相关信号,建议配合AXI4-Lite接口源码分析文章一并查看,有助于理解。

带你快速入门AXI4总线--汇总篇(直达链接)https://wuzhikai.blog.csdn.net/article/details/121574746https://wuzhikai.blog.csdn.net/article/details/121574746


1、调用IP

首先新建一个工程,然后点击Tools-----create and package new ip

点击Next

选择选项4,点击Next,各选项含义:

  • 1---将当前工程打包为IP核
  • 2----将当前工程的模块设计打包为IP核
  • 3----将一个特定的文件夹目录打包为IP核
  • 4----创建一个带AXI接口的IP核

填写IP信息(基本不修改,只改下名称方便后续管理),点击Next

选择Full接口,接口类型选择从机slave,数据位宽32位,存储器大小选择64即可,然后点击Next

这里选择第3个,使用AXI4 VIP来验证IP,然后点击Next。(AXI4 VIP是XILINX的一个IP核,该IP核可以提供多种连接方式来对AXI接口进行验证,用起来很是贴心方便,我们后面会写相关文章,还请期待。)

到此就生成了一个slave接口的验证工程。不着急仿真,先跟它耍耍。整个工程的结构如下:

双击上个表示的BD模块,打开工程框图,如下:

整个工程由两部分构成:1、我们打包的IP,该IP的接口是AIX4-Full-slave;2、AXI Verification IP,这是一个AXI的验证IP,提供多种验证方式,功能很强大,双击这个IP,看看它的内置定制信息:
        可以看到,它可选选择接口模式来实现主机或从机或直通功能;可选协议类型,地址位宽,数据位宽等。我们这里不动它,直接cancel。

2、Slave接口的源码分析

在如下路径下有生成的接口源码:

接下来双击打开,我们一探究竟。(由于源码较长700行,一次性展开不利于阅读,我接下来分块进行讲解)

NO.1----模块参数、输入输出信号:

        参数主要是数据、地址、ID的位宽;

接口即为标准的AXI4-Full的标准接口,忘记了信号定义的可以看这里:带你快速入门AXI4总线--AXI4-Full篇(1)----AXI4-Full总线

`timescale 1 ns / 1 psmodule myip_axi4_Full_slave_v1_0_S00_AXI #(// Users to add parameters here// User parameters ends// Do not modify the parameters beyond this line// Width of ID for for write address, write data, read address and read dataparameter integer C_S_AXI_ID_WIDTH   = 1,// Width of S_AXI data busparameter integer C_S_AXI_DATA_WIDTH = 32,// Width of S_AXI address busparameter integer C_S_AXI_ADDR_WIDTH = 6,// Width of optional user defined signal in write address channelparameter integer C_S_AXI_AWUSER_WIDTH    = 0,// Width of optional user defined signal in read address channelparameter integer C_S_AXI_ARUSER_WIDTH = 0,// Width of optional user defined signal in write data channelparameter integer C_S_AXI_WUSER_WIDTH    = 0,// Width of optional user defined signal in read data channelparameter integer C_S_AXI_RUSER_WIDTH = 0,// Width of optional user defined signal in write response channelparameter integer C_S_AXI_BUSER_WIDTH    = 0)(// Users to add ports here// User ports ends// Do not modify the ports beyond this line// Global Clock Signalinput wire  S_AXI_ACLK,// Global Reset Signal. This Signal is Active LOWinput wire  S_AXI_ARESETN,// Write Address IDinput wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_AWID,// Write addressinput wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,// Burst length. The burst length gives the exact number of transfers in a burstinput wire [7 : 0] S_AXI_AWLEN,// Burst size. This signal indicates the size of each transfer in the burstinput wire [2 : 0] S_AXI_AWSIZE,// Burst type. The burst type and the size information, // determine how the address for each transfer within the burst is calculated.input wire [1 : 0] S_AXI_AWBURST,// Lock type. Provides additional information about the// atomic characteristics of the transfer.input wire  S_AXI_AWLOCK,// Memory type. This signal indicates how transactions// are required to progress through a system.input wire [3 : 0] S_AXI_AWCACHE,// Protection type. This signal indicates the privilege// and security level of the transaction, and whether// the transaction is a data access or an instruction access.input wire [2 : 0] S_AXI_AWPROT,// Quality of Service, QoS identifier sent for each// write transaction.input wire [3 : 0] S_AXI_AWQOS,// Region identifier. Permits a single physical interface// on a slave to be used for multiple logical interfaces.input wire [3 : 0] S_AXI_AWREGION,// Optional User-defined signal in the write address channel.input wire [C_S_AXI_AWUSER_WIDTH-1 : 0] S_AXI_AWUSER,// Write address valid. This signal indicates that// the channel is signaling valid write address and// control information.input wire  S_AXI_AWVALID,// Write address ready. This signal indicates that// the slave is ready to accept an address and associated// control signals.output wire  S_AXI_AWREADY,// Write Datainput wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,// Write strobes. This signal indicates which byte// lanes hold valid data. There is one write strobe// bit for each eight bits of the write data bus.input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,// Write last. This signal indicates the last transfer// in a write burst.input wire  S_AXI_WLAST,// Optional User-defined signal in the write data channel.input wire [C_S_AXI_WUSER_WIDTH-1 : 0] S_AXI_WUSER,// Write valid. This signal indicates that valid write// data and strobes are available.input wire  S_AXI_WVALID,// Write ready. This signal indicates that the slave// can accept the write data.output wire  S_AXI_WREADY,// Response ID tag. This signal is the ID tag of the// write response.output wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_BID,// Write response. This signal indicates the status// of the write transaction.output wire [1 : 0] S_AXI_BRESP,// Optional User-defined signal in the write response channel.output wire [C_S_AXI_BUSER_WIDTH-1 : 0] S_AXI_BUSER,// Write response valid. This signal indicates that the// channel is signaling a valid write response.output wire  S_AXI_BVALID,// Response ready. This signal indicates that the master// can accept a write response.input wire  S_AXI_BREADY,// Read address ID. This signal is the identification// tag for the read address group of signals.input wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_ARID,// Read address. This signal indicates the initial// address of a read burst transaction.input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,// Burst length. The burst length gives the exact number of transfers in a burstinput wire [7 : 0] S_AXI_ARLEN,// Burst size. This signal indicates the size of each transfer in the burstinput wire [2 : 0] S_AXI_ARSIZE,// Burst type. The burst type and the size information, // determine how the address for each transfer within the burst is calculated.input wire [1 : 0] S_AXI_ARBURST,// Lock type. Provides additional information about the// atomic characteristics of the transfer.input wire  S_AXI_ARLOCK,// Memory type. This signal indicates how transactions// are required to progress through a system.input wire [3 : 0] S_AXI_ARCACHE,// Protection type. This signal indicates the privilege// and security level of the transaction, and whether// the transaction is a data access or an instruction access.input wire [2 : 0] S_AXI_ARPROT,// Quality of Service, QoS identifier sent for each// read transaction.input wire [3 : 0] S_AXI_ARQOS,// Region identifier. Permits a single physical interface// on a slave to be used for multiple logical interfaces.input wire [3 : 0] S_AXI_ARREGION,// Optional User-defined signal in the read address channel.input wire [C_S_AXI_ARUSER_WIDTH-1 : 0] S_AXI_ARUSER,// Write address valid. This signal indicates that// the channel is signaling valid read address and// control information.input wire  S_AXI_ARVALID,// Read address ready. This signal indicates that// the slave is ready to accept an address and associated// control signals.output wire  S_AXI_ARREADY,// Read ID tag. This signal is the identification tag// for the read data group of signals generated by the slave.output wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_RID,// Read Dataoutput wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,// Read response. This signal indicates the status of// the read transfer.output wire [1 : 0] S_AXI_RRESP,// Read last. This signal indicates the last transfer// in a read burst.output wire  S_AXI_RLAST,// Optional User-defined signal in the read address channel.output wire [C_S_AXI_RUSER_WIDTH-1 : 0] S_AXI_RUSER,// Read valid. This signal indicates that the channel// is signaling the required read data.output wire  S_AXI_RVALID,// Read ready. This signal indicates that the master can// accept the read data and response information.input wire  S_AXI_RREADY);

NO.2----寄存器定义:

        主要是对AXI4的输出端口的寄存器定义,避免直接对输出端口操作;

wrap突发模式的相关信号,包括地址、长度、使能等(在本次验证中没有使用到wrap突发模式,所以我直接无视它了);

memory相关信号,这个memory等于是构造了一个双口RAM,将主机发送过来的数据寄存起来。

// AXI4FULL signalsreg [C_S_AXI_ADDR_WIDTH-1 : 0]    axi_awaddr;reg                              axi_awready;reg                             axi_wready;reg [1 : 0]                  axi_bresp;reg [C_S_AXI_BUSER_WIDTH-1 : 0]   axi_buser;reg                           axi_bvalid;reg [C_S_AXI_ADDR_WIDTH-1 : 0]   axi_araddr;reg                              axi_arready;reg [C_S_AXI_DATA_WIDTH-1 : 0]  axi_rdata;reg [1 : 0]                   axi_rresp;reg                           axi_rlast;reg [C_S_AXI_RUSER_WIDTH-1 : 0]   axi_ruser;reg                           axi_rvalid;//wrap突发模式信号 // aw_wrap_en determines wrap boundary and enables wrappingwire aw_wrap_en;// ar_wrap_en determines wrap boundary and enables wrappingwire ar_wrap_en;// aw_wrap_size is the size of the write transfer, the// write address wraps to a lower address if upper address// limit is reachedwire [31:0]  aw_wrap_size ; // ar_wrap_size is the size of the read transfer, the// read address wraps to a lower address if upper address// limit is reachedwire [31:0]  ar_wrap_size ; // The axi_awv_awr_flag flag marks the presence of write address validreg axi_awv_awr_flag;//The axi_arv_arr_flag flag marks the presence of read address validreg axi_arv_arr_flag; // The axi_awlen_cntr internal write address counter to keep track of beats in a burst transactionreg [7:0] axi_awlen_cntr;//The axi_arlen_cntr internal read address counter to keep track of beats in a burst transactionreg [7:0] axi_arlen_cntr;reg [1:0] axi_arburst;reg [1:0] axi_awburst;reg [7:0] axi_arlen;reg [7:0] axi_awlen;//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 42 bits (n downto 3)localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32)+ 1;localparam integer OPT_MEM_ADDR_BITS = 3;localparam integer USER_NUM_MEM = 1;//----------------------------------------------//-- Signals for user logic memory space example//------------------------------------------------wire [OPT_MEM_ADDR_BITS:0]         mem_address;wire [USER_NUM_MEM-1:0]             mem_select;reg [C_S_AXI_DATA_WIDTH-1:0]         mem_data_out[0 : USER_NUM_MEM-1];genvar i;genvar j;genvar mem_byte_index;

NO.3----wire信号赋值:

对AXI4的输出信号赋值,避免直接对其进行操作。

 // I/O Connections assignmentsassign S_AXI_AWREADY = axi_awready;assign S_AXI_WREADY   = axi_wready;assign S_AXI_BRESP    = axi_bresp;assign S_AXI_BUSER = axi_buser;assign S_AXI_BVALID    = axi_bvalid;assign S_AXI_ARREADY = axi_arready;assign S_AXI_RDATA    = axi_rdata;assign S_AXI_RRESP = axi_rresp;assign S_AXI_RLAST = axi_rlast;assign S_AXI_RUSER = axi_ruser;assign S_AXI_RVALID    = axi_rvalid;assign S_AXI_BID = S_AXI_AWID;assign S_AXI_RID = S_AXI_ARID;
//wrap突发模式信号    assign  aw_wrap_size = (C_S_AXI_DATA_WIDTH/8 * (axi_awlen)); assign  ar_wrap_size = (C_S_AXI_DATA_WIDTH/8 * (axi_arlen)); assign  aw_wrap_en = ((axi_awaddr & aw_wrap_size) == aw_wrap_size)? 1'b1: 1'b0;assign  ar_wrap_en = ((axi_araddr & ar_wrap_size) == ar_wrap_size)? 1'b1: 1'b0;

NO.4----写地址通道:

完成写地址通道的握手,即根据主机给出的握手信号来拉高axi_awready,并拉高axi_awv_awr_flag信号,表示从机进入了被写入数据的过程。

 // 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.always @( posedge S_AXI_ACLK )beginif ( S_AXI_ARESETN == 1'b0 )beginaxi_awready <= 1'b0;axi_awv_awr_flag <= 1'b0;end elsebegin    if (~axi_awready && S_AXI_AWVALID && ~axi_awv_awr_flag && ~axi_arv_arr_flag)begin// slave is ready to accept an address and// associated control signalsaxi_awready <= 1'b1;axi_awv_awr_flag  <= 1'b1; // used for generation of bresp() and bvalidendelse if (S_AXI_WLAST && axi_wready)          // preparing to accept next address after current write burst tx completionbeginaxi_awv_awr_flag  <= 1'b0;endelse        beginaxi_awready <= 1'b0;endend end

NO.5----锁存写入相关信息:

锁存写入地址(突发传输的首地址)、突发模式、突发长度等信息,并根据握手过程来累加写入计数器axi_awlen_cntr,跟踪写入过程。从机需将此类信息锁存起来,才能对RAM进行操作。

下面的代码还支持3种突发模式,但测试数据仅仅给出了第二种模式:递增突发。

 always @( posedge S_AXI_ACLK )beginif ( S_AXI_ARESETN == 1'b0 )beginaxi_awaddr <= 0;axi_awlen_cntr <= 0;axi_awburst <= 0;axi_awlen <= 0;end elsebegin    if (~axi_awready && S_AXI_AWVALID && ~axi_awv_awr_flag)begin// address latching axi_awaddr <= S_AXI_AWADDR[C_S_AXI_ADDR_WIDTH - 1:0];  axi_awburst <= S_AXI_AWBURST; axi_awlen <= S_AXI_AWLEN;     // start address of transferaxi_awlen_cntr <= 0;end   else if((axi_awlen_cntr <= axi_awlen) && axi_wready && S_AXI_WVALID)        beginaxi_awlen_cntr <= axi_awlen_cntr + 1;case (axi_awburst)2'b00: // fixed burst// The write address for all the beats in the transaction are fixedbeginaxi_awaddr <= axi_awaddr;          //for awsize = 4 bytes (010)end   2'b01: //incremental burst// The write address for all the beats in the transaction are increments by awsizebeginaxi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;//awaddr aligned to 4 byte boundaryaxi_awaddr[ADDR_LSB-1:0]  <= {ADDR_LSB{1'b0}};   //for awsize = 4 bytes (010)end   2'b10: //Wrapping burst// The write address wraps when the address reaches wrap boundary if (aw_wrap_en)beginaxi_awaddr <= (axi_awaddr - aw_wrap_size); endelse beginaxi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;axi_awaddr[ADDR_LSB-1:0]  <= {ADDR_LSB{1'b0}}; end                      default: //reserved (incremental burst for example)beginaxi_awaddr <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;//for awsize = 4 bytes (010)endendcase              endend end       

NO.6----写数据通道:

完成写数据通道的握手,即根据主机给出的握手信号来拉高axi_wready。

 // 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. always @( posedge S_AXI_ACLK )beginif ( S_AXI_ARESETN == 1'b0 )beginaxi_wready <= 1'b0;end elsebegin    if ( ~axi_wready && S_AXI_WVALID && axi_awv_awr_flag)begin// slave can accept the write dataaxi_wready <= 1'b1;end//else if (~axi_awv_awr_flag)else if (S_AXI_WLAST && axi_wready)beginaxi_wready <= 1'b0;endend end    

NO.7----写响应通道:

完成写响应通道的握手,即根据主机给出的握手信号来拉高axi_bvalid。并直接回复响应陈工:OKAY(意思暂不支持其他回复)。

 always @( posedge S_AXI_ACLK )beginif ( S_AXI_ARESETN == 1'b0 )beginaxi_bvalid <= 0;axi_bresp <= 2'b0;axi_buser <= 0;end elsebegin    if (axi_awv_awr_flag && axi_wready && S_AXI_WVALID && ~axi_bvalid && S_AXI_WLAST )beginaxi_bvalid <= 1'b1;axi_bresp  <= 2'b0; // 'OKAY' response end                   elsebeginif (S_AXI_BREADY && axi_bvalid) //check if bready is asserted while bvalid is high) //(there is a possibility that bready is always asserted high)   beginaxi_bvalid <= 1'b0; end  endendend

NO.8----读地址通道:

完成读地址通道的握手,即根据主机给出的握手信号来拉高axi_arready,并拉高axi_awv_awr_flag信号,表示从机进入了被读取数据的过程。

 // 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.always @( posedge S_AXI_ACLK )beginif ( S_AXI_ARESETN == 1'b0 )beginaxi_arready <= 1'b0;axi_arv_arr_flag <= 1'b0;end elsebegin    if (~axi_arready && S_AXI_ARVALID && ~axi_awv_awr_flag && ~axi_arv_arr_flag)beginaxi_arready <= 1'b1;axi_arv_arr_flag <= 1'b1;endelse if (axi_rvalid && S_AXI_RREADY && axi_arlen_cntr == axi_arlen)// preparing to accept next address after current read completionbeginaxi_arv_arr_flag  <= 1'b0;endelse        beginaxi_arready <= 1'b0;endend end 

NO.9----锁存读取相关信息:

锁存读取地址(突发传输的首地址)、突发模式、突发长度等信息,并根据握手过程来累加读取计数器axi_arlen_cntr,跟踪写入过程。从机需将此类信息锁存起来,才能对RAM进行操作。

根据读写长度计数器的值来适时地拉高axi_rlast,表示这是当前读取的最后一个数据。

下面的代码还支持3种突发模式,但测试数据仅仅给出了第二种模式:递增突发。

 // Implement axi_araddr latching//This process is used to latch the address when both //S_AXI_ARVALID and S_AXI_RVALID are valid. always @( posedge S_AXI_ACLK )beginif ( S_AXI_ARESETN == 1'b0 )beginaxi_araddr <= 0;axi_arlen_cntr <= 0;axi_arburst <= 0;axi_arlen <= 0;axi_rlast <= 1'b0;axi_ruser <= 0;end elsebegin    if (~axi_arready && S_AXI_ARVALID && ~axi_arv_arr_flag)begin// address latching axi_araddr <= S_AXI_ARADDR[C_S_AXI_ADDR_WIDTH - 1:0]; axi_arburst <= S_AXI_ARBURST; axi_arlen <= S_AXI_ARLEN;     // start address of transferaxi_arlen_cntr <= 0;axi_rlast <= 1'b0;end   else if((axi_arlen_cntr <= axi_arlen) && axi_rvalid && S_AXI_RREADY)        beginaxi_arlen_cntr <= axi_arlen_cntr + 1;axi_rlast <= 1'b0;case (axi_arburst)2'b00: // fixed burst// The read address for all the beats in the transaction are fixedbeginaxi_araddr       <= axi_araddr;        //for arsize = 4 bytes (010)end   2'b01: //incremental burst// The read address for all the beats in the transaction are increments by awsizebeginaxi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1; //araddr aligned to 4 byte boundaryaxi_araddr[ADDR_LSB-1:0]  <= {ADDR_LSB{1'b0}};   //for awsize = 4 bytes (010)end   2'b10: //Wrapping burst// The read address wraps when the address reaches wrap boundary if (ar_wrap_en) beginaxi_araddr <= (axi_araddr - ar_wrap_size); endelse beginaxi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1; //araddr aligned to 4 byte boundaryaxi_araddr[ADDR_LSB-1:0]  <= {ADDR_LSB{1'b0}};   end                      default: //reserved (incremental burst for example)beginaxi_araddr <= axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB]+1;//for arsize = 4 bytes (010)endendcase              endelse if((axi_arlen_cntr == axi_arlen) && ~axi_rlast && axi_arv_arr_flag )   beginaxi_rlast <= 1'b1;end          else if (S_AXI_RREADY)   beginaxi_rlast <= 1'b0;end          end end

NO.10----读数据通道:

完成读数据通道的握手,即根据主机给出的握手信号来拉高axi_rvalid。同时给出正常的读响应值。

 // 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).  always @( posedge S_AXI_ACLK )beginif ( S_AXI_ARESETN == 1'b0 )beginaxi_rvalid <= 0;axi_rresp  <= 0;end elsebegin    if (axi_arv_arr_flag && ~axi_rvalid)beginaxi_rvalid <= 1'b1;axi_rresp  <= 2'b0; // 'OKAY' responseend   else if (axi_rvalid && S_AXI_RREADY)beginaxi_rvalid <= 1'b0;end            endend 

NO.11----RAM的写、读操作:

通过二维数组,以及使能、地址指针等控制信号,构造了一个简单的双口RAM来用于数据存取。

 // ------------------------------------------// -- Example code to access user logic memory region// ------------------------------------------generateif (USER_NUM_MEM >= 1)beginassign mem_select  = 1;assign mem_address = (axi_arv_arr_flag? axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]:(axi_awv_awr_flag? axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]:0));endendgenerate// implement Block RAM(s)generate for(i=0; i<= USER_NUM_MEM-1; i=i+1)begin:BRAM_GENwire mem_rden;wire mem_wren;assign mem_wren = axi_wready && S_AXI_WVALID ;assign mem_rden = axi_arv_arr_flag ; //& ~axi_rvalidfor(mem_byte_index=0; mem_byte_index<= (C_S_AXI_DATA_WIDTH/8-1); mem_byte_index=mem_byte_index+1)begin:BYTE_BRAM_GENwire [8-1:0] data_in ;wire [8-1:0] data_out;reg  [8-1:0] byte_ram [0 : 15];integer  j;//assigning 8 bit dataassign data_in  = S_AXI_WDATA[(mem_byte_index*8+7) -: 8];assign data_out = byte_ram[mem_address];always @( posedge S_AXI_ACLK )beginif (mem_wren && S_AXI_WSTRB[mem_byte_index])beginbyte_ram[mem_address] <= data_in;end   end    always @( posedge S_AXI_ACLK )beginif (mem_rden)beginmem_data_out[i][(mem_byte_index*8+7) -: 8] <= data_out;end   end    endend       endgenerate//Output register or memory read dataalways @( mem_data_out, axi_rvalid)beginif (axi_rvalid) begin// Read address muxaxi_rdata <= mem_data_out[0];end   elsebeginaxi_rdata <= 32'h00000000;end       end    // Add user logic here// User logic endsendmodule

3、仿真波形

接下来使用Vivado自带的仿真器来进行仿真,观看仿真结果

3.1、AXI4-Full总线的仿真波形

我们先把自动生成的仿真信号删除,添加如下的波形信号:

仿真结果如下:

可以看到仿真结果是用这个彩条+字符的形式表示的,非常清晰。这就是添加了AXI VIP IP的效果。

在AXI4-Full总线上共发生了2个事务:先是写事务,接着读事务。下面的五个通道分别示意了此时通道内执行的握手操作,将鼠标放在其中任意一处上,会出现如下信息(顺序1、地址0、突发类型递增突发、突发长度8等):

在左键点击,会显示具体的事务流程如下:

从上图的箭头我们可以直到一次写事务的流程:写地址----写数据----写响应。再看看读事务的流程:

可以看到读事务的流程:读地址----读数据(包含读响应)。

3.2、从机IP的slave接口仿真波形

看完了AXI4-Full总线的仿真波形,我们再看下上面具体解析代码(可以理解为底层驱动)的仿真波形。按如下方法添加:

将信号按通道或用途做好分类,写事务的仿真结果如下:

读事务的仿真结果如下:

写入的数据与读出的数据一致。

4、其他

  • 可以看到其实AXI4-Full总线的使用还是相对比较简单的,只要设计好各个通道的握手时序,以及读写的时序关系就好了。下一篇文章我们再继续分析AXI4-Full总线的Master接口的代码。
  • 创作不易,希望各位大佬多多三连支持!一家之言,如有错误还请指正!

版本信息

文件:V1.0

编号:66

Vivado:Vivado 2019.2

Modelsim:无

Quartus II:无

带你快速入门AXI4总线--AXI4-Full篇(2)----XILINX AXI4-Full接口IP源码仿真分析(Slave接口)相关推荐

  1. 带你快速入门AXI4总线--AXI4-Full篇(3)----XILINX AXI4-Full接口IP源码仿真分析(Master接口)

    写在前面 接slave接口篇,本文继续打包一个AXI4-Full-Master接口的IP,学习下源码,再仿真看看波形. 带你快速入门AXI4总线--AXI4-Full篇(2)----XILINX AX ...

  2. 带你快速入门AXI4总线--AXI4-Stream篇(1)----AXI4-Stream总线

    写在前面 随着对XILINX器件使用的深入,发现越来越多的IP都选配了AXI4的接口.这使得只要学会了AXI4总线的使用,基本上就能对XILINX IP的使用做到简单的上手.所以学会AXI4总线,对X ...

  3. 带你快速入门AXI4总线--AXI4-Full篇(1)----AXI4-Full总线

    写在前面 AXI4系列链接:带你快速入门AXI4总线--汇总篇(直达链接) 1.什么是AXI4-Full? AXI 表示 Advanced eXtensible Interface(高级可扩展接口), ...

  4. 【效率】超详细!手把手带你快速入门 GitHub!

    作者:Peter     编辑:JackTian 来源:公众号「杰哥的IT之旅」 快速入门GitHub GitHub在程序开发领域家喻户晓,现在几乎整个互联网的开发者都将版本管理工具GitHub作为版 ...

  5. 一文带你快速入门【哈希表】

    最近开始学习哈希表,为此特写一遍文章介绍一下哈希表,带大家快速入门哈希表

  6. 手把手带你快速入门超越GAN的Normalizing Flow

    手把手带你快速入门超越GAN的Normalizing Flow 作者:Aryansh Omray,微软数据科学工程师,Medium技术博主 机器学习领域的一个基本问题就是如何学习复杂数据的表征是机器学 ...

  7. 四篇文章带你快速入门Jetpck(中)之ViewModel,DataBinding

    文章目录 四篇文章带你快速入门Jetpck(中)之ViewModel,DataBinding Jetpack 官方推荐架构 ViewModel 添加依赖 创建ViewModel 初始化ViewMode ...

  8. 带你快速了解PROFIBUS总线接口技术

    带你快速了解PROFIBUS总线接口技术 一.概述 1.PROFIBUS是一种用于工厂自动化车间级监控和现场设备层数据通信与控制的现场总线技术.可实现现场设备层到车间级监控的分散式数字控制和现场通信网 ...

  9. Markdown 快速入门上(基础语法篇)

    Markdown 快速入门上(基础语法篇) 1. 简介 Markdown 是一门轻量级的标记性语言,可以用来修饰纯文本使得文档具有一定的优美格式. 像Microsoft Word 文本编辑器, 你需要 ...

  10. 新手如何快速入门Python(菜鸟必看篇)

    学习任何一门语言都是从入门(1年左右),通过不间断练习达到熟练水准(3到5年),少数人最终能精通语言,成为执牛耳者,他们是金字塔的最顶层.虽然万事开头难,但好的开始是成功的一半,今天这篇文章就来谈谈如 ...

最新文章

  1. bmp转换tiff c++代码_Creative Convert for Mac(文件格式转换工具)
  2. 2006---2009年杭电计算机历年研究生复试---笔试编程
  3. BP神经网络识别手写数字项目解析及matlab实现
  4. JNDI配置原理详解
  5. 图像处理相关知识(不断更新)
  6. 【李宏毅机器学习】Introduction of ELMO、BERT、GPT(p25) 学习笔记
  7. vue常用的按键修饰符
  8. SEO优化外包 避坑指南
  9. 雅虎谷歌恩怨回顾:养虎为患自食苦果
  10. Parallels Desktop启动后黑屏无法进入Windows系统
  11. lerna import报错
  12. 微信小程序项目实例小程序记事本+后台
  13. 17-面向对象之语法(2)
  14. 国内外php主流开源cms、商城、点评、SNS、DIGG、RSS、分类信息、Wiki汇总
  15. 跟刀客一起追寻昨日的足迹
  16. 导出Excel功能代码
  17. 阿里面试官常问问题,TCP和UDP的区别,你真的弄懂了吗?
  18. 【Jmeter】安装配置:Jmeter 自定义创建桌面快捷方式
  19. 推荐系统: 问题、算法与研究思路
  20. 怎么用频谱仪测低噪声放大器的噪声系数?

热门文章

  1. 产品更新|用于语音压缩的新型极低比特率编解码器,Lyra 长什么样?
  2. 【Windows Server 2019】存储服务器的配置和管理——iSCSI的安装和配置(下)
  3. 资本纷纷入局,咖啡赛道还能香多久?
  4. html网页图片自动切换代码,html5图片列表切换浏览模式代码
  5. PC端微信一直显示“正在登录”问题处理
  6. 电脑端实现微信双开(登录两个微信)
  7. MEMS传感市场,美/日/德企占主导地位
  8. 编写WPF应用程序实现以下功能:定义一个RandomHelp类,该类提供一个静态的GetIntRandomNumber方法,一个静态的GetDoubleRandomNumber方法。
  9. 真香啊,手把手教你使用 Python 获取基金信息
  10. Android解析短视频无水印链接(精)抖音/快手/微视